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

问题描述 投票:0回答:7

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

感谢您的帮助

java casting type-safety unchecked
7个回答
86
投票

是的 - 这是类型擦除的自然结果。如果

o
实际上是
Action<String>
的实例,不会被强制转换捕获 - 只有当您尝试使用它时,传入
ClientInterface
而不是字符串,您才会看到问题。

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

@SuppressWarnings("unchecked")

作为函数注释,但你无法轻松解决底层问题:(


16
投票

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

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

鉴于

class ClientAction implements Action<ClientInterface> {}

您可以写:

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

这消除了强制转换和警告,但代价是引入非泛型类型,因此您可以使用

.class
来获得类型足够准确的
Class
对象。


7
投票

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

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

@SuppressWarnings("unchecked")

2
投票

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


2
投票

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

您收到此警告是因为转换的目标类型

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
的对象,因为进一步的通用类型信息将被擦除在运行时。


1
投票

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


0
投票

现在你可以简单地做

  if (o instanceof Action<ClientInterface> action) {
   //now you can use action
   }

如果 o 是实例 eof 动作,则该对象将自动转换为动作

© www.soinside.com 2019 - 2024. All rights reserved.