Java Inner Class and Static Nested Class

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.

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.

Java access static nested class

You can use :

A.B.C.D.E e = new A.B.C.D.E();//create an instance of class E
e.methodA();//call methodA
e.methodB();//call methodB

Or like @Andreas mention in comment you can use import A.B.C.D.E;, so if your class is in another packager then you can call your class using name_of_package.A.B.C.D.E like this:

import com.test.A.B.C.D.E;
// ^^^^^^^^------------------------name of package

public class Test {

public static void main(String[] args) {
E e = new E();
e.methodA();
e.methodB();
}
}

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.

Instance variable of a static nested class vs static variable of an outer class

They are different.

From a memory allocation point of view, a static inner class is no different from a top level class. Your StaticFoo will be compiled to a class (Foo$StaticFoo.class) that is essentially independent from its parent class at runtime. At compile time, there are access checks for private members.

So, in case 1, you have a static field in a class. It will be allocated as a field on a Foo.class object on the heap. There will only be one instance per ClassLoader that loads the Foo class, which generally means just one shared instance for the whole JVM.

In case 2, you have an instance field in the Foo$StaticFoo class. On the heap, there will be space allocated (and a value assigned) for (and in) each instance of StaticFoo created. Each StaticFoo that gets created will access its own instance of that field, and since it's not final, the value of each instance can be independently changed.

If you changed StaticFoo.fooInner to be static, then it would be exactly the same as case 1.

Note: The above is true only for Java 8 and later. For earlier JVMs, that amount of memory allocated in each case still matches the description above, but static variables, as well as being singletons per ClassLoader, are also stored in a different memory pool: PermGen Space rather than the main heap. See this answer for more details.

Mixing inner class and static nested class

Nested classes are a little weird. In this first example, we have a static nested class. It has to access variable via a "parent" instance of OuterClass because it has no enclosing OuterClass instance. When we define nested classes statically, it's almost as if they were defined in their own separate file. The only difference is that static nested classes get access to private members of OuterClass whereas they wouldn't if they were defined in their own separate file.

public class OuterClass{
private Object variable = "variable";

private static class StaticNestedClass{
private OuterClass parent;

private StaticNestedClass(OuterClass p){ parent = p; }

private void method(){
//This line compiles:
System.out.println("variable = "+parent.variable);

//This won't - there's no OuterClass enclosing instance:
//System.out.println("variable = "+OuterClass.this.variable);

//This one won't either, for the same reason:
//System.out.println("variable = "+variable);
}
}
}

Let's change it up a bit. Now our nested class is NOT static, meaning it comes enclosed in an instance of OuterClass. It still gets access to private members of OuterClass, but we don't need to store an instance of OuterClass to its constructor for storage purposes because it implicitly has a reference to the OuterClass instance that encloses it.

public class OuterClass{
private Object variable = "variable";

private class InnerClass{
private void method(){
//This line compiles:
System.out.println("variable = "+variable);

//So does this one - both lines refer to the same
//enclosing instance of OuterClass:
System.out.println("variable = "+OuterClass.this.variable);
}
}
}


Related Topics



Leave a reply



Submit