有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

guava如何设计一个包含java的不可变值类。什么是弦?

客观的

创建一个类,用作String对象的不可变列表

接近

我决定利用{a2}{a3}集合,而不是用{a5}包装一个简单的{a4},因为我知道这样可以避免对后台{a4}进行不必要的并发检查,而后台{a4}不知道被包装(来源:ImmutableCollectionsExplained

要求

  • 类可以是跨线程使用的“值持有者”
  • 创建后不允许任何代码更改内部值

很高兴拥有

  • 类应该实现Iterable<E>以便按照创建顺序对值进行迭代
  • 对于给定的String集,应该只有一个类

尝试

这里有一些尝试,尽管可能有更多的组合。原谅这个幽默的表演

尝试#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 GuavaImmutableList<E>存储和公开所有内容

  • 3以创建专门构造函数为代价,将内部引用保持为最终引用,在没有其他初始化选项的情况下,可能会使静态工厂方法初始化看起来很愚蠢(在实际类中实际存在)

问题:

请帮助我从这些实现中选择一个,并说明选择背后的原因

我认为方法#2的主要缺点是客户需要对专业的Google Guava类型有认知/可见性,而他们可能不应该


共 (3) 个答案

  1. # 1 楼答案

    从你的问题陈述(“一组给定的字符串应该只有一个类”),听起来你真正想要的是一个Interner<ImmutableSet<String>>

    • Interner是一个实用工具(用Interners.newStrongInterner()构造一个),用于确保只有一个对象的实例包含任何给定数据
    • ^如果您的集合是不可变的,并且是支持成员身份测试的任意顺序的集合,{a2}是正确的选择

    或者,您可能希望查看Cache<ImmutableSet<String>>(有关详细信息,请参见Caches Explained

  2. # 2 楼答案

    显然,在我看来#3是最好的选择final强制并记录类(该字段)的不可变性,而不仅仅是List本身是不可变的

    无论是在getter中用一些javadoc公开List还是实际的ImmutableList都是另一回事。我看到过一些观点,返回ImmutableList清楚地记录了意图,但仍然是将自己绑定到一个实现上,而不是一个接口,用于一些低级别的东西,并且将来可能需要更改(即使不变性“通常”是好的)。因此,对于您的应用程序来说,它更像是一种全球性的设计选择,而不仅仅是一个用例。如果你使用ImmutableList,我不认为这对客户端来说是一个真正的问题,它的名字是明确的,通过你的IDE可以很容易地看到它是List的实现,如果他们想要更多信息,他们可以访问javadoc。谁知道呢,他们可能会喜欢它,并开始使用它,以及番石榴提供的所有其他好吃的东西:-)

  3. # 3 楼答案

    我会在Attempt #1上使用Attempt #2,因为它记录了您总是返回ImmutableList实例的情况。一般来说,选择尽可能具体的返回类型和尽可能一般的参数类型是很有用的。但对于这两种情况,我们更喜欢接口而不是具体的类

    嗯,ImmutableList是一个抽象类,而不是一个接口。但由于其本质,它的行为非常像一个接口

    当类成员引用spellings在对象的生命周期内无法更改,和/或希望整个类本身不可变时,Attempt #3是有意义的。否则,当spellings可以在对象生存期内分配给另一个ImmutableList时,它就没有意义了

    考虑到你例子中的用例,我倾向于说#3是最好的选择