类型安全:从Object中取消选中强制转换

时间:2010-04-07 13:10:40

标签: java casting type-safety unchecked

我尝试将一个对象强制转换为我的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();
 }
 [...]

感谢您的帮助

6 个答案:

答案 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}的对象因为进一步的泛型类型信息将在运行时擦除