这两种方法都有什么优势吗?

示例1:

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

示例2:

class A {
    B b;

    A() {
         b = new B();
    }
}

当前回答

第二种选择更可取,因为它允许在ctors中使用不同的逻辑进行类实例化,并使用ctors链接。如。

class A {
    int b;

    // secondary ctor
    A(String b) {
         this(Integer.valueOf(b));
    }

    // primary ctor
    A(int b) {
         this.b = b;
    }
}

所以第二种选择更加灵活。

其他回答

另一种选择是使用依赖注入。

class A{
   B b;

   A(B b) {
      this.b = b;
   }
}

This removes the responsibility of creating the B object from the constructor of A. This will make your code more testable and easier to maintain in the long run. The idea is to reduce the coupling between the two classes A and B. A benefit that this gives you is that you can now pass any object that extends B (or implements B if it is an interface) to A's constructor and it will work. One disadvantage is that you give up encapsulation of the B object, so it is exposed to the caller of the A constructor. You'll have to consider if the benefits are worth this trade-off, but in many cases they are.

第二种选择更可取,因为它允许在ctors中使用不同的逻辑进行类实例化,并使用ctors链接。如。

class A {
    int b;

    // secondary ctor
    A(String b) {
         this(Integer.valueOf(b));
    }

    // primary ctor
    A(int b) {
         this.b = b;
    }
}

所以第二种选择更加灵活。

There is one more subtle reason to initialize outside the constructor that no one has mentioned before (very specific I must say). If you are using UML tools to generate class diagrams from the code (reverse engineering), most of the tools I believe will note the initialization of Example 1 and will transfer it to a diagram (if you prefer it to show the initial values, like I do). They will not take these initial values from Example 2. Again, this is a very specific reason - if you are working with UML tools, but once I learned that, I am trying to take all my default values outside of constructor unless, as was mentioned before, there is an issue of possible exception throwing or complicated logic.

这两种方法都可以接受。注意,在后一种情况下,如果存在另一个构造函数,b=new b()可能无法初始化。将构造函数外部的初始化器代码看作一个公共构造函数,代码将被执行。

我认为这几乎只是一个品味问题,只要初始化是简单的,不需要任何逻辑。

如果不使用初始化块,构造函数方法会更脆弱一些,因为如果稍后添加第二个构造函数而忘记在那里初始化b,则只有在使用最后一个构造函数时才会得到一个空b。

有关Java中初始化的更多细节,请参阅http://java.sun.com/docs/books/tutorial/java/javaOO/initial.html(以及关于初始化器块和其他不为人所知的初始化特性的解释)。