使用本地类时出现错误“实例的非法泛型类型”

2022-08-31 15:41:38

我有以下使用本地类的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) {}
    }
}

它不会编译并显示以下错误消息:

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

我知道局部类继承了 的泛型类型签名,是一个内部类。在此示例中出现相同类型的编译错误,其中不是本地的,但仍然是内部的:ZX<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
    }
}

它可以通过使非内部/静态来解决: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
    }
}

或者通过验证 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
        }
    }
}

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


答案 1

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

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

如果将 Z 声明为泛型,则该运算符将被视为原始类型,其中它的所有泛型属性(在本例中为封闭类)也被视为原始类型。(类似于原始类型的泛型方法,尽管存在任何泛型签名,但仍被视为原始方法。这是一种保持类型生成向后兼容性的度量。由于任何原始类型都是可重用的,因此将编译将 Z 声明为泛型。instanceofZ


答案 2

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

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)) {}
    }
}

推荐