2015-02-12 113 views
5

我有一个示例代码try.The代码似乎没有编译错误。为什么它使用静态嵌套类节点?当我删除static中的Node嵌套类并编译时,错误显示create generic arrayprivate Node[] next = new Node[R];中。究竟发生了什么?为什么静态嵌套类?

public class TrieST<Value> { 
    private static final int R = 256;  // extended ASCII 


    private Node root;  // root of trie 
    private int N;   // number of keys in trie 

    // R-way trie node 
    private static class Node { 
     private Object val; 
     private Node[] next = new Node[R]; 
    } 


    public TrieST() { 
    } 
} 
+4

首先,你知道为什么通用数组是不允许的吗? (例如'新ArrayList [5];'显示此错误) – immibis 2015-02-12 01:58:21

+0

可能的重复[如何创建通用数组?](http://stackoverflow.com/questions/18581002/how-to-create-a-generic -array) – alfasin 2015-02-12 02:15:03

+0

你可以解释为什么添加静态时没有这样的错误? – Peterxwl 2015-02-12 02:18:02

回答

2

假设在您的代码段,你正在使用的,而不是像这样的静态嵌套类的非静态内部类:​​,在这种情况下,你会尝试实例化一个Array这是不可能的, 我们不能实例化泛型类Array,因为仿制药没有任何关于其在运行时类型的任何信息,而数组创建表达式指定元素类型。

那么,为什么使用Static Nested Class编译的原因是,这样的类被视为“顶级”类(在行为方面):

一个静态嵌套类的实例成员进行交互它的外部 类(和其他类)就像任何其他顶级类一样。在 的效果中,静态嵌套类在行为上是一个顶级类,为了便于打包,它已嵌套在另一个顶级类中。

现在,让我们所有的到这一点,并回到由编译器显示的确切错误:

无法创建TrieST<Value>.Node

通用阵列这意味着,您要创建的array的类型是TrieST<Value>.Node,其运行时类型未知,因此可以将不同类型插入到next阵列中。更清楚和说明的例子可以在Cannot Create Arrays of Parameterized Types

发现而,静态嵌套类不表现作为内部类的TrieST<Value>,从而instiating内部Node阵列不会非法因为它是类型TrieST<Value>.Node的不,其类型为Node,如果它是顶级类别)。

+0

你能解释一下为什么以及如何将嵌套静态的“抑制”这个错误视为顶级类? – Peterxwl 2015-02-12 02:24:50

+0

顶级类是一个非内部类,所以这意味着静态嵌套类和外部类之间不存在隐式关系,因此实例化一个数组不会影响外部类(您的泛型类) – Tarik 2015-02-12 02:30:12

+0

@Peterxwl我刚添加了一个更新,请现在看看 – Tarik 2015-02-12 02:50:11

1

因为使用static创建:Node[] next = new Node[R]并使用非静态内部类创建与具有泛型类型的外部类的实例关联的Node。禁止创建通用数组。

但是让我们回到了几步:

class TrieST<V> { 
    private static final int R = 256;   

    private Node root;  // root of trie 
    private int N;   // number of keys in trie 
    private TrieST<String> inst = new TrieST<String>(); // must create an instance of the outer class first 

    // R-way trie node 
    private class Node { 
     private Object val; 
     private TrieST<String>.Node next = inst.new Node(); //must use an instance of the outer class to instantiate an object of the inner class 
    } 

    public TrieST() { 
    } 
} 

现在,如果我们会尝试改变的实现:实例化一个内部类(非静态)如下(例子)的方式从内部类的一个实例到一个数组,我们将得到generic array creation,因为由于数组的性质(Shape[]superTriangle[]),它禁止创建具有泛型类型的数组,因为它不能很好地与不变式仿制药的性质(List<Object>List<String>)。在“Effective Java”中,Bloch提供了更详细的解释,如果您想深入研究。

如果您坚持使用内部类,则可以使用Array.newInstance()来解决此限制,它可以创建仅知道类型的数组在运行时如下:

private Node[] next = (Node[]) Array.newInstance(Node.class, R); 
+0

如果我仍然想在非静态内部类中使用'Node [] next',该怎么办? – Peterxwl 2015-02-12 03:40:52

+0

@Peterxwl你可以欺骗编译器:'private Node [] next =(Node [])Array.newInstance(Node.class,R);'我将它添加到答案中。 – alfasin 2015-02-12 03:43:57