类型安全:从Object中取消选中

时间:2021-11-02 16:03:31

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

感谢您的任何帮助

6 个解决方案

#1


56  

Yes - this is a natural consequence of type erasure. If o is 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 ClientInterface instead of a string.

是的 - 这是类型擦除的自然结果。如果o实际上是一个不会被强制转换捕获的Action 的实例 - 当您尝试使用它时,只会传入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 :(

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

#2


14  

As usual, Jon Skeet is right.

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

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 .class to get a sufficiently accurately typed Class object.

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

#3


5  

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")

#4


1  

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

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

#5


1  

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.

由于擦除(即参数化类型已被删除),您丢失了类型信息,因此发出警告。除了清理周围的代码以便更频繁地使用泛型之外,您无法对此做任何事情,因此您可以传递泛型类型信息并完全避免进行转换。

#6


0  

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 type and the compiler cannot guarantee that the object being type casted is of the same type.

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

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:

如果您不想禁止此警告而不关心type参数,可以使用通配符将代码更改为:

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 instanceof can't check that o is a object of Action<ClientInterface>, it just check if o is a object of Action since further generic type information will be erased at runtime.

这样更安全,因为instanceof无法检查o是否是Action 的对象,它只是检查o是否是Action的对象,因为在运行时将删除更多泛型类型信息。

#1


56  

Yes - this is a natural consequence of type erasure. If o is 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 ClientInterface instead of a string.

是的 - 这是类型擦除的自然结果。如果o实际上是一个不会被强制转换捕获的Action 的实例 - 当您尝试使用它时,只会传入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 :(

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

#2


14  

As usual, Jon Skeet is right.

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

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 .class to get a sufficiently accurately typed Class object.

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

#3


5  

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")

#4


1  

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

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

#5


1  

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.

由于擦除(即参数化类型已被删除),您丢失了类型信息,因此发出警告。除了清理周围的代码以便更频繁地使用泛型之外,您无法对此做任何事情,因此您可以传递泛型类型信息并完全避免进行转换。

#6


0  

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 type and the compiler cannot guarantee that the object being type casted is of the same type.

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

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:

如果您不想禁止此警告而不关心type参数,可以使用通配符将代码更改为:

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 instanceof can't check that o is a object of Action<ClientInterface>, it just check if o is a object of Action since further generic type information will be erased at runtime.

这样更安全,因为instanceof无法检查o是否是Action 的对象,它只是检查o是否是Action的对象,因为在运行时将删除更多泛型类型信息。