Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this statement throw a StackOverflowError?

I just saw this weird piece of code in another question. I thought it would result in a StackOverflowError being thrown, but it doesn't...

public class Node {     private Object one;     private Object two;     public static Node NIL = new Node(Node.NIL, Node.NIL);      public Node(Object one, Object two) {         this.one = one;         this.two = two;     } } 

I thought it was going to thow an exception, because of the Node.NIL referencing itself to build.

I can't figure it out why it does not.

like image 677
Anthony Raymond Avatar asked Jan 30 '17 09:01

Anthony Raymond


People also ask

What does StackOverflowError mean?

StackOverflowError is a runtime error which points to serious problems that cannot be caught by an application. The java. lang. StackOverflowError indicates that the application stack is exhausted and is usually caused by deep or infinite recursion.

Is StackOverflowError an exception?

StackOverflowError is an error which Java doesn't allow to catch, for instance, stack running out of space, as it's one of the most common runtime errors one can encounter.

What causes stack overflow error?

The most-common cause of stack overflow is excessively deep or infinite recursion, in which a function calls itself so many times that the space needed to store the variables and information associated with each call is more than can fit on the stack.


2 Answers

NIL is a static variable. It is initialized one time, when the class is initialized. When it is initialized, a single Node instance is created. The creation of that Node doesn't trigger creation of any other Node instances, so there is not infinite chain of calls. Passing Node.NIL to the constructor call has the same effect as passing null, since Node.NIL is not yet initialized when the constructor is called. Therefore public static Node NIL = new Node(Node.NIL, Node.NIL); is the same as public static Node NIL = new Node(null, null);.

If, on the other hand, NIL was an instance variable (and wasn't passed as an argument to the Node constructor, since the compiler would have prevented you from passing it to the constructor in that case), it would be initialized every time an instance of Node was created, which would create a new Node instance, whose creation would initialize another NIL instance variable, leading to infinite chain of constructor calls that would end in StackOverflowError.

like image 108
Eran Avatar answered Oct 01 '22 20:10

Eran


The variable NIL is first given the value null and then initialised once top to bottom. It isn't a function and isn't defined recursively. Any static field you use before it is initialised has the default value and your code is the same as

public static Node {     public static Node NIL;      static {         NIL = new Node(null /*Node.NIL*/, null /*Node.NIL*/);     }      public Node(Object one, Object two) {         // Assign values to fields     } } 

This is no different to writing

NIL = null; // set implicitly NIL = new Node(NIL, NIL); 

If you defined a function or method like this, you would get a StackoverflowException

Node NIL(Node a, Node b) {     return NIL(NIL(a, b), NIL(a, b)); } 
like image 22
Peter Lawrey Avatar answered Oct 01 '22 22:10

Peter Lawrey