Static nested class in Java, why?

Viewed 124093

I was looking at the Java code for LinkedList and noticed that it made use of a static nested class, Entry.

public class LinkedList<E> ... {
...

 private static class Entry<E> { ... }

}

What is the reason for using a static nested class, rather than an normal inner class?

The only reason I could think of, was that Entry doesn't have access to instance variables, so from an OOP point of view it has better encapsulation.

But I thought there might be other reasons, maybe performance. What might it be?

Note. I hope I have got my terms correct, I would have called it a static inner class, but I think this is wrong: http://java.sun.com/docs/books/tutorial/java/javaOO/nested.html

14 Answers

The Sun page you link to has some key differences between the two:

A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class.
...

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

There is no need for LinkedList.Entry to be top-level class as it is only used by LinkedList (there are some other interfaces that also have static nested classes named Entry, such as Map.Entry - same concept). And since it does not need access to LinkedList's members, it makes sense for it to be static - it's a much cleaner approach.

As Jon Skeet points out, I think it is a better idea if you are using a nested class is to start off with it being static, and then decide if it really needs to be non-static based on your usage.

To my mind, the question ought to be the other way round whenever you see an inner class - does it really need to be an inner class, with the extra complexity and the implicit (rather than explicit and clearer, IMO) reference to an instance of the containing class?

Mind you, I'm biased as a C# fan - C# doesn't have the equivalent of inner classes, although it does have nested types. I can't say I've missed inner classes yet :)

There are non-obvious memory retention issues to take into account here. Since a non-static inner class maintains an implicit reference to it's 'outer' class, if an instance of the inner class is strongly referenced, then the outer instance is strongly referenced too. This can lead to some head-scratching when the outer class is not garbage collected, even though it appears that nothing references it.

Static inner class is used in the builder pattern. Static inner class can instantiate it's outer class which has only private constructor. You can not do the same with the inner class as you need to have object of the outer class created prior to accessing the inner class.

class OuterClass {
    private OuterClass(int x) {
        System.out.println("x: " + x);
    }
    
    static class InnerClass {
        public static void test() {
            OuterClass outer = new OuterClass(1);
        }
    }
}

public class Test {
    public static void main(String[] args) {
        OuterClass.InnerClass.test();
        // OuterClass outer = new OuterClass(1); // It is not possible to create outer instance from outside.
    }
}

This will output x: 1

Well, for one thing, non-static inner classes have an extra, hidden field that points to the instance of the outer class. So if the Entry class weren't static, then besides having access that it doesn't need, it would carry around four pointers instead of three.

As a rule, I would say, if you define a class that's basically there to act as a collection of data members, like a "struct" in C, consider making it static.

Simple example :

package test;

public class UpperClass {
public static class StaticInnerClass {}

public class InnerClass {}

public static void main(String[] args) {
    // works
    StaticInnerClass stat = new StaticInnerClass();
    // doesn't compile
    InnerClass inner = new InnerClass();
}
}

If non-static the class cannot be instantiated exept in an instance of the upper class (so not in the example where main is a static function)

One of the reasons for static vs. normal have to do with classloading. You cannot instantiate an inner class in the constructor of it's parent.

PS: I've always understood 'nested' and 'inner' to be interchangeable. There may be subtle nuances in the terms but most Java developers would understand either.

  1. JVM knows no nested classes. Nesting is just syntactic sugar.

    Below images shows Java file:

    enter image description here

    Below images show class files representation of the java file :

    enter image description here

    Notice that 2 class files are generated, one for parent and another for nested class.

  2. Non-static nested class' objects have access to the enclosing scope. That access to the enclosing scope is maintained by holding an implicit reference of the enclosing scope object in the nested object

  3. Nested class is a way to represent the intent that the nested class type represents a component of the parent class.

    public class Message {
    
    private MessageType messageType; // component of parent class
    
    public enum MessageType {
        SENT, RECEIVE;
    }
    }
    
    
    
    class Otherclass {
    
    public boolean isSent(Message message) {
        if (message.getMessageType() == MessageType.SENT) { // accessible at other places as well
            return true;
        }
        return false;
    }
    }
    
  4. private static nested class represents Point#3 & the fact the nested type can only be the subcomponent to the parent class. It can't be used separately.

    public class Message {
    
     private Content content; // Component of message class
    
     private static class Content { // can only be a component of message class
    
      private String body;
      private int sentBy;
    
      public String getBody() {
         return body;
      }
    
      public int getSentBy() {
         return sentBy;
      }
    
    }
    }
    
    class Message2 {
      private Message.Content content; // Not possible
    }
    
  5. More details here.

I don't know about performance difference, but as you say, static nested class is not a part of an instance of the enclosing class. Seems just simpler to create a static nested class unless you really need it to be an inner class.

It's a bit like why I always make my variables final in Java - if they're not final, I know there's something funny going on with them. If you use an inner class instead of a static nested class, there should be a good reason.

Using a static nested class rather than non-static one may save spaces in some cases. For example: implementing a Comparator inside a class, say Student.

public class Student {
  public static final Comparator<Student> BY_NAME = new ByName();
  private final String name;
  ...
  private static class ByName implements Comparator<Student> {
    public int compare() {...}
  }
}

Then the static ensures that the Student class has only one Comparator, rather than instantiate a new one every time a new student instance is created.

Related