为什么我会得到“非法泛型类型”?

2022-09-01 00:05:53

鉴于:

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 行的“未检查的投射”警告。为什么?它不是一个泛型类型 - 它只是一个普通的.如何通过检查和强制转换为 的实例来正确实现 ?oObjectequals()D

注意:显然,此代码示例是我的实际代码的缩减版本。和 的实数类要大得多,并且是其实现所使用的内部类。CDDprivateC

仅供参考:real确实利用了通用参数。DT


答案 1

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

这不是问题所在。问题...以及两个编译错误的根本原因...是一个泛型类。它是泛型的,因为它是泛型类中的非静态嵌套类。其完全限定的名称将为 。Dsome.pkg.C<T>.D

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

事实上,它可以利用它来构成一个泛型类。TD

不能使用 的原因 或 是泛型类型擦除。基本上,运行时无法区分 (比如)和 的类型。并且由于它不能这样做,因此它无法确定是否应该返回或是否应该成功或投掷 。instanceof D(D)C<String>.DC<Integer>.Dinstanceof Dtruefalse(D)ClassCastException

一种解决方案是声明为静态。但这不适用于您的“真实 D”,因为静态类不能使用封闭类(es)中的泛型类型参数。您的“FYI”说它这样做。D

另一种解决方案是实例化外部类,将其作为实例传递实际类型。然后使用此实例根据需要实现运行时类型检查和强制转换。这很混乱。CTjava.lang.Class<T>Class

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

什么类型的擦除?“o”是直接类型对象。

实际上是变量的声明类型。实际对象很可能具有其他类型,并且正是类型(例如,如果它是实例)将受到类型擦除的影响。ObjectoD


答案 2

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

if ( !(o instanceof C.D) )

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

推荐