为什么我不能创建泛型类型的内部类的数组?

时间:2022-04-05 22:28:19

The following code gives a "generic array creation" error.

以下代码给出了“通用数组创建”错误。

public class TestClass<K, V> {
    Entry[] entry;

    private TestClass() {
        entry = new Entry[10]; // <--- this line gives generic array creation error
    }

    private class Entry {
        public Entry() {

        }
    }
}

I'm wondering why this is, because class Entry is not a generic class and has no objects of generic type.

我想知道为什么会这样,因为类Entry不是泛型类,并且没有泛型类型的对象。

Is it because the inner class still has access to the generic types, even if it doesn't use any? That's the best I can come up with, though if it were the case, I don't understand why Java couldn't look and see it makes no use of generic types and is therefore not a generic class?

是因为内部类仍然可以访问泛型类型,即使它不使用任何类型?这是我能想到的最好的,但如果是这样的话,我不明白为什么Java看起来不会看到它不使用泛型类型,因此不是泛型类?

And yes, I have seen many many threads about generic type arrays, but no, I have not found a single one regarding inner classes.

是的,我看过很多关于泛型类型数组的线程,但是没有,我没有找到一个关于内部类的线程。

3 个解决方案

#1


6  

The type is actually TestClass<K, V>.Entry (yes it's because it's an inner class). You can solve this by transforming it into a nested static class:

类型实际上是TestClass .Entry(是的,因为它是一个内部类)。您可以通过将其转换为嵌套的静态类来解决此问题: ,v>

private static class Entry {
    public Entry() {

    }
}

#2


4  

That's about what JLS's talking about the array-creation expression:

这是关于JLS谈论数组创建表达式的内容:

ArrayCreationExpression:
    [...]
    new ClassOrInterfaceType DimExprs [Dims] 
    [...]

JLS 15.10.1:

It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (§4.7). Otherwise, the ClassOrInterfaceType may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type.

如果ClassOrInterfaceType不表示可再现类型(第4.7节),则为编译时错误。否则,ClassOrInterfaceType可以命名任何命名引用类型,甚至是抽象类类型(第8.1.1.1节)或接口类型。

JLS 4.7:

A type is reifiable if and only if one of the following holds:

当且仅当下列之一成立时,类型才可以恢复:

  • It refers to a non-generic class or interface type declaration.

    它引用非泛型类或接口类型声明。

  • It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).

    它是一种参数化类型,其中所有类型参数都是*通配符(第4.5.1节)。

  • It is a raw type (§4.8).

    它是原始类型(§4.8)。

  • It is a primitive type (§4.2).

    它是一种原始类型(§4.2)。

  • It is an array type (§10.1) whose element type is reifiable.

    它是一种数组类型(第10.1节),其元素类型是可恢复的。

#3


0  

Entry is a non-static inner class. That means it is in the scope of the outer class's generic parameters. Every time you just write an unqualified Entry inside TestClass, it implicitly means TestClass<K,V>.Entry, which is a parameterized type! As you know, you cannot create arrays of a parameterized type, e.g. you cannot do new ArrayList<String>[5].

Entry是一个非静态的内部类。这意味着它属于外部类的泛型参数的范围。每次你在TestClass中写一个非限定条目时,它隐含地意味着TestClass .Entry,这是一个参数化类型!如您所知,您无法创建参数化类型的数组,例如你不能做新的ArrayList [5]。 ,v>

Usually, the workaround to creating arrays of a parameterized type, is to create an array of the raw type instead, i.e. new ArrayList[5], or an array of the wildcard-parameterized type, i.e. new ArrayList<?>[5]. But in this case, what is the raw type? The answer is that you must explicitly qualify Entry with the raw outer class type:

通常,创建参数化类型数组的解决方法是创建一个原始类型的数组,即new ArrayList [5],或者通配符参数化类型的数组,即new ArrayList [5]。但在这种情况下,什么是原始类型?答案是您必须使用原始外部类类型明确限定Entry:

entry = new TestClass.Entry[10];

or alternately with the wildcard-parameterized type:

或者使用通配符参数化类型:

entry = (Entry[])new TestClass<?>.Entry[10];

#1


6  

The type is actually TestClass<K, V>.Entry (yes it's because it's an inner class). You can solve this by transforming it into a nested static class:

类型实际上是TestClass .Entry(是的,因为它是一个内部类)。您可以通过将其转换为嵌套的静态类来解决此问题: ,v>

private static class Entry {
    public Entry() {

    }
}

#2


4  

That's about what JLS's talking about the array-creation expression:

这是关于JLS谈论数组创建表达式的内容:

ArrayCreationExpression:
    [...]
    new ClassOrInterfaceType DimExprs [Dims] 
    [...]

JLS 15.10.1:

It is a compile-time error if the ClassOrInterfaceType does not denote a reifiable type (§4.7). Otherwise, the ClassOrInterfaceType may name any named reference type, even an abstract class type (§8.1.1.1) or an interface type.

如果ClassOrInterfaceType不表示可再现类型(第4.7节),则为编译时错误。否则,ClassOrInterfaceType可以命名任何命名引用类型,甚至是抽象类类型(第8.1.1.1节)或接口类型。

JLS 4.7:

A type is reifiable if and only if one of the following holds:

当且仅当下列之一成立时,类型才可以恢复:

  • It refers to a non-generic class or interface type declaration.

    它引用非泛型类或接口类型声明。

  • It is a parameterized type in which all type arguments are unbounded wildcards (§4.5.1).

    它是一种参数化类型,其中所有类型参数都是*通配符(第4.5.1节)。

  • It is a raw type (§4.8).

    它是原始类型(§4.8)。

  • It is a primitive type (§4.2).

    它是一种原始类型(§4.2)。

  • It is an array type (§10.1) whose element type is reifiable.

    它是一种数组类型(第10.1节),其元素类型是可恢复的。

#3


0  

Entry is a non-static inner class. That means it is in the scope of the outer class's generic parameters. Every time you just write an unqualified Entry inside TestClass, it implicitly means TestClass<K,V>.Entry, which is a parameterized type! As you know, you cannot create arrays of a parameterized type, e.g. you cannot do new ArrayList<String>[5].

Entry是一个非静态的内部类。这意味着它属于外部类的泛型参数的范围。每次你在TestClass中写一个非限定条目时,它隐含地意味着TestClass .Entry,这是一个参数化类型!如您所知,您无法创建参数化类型的数组,例如你不能做新的ArrayList [5]。 ,v>

Usually, the workaround to creating arrays of a parameterized type, is to create an array of the raw type instead, i.e. new ArrayList[5], or an array of the wildcard-parameterized type, i.e. new ArrayList<?>[5]. But in this case, what is the raw type? The answer is that you must explicitly qualify Entry with the raw outer class type:

通常,创建参数化类型数组的解决方法是创建一个原始类型的数组,即new ArrayList [5],或者通配符参数化类型的数组,即new ArrayList [5]。但在这种情况下,什么是原始类型?答案是您必须使用原始外部类类型明确限定Entry:

entry = new TestClass.Entry[10];

or alternately with the wildcard-parameterized type:

或者使用通配符参数化类型:

entry = (Entry[])new TestClass<?>.Entry[10];