Java:为什么我能够引用具体参数化类型的非null数组?

sco*_*ttb 6 java arrays generics

我很惊讶,但是...这个编译:

public <T extends Database> ColMetaData<T>[] getTableColumnsAsEnums() {
            Class<? extends ColMetaData> cls = this.columnsEnumToken();
            return cls.<ColMetaData<T>[]>getEnumConstants(); }
Run Code Online (Sandbox Code Playgroud)

这是columnsEnumToken的方法:

// Returns a class token for an enum class
public Class<? extends ColMetaData> columnsEnumToken()  { 
    return this.e_colsToken; 
}
Run Code Online (Sandbox Code Playgroud)

(我想我可以看到为什么下面的第二行不能编译)

一些问题:

  • 这种方法"类型安全"吗?

  • 为什么这行编译:

    Class<? extends ColMetaData> cls = this.columnsEnumToken();

    但由于类型不兼容,这个无法编译:

    Class<? extends ColMetaData<T>> cls = this.columnsEnumToken();

  • 为什么getTableColumnsAsEnums()返回一个具体参数化类型数组的方法是合法的,ColMetaData<T>[].我曾经认为这些是严格禁止的,因为没有运行时方式让它们安全地操作类型.

Zho*_*gYu 2

班级

理论上,类不能表示参数化类型。例如,没有 的类List<String>,所以你不应该写Class<List<String>>,而只能写Class<List>

不过Class<? extends List<String>>可能有道理。例如,如果我们有

    public class MyStringList extends ArrayList<String>{}
Run Code Online (Sandbox Code Playgroud)

MyStringList.class是一个Class<MyStringList>这是一个Class<? extends List<String>>

通用数组

泛型数组类型并没有什么问题,只是 Java 禁止我们实例化任何类型……但是原因并不是很有说服力。只要您知道这是安全的,您就可以继续通过强制类型转换来创建一个。

实际上,Java 中有一种简单的方法来创建通用数组。当我们使用 varargs 调用方法时,将创建X...一个对象 - 并且 X 可以是任何类型。X[]

兼容作业

显然出于某些向后兼容性的原因,我们可以将 a 分配List[]List<String>[]. 这就是为什么你可以ColMetaData[]在返回类型为 时返回一个对象 ColMetaData<T>[]