简体   繁体   English

Java不允许泛型类的内部类数组

[英]Java doesn't allow arrays of inner classes for a generic class

I know that you cannot create an array of a generic type, Instead you have to resort to a hack. 我知道你不能创建一个泛型类型的数组,而是你必须求助于黑客攻击。 (Given Java supports generic arrays, just not their creation, it is not clear to me why a hack is better than Java supporting creating generic arrays) (鉴于Java支持通用数组,而不是它们的创建,我不清楚为什么hack比支持创建泛型数组的Java更好)

Instead of writing this 而不是写这个

Map.Entry<K, V>[] entries = new Map.Entry<K, V>[numEntries];

you have to write this 你必须写这个

@SuppressWarnings("unchecked")
Map.Entry<K, V>[] entries = (Map.Entry<K, V>) new Map.Entry[numEntries];

Unfortunately this doesn't work if you have an array of nested type of a generic 不幸的是,如果你有一个嵌套类型的泛型数组,这不起作用

public class Outer<E> {
    final Inner[] inners = new Inner[16]; // Generic array creation

    class Inner {
    }
}

The best work around appears to be 最好的工作似乎是

@SuppressWarnings("unchecked")
final Inner[] inners = (Inner[]) Array.newInstance(Inner.class, 16);

Is this the most "elegant" solution? 这是最“优雅”的解决方案吗?


I make seen Generic Array Creation Compilation Error From Inner Class but the solution here is worse IMHO. 从内部类看到了通用数组创建编译错误,但这里的解决方案更糟糕恕我直言。

Do the following: 请执行下列操作:

@SuppressWarnings("unchecked")
final Inner[] inners = (Inner[])new Outer<?>.Inner[16];

The equivalent to your first example would have been new Outer.Inner[16] but this will isolate the unchecked cast and avoid the raw type. 与你的第一个例子相同的是new Outer.Inner[16]但是这将隔离未经检查的强制转换并避免原始类型。

What you need to realize is that your situation is the same as the first situation you described. 您需要意识到的是,您的情况与您描述的第一种情况相同。

Inner is a non-static inner class of Outer , a generic class. InnerOuter的非静态内部类,是泛型类。 That means Inner is within the scope of the type parameter, and simply writing Inner is short for Outer<E>.Inner . 这意味着Inner属于type参数的范围,而简单地写InnerOuter<E>.Inner缩写。 ie it may not look it, but simply Inner is a parameterized type, just like Map.Entry<K, V> , because the type parameter E of the outer class becomes implicitly a type parameter of the inner class. 即它可能看不到它,但简单地说Inner是一个参数化类型,就像Map.Entry<K, V> ,因为外部类的类型参数E隐式地变成了内部类的类型参数。 The solution to both problems is the same. 两个问题的解决方案是相同的。

Your solution to the first problem was to create an array of the raw type, ie new Map.Entry[numEntries]; 你解决第一个问题的方法是创建一个原始类型的数组,即new Map.Entry[numEntries]; . What is the raw type here? 这里的原始类型是什么? Not Inner , as we already discussed. 正如我们已经讨论的那样,不是Inner Instead, you need to explicitly qualify the outer type to access the raw type: new Outer.Inner[16]; 相反,您需要明确限定外部类型以访问原始类型: new Outer.Inner[16]; . Of course, you need a cast to cast it back into the desired generic array type: 当然,您需要使用强制转换将其强制转换为所需的通用数组类型:

(Inner[])new Outer.Inner[16]

There is another way to create an array of a generic type, without using a raw type -- using a wildcarded type, ie new Map.Entry<?, ?>[numEntries]; 还有另一种创建泛型类型数组的方法,不使用原始类型 - 使用通配类型,即new Map.Entry<?, ?>[numEntries]; . The equivalent for our case would be new Outer<?>.Inner[16]; 我们案例的等价物是new Outer<?>.Inner[16]; . With the cast: 随着演员:

(Inner[])new Outer<?>.Inner[16]

Is it an option for you to make the inner class static ? 你可以选择让内部类static吗?

If that is possible you shold be able to create array of the inner class using the standard way: 如果可能,您可以使用标准方式创建内部类的数组:

public class Outer<E> {
    final Inner[] inners = new Inner[16]; // works

    static class Inner {
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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