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

来源:互联网 发布:成塔软件怎么样? 编辑:程序博客网 时间:2024/05/21 09:27

我在Stack Overflow问的一个问题:

http://stackoverflow.com/questions/12987135/difference-between-two-java-class-construction


Difference between two Java class construction 

这两个Java类的构造过程有什么不同? 

Is there any difference between A1 and A2?
A1 和A2 有什么不一样吗?

class A1 {   B b = new B();   A1() {   }}//and  class A2 {   B b;   A2() {      b = new B();   }}


I want to know when the class B b does its construction if I instantiate the A1 and A2 classes.

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

berry120:

 Not in the example you've given - there's no difference. They'll both initiate a reference to B on object creation.

在你给出的例子里没有区别.他们都实例化了一个B的对象.

However, in terms of style I would personally lean towards A2.
但是,风格上我个人更偏向于A2

If we unpack class A1 a bit more, it's equivalent to this:
如果我们将A1进一步解包 ,它将等同于:

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


The unnamed block of code in the above is the initialisation block, a block of code which is run each and every time an object is created (irrespective of the called constructor, and it runs before the constructor.) It's semantically equivalent to putting all the statements in it at the start of each constructor, which brings us back to A2. Therefore, they're identical.
上述未命名的代码块是初始化代码块, 他会在每次对象创建的时候运行(无论调用的是哪个构造函数,并且会在构造函数之前运行.)这也就相当于将这些声明语句放在了每一个构造函数的开始,这就和A2没有两样了.也就是说 他们是相同的


Rohit Jain:
There is no difference between them. The compiler automatically puts the instance variable initialization inside every constructor you declare, within an initializer block.
他俩没啥不同. 编译器会自动将变量的初始化语句放在你声明的每一个构造函数里的初始化代码块里.
So, your first way, after compilation becomes:
也就是说,方法1在编译后变成了:
class A1 {   B b;   A1() {      {         b = new B();      }   }}


But, the 2nd way is more readable.
但是第二种方法更有可读性.
From the book Java in a nutshell - Chapter#3:

Field declarations, however, are not part of any method, so they cannot be executed as statements are. Instead, the Java compiler generates instance-field initialization code automatically and puts it in the constructor or constructors for the class. The initialization code is inserted into a constructor in the order it appears in the source code, which means that a field initializer can use the initial values of fields declared before it.

(没读懂 翻译不准确)
在这本书第三节中说:
但是,字段(变量?)声明不属于任何一个方法,所以他们不能像声明一样运行. 取而代之的是,JAVA编译器自动生成实例化字段的代码,并将之放在类的构造函数里.初始化代码按照在源代码中出现的顺序排列,这即表示字段的实例化代码段可以使用之前声明过的初始值. 
以下为对Rohit Jain评论:

Personally I find the 1st way more readable. Largely because the initialization code is completely obvious, especially if there are multiple constructors and especially when they can't call each other - you then have code duplication. And what would happen if you removed all constructors - you'd have to use the 1st way. Also, the 2nd way is simply more lines of code adding no value = code bloat. If I saw version 2 in my code base I would refactor to version 1 without hesitation, and scold the programmer who wrote it. – Bohemian
个人认为第一种方法更有可读性.大部分是因为初始化代码相当明显,尤其是当有多个构造函数,并且他们不能互相调用时 - 你必须复制你的代码. 而当你想移除所有的构造函数时会发生什么?你必须使用第一种方法.另外还有,第二种方法只会让代码膨胀.如果我看见第二种版本的代码,我会毫无疑问的将之改为第一种,并骂之前写这段代码的人–Bohemian


@Bohemian. As far as code duplication is concerned, as I said, compiler move the initialization in each of the constructor.. So that part is not the reason for using the first one. –Rohit Jain
至于说担心代码膨胀 ,照我看来, 既然编译器会将初始化代码放在每一个构造函数里...那这就不是使用第一种方法的原因吧

@Bohemian. But using 1st one or the 2nd one is always a programmer's own choice. That will not make much of a difference. –Rohit Jain
但是使用第一种或者第二种方法始终是程序猿自己的选择.这并不会有很大的出入
原创粉丝点击