类型安全:从对象未选中投
-
25-09-2019 - |
题
我尝试对象转换我的Action类,但它导致了警告:
Type safety: Unchecked cast from Object to Action<ClientInterface>
Action<ClientInterface> action = null;
try {
Object o = c.newInstance();
if (o instanceof Action<?>) {
action = (Action<ClientInterface>) o;
} else {
// TODO 2 Auto-generated catch block
throw new InstantiationException();
}
[...]
感谢您的帮助。
解决方案
是 - 这是类型擦除。如果o
实际上是不会被中投陷入Action<String>
的实例 - 你只看到问题,当您尝试使用它,通过在ClientInterface
而不是字符串
您可以开始使用摆脱了警告:
@SuppressWarnings("unchecked")
作为功能注释,但不能容易地梳理潜在的问题:(
其他提示
和往常一样,乔恩斯基特是正确的。
要详细说明他的回答的未轻易部分:
鉴于
class ClientAction implements Action<ClientInterface> {}
可以写:
Class<? extends Action<ClientInterface>> c = ClientAction.class;
Action<ClientInterface> action = c.newInstance();
这消除了铸造二者以及警告,在引入一个非通用类型,以便可以用.class
得到一个足够精确地类型化的对象Class
的价格。
在警告意味着,编译器不能保证类型安全,即使铸造在运行时工作正常。由于擦除,在运行时的铸造是一个简单的铸件行动。这可能是因为预期基础通用类的类型ClientInterface的不是。在这种情况下,将出现该问题后(甚至更晚),作为一个ClassCastException。
在该特定情况下,我建议通过以下的编译器指令抑制该特定的警告:
@SuppressWarnings("unchecked")
不要担心。这是因为Java编译器没有办法知道,什么是真正的类型的对象。
您已经失去了类型信息,因为擦除(即,参数化类型已经被擦除)的,因此,该警告。你不能做任何事情,比清理周围的代码,使仿制药更频繁地使用,这样你就可以通过在所有的泛型类型的信息,避免铸造等。
这是一个向下转换。这是动态转换编译器在其中有没有引用指向的实际对象的想法。
您因为投Action<ClientInterface>
的目标类型是参数化类型得到这样的警告和编译器不能保证铸造对象是类型相同类型的。
如果你不想抑制这种警告,不关心类型参数,您可以通过使用通配符更改代码这样:
Action<?> action = null;
try {
Object o = c.newInstance();
if (o instanceof Action<?>) {
action = (Action<?>) o;
} else {
// TODO 2 Auto-generated catch block
throw new InstantiationException();
}
[...]
这是更安全的,因为instanceof
不能检查o
是Action<ClientInterface>
的目的,它仅仅检查是否o
是Action
的对象,因为进一步的通用类型的信息将是的擦除是在运行时。