[英]Java Generic Cast Error
我在Java中有一个我不了解的问题,有人可以向我解释这种奇怪的行为吗?
我的代码:
package com.test;
import junit.framework.TestCase;
public class MyTest extends TestCase{
class Container<I, J extends I> {
protected J data;
public J getData() {
return data;
}
@SuppressWarnings("unchecked")
public void setData(I data) {
try {
this.data = (J) data;
} catch (ClassCastException e) {
System.err.println("Cast" + e);
}
}
}
class A {
public String a = "A";
}
class B extends A {
public String B = "B";
}
class C extends A {
public String C = "C";
}
public void test1() throws Exception{
Container<A, B> container = new Container<>();
container.setData(new C());
assertNull(container.getData());
}
}
我希望该测试能够通过,但是出现以下错误:
junit.framework.AssertionFailedError: Expected: <null> but was: com.test.MyTest$C@5c228bbd
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.assertTrue(Assert.java:22)
at junit.framework.Assert.assertNull(Assert.java:277)
at junit.framework.Assert.assertNull(Assert.java:268)
at junit.framework.TestCase.assertNull(TestCase.java:438)
at com.test.MyTest.test1(MyTest.java:39)
容器怎么可能将C类包含为B类?
另外,如果我尝试从数据中获取B值,则会收到ClassCastException ...
public void test1() throws Exception{
Container<A, B> container = new Container<>();
container.setData(new C());
System.out.println(container.getData().B);
}
执行该测试会出现以下错误:
java.lang.ClassCastException: com.test.MyTest$C cannot be cast to com.test.MyTest$B
at com.test.MyTest.test1(MyTest.java:39)
您不应抑制编译时警告,否则您的代码具有奇怪的运行时行为就不会感到惊讶。 由于类型擦除,您对setData
的强制转换未选中,这意味着它永远不会失败。 如果要传递J
,只需在签名中使用J
而不是I
。 类型一致性将在编译时得到保证。
顺便说一句, assertNull
不是测试此行为的正确方法。 您应该让ClassCastException
传播并使用JUnit批注:
@Test(expected = ClassCastException.class)
public void test1() {
Container<A, B> container = new Container<>();
container.setData(new C());
}
这是因为类型擦除 。 通用内容仅用于编译时检查(您的代码通过了)。 编译代码后,将在生成的代码中将I
和J
泛型类型替换为Object
。
因此,正在运行的代码确实看起来像:
public void setData(Object data) {
try {
this.data = (Object) data; //Obviously always works!
} catch (ClassCastException e) {
System.err.println("Cast" + e); //This line never reached
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.