48

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

感谢您的任何帮助

4

6 回答 6

78

是的 - 这是类型擦除的自然结果。If is 实际上是一个不会被强制转换捕获o的实例- 你只会在尝试使用它时看到问题,传入 a而不是字符串。Action<String>ClientInterface

您可以使用以下方法消除警告:

@SuppressWarnings("unchecked")

作为函数注释,但您无法轻松解决根本问题:(

于 2010-04-07T13:13:35.017 回答
16

像往常一样,Jon Skeet 是对的。

详细说明他的答案中不容易的部分:

给定

class ClientAction implements Action<ClientInterface> {}

你可以写:

Class<? extends Action<ClientInterface>> c = ClientAction.class;
Action<ClientInterface> action = c.newInstance();

这消除了强制转换和警告,代价是引入了非泛型类型,因此您可以使用它.class来获得足够准确的类型Class对象。

于 2010-04-07T13:35:57.113 回答
6

该警告意味着即使转换在运行时工作正常,编译器也无法保证类型安全。由于擦除,在运行时强制转换只是对动作的强制转换。底层泛型类可能不是预期的 ClientInterface 类型。在这种情况下,问题将在稍后(甚至可能更晚)出现,作为 ClassCastException。

在这种特定情况下,我建议通过以下编译器指令抑制此特定警告:

@SuppressWarnings("unchecked")
于 2010-04-07T13:23:09.960 回答
2

别担心。这是因为Java编译器无法知道对象的真实类型是什么。

于 2010-04-07T13:14:12.127 回答
1

由于擦除(即参数化类型已被擦除),您已经丢失了类型信息,因此出现了警告。除了清理周围的代码以便更频繁地使用泛型之外,您无能为力,因此您可以传递泛型类型信息并完全避免强制转换。

于 2010-04-07T13:19:58.493 回答
0

这是一种沮丧。这是编译器不知道引用指向的实际对象的动态转换。

您会收到此警告,因为转换的目标类型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因为进一步的泛型类型信息将在运行时被删除

于 2018-03-26T14:02:20.983 回答