使用本地类时出现错误“ instanceof的非法通用类型”

Luk*_*der 61 java generics local-class

我有以下使用本地类的 Java代码。

import java.util.Arrays;

public class X<T> {
    void m() {
        class Z {}

        for (Object o : Arrays.asList(1, 2, 3))
            if (o instanceof Z) {}
    }
}
Run Code Online (Sandbox Code Playgroud)

它不会与以下错误消息一起编译:

X.java:8: error: illegal generic type for instanceof
            if (o instanceof Z) {}
                             ^
1 error
Run Code Online (Sandbox Code Playgroud)

我了解到,本地类Z继承了的通用类型签名X<T>,即内部类。在此示例中,出现了相同类型的编译错误,该错误Z不是本地的,但仍然是内部的:

import java.util.Arrays;

public class X<T> {
    class Z {}

    void m() {
        for (Object o : Arrays.asList(1, 2, 3))
            if (o instanceof Z) {} // Compilation error
    }
}
Run Code Online (Sandbox Code Playgroud)

可以通过使Z非内部/静态方式解决此问题:

import java.util.Arrays;

public class X<T> {
    static class Z {}

    void m() {
        for (Object o : Arrays.asList(1, 2, 3))
            if (o instanceof Z) {} // Compiles now
    }
}
Run Code Online (Sandbox Code Playgroud)

或通过排位赛X.Z

import java.util.Arrays;

public class X<T> {
    class Z {}

    void m() {
        for (Object o : Arrays.asList(1, 2, 3)) {
            if (o instanceof X.Z) {}    // Compiles now
            if (o instanceof X<?>.Z) {} // Also
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如何在不更改本地班级本身的情况下限定本地班级或解决此限制?

Raf*_*ter 43

对我来说,这似乎是Java语言的疏忽或限制,我认为这是不可能的。

instanceof表达式中的引用类型必须根据JLS 4.7是可验证的,这意味着必须通过其完全限定的名称将其表示为可验证的类型。同时,JLS 6.7声明本地类没有完全限定的名称,因此不能将它们表示为可验证的。

如果将Z声明为泛型,则instanceof运算符会将Z其所有泛型属性(在本例中为封闭类)也视为原始类型,并将其视为原始类型。(类似于原始类型的泛型方法,尽管有任何泛型签名也被视为原始类型。这是一种保持类型生成向后兼容的措施。)由于任何原始类型都是可修正的,因此将Z声明为泛型即可编译。

  • 泛型被修补到该语言中,并且某些极端情况(例如类文字)没有得到适当覆盖。没有什么是完美的,我认为有进行监督的机会。;) (5认同)

Luk*_*der 28

可能的解决方法是使用反射:

import java.util.Arrays;

public class X<T> {
    void m() {
        class Z {}

        for (Object o : Arrays.asList(1, 2, 3))
            if (Z.class.isInstance(o)) {}
    }
}
Run Code Online (Sandbox Code Playgroud)


Edo*_*chi 5

显然,通过使Z泛型编译成功。我希望将其<T>作为类型参数,但是您只需要使其通用即可,因此任何操作都可以

import java.util.Arrays;

public class X<T> {
    void m() {
        class Z<Anything> {}

        for (Object o : Arrays.asList(1, 2, 3))
            if (Z.class.isInstance(o)) {}
    }
}
Run Code Online (Sandbox Code Playgroud)

正确的解决方案将使本地课程合格,但我认为您不能。您可以将其重构为私有静态类,或者可能是最好的。

  • 一旦将`Z`设为通用,就不再需要应用反射解决方法了... (2认同)