Java 在声明中初始化与在构造函数中初始化

Java 在声明中初始化与在构造函数中初始化,java,Java,可能重复: 我想知道,哪一种做法更好,为什么。我应该在声明时初始化类字段,还是应该在构造函数中初始化?考虑到这是一个简单的单行初始化 class Dude { String name = "El duderino"; Dude() { // irrelevant code } } vs Edit:我知道在某些情况下,其中一种样式比另一种样式更受欢迎,比如在执行可能引发异常的初始值设定项代码时。我这里说的是两种风格完全相同的情况。两种方法都可以完成相同

可能重复:

我想知道,哪一种做法更好,为什么。我应该在声明时初始化类字段,还是应该在构造函数中初始化?考虑到这是一个简单的单行初始化

class Dude
{
    String name = "El duderino";

    Dude() {
        // irrelevant code
    }
}
vs


Edit:我知道在某些情况下,其中一种样式比另一种样式更受欢迎,比如在执行可能引发异常的初始值设定项代码时。我这里说的是两种风格完全相同的情况。两种方法都可以完成相同的任务。那么我应该使用哪一个呢?

第一个通常用于初始化静态变量,并且应该仅用于此目的

在这种情况下,您应该使用第二种方法


如果我错了,请纠正我。

为了保持一致性,最好在构造函数中声明变量。变量可能需要一个循环或if-else语句之类的语句来初始化它,如果不将操作放在方法内部,就无法在声明中进行初始化


此规则的例外是静态变量,应在构造函数外部声明。

单行声明不能包含复杂的初始化逻辑

如果将变量初始化为:

class AnotherClass
{
    MyClass anObject = new MyClass(); //MyClass() throws a checked exception.
}
然后,您会发现无法在单行中提供初始值。您需要将这样的代码放在一个块中,很明显,它位于构造函数(或非静态初始化块)中:

使用构造函数:

class AnotherClass
{
    MyClass anObject;

    AnotherClass()
    {
        try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/}
    }
}
class AnotherClass
{
    Integer[] integers;

    AnotherClass()
    {
        this.integers = new Integer[10];
        for(Integer integer: integers)
        {
            integer = Integer.MIN_VALUE;
        }
    }
}
使用初始化块:

class AnotherClass
{
    MyClass anObject;

    {
        try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/}
    }
}
我发现后者导致代码不易理解,因为声明和初始化彼此分离,并且初始化不会发生在开发人员编写的构造函数中(尽管在运行时没有区别)

这同样适用于涉及字段初始化的其他复杂例程。例如,如果要初始化
数组
集合
,并将数组/集合的内容设置为某个默认值,则应在构造函数中执行此操作:

class AnotherClass
{
    MyClass anObject;

    AnotherClass()
    {
        try{this.anObject = new MyClass();}catch(SomeException e){/*handle exception.*/}
    }
}
class AnotherClass
{
    Integer[] integers;

    AnotherClass()
    {
        this.integers = new Integer[10];
        for(Integer integer: integers)
        {
            integer = Integer.MIN_VALUE;
        }
    }
}
如果只能通过访问器(setter方法)设置成员,我更喜欢第一种样式。它提示初始化值是构造时的默认值

如果可以在构造过程中指定成员,我通常会将默认值从参数较少的构造函数传递给适当的构造函数。比如说,

final class Dude {

  private final String name;

  Dude() {
    this("El Duderino");
  }

  Dude(String name) {
    this.name = name;
  }

}

第一种方法适用于非静态字段。这是第二种合成糖。是的,我知道你的意思。但是如果你已经使用C++,你会知道在初始化静态变量的过程中,他没有做过什么事情,而且为了精确的目的,它被添加到java中——初始化静态变量。因此,它必须用于它的用途。我认为没有理由为静态变量保留第一种样式。你能提供任何理由吗?另一个原因是这样的声明可能会与常量声明混淆。我不同意。使用构造函数意味着a)第一眼看不到变量的值(必须查看所有构造函数,看看它是否总是初始化为相同的值)和b)必须为编写的每个构造函数编写初始化。实际上,这里也可以使用初始值设定项块,因此即使在这种情况下,构造函数也不是唯一可能的方法。是的,这可能太令人困惑了。但这是我的意见。将进行编辑。我们可以使用初始化块初始化字段,否则这些字段只能在方法或构造函数中初始化。这听起来很合理。但我所说的是,无论哪种方式,字段的初始化都是相同的,也就是说,不会使用从构造函数检索的数据。类似于初始化用于存储子元素的空内部列表。你还会在构造函数中初始化它吗?@amrhassan-在这种情况下,我会在声明它时初始化它,并将它声明为
final
。在你的示例中,我可以看到使它成为
final
的原因,但是如果有一个setter
setName(字符串名)
。。。