在擦除之后,ClassCastException怎么会发生?
应用擦除后,很难确定未检查的强制转换是否会触发
ClassCastException
. 毕竟,这些类型被简化为
Object
;为什么选演员
对象
抛出铸造异常?此错误的一个原因是调用非泛型实现的泛型代码,其中显式声明了类型。举个例子:
class Test<K> {
public void foo(Object o) {
bar((K) o);
}
public void bar(K k) {
System.out.println(k);
}
public static void main(String[] args) {
Test<Integer> test = new Test<>();
test.foo("hello");
}
}
上面的示例仍将打印
"hello"
Integer
. 删除方法后
bar
只需要一个对象:
public bar(Ljava/lang/Object;)V
如果我们扩展
Test
和覆盖
酒吧
如果类型是显式的,则会产生错误。
class TestInteger extends Test<Integer> {
@Override
public void bar(Integer k) {
super.bar(k);
}
public static void main(String[] args) {
Test<Integer> test = new TestInteger();
test.foo("hello");
}
}
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at TestInteger.bar(TestInteger.java:17)
at Test.foo(TestInteger.java:9)
at TestInteger.foo(TestInteger.java:17)
at TestInteger.main(TestInteger.java:24)
在这个子类中,被重写的方法与由
Test<K>
合成的
或
桥梁法
,以便调用
酒吧
写在
TestInteger
. 这种桥接方法是
发生。它看起来像是吼:
public void bar(Object k) {
bar((Integer) k); //java.lang.String cannot be cast to java.lang.Integer
}
public void bar(Integer k) {
System.out.println(k);
}
keyExtractor.apply((E)o)
存在依赖于导致强制转换异常的显式类型的签名。
铸造前可以检查型号吗?
是的,这是可能的,但是你必须提供
KeyedHashSet
用额外的数据初始化。你不能直接得到
Class
一种方法是注射
等级
isInstance
:
这个方法是Java语言的动态等价物
instanceof
接线员。方法返回
true
对象
参数不为空,可以强制转换为
等级
类别例外
. 它回来了
false
否则。
public class Test<K> {
final Class<K> clazz;
Test(Class<K> clazz) { this.clazz = clazz; }
public void foo(Object o) {
if (clazz.isInstance(o)) {
bar((K) o);
}
}
...
Test<Integer> test = new Test<>(Integer.class);
test.foo("string");
public class Test<K> {
final Function<Object, Boolean> validator;
Test(Function<Object, Boolean> validator) { this.validator = validator; }
public void foo(Object o) {
if (validator.apply(o)) {
bar((K) o);
}
}
...
Test<Integer> test = new Test<>(k -> k instanceof Integer);
test.foo("string");
另一个选项可以是将类型检查移动到
Function<E,K> keyExtractor
Function<Object,K> keyExtractor
,返回
null
理论上也有可能对
keyExtractor
得到一个
实例,但不能保证它的实现也将显式定义类型参数。
检查实例是否会减慢我的应用程序?
isInstance公司
实际上相当快。
There's an interesting article
在实验上比较了试捕和不安全抛投的速度
isInstance公司
解决方案。在实验结果中,显式检查类型的解决方案只比不安全的解决方案稍微慢一些。
contains
方法。如果您保持try-catch解决方案的原样,则可能最终会掩盖由于实现
keyExtractor.apply
,
map.get
,
elem.equals