如何创建条目具有通用字段的项目数组?

时间:2015-07-29 13:48:02

标签: java generics type-erasure nested-generics

我有这段代码:

constant

当我编译它时,我收到一个错误,说:

import java.util.*;
import java.lang.*;
import java.io.*;

class Main{
    public static void main (String[] args){
        Foo<String> foo = new Foo<String>(1000);
    }
}

class Foo<Key extends Comparable<Key>>{
    private Entry[] a;
    private class Entry{
        Key key;
    }
    public Foo(int size){
        a = (Entry[])new Object[size]; // <- this is the problem
    }
}

我试过了:

Exception in thread "main" java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [LFoo$Entry;
at Foo.<init>(Main.java:17)
at Main.main(Main.java:7)

但后来我发了一个错误说:

import java.util.*;
import java.lang.*;
import java.io.*;

class Main{
    public static void main (String[] args){
        Foo<String> foo = new Foo<String>(1000);
    }
}

class Foo<Key extends Comparable<Key>>{
    private Entry[] a;
    private class Entry{
        Key key;
    }
    public Foo(int size){
        a = new Entry[size];
    }
}

是否可以创建该数组?

4 个答案:

答案 0 :(得分:1)

因为Generics don't cope very well with arrays(在编译时)。

您应该使用一些Collection,而不是:

class Foo<Key extends Comparable<Key>> {
    private List<Entry> a;

    private class Entry {
        Key key;
    }

    public Foo(int size) {
        a = new ArrayList<Entry>(size);
    }
}

答案 1 :(得分:1)

嗯,实际上你可以通过reflection

public class Main {
    public static void main(String[] args) {
        Foo<String> foo = new Foo<String>(1000);
        foo.a[0] = foo.new Entry();
        foo.a[0].key = "ss";
    }
}

class Foo<Key extends Comparable<Key>> {
    public Entry[] a;

    public class Entry {
        Key key;
    }

    public Foo(int size) {
        a = (Entry[]) java.lang.reflect.Array.newInstance(Entry.class, size);
    }
}

答案 2 :(得分:1)

我同意kocko你应该使用一些Collection而不是数组。但具体到你的观点,这为我编译并运行。这只是将创建数组的责任推迟到Array.newInstance方法。缺点是它迫使演员

 class Foo<Key extends Comparable<Key>>{
     private Entry[] a;
     private class Entry{
       Key key;
     }
     public Foo(int size){
       a = (Entry[])Array.newInstance(Entry.class,size);
     }
}

答案 3 :(得分:0)

作为内部类,Entry类型在封闭类中声明的类型参数Key的范围内。换句话说,Entry也是通用的。

您可以使用

a = (Entry[]) new Foo<?>.Entry[size];

或原始等价物(我不推荐)

a = (Entry[]) new Foo.Entry[size];

这种类型的array creation在JLS中解释

ArrayCreationExpression:
    new ClassOrInterfaceType DimExprs [Dims]

说明

  

如果ClassOrInterfaceType 未表示,则为编译时错误   可再生类型§4.7)。

其中reifiable type

  

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

     
      
  • 它指的是非泛型类或接口类型声明。
  •   
  • 这是一种参数化类型,其中所有类型参数都是无界通配符(§4.5.1)。
  •   
  • 这是一种原始类型(§4.8)。
  •   
  • 这是一种原始类型(§4.2)。
  •   
  • 它是一种数组类型(第10.1节),其元素类型是可以恢复的。
  •   
  • 这是一种嵌套类型,对于以“。”分隔的每种类型TT本身都是可以恢复的。
  •   

通过使用带通配符或原始类型的参数化,我们可以得到上面给出的数组创建表达式。