简体   繁体   中英

Why can't I create an array of an inner class of a generic type?

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.

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?

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

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:

private static class Entry {
    public Entry() {

    }
}

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

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.

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).

  • It is a raw type (§4.8).

  • It is a primitive type (§4.2).

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

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, eg you cannot do new ArrayList<String>[5] .

Usually, the workaround to creating arrays of a parameterized type, is to create an array of the raw type instead, ie new ArrayList[5] , or an array of the wildcard-parameterized type, ie 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:

entry = new TestClass.Entry[10];

or alternately with the wildcard-parameterized type:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM