A1
和有什么区别A2
吗?
class A1 {
B b = new B();
A1() {
}
}
//and
class A2 {
B b;
A2() {
b = new B();
}
}
B b
如果我实例化A1
and类,我想知道该类何时进行构造A2
。
A1
和有什么区别A2
吗?
class A1 {
B b = new B();
A1() {
}
}
//and
class A2 {
B b;
A2() {
b = new B();
}
}
B b
如果我实例化A1
and类,我想知道该类何时进行构造A2
。
它们之间没有区别。编译器自动将实例变量初始化放入您声明的每个构造函数中,在初始化程序块中。
所以,你的第一种方式,编译后变成:
class A1 {
B b;
A1() {
{
b = new B();
}
}
}
但是,第二种方式更具可读性。
简而言之Java一书-Chapter#3:
但是,字段声明不是任何方法的一部分,因此它们不能像语句一样执行。相反,Java 编译器会自动生成实例字段初始化代码并将其放入类的一个或多个构造函数中。初始化代码按照它在源代码中出现的顺序插入到构造函数中,这意味着字段初始化器可以使用在它之前声明的字段的初始值。
B b
当您调用 and 的构造函数时,A1
这两个类都会进行构造A2
,因为构造函数用于初始化非静态数据成员并且B b
是数据成员的引用类型。如果你定义
class A1{
static B b=new B();
A1(){
}
}
然后它将在类加载时加载。编译器将加载类B
并在类加载时创建一个实例,B
否则两者之间没有区别。
不在您给出的示例中-没有区别。他们都会在对象创建时启动对 B 的引用。
但是,就风格而言,我个人倾向于A2
.
如果我们对类A1
进行更多的解包,它就相当于:
class A1 {
B b;
{
b = new B();
}
A1() {
}
}
上面未命名的代码块是初始化块,每次创建对象时都会运行的代码块(与调用的构造函数无关,它在构造函数之前运行。)它在语义上等同于将所有在每个构造函数开始时在其中声明,这使我们回到A2
. 因此,它们是相同的。