Why is a static nested class?

I have some sample code for try.The seems to have no compilation errors. Why does it use a static nested node class? when I delete static in Node nested class and compile, the error shows create generic array in private Node[] next = new Node[R]; . What happened?

 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() { } } 
+5
source share
2 answers

Assuming you use a non-static inner class instead of a static nested class in the code snippet as follows: private class Node , in this case you try to create an Array instance that is not possible, we cannot create an Array instance in the generic class because generics has no information about its type at runtime , while the expression for creating arrays indicates the type of element.

So, the reason the Static Nested Class is compiled is because such classes are considered a β€œtop-level” class (in terms of behavior):

A static nested class interacts with the members of an instance of its outer class (and other classes), like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been placed in another top-level class for ease of packaging.

Now consider all of this and return to the exact error displayed by the compiler:

Unable to create shared array TrieST<Value>.Node

This means that the Array type you want to create is a TrieST<Value>.Node whose type is not known, so you can insert various types into the next array. More clear and well-explained examples can be found in Unable to create arrays of parameterized types.

While the static Nested class does not behave like the inner class TrieST<Value> , therefore, initializing the array inside Node will not be illegal, since it is not the type TrieST<Value>.Node , its type is Node ( as if it is a top-level class )

+2
source

Since with static you create: Node[] next = new Node[R] and with a non-stationary inner class, you create a Node that is associated with an instance of an outer class that has a common type. And creating shared arrays is forbidden.

But back to a few steps: the way to create an inner class (non-static) is as follows (example):

 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() { } } 

Now, if we try to change the above implementation from an instance of the inner class to an array, we get the creation of a common array , since it prohibits creating arrays with a common type due to the covariance nature of arrays ( Shape[] is super of Triangle[] ), which is not works very well with the invariant nature of generics ( List<Object> not super of List<String> ). In Effective Java, Bloch provides a more detailed explanation if you want to look into it.

If you insist on using an inner class, you can get around this limitation using Array.newInstance() , which can create an array of a type known only at runtime, as follows:

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

Source: https://habr.com/ru/post/1213191/


All Articles