6

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

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

下面是 columnsEnumToken 的方法:

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

(我想我可以明白为什么下面的第二行无法编译)

一些问题:

  • 这种方法是“类型安全的”吗?

  • 为什么这行编译:

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

    但是由于类型不兼容,这个编译失败:

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

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

4

2 回答 2

2

班级

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

然而Class<? extends List<String>>可能是有道理的。例如,如果我们有

    public class MyStringList extends ArrayList<String>{}

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

通用数组

泛型数组类型并没有什么问题,只是Java 禁止我们实例化任何类型的......但原因不是很令人信服。只要您知道它是安全的,您就可以继续通过演员表创建一个。

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

兼容分配

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

于 2013-06-13T01:07:53.043 回答
1

想想ColMetaData<T>[]代表什么。在 Java 中,泛型严格来说是一个编译时问题。在运行时,它们不复存在。所以你真正告诉运行时的是你有一个ColMetaData实例数组,这确实是一个具体的类型。但是,这与对数组使用任意类型不同。数组类型仍然是ColMetaData,Java 可以在编译时确定这一点。然后编译器只需要跟踪您存储的实例是否使用了正确的泛型类型。

于 2013-06-13T01:45:57.943 回答