Почему несколько `this()` с другим аргументом не работает в родительском конструкторе?
Зачем this()
должен быть в первом утверждении конструктора-цепочки?
почему несколько this()
с другим аргументом не работает в конечном конструкторе?
package thislatest;
public class ThisLatest {
public static void main(String[] args) {
A a1= new A(10,20,30);
a1.display();
}
}
class A
{
int x,b;
static int c;
A(){ System.out.println("constructor chaining1");}
A(int y)
{ //this();
System.out.println("constructor chaining2");
b=y;
}
A(int x,int y)
{
// this(x);
System.out.println("constructor chaining3");
x=x;
x=y;
}
A(int x,int y,int c)
{ this();
this(y);
this(x,y);
x=x; //self reference initialised by previous constructor
b=y; //no need of this keyword since name is different
this.c=c; //current instance variable or A.c=c will also work
}
void display()
{
System.out.println(x+b); //wrong result due to self reference
System.out.println(c+b); //correct reference
}
}
почему я не могу использовать несколько this()
в конструкторе A(int x,int y,int c)
?
Почему это должно быть первым утверждением?
Это просто для поддержания потока языка?
Я новичок, пожалуйста, используйте простые термины:)
3 ответа
Вы не можете вызывать несколько конструкторов в одном конструкторе, но вы можете связать их так, чтобы один вызывал другой, и так далее. Вы можете делать это, пока у вас не закончатся конструкторы в вашем классе. Рассмотрим класс ниже:
public class MyClass() {
public MyClass() {
this(1);
System.out.printf("Calling MyClass()%n");
}
public MyClass(int a) {
this(a, 2);
System.out.printf("Calling MyClass(%d)%n", a);
}
public MyClass(int a, int b) {
System.out.printf("Calling MyClass(%d, %d)%n", a, b);
}
}
И следующий код клиента:
public class Client() {
public static void main(String[] args) {
new MyClass();
}
}
Вывод, если вы запустили код выше:
Calling MyClass(1, 2)
Calling MyClass(1)
Calling MyClass()
Порядок вывода выше, кажется, в неправильном порядке, потому что printf()
вызовы выполняются после вызова конструктора. Следуя стрелкам ниже, вы можете увидеть, где начинаются вызовы конструктора, и где он окончательно заканчивается:
Object MyClass Client
------ ------- ------
MyClass() <---------- main(String[])
|
V
MyClass(int)
|
V
Object() <--- MyClass(int, int)
Если вам интересно, что означает последняя стрелка: все Java-классы, включая MyClass
Тайно продли Object
-учебный класс. Последний конструктор в MyClass
на самом деле выглядит так:
public MyClass(int a, int b) {
super();
System.out.printf("Calling MyClass(%d, %d)%n", a, b);
}
Вашему классу нужен как минимум один конструктор, который вызывает super()
неявно или явно, иначе цепочка конструктора застрянет в цикле. Компилятор выдает ошибку, если это произойдет.
почему this() должен быть в первом утверждении конструктор-цепочки?: потому что это требуется спецификациями Java! Например, Python позволяет программисту вызывать метод инициализации суперкласса в любом месте. Но Java не позволяет этого. Полная остановка.
почему несколько this() с другим аргументом не работает в конечном конструкторе? тот же ответ, что и выше. Бесполезно спрашивать почему, просто подумайте, как, потому что вы не будете менять языковые спецификации.
Итак, давайте подумаем о том, как. У вас могут быть веские причины вызывать метод инициализации не в качестве первой инструкции конструктора. В этом случае просто используйте неинициализированные методы инициализации и вызовите эти методы из конструкторов:
class A {
private void init1(int x) {
// do something with x
}
private void init2(int x, int y) {
// do something with x and y
...
init1(x); // eventually call init1 in the middle of init2
...
}
A(int x) {
y = 2 *x + 1;
init2(x, y); // call initialization method in the middle of ctor
}
A(int x,int y) {
// eventually some instructions
init2(x, y);
// eventually other instructions
}
}
В языке Java конструкторы особенные. Вам придется использовать другой язык, если вы не можете принять его.
Каждый конструктор инициализирует один экземпляр класса. Таким образом, в конструкторе вы можете вызвать только один другой конструктор. Причина, по которой вызов конструктора должен быть первым, заключается в том, что вы делегируете создание экземпляра другому конструктору. В противном случае, если первая строка вашего конструктора не является вызовом другого конструктора, экземпляр создается уже перед выполнением первой строки (т. Е. Super() вызывается неявно). Таким образом, вызов конструктора после аналогичен вызову какого-либо конструктора внутри вашего конструктора во второй раз, что, очевидно, будет недопустимым, поскольку конструктор создает экземпляр только для одного экземпляра.