Java:用ArrayList写pojo最高效的方法

Java: The most efficient way to write pojo with ArrayList

在时间和内存消耗方面,编写包含 ArrayList 的简单 pojo class 最正确 and/or 最有效的方法是什么? (关于引用的 java 机制,通过 ref' 传递,赋值等):

public class MyClass {

    //1. Do we need to initialize here?
    public List<String> mList = new ArrayList<>();

    //2. Do we need to declare D. Constructor?
    public MyClass() {}

    //3. Need to initialize the list here or just pass?
    public MyClass(List<String> list) {
        this.mList = list;
    }

    //4. Better way for copy/assignment?
    public void setMlist(List<String> list) {
        this.mList = list;
    }

    public List<String> getMList() {
        return this.mList;
    }

}
  1. Do we need to initialize here?

不,只在需要时才初始化它。如果有可能在未初始化的情况下使用它,请务必检查 null。

  1. Do we need to declare D. Constructor?

如果你什么都不做,我真的不明白拥有它的意义。请注意,有些人更喜欢仍然声明它在其中写评论并指示它不应该做任何事情:

public MyClass(){
    //NOP
}

参见NOP。这不会改变与内存使用相关的任何内容。但是从逻辑上讲,默认构造函数应该初始化列表而不是在开始时初始化它。所以我们有两个选择,我们传递一个已经存在的(使用参数化构造函数)或者我们使用默认构造函数并创建一个空列表。

  1. Need to initialize the list here or just pass?

通过,否则接收它作为参数有什么意义?如果您对其进行初始化并重新分配,那将毫无意义。您可能需要检查接收到的是否为空,否则对其进行初始化。

  1. Better way for copy/assignment?

如果你真的想制作副本,你可能需要检查 Collections#copy。然而,这不是setter的重点,你在这里所做的是正确的。

如果不了解您的意图,这是不可能回答的。即使在编写 "simple pojo class containing ArrayList" 时,您也必须做出大量的设计决策。这里有 8 个,但还有很多很多。

  • 您要将字段设为 public 还是 private? (可能 private。)
  • 如果private,是否要提供get方法?
  • 你想提供一个set方法,还是希望字段在构造函数中一劳永逸地初始化?
  • 你的构造函数 and/or set 方法的参数应该只接受 List<String> 还是你会允许更通用的东西,比如 Collection<? extends CharSequence>?
  • 您希望使用您的 class 的人能够修改 mList 吗? (这不同于重新分配 mList。)
  • 你想写子classes,还是你想把class写成final
  • 如果你想写子classes,你想做任何方法吗final
  • 你想提供一个没有参数的构造函数来将 ArrayList 初始化为合理的默认值吗?

这些问题中最微妙的一个是第 5 个问题。假设有人这样做

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
myClass.setMList(list);

然后再这样做

System.out.println(myClass.getMList());

他们可能希望看到 [a, b, c],但这可能不会发生,因为可以在两者之间修改 myClass 的内部结构。例如:

List<String> list = new ArrayList<>(Arrays.asList("a", "b", "c"));
myClass.setMList(list);
list.remove(1);                         // Modifies the List stored by myClass
System.out.println(myClass.getMList()); // prints [a, c]

如果你不希望这种事情成为可能,你将不得不编写一个 class 在构造函数中复制 List 个对象,setter 和 getter。这将对性能产生影响(但对于小列表来说会很小)。

没有正确或错误的答案。您需要仔细考虑谁在使用 class、他们为什么需要它,并在回答上述所有问题时权衡所有相关因素。