泛型类型转换 [英] Generic Type cast
问题描述
我有以下类(简化但仍然是一个工作示例):
class Test< T> {
列表< T> l = new ArrayList<>();
$ b $ public Test(){
}
public void add(Object o){
l.add((T)o);
以及测试代码:
测试< Double> t = new Test<>();
t.add(1);
t.add(1.2);
t.add(-5.6e-2);
t.add(hello);
一切正常,这并不是我所期待的。不应该 add
方法抛出 ClassCastException
?如果我添加一个 get
方法或多或少是同一件事:
public T get(int i){
return l.get(i);
}
... / ...
t.get(1); // 好。
t.get(3); // OK(?)
Double d = t.get(3); //抛出ClassCastException
为什么只在变量赋值时抛出异常?如果(T)
转换不起作用,我该如何执行类型一致性? 解决方案 div>
不应该使用add方法抛出
ClassCastException
?
不,它不应该(虽然我希望它)。长话短说,编译代码后Java的泛型实现丢弃了类型信息,所以 List< T>
可以接受任何 Object
,并且你的 add
方法中的强制转换不会被检查。
为什么只在变量赋值时抛出异常?
因为转换为 Double
由编译器插入。 Java编译器知道 get
的返回类型是 T
,它是 Double
,因此它会插入一个强制类型以匹配变量 d
的类型,结果将被赋值给它。
以下是您可以如何实现通用安全的强制转换:
class Test< T> {
private final Class< T> CL;
列表< T> l = new ArrayList<>();
public Test(Class< T> c){
cl = c;
}
public void add(Object o){
.add(cl.cast(o));
现在转换由 Class< T>
对象,因此尝试插入不正确类型的对象时,您将得到 ClassCastException
。
I have the following class (simplified but still a working example):
class Test<T> {
List<T> l = new ArrayList<>();
public Test() {
}
public void add(Object o) {
l.add((T)o);
}
}
And the test code:
Test<Double> t = new Test<>();
t.add(1);
t.add(1.2);
t.add(-5.6e-2);
t.add("hello");
Everything is working fine, and that's not what I was expecting. Shouldn't the add
method throw a ClassCastException
? If I add a get
method that's more or less the same thing:
public T get(int i) {
return l.get(i);
}
.../...
t.get(1); // OK.
t.get(3); // OK (?)
Double d = t.get(3); // throws ClassCastException
Why is it only on variable assignment that the exception is thrown? How can I enforce type consistency if the (T)
cast doesn't work?
解决方案
Shouldn't the add method throw a ClassCastException
?
No, it shouldn't (although I wish it did). Long story short, Java implementation of generics discards type information after compiling your code, so List<T>
is allowed to take any Object
, and the cast inside your add
method is not checked.
Why is it only on variable assignment that the exception is thrown?
Because the cast to Double
there is inserted by the compiler. Java compiler knows that the return type of get
is T
, which is Double
, so it inserts a cast to match the type of the variable d
, to which the result is being assigned.
Here is how you can implement a generic-safe cast:
class Test<T> {
private final Class<T> cl;
List<T> l = new ArrayList<>();
public Test(Class<T> c) {
cl = c;
}
public void add(Object o) {
l.add(cl.cast(o));
}
}
Now the cast is performed by a Class<T>
object, so you will get a ClassCastException
on an attempt to insert an object of an incorrect type.
这篇关于泛型类型转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!