我尝试将一个对象强制转换为我的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();
}
[...]
感谢您的帮助
答案 0 :(得分:61)
是的 - 这是type erasure的自然结果。如果o
实际上是Action<String>
的一个不会被演员捕获的实例 - 当您尝试使用它时,您只能看到问题,传入ClientInterface
代替一个字符串。
您可以使用以下方法删除警告:
@SuppressWarnings("unchecked")
作为函数注释,但你不能轻易地解决潜在的问题:(
答案 1 :(得分:15)
像往常一样,Jon Skeet是对的。
详细说明他答案的不易部分:
给出
class ClientAction implements Action<ClientInterface> {}
你可以写:
Class<? extends Action<ClientInterface>> c = ClientAction.class;
Action<ClientInterface> action = c.newInstance();
这会消除强制转换和警告,但代价是引入非泛型类型,因此您可以使用.class
来获得足够准确的Class
对象。
答案 2 :(得分:6)
警告意味着即使在运行时铸件工作正常,编译器也无法保证类型安全。由于擦除,在运行时,转换只是对Action的转换。底层泛型类可能不是预期的ClientInterface类型。在这种情况下,问题将在稍后(可能甚至更晚)出现,作为ClassCastException。
在这种特定情况下,我建议通过以下编译器指令来抑制此特定警告:
@SuppressWarnings("unchecked")
答案 3 :(得分:2)
不要担心。这是因为Java编译器无法知道对象的真实类型是什么。
答案 4 :(得分:1)
由于擦除(即参数化类型已被删除),您丢失了类型信息,因此发出警告。除了清理周围的代码以便更频繁地使用泛型之外,您无法对此做任何事情,因此您可以传递泛型类型信息并完全避免投射。
答案 5 :(得分:0)
这是一个沮丧的人。这是动态转换,编译器不知道引用指向的实际对象。
您收到此警告是因为转换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();
}
[...]
的目标类型是参数化类型,并且编译器无法保证类型转换的对象属于同一类型。
如果您不想取消此警告而不关心type参数,可以使用通配符将代码更改为:
instanceof
这更加安全,因为o
无法检查Action<ClientInterface>
是o
的对象,只是检查Action
是{{1}的对象因为进一步的泛型类型信息将在运行时擦除。