这两种初始化模式之间有区别吗?

时间:2010-01-06 11:01:39

标签: java initialization

假设我有这个:

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这两个初始化之间的区别是什么?预先设置第一个变体是不对的?

3 个答案:

答案 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)

在这个特定的例子中,除了第一种形式更短之外没有区别。

但是,如果属性初始化表达式(可能)抛出异常,则第二种形式允许您捕获异常,或者将它们声明为在构造函数签名中抛出。

当然,如果你有多个构造函数,第二种形式允许你在每个构造函数中以不同方式初始化属性...或使用构造函数链接来初始化属性相同...或混合两种初始化样式。