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

示例1:

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

示例2:

class A {
    B b;

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

当前回答

没有区别——实例变量初始化实际上是由编译器放在构造函数中。 第一个变体可读性更强。 你不能对第一个变体进行异常处理。 另外还有初始化块,它也由编译器放在构造函数中: { a =新a (); }

检查孙的解释和建议

在本教程中:

但是,字段声明不是任何方法的一部分,因此它们不能像语句那样被执行。相反,Java编译器自动生成实例字段初始化代码,并将其放入类的构造函数中。初始化代码按照在源代码中出现的顺序插入构造函数,这意味着字段初始化器可以使用在它之前声明的字段的初始值。

此外,您可能希望惰性地初始化字段。如果初始化字段是一个昂贵的操作,你可以在需要的时候立即初始化它:

ExpensiveObject o;

public ExpensiveObject getExpensiveObject() {
    if (o == null) {
        o = new ExpensiveObject();
    }
    return o;
}

最后(正如Bill所指出的),为了依赖管理,最好避免在类中的任何地方使用new操作符。相反,使用依赖注入更可取——即让其他人(另一个类/框架)实例化并注入你的类中的依赖项。

其他回答

其实很不一样:

声明发生在构建之前。因此,如果在两个位置都初始化了变量(本例中为b),构造函数的初始化将取代在类级别所做的初始化。

所以在类级别声明变量,在构造函数中初始化它们。

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

我个人的“原则”(几乎从未被打破)是:

的开头声明所有变量 一块 使所有变量为final,除非它们 不能 每行声明一个变量 永远不要在某处初始化变量 宣布 只初始化a中的东西 构造函数时使用 的构造函数 初始化

我的代码是这样的:

public class X
{
    public static final int USED_AS_A_CASE_LABEL = 1; // only exception - the compiler makes me
    private static final int A;
    private final int b;
    private int c;

    static 
    { 
        A = 42; 
    }

    {
        b = 7;
    }

    public X(final int val)
    {
        c = val;
    }

    public void foo(final boolean f)
    {
        final int d;
        final int e;

        d = 7;

        // I will eat my own eyes before using ?: - personal taste.
        if(f)
        {
            e = 1;
        }
        else
        {
            e = 2;
        }
    }
}

This way I am always 100% certain where to look for variables declarations (at the start of a block), and their assignments (as soon as it makes sense after the declaration). This winds up potentially being more efficient as well since you never initialize a variable with a value that is not used (for example declare and init vars and then throw an exception before half of those vars needed to have a value). You also do not wind up doing pointless initialization (like int i = 0; and then later on, before "i" is used, do i = 5;.

我非常重视一致性,所以遵循这个“规则”是我一直在做的事情,它使处理代码变得更容易,因为你不需要到处寻找东西。

你的里程可能会有所不同。

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.

我认为例2更可取。我认为最佳实践是在构造函数外部声明,并在构造函数中初始化。