Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can a class have a member of its own type, isn't this infinite recursion?

Tags:

java

oop

class

Say I define a class that has as a member a variable of the same type as itself.

public class Abc {     private Abc p; } 

This actually works, much to my surprise.

Why I think it shouldn't: creating an instance of Abc, it contains a variable of type Abc, which contains a variable of type Abc, which contains a variable of type Abc, which .....

Obviously I'm wrong, could someone enlighten me as to how?

like image 749
jason Avatar asked Mar 20 '12 02:03

jason


People also ask

Can a class have a member of its own type?

Because in Java, a variable of type abc doesn't contain an abc object. A variable of type abc contains a reference to an abc object. Your reasoning would be valid in say C++. But a class can have static object of self type.

Can a class contain an object of itself?

A class declaration can contain static object of self type, it can also have pointer to self type, but it cannot have a non-static object of self type. For example, following program works fine.

Can a class have an instance variable of itself?

Class VariablesWhen a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables.


2 Answers

You're only declaring the variable and not creating it. Try creating it at declaration or in the constructor and let me know what happens:

public class Abc {    private Abc p = new Abc(); // have fun!     public static void main(String[] args) {       new Abc();    } } 

Incidentally, if you don't create it in the class, but rather accept a reference to it in a getter method or a constructor parameter, your code will work just fine. This is how some linked lists work.

like image 66
Hovercraft Full Of Eels Avatar answered Sep 21 '22 06:09

Hovercraft Full Of Eels


The difference lies in compile-time vs run-time checks.

In the first case (compile time), you are declaring that you will have a reference to a value of type Abc in this instance. The compiler will be aware of this when it checks for proper semantics, and since it knows the type upon compile time, it sees no issue with this.

In the second case (run time), you will actually create a value for this reference to refer to. This is where you could potentially get yourself into trouble. For example, if you said the following:

public class Abc {     private Abc p;      public Abc() {         p = new Abc();     } } 

This could lead you into trouble for the exact reason you cited (recursion that contains no base case and will continually allocate memory until you've run the VM out of heap space).

However, you can still do something similar to this and avoid the infinite recursion. By avoiding creating the value during construction, you put it off until a method is called for. In fact, it's one of the common ways to implement the singleton pattern in Java. For example:

public class Abc {     private Abc p;      private Abc() {  // Private construction. Use singleton method     }      public static synchronized Abc getInstance() {         if (p == null)             p = new Abc();          return p;     } } 

This is perfectly valid because you only create one new instance of the value, and since run-time will have loaded the class already, it will know the type of the instance variable is valid.

like image 28
pseudoramble Avatar answered Sep 17 '22 06:09

pseudoramble