假设我有这个:
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
或者说我有这个:
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
myList
这两个初始化之间的区别是什么?预先设置第一个变体是不对的?
答案 0 :(得分:13)
第一个变体将始终实例化数组列表,第二个仅在调用默认构造函数时实例化。对于第二个解决方案的含义,您必须为添加的任何其他构造函数调用默认构造函数,例如
public class Whatever {
private final List<String> myList;
public Whatever() {
myList = new ArrayList<String>();
}
public Whatever(String name) {
this();
// Other stuff done
}
public Whatever(List<String> myList) {
this.myList = myList;
}
}
如果你不总是使用列表(例如,如果你在我的例子中直接在另一个构造函数中设置列表)并且想要避免创建不必要的对象,那么(第二个)“懒惰”初始化方法可能会更好。 (编辑:我将ArrayList更改为一个接口并将其设置为final。这不是问题的一部分,但它是 - 如评论中所述 - 使用List集合的最佳方式。)
答案 1 :(得分:3)
JVM首先执行这样的代码(在构造函数之外):
public class Whatever {
private ArrayList<String> myList = new ArrayList<String>();
// more code goes here
}
只有这样的代码(在构造函数内):
public class Whatever {
private ArrayList<String> myList = null;
public Whatever() {
myList = new ArrayList<String>();
}
}
所以除非执行的顺序对你来说有点重要,我猜@ Daff的回答是正确的。
答案 2 :(得分:3)
在这个特定的例子中,除了第一种形式更短之外没有区别。
但是,如果属性初始化表达式(可能)抛出异常,则第二种形式允许您捕获异常,或者将它们声明为在构造函数签名中抛出。
当然,如果你有多个构造函数,第二种形式允许你在每个构造函数中以不同方式初始化属性...或使用构造函数链接来初始化属性相同...或混合两种初始化样式。