【发布时间】:2012-09-18 09:12:20
【问题描述】:
目标
创建一个类以用作 String 对象的不可变列表。
方法
我决定利用 Google Guava 的 ImmutableList<E> 集合,而不是用 包装一个简单的 List<E> Collections.unmodifiableList(List<? extends T> list) 因为我知道这可以避免对不知道被包装的支持 List<E> 进行不必要的并发检查(来源:ImmutableCollectionsExplained)。
要求
- 类是跨线程使用的“值持有者”
- 不应允许任何代码在创建后更改内部值
锦上添花
- 该类应实现 Iterable<E> 以按创建顺序迭代值
- 对于给定的一组 String s,应该只有一个类。
尝试
这里有一些尝试,虽然更多的组合是可能的。原谅幽默的演绎。
尝试 #1(包括使用示例)
import java.util.List;
import com.google.common.collect.ImmutableList;
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
britneySpears.spellings = ImmutableList.copyOf(spellings);
return britneySpears;
}
private List<String> spellings;
private BritnetSpearsSpellings() {
}
public List<String> getSpellings() {
return spellings;
}
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
public class Usage {
public static void main(String[] args) {
for (String sepllin : BritnetSpearsSpellings.of("Brittany Spears", "Brittney Spears", "Britany Spears"))
System.out.printf("You spel Britni like so: %s%n", sepllin);
}
}
}
尝试 #2
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings();
britneySpears.spellings = ImmutableList.copyOf(spellings);
return britneySpears;
}
private ImmutableList<String> spellings;
private BritnetSpearsSpellings() {
}
public ImmutableList<String> getSpellings() {
return spellings;
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
}
尝试 #3
class BritnetSpearsSpellings implements Iterable<String> {
public static BritnetSpearsSpellings of(String... spellings) {
BritnetSpearsSpellings britneySpears = new BritnetSpearsSpellings(ImmutableList.copyOf(spellings));
return britneySpears;
}
private final ImmutableList<String> spellings;
private BritnetSpearsSpellings(ImmutableList<String> spellings) {
this.spellings = spellings;
}
public ImmutableList<String> getSpellings() {
return spellings;
}
@Override
public Iterator<String> iterator() {
return spellings.iterator();
}
}
差异总结
-
1 在公共接口中保留 List<E>,在 JavaDoc 中记录不变性。
-
2 将所有内容存储并公开为 Google Guava 的 ImmutableList<E>
-
3 以创建专门的构造函数为代价将内部引用保持为最终引用,这可能会使静态工厂方法初始化在没有其他初始化选项(实际上存在于真实类中)的情况下看起来很傻
问题
请帮助我在这些实现中进行选择,并说明您选择背后的原因。
我认为方法 2 的主要缺点是客户需要对专门的 Google Guava 类型有认识/可见性,而他们可能不应该这样做?
【问题讨论】:
-
您的类
BritnetSpearsSpellings只不过是一个包含ImmutableList的简单包装器。为什么你需要这门课?为什么不直接使用ImmutableList? -
我个人认为 #2 很好,您希望使用该课程的任何人都能够弄清楚
ImmutableList的含义。如果您担心他们可能没有类定义,您可以只返回List和 JavaDoc 它是不可变的。 -
@Jesper Wrappers 还不错。显然,他不需要它,但对于使用/阅读他的代码的人来说,它仍然可以使事情变得更容易或更明显。
-
我需要上面简化示例中缺少的额外功能。我需要包装器。
标签: java guava immutability