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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4001938/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:18:59  来源:igfitidea点击:

Why do I get "Illegal generic type for instanceof"?

javagenerics

提问by Paul J. Lucas

Given:

鉴于:

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;
    }
}

I get:

我得到:

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

I also get an "unchecked cast" warning about line 6. Why? The ois nota generic type -- it's just a plain Object. How can I correctly implement equals()by both checking for and casting to an instance of D?

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

Note: Obviously, this code example is a whittled-down version of my actual code. The real classes for Cand Dare much larger and Dis a privateinner class of Cused by its implementation.

注意:显然,此代码示例是我实际代码的精简版本。真正的类CD都大得多,D是一个private内部类的C其实现中使用。

FYI: The real Ddoes make use of the generic parameter T.

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

回答by Stephen C

The o is not a generic type -- it's just a plain Object.

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

That's not the problem. The problem ... and the root cause of both compilation errors ... is that Dis a generic class. And it is generic because it is a non-static nested class in a generic class. Its fully qualified name would be some.pkg.C<T>.D.

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

FYI: The real D does make use of the generic parameter T.

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

And the fact that it couldmake use of Tis what makes Da generic class.

可以利用的事实T是什么造就D了泛型类。

The reason that you cannot use instanceof Dor (D)is generic type erasure. Basically, the runtime cannot distinguish between the types of (say) C<String>.Dand C<Integer>.D. And since it cannot do that, it cannot determine if instanceof Dshould return trueor falseor if (D)should succeed or throw ClassCastException.

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

One solution would be to declare Das static. But that will not work with your "real D" because a static class cannot make use of a generic type parameter from the enclosing class(es). Your "FYI" says that it does that.

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

Another solution is to instantiate the outer class Cpassing it the actual type of Tas a java.lang.Class<T>instance. Then use this Classinstance to implement the runtime type checks and casts as required. This is likely to be messy.

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

The third solution is to carefullyanalyze the code and determine if it is safe to a @SuppressWarning annotations to suppress the "unsafe cast" etc warnings.

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

What type erasure? 'o' is of type Object directly.

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

Actually Objectis the declaredtype of the ovariable. The actual object will most likely have some other type, and it is thattype that (if it is a Dinstance for example) will have been subjected to type erasure.

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

回答by newacct

@StephenC is right in that the problem is that Dmeans C<T>.D, which is a parameterized type. The solution is to use the raw type or the wildcard-parameterized type:

@StephenC 是对的,因为问题在于D意味着C<T>.D,它是一个参数化类型。解决方案是使用原始类型或通配符参数化类型:

if ( !(o instanceof C.D) )

or

或者

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

回答by Stefan Kendall

If you make the inner class static, the code compiles fine.

如果您将内部类设为静态,则代码编译良好。

Ex:

前任:

private static class D{...}

Read herefor the difference.

阅读此处了解区别。

You could also try o.getClass() != D.class(after guarding against o being null, of course)

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

回答by jederik

D.class.isInstance(o)

seems to work here.

似乎在这里工作。