通用对象的集合不按预期工作

时间:2011-11-26 13:34:08

标签: java

我有自己的泛型类,如下所示:

C1<T> {
    T value;
    ...
    void setValue(T val) {
        this.avlue = val;
    }
}

在其他地方我有这个系列:

  List<C1> list;

然后在另一段代码中,我实例化了一些类型为C1的对象:

C1<Integer> a;
C1<Float> b;
C1<String> c;
...

后来我把它们放在列表中;

list.add(a);
list.add(b)
...

我接下来要做的就是: 迭代列表执行此操作:

list.get(i).setValue(obj);

其中obj是Object类型的变量,可以是Integer,Float等。

现在问题是从列表返回的C1实例(让我们称之为c1)定义如下:

C1<Type1>

Java将允许这样:

c1.setValue(val2);

其中val2的类型为Type2,而Type2不等于Type1,甚至不在同一个类层次结构中(Object ofc除外)!

编辑: 忘了问问题:) 当我按上述方式访问时,如何使setValue“类型安全”?

2 个答案:

答案 0 :(得分:0)

您将集合定义为List<C1>,因此无论您如何参数化该类型,它都会接受C1类型的任何对象。如果您想将其限制为仅持有特定类型的C1,则需要执行List<C1<Type1>>

答案 1 :(得分:0)

如果将C1<Type1>C1<Type2>类型的对象存储在List<C1>中,则从列表中检索元素时无法确定确切的类型。您只会知道它是C1(与列表中的所有元素一样)。

如果你真的需要在运行时询问C1它的类型参数是什么,你需要在C1中存储一些类型标记:

 C1<T> {
    private final Class<T> cls;

    C1(Class<T> pCls) {
      cls = pCls;
    }

    Class<?> getTypeParameter() {
      return cls;
    }
  }

然后,您可以在列表中获取的实例上调用getTypeParameter(),并将其与您预期的类型进行比较。

请注意,如果您使用未经检查的演员,这仍然允许您将Type2的值存储在C1<Type1>中。如果您想消除这种可能性,请在val中针对cls检查setValue()的运行时类型,如果不匹配则抛出异常。