Variable Instantiation on Declaration vs. on Constructor in Java – Java中声明中的变量实例化与构造函数中的变量实例化

最后修改: 2022年 10月 11日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.绪论

There is uncertainty among Java developers on whether to initialize variables when they are declared or in a constructor.

在Java开发者中,对于是在声明变量时还是在构造函数中初始化变量存在不确定性。

In this tutorial, we’ll take a look at what happens when we initialize variables at their declaration or in a constructor. We’ll try to point out some differences and similarities between them if they exist.

在本教程中,我们将看看当我们在变量声明处或构造函数中初始化变量时会发生什么。我们将尝试指出它们之间存在的一些差异和相似之处。

2. Field Declaration Initialization

2.字段声明初始化

We need to know that the Java compiler takes out all field declaration initializations and moves them as code in the constructor in the order of their appearance in the class. From this, we can deduce there are no big differences between initializing variables at the declaration or in the constructor because, after compilation, they end up in the constructor anyways:

我们需要知道,Java编译器取出所有字段声明的初始化,并按照它们在类中出现的顺序将它们作为代码移入构造函数。由此,我们可以推断出在声明处初始化变量和在构造函数中初始化变量之间没有大的区别,因为在编译之后,无论如何它们最终都会出现在构造函数中。

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

3. Constructor Field Initialization

3.构造函数字段初始化

From our above code, after compilation, we end up with this constructor:

从我们上面的代码中,经过编译,我们最终得到了这个构造函数。

public class A {
    private B b;

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

Then does it matter where we initialize data?

那么我们在哪里初始化数据重要吗?

After knowing what happens after compilation, not that much. It’s more of a preference that we tend to form based on our experiences.

在了解了汇编后的情况后,就不那么重要了。这更像是我们倾向于根据我们的经验形成的一种偏好。

4. Guidelines

4.准则

We can look into some guidelines when deciding whether to initialize data at field declaration or in the constructor.

在决定是否在字段声明或构造函数中初始化数据时,我们可以研究一些准则。

This is a dependency injection constructor:

这是一个依赖注入构造函数。

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

A recommended way of initializing variables is to use dependency injection. By using this way of initializing objects, we adhere to different principles.

一种推荐的初始化变量的方式是使用依赖注入。通过使用这种初始化对象的方式,我们坚持了不同的原则。

4.1. Readability

4.1.可读性

For us to have better readability, it could be important to initialize the data either at field declaration or in the constructor, not both. Of course, we should take this as a guideline, not as a rule, since you can have both.

为了使我们有更好的可读性,在字段声明时或在构造函数中初始化数据可能是重要的,而不是同时进行。当然,我们应该把这作为一个准则,而不是规则,因为你可以同时拥有这两种情况。

Having all the initialization in one place makes it easier to know where to look for the initialization code. This will make it easier for any future developer to look at initialization in only one place, not scattered around multiple places.

把所有的初始化放在一个地方,可以让人更容易知道在哪里寻找初始化代码。这将使任何未来的开发者更容易只在一个地方看初始化,而不是散落在多个地方。

4.2. Single Responsibility

4.2.单一责任

By using the dependency injection constructor, we remove the responsibility of instantiating the B object from the A class. Following the single responsibility principle is always preferable where possible.

通过使用依赖注入构造函数,我们从A类中移除实例化B对象的责任。在可能的情况下,遵循单一责任原则始终是可取的。

This will also mean we will have lower coupling between classes, another awesome guideline to follow.

这也意味着我们将拥有较低的类间耦合度,这也是另一个值得遵守的准则。

4.3. Testability

4.3.可测试性

Using this constructor tends to have easier ways to test our code since we can easily mock our B object and then inject it into our A object with this constructor:

使用这个构造函数往往有更容易的方法来测试我们的代码,因为我们可以很容易地模拟我们的B对象,然后用这个构造函数把它注入我们的A对象。

B b = mock(B.class);
A a = new A(b);

4.4. Maintainability

4.4.可维护性

Having lower coupling classes also brings us better maintainability of the code. Thus, we’ll be able to modify the code easier.

拥有低耦合度的类也给我们带来更好的代码可维护性。因此,我们将能够更容易地修改代码。

5. Conclusion

5.总结

In this article, we’ve seen that using either field declaration or constructor initialization is more of a preference, and some differences between them can be the design principles that we want to follow.

在这篇文章中,我们已经看到,使用字段声明或构造函数初始化更多的是一种偏好,它们之间的一些差异可以成为我们要遵循的设计原则。

Using the constructor initialization and dependency injection can give us some advantages of design principles.

使用构造器初始化和依赖注入可以给我们带来一些设计原则的优势

As always, the source code for the examples is available over on GitHub.

像往常一样,这些例子的源代码可以在GitHub上找到