Static Nested Class in Java, Why

Java inner class and static nested class

From the Java Tutorial:

Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.

Static nested classes are accessed using the enclosing class name:

OuterClass.StaticNestedClass

For example, to create an object for the static nested class, use this syntax:

OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:

class OuterClass {
...
class InnerClass {
...
}
}

An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance.

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:

OuterClass outerObject = new OuterClass()
OuterClass.InnerClass innerObject = outerObject.new InnerClass();

see: Java Tutorial - Nested Classes

For completeness note that there is also such a thing as an inner class without an enclosing instance:

class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}

Here, new A() { ... } is an inner class defined in a static context and does not have an enclosing instance.

Why would you use private static inner class? Defeats the purpose of static inner class?

Remember that an non-static nested class ("inner class") instance has a reference to its containing instance. That isn't free. If you don't need it, you shouldn't have it.

LinkedList is an excellent example of exactly why you'd have a static nested class: LinkedList needs multiple instances of LinkedList.Node, and it doesn't need those instances to have a reference to the list itself. That would be pointless overhead. So the Node class is static in order not to have those back references to the list. It's also private because it's only for internal use by LinkedList.


Side note on terminology: There is no "static inner class" in Java. If it's static, it's not an inner class, it's a static nested class. More in the tutorial.

What members of the enclosing class can a static nested class access?

In Java nested non - static classes have a hidden reference to the instance of the parent class. That's why they can access all non-static members. The nested class doesn't have such an instance. However, its scope allows it to access the parent members if the parent class passes this.

So what the second quote is saying that the access doesn't happen automatically. You pass the reference to the enclosing class and the nested static class can access it. Otherwise, it doesn't know the address of the enclosing class.

Why using enclosing class's instance, the static nested class can't be instantiated?

See what this tutorial tells us:

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.

A top-level class is simply a class that is not nested within another class.

So, a static nested class is not different from a not nested classes. In your example Nested is not different from Outer in it's behaviour; it could be declared just outside Outer. Therefore new Outer().new Nested() is not valid syntax. Nesting a static class is just for packaging convenience, therefore new Outer.Nested() works, just like e.g. new java.util.ArrayList<String>() works.

Static nested class in Java, why?

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.

Why and when to use static inner class or instance inner class?

Non-static inner classes have an automatic reference to their enclosing class. A static inner classes only relationship to its enclosing class is that you have to reference it via the enclosing class' name: EnclosingClass.StaticInnerClass.

Non-static inner classes are good when you want to reference some of the data from the parent class.

A static inner class is good when you just want to associate the inner class with the enclosing class without dragging it along for the ride.

In other words, a non-static inner class can prevent the enclosing class from being garbage collected, since it has that reference, while a static inner class will never do that.

Why does java not initialise static nested class fields at the same time as static outter fields?

1) Is my understanding correct?

Basically yes. Consider what happens with your static member outerField :

public class OutterClass {

private static final OutterClass outterField = new OutterClass("outterField");

Theoretically, it's possible that the JVM could create that static final object when the program starts running, or when the class is loaded, but it doesn't. Instead, it'll only initialise it when needed - basically :

  • Instance of class is created, or
  • One of the Class's static fields or methods is accessed

(see https://docs.oracle.com/javase/specs/jls/se7/html/jls-12.html#jls-12.4.1 )

So also with the static inner class. As you say, the JVM regards it as a top level inner class, so will only initialise its members when it also is needed.

2) Has this got anything to do with the JIT compiler or the class loader?

No and no. Initialisation of static members does not take place at class load time, but later (as we said, when the class is accessed). This is not a matter of compiler optimisation, but explicitly specified behaviour. After all, when you load a possibly-large class library, you would not want your JVM to consume memory or time initialising all the static members of classes that your program never touches; only-on-demand is a much better approach.

Is the InnerClass loaded when the OuterClass is loaded?

Yes (but not initialised then)

What's the advantage of making an inner class as static with Java?

If the nested class does not access any of the variables of the enclosing class, it can be made static. The advantage of this is that you do not need an enclosing instance of the outer class to use the nested class.



Related Topics



Leave a reply



Submit