我应该在声明时还是在构造函数中实例化实例变量?

2022-08-31 05:36:24

这两种方法有什么好处吗?

示例 1:

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

示例 2:

class A {
    B b;

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

答案 1
  • 没有区别 - 实例变量初始化实际上是由编译器放在构造函数中的。
  • 第一个变体更具可读性。
  • 不能对第一个变体进行异常处理。
  • 还有初始化块,编译器也将其放在构造函数中:

    {
        a = new A();
    }
    

查看孙的解释和建议

本教程中

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

此外,您可能希望懒惰地初始化字段。如果初始化字段是一项成本高昂的操作,您可以在需要时立即对其进行初始化:

ExpensiveObject o;

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

最终(正如Bill所指出的那样),为了依赖关系管理,最好避免在类中的任何位置使用运算符。相反,使用依赖注入是可取的 - 即让其他人(另一个类/框架)实例化并注入类中的依赖关系。new


答案 2

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

class A{
   B b;

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

这消除了从 的构造函数创建对象的责任。从长远来看,这将使您的代码更具可测试性,更易于维护。这个想法是减少两个类和 之间的耦合。这给你的一个好处是,你现在可以将任何扩展(或者如果它是接口)的对象传递给 的构造函数,它将工作。一个缺点是放弃了对象的封装,因此它向构造函数的调用方公开。您必须考虑这些好处是否值得这种权衡,但在许多情况下,它们是值得的。BAABBBABA