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

Pau*_*cas 37 java generics

鉴于:

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我明白了:

C.java:4: illegal generic type for instanceof
          if ( !(o instanceof D) )
                              ^
Run Code Online (Sandbox Code Playgroud)

我还得到关于第6行的"未经检查的演员"警告.为什么?该o不是一个泛型类型-它只是一个普通的Object.如何equals()通过检查和转换为实例来正确实现D

注意:显然,这个代码示例是我实际代码的削减版本.真正的类CD更大,并且D是其实现privateC使用的内部类.

仅供参考:真实D的确使用了通用参数T.

Ste*_*n C 42

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

那不是问题.问题......和编译错误的根本原因...... D是一个泛型类.它是通用的,因为它是泛型类中的非静态嵌套类.它的完全限定名称some.pkg.C<T>.D.

仅供参考:真正的D确实利用了通用参数T.

可以利用的事实T是制作D泛型类的原因.

您无法使用instanceof D或是(D)通用类型擦除的原因.基本上,运行时无法区分(比如说)C<String>.DC<Integer>.D.而且,由于它不能做到这一点,就不能确定是否instanceof D应该返回true或者false或者(D)应该成功或抛出ClassCastException.

一种解决方案是声明D为静态.但这不适用于你的"真正的D",因为静态类不能使用封闭类中的泛型类型参数.你的"FYI"说这样做.

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

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

什么类型的擦除?'o'直接是Object类型.

实际上Object是变量的声明类型o.实际的对象将最有可能有一些其他类型的,并且它是类型的(如果它是一个D例如实例)将已经经受类型擦除.


Ste*_*all 7

如果你使内部类静态,代码编译得很好.

例如:

private static class D{...}
Run Code Online (Sandbox Code Playgroud)

请阅读这里的差异.

你也可以尝试o.getClass() != D.class(当然,在防止o为null之后)


new*_*cct 7

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

if ( !(o instanceof C.D) )
Run Code Online (Sandbox Code Playgroud)

要么

if ( !(o instanceof C<?>.D) )
Run Code Online (Sandbox Code Playgroud)


jed*_*rik 5

D.class.isInstance(o)
Run Code Online (Sandbox Code Playgroud)

似乎在这里工作.