Java 类型安全:来自 Object 的未经检查的强制转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2592642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 09:37:30  来源:igfitidea点击:

Type safety: Unchecked cast from Object

javacastingtype-safetyunchecked

提问by Matthew

I try to cast an object to my Action class, but it results in a warning:

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

Thank you for any help

感谢您的任何帮助

采纳答案by Jon Skeet

Yes - this is a natural consequence of type erasure. If ois actually an instance of Action<String>that won't be caught by the cast - you'll only see the problem when you try to use it, passing in a ClientInterfaceinstead of a string.

是的 - 这是类型擦除的自然结果。Ifo实际上是一个实例,Action<String>它不会被演员表捕获 - 只有在尝试使用它时才会看到问题,传入一个ClientInterface而不是字符串。

You can get rid of the warning using:

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

@SuppressWarnings("unchecked")

as a function annotation, but you can't easily sort out the underlying problem :(

作为一个函数注解,但你不能轻易理清潜在的问题:(

回答by Petar Minchev

Don't worry about. It is because the Java compiler has no way to know, what is the real type of the object.

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

回答by Chris Dennett

You've lost the type information because of erasure (i.e., the parameterised types have been erased), hence the warning. You can't do anything about it, other than clean up the surrounding code so that generics are used more frequently, so you can pass the generic type information and avoid casting at all.

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

回答by Eyal Schneider

The warning means that the compiler can't guarantee type safety even if the casting works fine at runtime. Due to erasure, at runtime the casting is simply a casting to Action. It is possible that the underlying generic class is not of type ClientInterface as expected. In this case, the problem will appear later (maybe even much later), as a ClassCastException.

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

In this specific case I recommend suppressing this specific warning by the following compiler directive:

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

@SuppressWarnings("unchecked")

回答by meriton

As usual, Jon Skeet is right.

像往常一样,乔恩斯基特是对的。

To elaborate on the not-easily part of his answer:

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

Given

给定的

class ClientAction implements Action<ClientInterface> {}

You can write:

你可以写:

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

This eliminates both the cast and the warning, at the price of introducing a non-generic type so you can use .classto get a sufficiently accurately typed Classobject.

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

回答by upupming

This is a downcast. It's the dynamic cast where the compiler has no idea of the actual object the reference is pointing to.

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

You get this warning because the target type of the cast Action<ClientInterface>is a parameterized typeand the compiler cannot guarantee that the object being type casted is of the same type.

您收到此警告是因为强制转换的目标类型Action<ClientInterface>参数化类型,并且编译器无法保证被强制转换的对象类型相同。

If you don't want to suppress this warning and don't care about the type parameter, you could change the code to this by using wildcards:

如果您不想取消此警告并且不关心类型参数,则可以使用通配符将代码更改为此:

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();
 }
 [...]

This is much safer because the instanceofcan't check that ois a object of Action<ClientInterface>, it just check if ois a object of Actionsince further generic type information will be erasedat runtime.

这更安全,因为instanceof无法检查它o是否是 of 的对象Action<ClientInterface>,它只是检查是否o是 of 的对象,Action因为在运行时将删除进一步的泛型类型信息。