【问题标题】:Why do I get "Illegal generic type for instanceof"?为什么我会得到“instanceof 的非法泛型类型”?
【发布时间】:2010-10-23 00:56:01
【问题描述】:

给定:

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 的真实类要大得多,Dprivate 的内部类 C 由其实现使用。

仅供参考:真正的D 确实使用了泛型参数T

【问题讨论】:

  • 您是否尝试过 instanceof C.D 而不是 instanceof D
  • 我只是要注意给出的示例 已损坏。
  • @Evan:行得通。但是为什么需要资格呢?
  • 这可能是编译器错误 (forums.sun.com/thread.jspa?threadID=5300129)。
  • @Evan:很好的链接——谢谢!但是,如果您通读所有 cmets,我认为这不是一个错误……只是 Java 泛型的一个奇怪结果。

标签: java generics


【解决方案1】:

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

这不是问题。问题......以及这两个编译错误的根本原因......是D 是一个泛型类。它是泛型的,因为它是泛型类中的非静态嵌套类。它的完全限定名称是some.pkg.C&lt;T&gt;.D

仅供参考:真正的 D 确实使用了泛型参数 T。

可以利用T这一事实使得D成为一个泛型类。

不能使用instanceof D(D) 的原因是泛型类型擦除。基本上,运行时无法区分(比如)C&lt;String&gt;.DC&lt;Integer&gt;.D 的类型。由于它不能这样做,它无法确定instanceof D 是否应该返回truefalse,或者(D) 是否应该成功或抛出ClassCastException

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

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

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

什么类型的擦除? 'o' 直接属于 Object 类型。

实际上Objecto 变量的声明 类型。实际对象很可能有其他类型,并且 那个 类型(例如,如果它是 D 实例)将受到类型擦除。

【讨论】:

    【解决方案2】:

    @StephenC 是对的,问题在于D 表示C&lt;T&gt;.D,这是一个参数化类型。解决方案是使用原始类型或通配符参数化类型:

    if ( !(o instanceof C.D) )
    

    if ( !(o instanceof C<?>.D) )
    

    【讨论】:

      【解决方案3】:
      D.class.isInstance(o)
      

      似乎在这里工作。

      【讨论】:

        【解决方案4】:

        如果将内部类设为静态,则代码可以正常编译。

        例如:

        private static class D{...}
        

        阅读here 了解其中的区别。

        你也可以试试o.getClass() != D.class(当然要防止 o 为空)

        【讨论】:

        • 我知道非静态和静态嵌套类的区别。在这种情况下,我需要它是非静态的。如果我将嵌套类设为静态,则无法使用泛型参数 T。
        • o.getClass() 和 D.class 比较呢?您不会知道它们属于相同的参数化类型,但我不确定您是否可以通过类型擦除可靠地做到这一点。
        • 什么类型的擦除? 'o' 直接属于 Object 类型。
        • 假设 'o' 指向某个类型 D,则无法判断它是 D 而不是 D。因此,如果我是 D,而 o 确实是 D,那么你可以说他们都是 D。
        • 但它是一个普通的对象,可以是 any 对象:D、Integer、Runnable 等。我不明白为什么类型很重要。
        猜你喜欢
        • 2010-12-26
        • 2012-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-03-22
        • 1970-01-01
        • 2021-02-16
        • 2013-10-26
        相关资源
        最近更新 更多