Java 我可以使用普通JDK框架强制集合中单个元素的不变性吗?

Java 我可以使用普通JDK框架强制集合中单个元素的不变性吗?,java,collections,Java,Collections,我知道有包装器方法,比如,和它的其他变体,比如,等等,如果客户机只通过这些方法返回的引用访问集合,而不是直接访问集合,那么这使得集合是不可变的。但它是否防止集合中的单个对象不可变?我可以用标准的JDK类而不是像Google Guava这样的API实现同样的功能吗?不,你必须使自己的类具有不可变的版本 样本: List< StringBuilder > l1 = new LinkedList< StringBuilder >(); l1.add( new StringBui

我知道有包装器方法,比如,和它的其他变体,比如,等等,如果客户机只通过这些方法返回的引用访问集合,而不是直接访问集合,那么这使得集合是不可变的。但它是否防止集合中的单个对象不可变?我可以用标准的JDK类而不是像Google Guava这样的API实现同样的功能吗?

不,你必须使自己的类具有不可变的版本

样本:

List< StringBuilder > l1 = new LinkedList< StringBuilder >();
l1.add( new StringBuilder()); // ok
List< StringBuilder > l2 = Collections.unmodiableList( l1 );
l2.get(0).append( "Hello" );  // ok, because StringBuilder, unlike String is mutable
l2.add( new StringBuilder()); // throws exception
Listl1=newlinkedlist();
l1.添加(新的StringBuilder());//好啊
Listl2=Collections.undiablelist(l1);
l2.get(0).append(“Hello”);//好的,因为StringBuilder与String不同,它是可变的
l2.添加(新的StringBuilder());//抛出异常

我能想到的使类不可变的唯一方法是将其包装在代理中,然后您可以访问控制任何变化的方法:

然后

MyProxy {
  private MyClass myClass = ...;

  public int getInt() {
      return myClass.getInt();
  }
  ...
等等

您还可以通过反射实现相同的功能(与Spring包装bean的方式相同,您通常只与它们的代理进行交互)


尽管如此,如果客户机获得了实际的底层类(本例中为MyClass),那么他们将能够改变内部结构。如果我理解你的目标,没有什么真正的方法可以直接阻止这一点,除非永远只公开你让客户看到的“可变”包装。你可以用这样的东西

class Wraper<T>{
    List<T> list = new ArrayList<T>(); //Other Collection?
    T someObj = getYourInstance();
    public T get(int index) {
        T obj = list.get(index);
        if (obj.equals(someObj)){//should be overriden
           return createInstanceOf(obj);
        } else {
           return obj;
        }
    }
}
类包装器{
List List=new ArrayList();//其他集合?
T someObj=getYourInstance();
公共T获取(整数索引){
T obj=list.get(索引);
如果(obj.equals(someObj)){//应该被重写
返回createInstanceOf(obj);
}否则{
返回obj;
}
}
}

您要求的是Java中的
const
等价物。这是不可能的。多年来,许多用户(包括我自己)都要求这样做,作为对Java的增强。它被关闭并被Sun拒绝


如果您想这样做,您必须在对象中构建一个可变标志(可能在构建时)。然后在每个mutator方法中,检查可变性标志。也许您可以使用代理库(如CGLIB)做一些更“奇特”的事情,但对于您试图实现的目标来说,这可能过于复杂。

番石榴如何实现您的目标?@Kent我不是说番石榴实现了我的目标。我基本上是在寻找没有番石榴的方法,即使它达到了我的目标。我希望现在的意图更清楚了。为什么不吃番石榴呢?广泛使用-因此经过所有用户的测试,将继续改进并获得bug修复,而无需您做任何事情,你也可以访问其他所有的东西吗?“Joeg,因为我不负责为增加我的项目中包括第三方坛子的技术栈做出设计决定。我会考虑推荐它(我甚至从来没有去过谷歌大楼),但如果您不能也没有看过这篇SO文章,它可能会有所帮助:
class Wraper<T>{
    List<T> list = new ArrayList<T>(); //Other Collection?
    T someObj = getYourInstance();
    public T get(int index) {
        T obj = list.get(index);
        if (obj.equals(someObj)){//should be overriden
           return createInstanceOf(obj);
        } else {
           return obj;
        }
    }
}