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

时间:2022-06-25 21:44:27

I was surprised, but ... this compiles:

我感到很惊讶,但......编译:

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

Here is the method for columnsEnumToken:

这是columnsEnumToken的方法:

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

(I guess I can see why the second line below doesn't compile)

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

Some questions:

  • Is this method "type safe"?

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

  • Why does this line compile:

    为什么这行编译:

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

    类 cls = this.columnsEnumToken();

    But this one fails to compile because of incompatible types:

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

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

    类 > cls = this.columnsEnumToken();

  • Why is it legal for method getTableColumnsAsEnums() to return an array of a concrete parameterized type, ColMetaData<T>[]. I had thought that these were strictly verboten because there was no runtime way to have them operate type safely.

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

2 个解决方案

#1


2  

Class

Theoretically, a Class cannot represent a parameterized type. For example, there is no class for List<String>, so you should not write Class<List<String>>, but only Class<List>.

从理论上讲,Class不能表示参数化类型。例如,List 没有类,因此您不应该编写Class >,而只能编写Class

However Class<? extends List<String>> could make sense. For example, if we have

然而Class >可能有意义。例如,如果我们有

    public class MyStringList extends ArrayList<String>{}

MyStringList.class is a Class<MyStringList> which is a Class<? extends List<String>>

MyStringList.class是一个Class ,它是一个Class >

Generic Array

There's nothing wrong with generic array type, it's just that Java forbids us to instantiate any... But the reason isn't very convincing. You can just go ahead and create one through casts, as long as you know it's safe.

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

Actually, there is a straightforward way in Java to create a generic array. When we call a method with varargs X..., an X[] object will be created - and X can be any type.

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

Compatible assignment

Apparently for some backward compatibility reason, we can assign a List[] to List<String>[]. That's why you can return a ColMetaData[] object while the return type is ColMetaData<T>[].

显然出于某些向后兼容的原因,我们可以将List []分配给List []。这就是为什么你可以返回一个ColMetaData []对象,而返回类型是ColMetaData []。

#2


1  

Think about what ColMetaData<T>[] represents. In Java, generics are strictly a compile time issue. At run time, they cease to exist. So what you're really telling the runtime is that you have an array of ColMetaData instances, which indeed is a concrete type. This is different, however, than using an arbitrary type for the array. The array type is still ColMetaData, and Java can determine this at compile time. Then the compiler needs only to track that the instances you store use the correct generic type.

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

#1


2  

Class

Theoretically, a Class cannot represent a parameterized type. For example, there is no class for List<String>, so you should not write Class<List<String>>, but only Class<List>.

从理论上讲,Class不能表示参数化类型。例如,List 没有类,因此您不应该编写Class >,而只能编写Class

However Class<? extends List<String>> could make sense. For example, if we have

然而Class >可能有意义。例如,如果我们有

    public class MyStringList extends ArrayList<String>{}

MyStringList.class is a Class<MyStringList> which is a Class<? extends List<String>>

MyStringList.class是一个Class ,它是一个Class >

Generic Array

There's nothing wrong with generic array type, it's just that Java forbids us to instantiate any... But the reason isn't very convincing. You can just go ahead and create one through casts, as long as you know it's safe.

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

Actually, there is a straightforward way in Java to create a generic array. When we call a method with varargs X..., an X[] object will be created - and X can be any type.

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

Compatible assignment

Apparently for some backward compatibility reason, we can assign a List[] to List<String>[]. That's why you can return a ColMetaData[] object while the return type is ColMetaData<T>[].

显然出于某些向后兼容的原因,我们可以将List []分配给List []。这就是为什么你可以返回一个ColMetaData []对象,而返回类型是ColMetaData []。

#2


1  

Think about what ColMetaData<T>[] represents. In Java, generics are strictly a compile time issue. At run time, they cease to exist. So what you're really telling the runtime is that you have an array of ColMetaData instances, which indeed is a concrete type. This is different, however, than using an arbitrary type for the array. The array type is still ColMetaData, and Java can determine this at compile time. Then the compiler needs only to track that the instances you store use the correct generic type.

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