我应该在构造函数或外部构造函数初始化variables
当我使用基于C ++知识的Java时,我喜欢用以下方式初始化variables。
public class ME { private int i; public ME() { this.i = 100; } }
过了一段时间,我改变了这个习惯
public class ME { private int i = 100; public ME() { } }
我遇到过其他的源代码,有些正在使用第一个约定,另外一个是使用第二个约定。
我能否知道你们都推荐哪个会议?为什么?
我发现第二种风格(声明+初始化一次性)优越。 原因:
- 它一目了然地清楚variables是如何初始化的。 通常情况下,当读取一个程序并碰到一个variables时,你首先会去声明它(通常在IDE中是自动的)。 使用样式2时,您会立即看到默认值。 对于样式1,您还需要查看构造函数。
- 如果你有多个构造函数,你不必重复初始化(你不能忘记它们)。
当然,如果初始化值在不同的构造函数中是不同的(甚至是在构造函数中计算的),那么必须在构造函数中完成。
我倾向于使用第二个来避免一个复杂的构造函数 (或无用的),我也不认为这是一个初始化(即使它是一个初始化),但更像是给一个默认值。
例如在你的第二个代码片段中,你可以删除构造函数,并有一个更清晰的代码。
我有几乎总是在构造器中初始化的习惯(习惯)有两个原因,一个在我看来,它增加了readablitiy(更清晰),另外两个构造器中的逻辑控制比一行更多。 即使最初的实例variables不需要逻辑,如果需要的话,在构造函数中给它添加更多的逻辑灵活性。
至于上面提到的有关多个构造函数的问题,通过使用一个无参数构造函数来初始化所有对所有构造函数都是相同的实例variables,然后每个构造函数在第一行调用this(),可以轻松解决这个问题。 这解决了你的reduncancy问题。
我看到的第一个方法唯一的问题是如果你打算增加更多的构造函数。 那么你将重复代码和可维护性会受到影响。
如果你在顶层或者在构造函数中进行初始化,它没有太大的区别。但是在某些情况下,在构造函数中初始化是有道理的。
class String { char[] arr/*=char [20]*/; //Here initializing char[] over here will not make sense. String() { this.arr=new char[0]; } String(char[] arr) { this.arr=arr; } }
所以根据情况有时你必须在顶部初始化,有时在构造函数中初始化。
FYI其他选项的初始化,而不使用构造函数:
class Foo { int i; static int k; //instance initializer block { //run's every time a new object is created i=20; } //static initializer block static{ //run's only one time when the class is loaded k=18; } }
有一件事,不pipe你如何初始化字段,如果可能的话,使用final
限定符将确保在multithreading环境中字段值的可见性。
我build议在构造函数中初始化variables。 这就是为什么它们存在:确保您的对象正确构build(初始化)。
无论哪种方式将工作,这是一个风格的问题,但我更喜欢构造函数的成员初始化。
我认为两者都是正确的编程明智的,
但是我认为你的第一个select是以面向对象的方式更正确的,因为在构造函数中是当对象被创build的时候,并且是variables初始化的时候。
我认为这是“按书”的惯例,但是可以开放讨论。
维基百科
这两个选项可以根据你的情况是正确的。
一个非常简单的例子是:如果你有多个构造函数,所有的variables都以相同的方式初始化variables(int x = 2)。 在声明中初始化variables是有意义的,以避免冗余。
在这种情况下考虑最终variables也是有意义的。 如果你知道最终variables在声明中有什么价值,那么在构造函数之外初始化它是有意义的。 但是,如果您希望类的用户通过构造函数初始化最终variables,则需要延迟初始化直到构造函数。
它可以取决于你正在初始化什么 ,例如,如果涉及检查的exception,你不能只使用字段初始化。 例如,以下内容:
public class Foo { FileInputStream fis = new FileInputStream("/tmp"); // throws FileNotFoundException }
除非你还包含声明检查exception的构造函数,否则会导致编译时错误,或者扩展一个超类,例如:
public Foo() throws FileNotFoundException {}
我会说,这取决于默认 。 例如
public Bar { ArrayList<Foo> foos; }
我会在构造函数之外创build一个new ArrayList
,如果我总是假设foos
不能为null。 如果Bar
是一个有效的对象,不关心foos
是否为null,我会把它放在构造函数中。
你可能会不同意,并说这是把对象置于有效状态的构造器工作。 但是,如果显然所有的构造函数都应该做同样的事情(初始化foos
),为什么要复制这些代码呢?