我有自己的泛型类,如下所示:
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“类型安全”?
答案 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()
的运行时类型,如果不匹配则抛出异常。