2010-10-23 68 views
27

考虑:为什么我会得到“instanceof非法通用类型”?

public class C<T> { 
    private class D { 
     public boolean equals(Object o) { 
      if (!(o instanceof D)) // line 4 
       return false; 
      D other = (D)o;    // line 6 
      return i == other.i; 
     } 
     int i; 
    } 
} 

我得到:

C.java:4: illegal generic type for instanceof 
      if (!(o instanceof D)) 
          ^

我也得到一个 “未投” 警告约6行么? o而不是通用类型 - 它只是一个普通的Object。如何通过检查和铸造D的实例来正确执行equals()

注:显然,这个代码示例是我的实际代码的削减版本。 CD的真实类别要大得多,而DCprivate内部类别。

供参考:真正的D确实使用通用参数T

+7

你试过*的instanceof C.D *而不是*的instanceof d *? – 2010-10-23 00:59:28

+0

我只是要指出,给出*的例子*被打破。 – 2010-10-23 01:00:09

+0

@Evan:行之有效。但为什么资格是必要的? – 2010-10-23 01:09:02

回答

30

的o是不是一个泛型类型 - 它只是一个普通的对象。

这不是问题所在。问题......和编译错误的根本原因...... D是一个泛型类。它是通用的,因为它是泛型类中的非静态嵌套类。其完全合格的名称将是some.pkg.C<T>.D

FYI:真正的d确实使用泛型参数T.

而事实上,它可能利用T是什么使D泛型类的。

您不能使用instanceof D(D)的原因是通用类型擦除。基本上,运行时不能区分(说)C<String>.DC<Integer>.D的类型。并且由于它不能这样做,所以它不能确定instanceof D应该返回true还是false或者(D)应该成功或丢弃ClassCastException

一种解决方案是宣布D为静态。但是这不适用于你的“真正的D”,因为静态类不能使用封闭类中的泛型类型参数。你的“供参考”说它是这样做的。

另一种解决方案是实例化外部类C,将实际类型T作为java.lang.Class<T>实例传递给它。然后使用这个Class实例来实现运行时类型检查并根据需要进行强制转换。这很可能是凌乱的。

第三种解决方案是仔细地分析代码并确定@SuppressWarning注释是否安全以抑制“不安全转换”等警告。

什么类型的擦除? 'o'是Object的类型。

实际上Object声明类型o可变的。实际的对象很可能有其他类型,并且它是,即类型(例如,如果它是例如D实例)将进行类型擦除。

7

如果你让内部类是静态的,代码编译得很好。

例:

private static class D{...} 

阅读here的差异。

你也可以尝试o.getClass() != D.class(后防范o为空,当然)

+0

我知道非静态和静态嵌套类之间的区别。在这种情况下,我需要它是非静态的。如果我使嵌套类静态,我不能使用通用参数T. – 2010-10-23 01:05:40

+1

o.getClass()和D.class比较怎么办?你不会知道它们具有相同的参数化类型,但我不确定你是否可以通过类型擦除来可靠地完成此操作。 – 2010-10-23 01:07:03

+0

什么类型的擦除? 'o'是Object的类型。 – 2010-10-23 01:12:29

3
D.class.isInstance(o) 

似乎在这里工作。

6

@StephenC是正确的,问题是D意味着C<T>.D,这是一个参数化类型。该解决方案是使用原始类型或通配符参数化类型:

if (!(o instanceof C.D)) 

if (!(o instanceof C<?>.D)) 
相关问题