Using an object in its own constructor
Is it possible (or reasonable) to use an object in its own constructor? (Sorry for the poorly worded nob question)
Let's say I have a class "Students" that contains an arrayList of the subclass Student and a method for adding new students to the array.
Can I in my Student constructor use the addStudent method to add a new instance to the array on creation? ... like this:
//Students
class Students{
private static ArrayList<Student> STUDENTS = new ArrayList<>();
public static void addStudents(Student student){
STUDENTS.add(student);
}
}
//Student
class Student /*extends Students <- old misstake left for reference*/{
private String name = "";
private int birthYear = 0;
Student(String _name, int _birthYear){
this.name = _name;
this.birthYear = _birthYear;
//insert wild guess
Students.addStudents(this(name,birthYear));
}
}
Or will it just loop and create many objects until everything works?
source to share
You can; you just don't have to.
One reason is that you cannot always add all instances Student
to the same shared list. For example, if you instantiate Student
in a unit test and add them to the list Students
in the constructor, you will have to worry about clearing the list after the test to avoid accidentally sharing state between tests.
Another reason is that adding an instance to a constructor is called unsafe publishing. You are passing a reference to an instance that has not been fully initialized. This can lead to some very tricky bugs, especially concurrency related.
You should always wait until the instance is fully initialized (i.e. one new Whatever
returned) before doing anything with it.
Better to decouple the creation Student
from adding to the list Students
. Use a factory method to create students:
class Students{
private static ArrayList<Student> STUDENTS = new ArrayList<>();
public static void addStudents(Student student){
STUDENTS.add(student);
}
// Factory method.
public static Student createAndAddStudent(String name, int birthYear) {
Student student = new Student(name, birthYear);
addStudents(student);
return student;
}
}
In terms of your current code, you don't need extends Students
. Logically, Student
it is Students
n't, Car
it won't be anymore Cars
(let's say it's loud, it just doesn't make sense).
All you have to do is call a static method:
class Student {
Student() {
// ...
Students.addStudents(this);
// ...
}
}
source to share
Incorrect use of the keyword this
. You are not sending any values ββalong with this
. this
is a reference to the current object.
The advantage of using this method is that you never have to individually add all students to the list. Along with that, it saves you the trouble of accidentally forgetting to add it to your array.
class Student extends Students{
private String name = "";
private int birthYear = 0;
Student(String _name, int _birthYear){
this.name = _name;
this.birthYear = _birthYear;
addStudents(this);
}
public static void main(String[] args){
Student s = new Student("Ryan", 1999);
}
}
source to share