我有两个问题,分别在构造函数中使用“this”和“super”。
如果从另一个构造函数调用重载的构造函数,那么调用语句 this(......)是第一个吗?我听说否则会出现编译错误。
如果从派生类构造函数内部调用基类构造函数,建议(非强制)调用语句 super(.....)是第一个吗?我听说否则编译器会插入一个没有参数的默认 super(),并将其作为第一个语句。
如果上述概念属实,似乎编译器对“this”更严格,对“super”更灵活。
答案 0 :(得分:2)
如果从另一个构造函数调用重载的构造函数,那么“this”语句必须是第一个吗?我听说否则会出现编译错误。
如果您尝试使用其他构造函数初始化对象字段并通过this(...)
调用它,那么它需要是调用构造函数的第一个语句
如果从派生类构造函数内部调用基类构造函数,建议(非强制)“super”语句是第一个吗?我听说否则编译器会插入super()并将其作为第一个语句。
是
如果上述概念属实,似乎编译器对“this”更严格,对“super”更灵活。
在创建子类的实例时,无论如何都要初始化超类的字段,因此需要隐式调用默认构造函数
答案 1 :(得分:2)
任何构造函数的第一个语句总是super()
(隐式); 除非您将第一行显式调用super()
构造函数或添加到this()
构造函数。
这由JLS-8.8.9. Default Constructor涵盖(部分)
如果一个类不包含构造函数声明,则隐式声明一个没有形式参数且没有throws子句的默认构造函数。
如果声明的类是原始类Object,则默认构造函数具有空体。否则,默认构造函数只调用不带参数的超类构造函数。
如果默认构造函数是隐式声明的,但是超类没有可访问的构造函数(§6.6)且没有参数且没有throws子句,那么这是一个编译时错误。
答案 2 :(得分:1)
如果有一个this(...);
调用一个构造函数调用另一个构造函数,它必须首先出现在正文中。
如果有一个super(...);
调用构造函数来调用超类的构造函数,它也必须首先出现在正文中。 (您不能包含其他一些语句,然后调用super(...)
。)所以这真的不比this(...)
的规则更灵活。如果根本没有super(...)
,而没有this(...)
,则会有一个隐式super()
,没有参数,作为正文的第一个语句插入。如果超类定义构造函数但没有定义无参构造函数,那么子类构造函数必须以super(...)
调用[或this(...)
]开头,否则编译器将给你一个错误:
public class Class1 {
public Class1(int arg) { ... }
public Class1(String arg) { ... }
}
public class Class2 {
public Class2() {
// The body MUST start with this "super" statement:
super(<something>);
// where the argument can be converted to an int or String, or else it's
// an error! (Exception: it can start with a this() to call another constructor
// defined for Class2.)
}
}