Java中有关类的构造和初始化

2012年 10月 31日

tags: java


这是我在Stack Overflow问的一个问题:


这两个Java类的构造过程有什么不同? A1 和A2 有什么不一样吗?

class A1 {
   B b = new B();
   A1() {
   }
}

//and  

class A2 {
   B b;
   A2() {
      b = new B();
   }
}

我想知道的是 在我实例化A1和A2的时候 B都是什么时候构造的


berry120: 在你给出的例子里没有区别.他们都实例化了一个B的对象.
但是,风格上我个人更偏向于A2
如果我们将A1进一步解包 ,它将等同于:

class A1 {
   B b;
   {
       b = new B();
   }

   A1() {
   }
}

上述未命名的代码块是初始化代码块, 他会在每次对象创建的时候运行(无论调用的是哪个构造函数,并且会在构造函数之前运行.)这也就相当于将这些声明语句放在了每一个构造函数的开始,这就和A2没有两样了.也就是说 他们是相同的.


Rohit Jain: 他俩没啥不同. 编译器会自动将变量的初始化语句放在你声明的每一个构造函数里的初始化代码块里. 也就是说,方法1在编译后变成了:

class A1 {
   B b;
   A1() {
      {
         b = new B();
      }
   }
}

但是第二种方法更有可读性.

在Java in a nutshell这本书第三节中说: 但是,字段声明不属于任何一个方法,所以他们不能像声明一样运行. 取而代之的是,JAVA编译器自动生成实例化字段的代码,并将之放在类的构造函数里.初始化代码按照在源代码中出现的顺序排列,这即表示字段的实例化代码段可以使用之前声明过的初始值.

以下为对Rohit Jain评论: 个人认为第一种方法更有可读性.大部分是因为初始化代码相当明显,尤其是当有多个构造函数,并且他们不能互相调用时 - 你必须复制你的代码. 而当你想移除所有的构造函数时会发生什么?你必须使用第一种方法.另外还有,第二种方法只会让代码膨胀.如果我看见第二种版本的代码,我会毫无疑问的将之改为第一种,并骂之前写这段代码的人–Bohemian 至于说担心代码膨胀 ,照我看来, 既然编译器会将初始化代码放在每一个构造函数里...那这就不是使用第一种方法的原因吧 –Rohit Jain 但是使用第一种或者第二种方法始终是程序猿自己的选择.这并不会有很大的出入 –Rohit Jain

评论!

社交