63

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

我知道本地类Z继承了 的泛型类型签名X<T>,是一个内部类。这个例子中出现了同样的编译错误,where Zis not local,但还是inner:

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

但是我怎样才能在不改变本地类本身的情况下限定本地类,或者解决这个限制呢?

4

4 回答 4

43

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

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

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

于 2019-04-16T08:57:13.777 回答
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)) {}
    }
}
于 2019-04-16T08:35:37.523 回答
6

显然,通过使 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)) {}
    }
}

正确的解决方案是使本地课程合格,但我认为您不能。要么将它重构为私有静态类,要么这可能是你能得到的最好的。

于 2019-04-16T08:42:40.147 回答
3

这也应该有效。也使用反射。但似乎是一个有效的解决方案。

import java.util.Arrays;

public class X<T> {


    void m() {

        class Z2 {
        }

        for(Object o: Arrays.asList(1,2,3)) {
            if(Z2.class.isAssignableFrom(o.getClass())) {

            }
        }

    }

}
于 2019-04-16T08:41:30.307 回答