我正在我的系统中创建一个“事件”的不可变表示,因此对于在构造函数中传递的所有者列表,我想对它们进行只读视图。此外,如果他们传入null
列表,我想在这种情况下制作一个只读的空列表。
现在,自从Collections.unmodifiableList
null
以来,我现在有了这个:
userOwners_ = Collections.unmodifiableList(userOwners != null
? userOwners
: new ArrayList<String>(0));
但这似乎有点丑陋和低效。在Java中有更优雅的方法吗?
答案 0 :(得分:5)
Collections.emptyList()
。但严重的是,null
应该是NPE。
答案 1 :(得分:3)
同样丑陋,但效率稍高的答案
userOwners_ = userOwners != null ?
Collections.unmodifiableList(userOwners) :
Collections.emptyList();
然而,还有其他一些事情要注意。
似乎在某些时候,有人决定使用null
来表示空列表。这是糟糕的设计......导致需要特殊处理。最好将其设置为新列表,如果您知道列表始终为空,则为emptyList()
。
如果你没有有意识地决定null
是表示空列表的方式,那么null
是“意外的”,你应该让它抛出一个NPE,所以你可以追踪并解决原因。 (它可能是你假设的变量在其他地方被初始化......但不是。这是一个错误。)
对于您是否需要“只读”列表或“不可变”列表存在一些疑惑:
unmodifiableList()
方法为您提供了一个无法修改的列表;即它是“只读”。但原始列表仍然可以修改,这些更改将通过“只读”包装器显示。clone()
原始列表,然后使用unmodifiableList()
包装克隆。标识符userOwners_
是最广泛接受/使用的Java样式指南中的代码样式违规。
答案 2 :(得分:1)
结果userOwners_仍然是可变的 - 对userOwners的任何更改都将成为userOwners _的一部分。
如果您真的希望该成员变量是不可变的,那么正确的方法是这样做:
private final List<String> userOwners;
public MyObject(List<String> userOwners){
this.userOwners = userOwners != null ? Collections.unmodifiableList(new ArrayList<String>(userOwners)) : Collections.emptyList();
}
作为一个小问题,您的成员变量命名不符合Java样式指南(userOwners_对我们这些经常阅读Java代码的人来说很奇怪)
扩展另一张海报所写的内容:在接受公共方法的空输入(不抛弃NPE)之前,真的很难想。这种行为可以隐藏错误 - 更好地快速失败并迫使调用者思考他们正在做什么。
答案 3 :(得分:1)
我首选的方法是使用Guava:
this.userOwners = ImmutableList.copyOf(Preconditions.checkNotNull(userOwners));
与tackline的答案一样,这也会引发异常,而不是将null静态转换为空列表。
与此处的其他答案不同,使用ImmutableList.copyOf()
可确保调用者无法向您传递他们以后可以变异的列表。