What is the main difference between an inner class and a static nested class in Java? Does design / implementation play a role in choosing one of these?
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.
The Java tutorial says:
Terminology: 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.
In common parlance, the terms "nested" and "inner" are used interchangeably by most programmers, but I'll use the correct term "nested class" which covers both inner and static.
Classes can be nested ad infinitum, e.g. class A can contain class B which contains class C which contains class D, etc. However, more than one level of class nesting is rare, as it is generally bad design.
There are three reasons you might create a nested class:
organization: sometimes it seems most sensible to sort a class into the namespace of another class, especially when it won't be used in any other context
access: nested classes have special access to the variables/fields of their containing classes (precisely which variables/fields depends on the kind of nested class, whether inner or static).
convenience: having to create a new file for every new type is bothersome, again, especially when the type will only be used in one context
There are four kinds of nested class in Java. In brief, they are:
static class: declared as a static member of another class
inner class: declared as an instance member of another class
local inner class: declared inside an instance method of another class
anonymous inner class: like a local inner class, but written as an expression which returns a one-off object
Let me elaborate in more details.
Static Classes
Static classes are the easiest kind to understand because they have nothing to do with instances of the containing class.
A static class is a class declared as a static member of another class. Just like other static members, such a class is really just a hanger on that uses the containing class as its namespace, e.g. the class Goat declared as a static member of class Rhino in the package pizza is known by the name pizza.Rhino.Goat.
package pizza;
public class Rhino {
...
public static class Goat {
...
}
}
Frankly, static classes are a pretty worthless feature because classes are already divided into namespaces by packages. The only real conceivable reason to create a static class is that such a class has access to its containing class's private static members, but I find this to be a pretty lame justification for the static class feature to exist.
Inner Classes
An inner class is a class declared as a non-static member of another class:
package pizza;
public class Rhino {
public class Goat {
...
}
private void jerry() {
Goat g = new Goat();
}
}
Like with a static class, the inner class is known as qualified by its containing class name, pizza.Rhino.Goat, but inside the containing class, it can be known by its simple name. However, every instance of an inner class is tied to a particular instance of its containing class: above, the Goat created in jerry, is implicitly tied to the Rhino instance this in jerry. Otherwise, we make the associated Rhino instance explicit when we instantiate Goat:
Rhino rhino = new Rhino();
Rhino.Goat goat = rhino.new Goat();
(Notice you refer to the inner type as just Goat in the weird new syntax: Java infers the containing type from the rhino part. And, yes new rhino.Goat() would have made more sense to me too.)
So what does this gain us? Well, the inner class instance has access to the instance members of the containing class instance. These enclosing instance members are referred to inside the inner class via just their simple names, not via this (this in the inner class refers to the inner class instance, not the associated containing class instance):
public class Rhino {
private String barry;
public class Goat {
public void colin() {
System.out.println(barry);
}
}
}
In the inner class, you can refer to this of the containing class as Rhino.this, and you can use this to refer to its members, e.g. Rhino.this.barry.
Local Inner Classes
A local inner class is a class declared in the body of a method. Such a class is only known within its containing method, so it can only be instantiated and have its members accessed within its containing method. The gain is that a local inner class instance is tied to and can access the final local variables of its containing method. When the instance uses a final local of its containing method, the variable retains the value it held at the time of the instance's creation, even if the variable has gone out of scope (this is effectively Java's crude, limited version of closures).
Because a local inner class is neither the member of a class or package, it is not declared with an access level. (Be clear, however, that its own members have access levels like in a normal class.)
If a local inner class is declared in an instance method, an instantiation of the inner class is tied to the instance held by the containing method's this at the time of the instance's creation, and so the containing class's instance members are accessible like in an instance inner class. A local inner class is instantiated simply via its name, e.g. local inner class Cat is instantiated as new Cat(), not new this.Cat() as you might expect.
Anonymous Inner Classes
An anonymous inner class is a syntactically convenient way of writing a local inner class. Most commonly, a local inner class is instantiated at most just once each time its containing method is run. It would be nice, then, if we could combine the local inner class definition and its single instantiation into one convenient syntax form, and it would also be nice if we didn't have to think up a name for the class (the fewer unhelpful names your code contains, the better). An anonymous inner class allows both these things:
new *ParentClassName*(*constructorArgs*) {*members*}
This is an expression returning a new instance of an unnamed class which extends ParentClassName. You cannot supply your own constructor; rather, one is implicitly supplied which simply calls the super constructor, so the arguments supplied must fit the super constructor. (If the parent contains multiple constructors, the “simplest” one is called, “simplest” as determined by a rather complex set of rules not worth bothering to learn in detail--just pay attention to what NetBeans or Eclipse tell you.)
Alternatively, you can specify an interface to implement:
new *InterfaceName*() {*members*}
Such a declaration creates a new instance of an unnamed class which extends Object and implements InterfaceName. Again, you cannot supply your own constructor; in this case, Java implicitly supplies a no-arg, do-nothing constructor (so there will never be constructor arguments in this case).
Even though you can't give an anonymous inner class a constructor, you can still do any setup you want using an initializer block (a {} block placed outside any method).
Be clear that an anonymous inner class is simply a less flexible way of creating a local inner class with one instance. If you want a local inner class which implements multiple interfaces or which implements interfaces while extending some class other than Object or which specifies its own constructor, you're stuck creating a regular named local inner class.
I don't think the real difference became clear in the above answers.
First to get the terms right:
A nested class is a class which is contained in another class at the source code level.
It is static if you declare it with the static modifier.
A non-static nested class is called inner class. (I stay with non-static nested class.)
Martin's answer is right so far. However, the actual question is: What is the purpose of declaring a nested class static or not?
You use static nested classes if you just want to keep your classes together if they belong topically together or if the nested class is exclusively used in the enclosing class. There is no semantic difference between a static nested class and every other class.
Non-static nested classes are a different beast. Similar to anonymous inner classes, such nested classes are actually closures. That means they capture their surrounding scope and their enclosing instance and make that accessible. Perhaps an example will clarify that. See this stub of a Container:
public class Container {
public class Item{
Object data;
public Container getContainer(){
return Container.this;
}
public Item(Object data) {
super();
this.data = data;
}
}
public static Item create(Object data){
// does not compile since no instance of Container is available
return new Item(data);
}
public Item createSubItem(Object data){
// compiles, since 'this' Container is available
return new Item(data);
}
}
In this case you want to have a reference from a child item to the parent container. Using a non-static nested class, this works without some work. You can access the enclosing instance of Container with the syntax Container.this.
More hardcore explanations following:
If you look at the Java bytecodes the compiler generates for an (non-static) nested class it might become even clearer:
// class version 49.0 (49)
// access flags 33
public class Container$Item {
// compiled from: Container.java
// access flags 1
public INNERCLASS Container$Item Container Item
// access flags 0
Object data
// access flags 4112
final Container this$0
// access flags 1
public getContainer() : Container
L0
LINENUMBER 7 L0
ALOAD 0: this
GETFIELD Container$Item.this$0 : Container
ARETURN
L1
LOCALVARIABLE this Container$Item L0 L1 0
MAXSTACK = 1
MAXLOCALS = 1
// access flags 1
public <init>(Container,Object) : void
L0
LINENUMBER 12 L0
ALOAD 0: this
ALOAD 1
PUTFIELD Container$Item.this$0 : Container
L1
LINENUMBER 10 L1
ALOAD 0: this
INVOKESPECIAL Object.<init>() : void
L2
LINENUMBER 11 L2
ALOAD 0: this
ALOAD 2: data
PUTFIELD Container$Item.data : Object
RETURN
L3
LOCALVARIABLE this Container$Item L0 L3 0
LOCALVARIABLE data Object L0 L3 2
MAXSTACK = 2
MAXLOCALS = 3
}
As you can see the compiler creates a hidden field Container this$0. This is set in the constructor which has an additional parameter of type Container to specify the enclosing instance. You can't see this parameter in the source but the compiler implicitly generates it for a nested class.
Martin's example
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
would so be compiled to a call of something like (in bytecodes)
new InnerClass(outerObject)
For the sake of completeness:
An anonymous class is a perfect example of a non-static nested class which just has no name associated with it and can't be referenced later.
I think that none of the above answers explain to you the real difference between a nested class and a static nested class in term of application design :
OverView
A nested class could be nonstatic or static and in each case is a class defined within another class. A nested class should exist only to serve is enclosing class, if a nested class is useful by other classes (not only the enclosing), should be declared as a top level class.
Difference
Nonstatic Nested class : is implicitly associated with the enclosing instance of the containing class, this means that it is possible to invoke methods and access variables of the enclosing instance. One common use of a nonstatic nested class is to define an Adapter class.
Static Nested Class : can't access enclosing class instance and invoke methods on it, so should be used when the nested class doesn't require access to an instance of the enclosing class . A common use of static nested class is to implement a components of the outer object.
Conclusion
So the main difference between the two from a design standpoint is : nonstatic nested class can access instance of the container class, while static can't.
Here is key differences and similarities between Java inner class and static nested class.
Hope it helps!
Inner class
Can access to outer class both instance and static methods and fields
Associated with instance of enclosing class so to instantiate it first needs an instance of outer class (note new keyword place):
Outerclass.InnerClass innerObject = outerObject.new Innerclass();
Cannot define any static members itself
Cannot have Class or Interface declaration
Static nested class
Cannot access outer class instance methods or fields
Not associated with any instance of enclosing class So to instantiate it:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();
Similarities
Both Inner classes can access even private fields and methods of outer class
Also the Outer class have access to private fields and methods of inner classes
Both classes can have private, protected or public access modifier
Why Use Nested Classes?
According to Oracle documentation there're several reasons (full documentation):
It is a way of logically grouping classes that are only used in one place: If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.
It increases encapsulation: Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.
It can lead to more readable and maintainable code: Nesting small classes within top-level classes places the code closer to where it is used.
In simple terms we need nested classes primarily because Java does not provide closures.
Nested Classes are classes defined inside the body of another enclosing class. They are of two types - static and non-static.
They are treated as members of the enclosing class, hence you can specify any of the four access specifiers - private, package, protected, public. We don't have this luxury with top-level classes, which can only be declared public or package-private.
Inner classes aka Non-stack classes have access to other members of the top class, even if they are declared private while Static nested classes do not have access to other members of the top class.
public class OuterClass {
public static class Inner1 {
}
public class Inner2 {
}
}
Inner1 is our static inner class and Inner2 is our inner class which is not static. The key difference between them, you can't create an Inner2 instance without an Outer where as you can create an Inner1 object independently.
When would you use Inner class?
Think of a situation where Class A and Class B are related, Class B needs to access Class A members, and Class B is related only to Class A. Inner classes comes into the picture.
For creating an instance of inner class, you need to create an instance of your outer class.
OuterClass outer = new OuterClass();
OuterClass.Inner2 inner = outer.new Inner2();
or
OuterClass.Inner2 inner = new OuterClass().new Inner2();
When would you use static Inner class?
You would define a static inner class when you know that it does not have any relationship with the instance of the enclosing class/top class. If your inner class doesn't use methods or fields of the outer class, it's just a waste of space, so make it static.
For example, to create an object for the static nested class, use this syntax:
OuterClass.Inner1 nestedObject = new OuterClass.Inner1();
The advantage of a static nested class is that it doesn't need an object of the containing class/top class to work. This can help you to reduce the number of objects your application creates at runtime.
I think, the convention that is generally followed is this:
static class within a top level class is a nested class
non static class within a top level class is a inner class, which further
has two more form:
local class - named classes declared inside of a block like a method or constructor body
anonymous class - unnamed classes whose instances are created in expressions and statements
However, few other points to remembers are:
Top level classes and static nested class are semantically same except that in case of static nested class it can make static reference to private static fields/methods of its Outer [parent] class and vice versa.
Inner classes have access to instance variables of the enclosing instance of the Outer [parent] class. However, not all inner classes have enclosing instances, for example inner classes in static contexts, like an anonymous class used in a static initializer block, do not.
Anonymous class by default extends the parent class or implements the parent interface and there is no further clause to extend any other class or implement any more interfaces. So,
new YourClass(){}; means class [Anonymous] extends YourClass {}
new YourInterface(){}; means class [Anonymous] implements YourInterface {}
I feel that the bigger question that remains open which one to use and when? Well that mostly depends on what scenario you are dealing with but reading the reply given by #jrudolph may help you making some decision.
Nested class: class inside class
Types:
Static nested class
Non-static nested class [Inner class]
Difference:
Non-static nested class [Inner class]
In non-static nested class object of inner class exist within object of outer class. So that data member of outer class is accessible to inner class. So to create object of inner class we must create object of outer class first.
outerclass outerobject=new outerobject();
outerclass.innerclass innerobjcet=outerobject.new innerclass();
Static nested class
In static nested class object of inner class don't need object of outer class, because the word "static" indicate no need to create object.
class outerclass A {
static class nestedclass B {
static int x = 10;
}
}
If you want to access x, then write the following inside method
outerclass.nestedclass.x; i.e. System.out.prinltn( outerclass.nestedclass.x);
The instance of the inner class is created when instance of the outer class is created. Therefore the members and methods of the inner class have access to the members and methods of the instance (object) of the outer class. When the instance of the outer class goes out of scope, also the inner class instances cease to exist.
The static nested class doesn't have a concrete instance. It's just loaded when it's used for the first time (just like the static methods). It's a completely independent entity, whose methods and variables doesn't have any access to the instances of the outer class.
The static nested classes are not coupled with the outer object, they are faster, and they don't take heap/stack memory, because its not necessary to create instance of such class. Therefore the rule of thumb is to try to define static nested class, with as limited scope as possible (private >= class >= protected >= public), and then convert it to inner class (by removing "static" identifier) and loosen the scope, if it's really necessary.
There is a subtlety about the use of nested static classes that might be useful in certain situations.
Whereas static attributes get instantiated before the class gets instantiated via its constructor,
static attributes inside of nested static classes don't seem to get instantiated until after the
class's constructor gets invoked, or at least not until after the attributes are first referenced,
even if they are marked as 'final'.
Consider this example:
public class C0 {
static C0 instance = null;
// Uncomment the following line and a null pointer exception will be
// generated before anything gets printed.
//public static final String outerItem = instance.makeString(98.6);
public C0() {
instance = this;
}
public String makeString(int i) {
return ((new Integer(i)).toString());
}
public String makeString(double d) {
return ((new Double(d)).toString());
}
public static final class nested {
public static final String innerItem = instance.makeString(42);
}
static public void main(String[] argv) {
System.out.println("start");
// Comment out this line and a null pointer exception will be
// generated after "start" prints and before the following
// try/catch block even gets entered.
new C0();
try {
System.out.println("retrieve item: " + nested.innerItem);
}
catch (Exception e) {
System.out.println("failed to retrieve item: " + e.toString());
}
System.out.println("finish");
}
}
Even though 'nested' and 'innerItem' are both declared as 'static final'. the setting
of nested.innerItem doesn't take place until after the class is instantiated (or at least
not until after the nested static item is first referenced), as you can see for yourself
by commenting and uncommenting the lines that I refer to, above. The same does not hold
true for 'outerItem'.
At least this is what I'm seeing in Java 6.0.
The terms are used interchangeably. If you want to be really pedantic about it, then you could define "nested class" to refer to a static inner class, one which has no enclosing instance. In code, you might have something like this:
public class Outer {
public class Inner {}
public static class Nested {}
}
That's not really a widely accepted definition though.
In the case of creating instance, the instance of non
static inner class is created with the reference of
object of outer class in which it is defined. This
means it have inclosing instance.
But the instance of static inner class
is created with the reference of Outer class, not with
the reference of object of outer class. This means it
have not inclosing instance.
For example:
class A
{
class B
{
// static int x; not allowed here…..
}
static class C
{
static int x; // allowed here
}
}
class Test
{
public static void main(String… str)
{
A o=new A();
A.B obj1 =o.new B();//need of inclosing instance
A.C obj2 =new A.C();
// not need of reference of object of outer class….
}
}
I don't think there is much to add here, most of the answers perfectly explain the differences between static nested class and Inner classes. However, consider the following issue when using nested classes vs inner classes.
As mention in a couple of answers inner classes can not be instantiated without and instance of their enclosing class which mean that they HOLD a pointer to the instance of their enclosing class which can lead to memory overflow or stack overflow exception due to the fact the GC will not be able to garbage collect the enclosing classes even if they are not used any more. To make this clear check the following code out:
public class Outer {
public class Inner {
}
public Inner inner(){
return new Inner();
}
#Override
protected void finalize() throws Throwable {
// as you know finalize is called by the garbage collector due to destroying an object instance
System.out.println("I am destroyed !");
}
}
public static void main(String arg[]) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
// out instance is no more used and should be garbage collected !!!
// However this will not happen as inner instance is still alive i.e used, not null !
// and outer will be kept in memory until inner is destroyed
outer = null;
//
// inner = null;
//kick out garbage collector
System.gc();
}
If you remove the comment on // inner = null; The program will out put
"I am destroyed !", but keeping this commented it will not.
The reason is that white inner instance is still referenced GC cannot collect it and because it references (has a pointer to) the outer instance it is not collected too. Having enough of these objects in your project and can run out of memory.
Compared to static inner classes which does not hold a point to inner class instance because it is not instance related but class related.
The above program can print "I am destroyed !" if you make Inner class static and instantiated with Outer.Inner i = new Outer.Inner();
Nested class is a very general term: every class which is not top level is a nested class.
An inner class is a non-static nested class.
Joseph Darcy wrote a very nice explanation about Nested, Inner, Member, and Top-Level Classes.
Targeting learner, who are novice to Java and/or Nested Classes
Nested classes can be either:
1. Static Nested classes.
2. Non Static Nested classes. (also known as Inner classes) =>Please remember this
1.Inner classes
Example:
class OuterClass {
/* some code here...*/
class InnerClass { }
/* some code here...*/
}
Inner classes are subsets of nested classes:
inner class is a specific type of nested class
inner classes are subsets of nested classes
You can say that an inner class is also a nested class, but you can NOT say that a nested class is also an inner class.
Specialty of Inner class:
instance of an inner class has access to all of the members of the outer class, even those that are marked “private”
2.Static Nested Classes:
Example:
class EnclosingClass {
static class Nested {
void someMethod() { System.out.println("hello SO"); }
}
}
Case 1:Instantiating a static nested class from a non-enclosing class
class NonEnclosingClass {
public static void main(String[] args) {
/*instantiate the Nested class that is a static
member of the EnclosingClass class:
*/
EnclosingClass.Nested n = new EnclosingClass.Nested();
n.someMethod(); //prints out "hello"
}
}
Case 2:Instantiating a static nested class from an enclosing class
class EnclosingClass {
static class Nested {
void anotherMethod() { System.out.println("hi again"); }
}
public static void main(String[] args) {
//access enclosed class:
Nested n = new Nested();
n.anotherMethod(); //prints out "hi again"
}
}
Specialty of Static classes:
Static inner class would only have access to the static members of the outer class, and have no access to non-static members.
Conclusion:
Question: What is the main difference between a inner class and a static nested class in Java?
Answer: just go through specifics of each class mentioned above.
I think that none of the above answers give the real example to you the difference between a nested class and a static nested class in term of application design. And the main difference between static nested class and inner class is the ability to access the outer class instance field.
Let us take a look at the two following examples.
Static nest class: An good example of using static nested classes is builder pattern (https://dzone.com/articles/design-patterns-the-builder-pattern).
For BankAccount we use a static nested class, mainly because
Static nest class instance could be created before the outer class.
In the builder pattern, the builder is a helper class which is used to create the BankAccount.
BankAccount.Builder is only associated with BankAccount. No other classes are related to BankAccount.Builder. so it is better to organize them together without using name convention.
public class BankAccount {
private long accountNumber;
private String owner;
...
public static class Builder {
private long accountNumber;
private String owner;
...
static public Builder(long accountNumber) {
this.accountNumber = accountNumber;
}
public Builder withOwner(String owner){
this.owner = owner;
return this;
}
...
public BankAccount build(){
BankAccount account = new BankAccount();
account.accountNumber = this.accountNumber;
account.owner = this.owner;
...
return account;
}
}
}
Inner class: A common use of inner classes is to define an event handler.
https://docs.oracle.com/javase/tutorial/uiswing/events/generalrules.html
For MyClass, we use the inner class, mainly because:
Inner class MyAdapter need to access the outer class member.
In the example, MyAdapter is only associated with MyClass. No other classes are related to MyAdapter. so it is better to organize them together without using a name convention
public class MyClass extends Applet {
...
someObject.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...// Event listener implementation goes here...
...// change some outer class instance property depend on the event
}
}
}
Ummm… An inner class is a nested class… Do you mean anonymous class and inner class?
Edit: If you actually meant inner v.s. anonymous: an inner class is just a class defined within a class, such as:
public class A {
public class B {
}
}
…whereas an anonymous class is an extension of a class defined anonymously, so no actual "class" is defined, as in:
public class A {
}
A anon = new A() { /* You could change behavior of A here */ };
Further edit:
Wikipedia claims there is a difference in Java, but I've been working with Java for eight years, and it's the first time I heard such a distinction – not to mention there are no references there to back up the claim… Bottom line, an inner class is a class defined within a class (static or not), and nested is just another term to mean the same thing.
There is a subtle difference between static and non-static nested classes… Basically, non-static inner classes have implicit access to instance fields and methods of the enclosing class (thus they cannot be constructed in a static context, it will be a compiler error). On the other hand, static nested classes don't have implicit access to instance fields and methods and can be constructed in a static context.
Inner class and nested static class in Java both are classes declared inside another class, known as top level class in Java. In Java terminology, If you declare a nested class static, it will called nested static class in Java while non static nested class are simply referred as Inner Class.
What is Inner Class in Java?
Any class which is not a top level or declared inside another class is known as nested class and out of those nested classes, class which are declared non static are known as Inner class in Java. there are three kinds of Inner class in Java:
1) Local inner class - is declared inside a code block or method.
2) Anonymous inner class - is a class which doesn't have name to reference and initialized at same place where it gets created.
3) Member inner class - is declared as non static member of outer class.
public class InnerClassTest {
public static void main(String args[]) {
//creating local inner class inside method i.e. main()
class Local {
public void name() {
System.out.println("Example of Local class in Java");
}
}
//creating instance of local inner class
Local local = new Local();
local.name(); //calling method from local inner class
//Creating anonymous inner class in Java for implementing thread
Thread anonymous = new Thread(){
#Override
public void run(){
System.out.println("Anonymous class example in java");
}
};
anonymous.start();
//example of creating instance of inner class
InnerClassTest test = new InnerClassTest();
InnerClassTest.Inner inner = test.new Inner();
inner.name(); //calling method of inner class
}
//Creating Inner class in Java
private class Inner{
public void name(){
System.out.println("Inner class example in java");
}
}
}
What is nested static class in Java?
Nested static class is another class which is declared inside a class as member and made static. Nested static class is also declared as member of outer class and can be make private, public or protected like any other member. One of the main benefit of nested static class over inner class is that instance of nested static class is not attached to any enclosing instance of Outer class. You also don't need any instance of Outer class to create instance of nested static class in Java.
1) It can access static data members of outer class including private.
2) Static nested class cannot access non-static (instance) data member or method.
public class NestedStaticExample {
public static void main(String args[]){
StaticNested nested = new StaticNested();
nested.name();
}
//static nested class in java
private static class StaticNested{
public void name(){
System.out.println("static nested class example in java");
}
}
}
Ref: Inner class and nested Static Class in Java with Example
A diagram
The main difference between static nested and non-static nested classes is that static nested does not have an access to non-static outer class members
I think people here should notice to Poster that : Static Nest Class just only the first inner class.
For example:
public static class A {} //ERROR
public class A {
public class B {
public static class C {} //ERROR
}
}
public class A {
public static class B {} //COMPILE !!!
}
So, summarize, static class doesn't depend which class its contains. So, they cannot in normal class. (because normal class need an instance).
When we declare static member class inside a class, it is known as top level nested class or a static nested class. It can be demonstrated as below :
class Test{
private static int x = 1;
static class A{
private static int y = 2;
public static int getZ(){
return B.z+x;
}
}
static class B{
private static int z = 3;
public static int getY(){
return A.y;
}
}
}
class TestDemo{
public static void main(String[] args){
Test t = new Test();
System.out.println(Test.A.getZ());
System.out.println(Test.B.getY());
}
}
When we declare non-static member class inside a class it is known as inner class. Inner class can be demonstrated as below :
class Test{
private int i = 10;
class A{
private int i =20;
void display(){
int i = 30;
System.out.println(i);
System.out.println(this.i);
System.out.println(Test.this.i);
}
}
}
The following is an example of static nested class and inner class:
OuterClass.java
public class OuterClass {
private String someVariable = "Non Static";
private static String anotherStaticVariable = "Static";
OuterClass(){
}
//Nested classes are static
static class StaticNestedClass{
private static String privateStaticNestedClassVariable = "Private Static Nested Class Variable";
//can access private variables declared in the outer class
public static void getPrivateVariableofOuterClass(){
System.out.println(anotherStaticVariable);
}
}
//non static
class InnerClass{
//can access private variables of outer class
public String getPrivateNonStaticVariableOfOuterClass(){
return someVariable;
}
}
public static void accessStaticClass(){
//can access any variable declared inside the Static Nested Class
//even if it private
String var = OuterClass.StaticNestedClass.privateStaticNestedClassVariable;
System.out.println(var);
}
}
OuterClassTest:
public class OuterClassTest {
public static void main(String[] args) {
//access the Static Nested Class
OuterClass.StaticNestedClass.getPrivateVariableofOuterClass();
//test the private variable declared inside the static nested class
OuterClass.accessStaticClass();
/*
* Inner Class Test
* */
//Declaration
//first instantiate the outer class
OuterClass outerClass = new OuterClass();
//then instantiate the inner class
OuterClass.InnerClass innerClassExample = outerClass. new InnerClass();
//test the non static private variable
System.out.println(innerClassExample.getPrivateNonStaticVariableOfOuterClass());
}
}
The Java programming language allows you to define a class within another class. Such a class is called a nested class and is illustrated here:
class OuterClass {
...
class NestedClass {
...
}
}
Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are called static nested classes. Non-static nested classes are called inner classes.
One thing that we should keep in mind is Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes only have access to other members of the enclosing class if those are static. It can not access non static members of the outer class.
As with class methods and variables, a static nested class is associated with its outer class.
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject =
new OuterClass.StaticNestedClass();
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.InnerClass innerObject = new OuterClass().new InnerClass();
Why we use nested classes
It is a way of logically grouping classes that are only used in one place.
It increases encapsulation.
It can lead to more readable and maintainable code.
Source: The Java™ Tutorials - Nested Classes
First of all There is no such class called Static class.The Static modifier use with inner class (called as Nested Class) says that it is a static member of Outer Class which means we can access it as with other static members and without having any instance of Outer class. (Which is benefit of static originally.)
Difference between using Nested class and regular Inner class is:
OuterClass.InnerClass inner = new OuterClass().new InnerClass();
First We can to instantiate Outerclass then we Can access Inner.
But if Class is Nested then syntax is:
OuterClass.InnerClass inner = new OuterClass.InnerClass();
Which uses the static Syntax as normal implementation of static keyword.
Another use case for nested classes, in addition to those that already have been mentioned, is when the nested class has methods that should only be accessible from the outer class. This is possible because the outer class has access to the private constructors, fields and methods of the nested class.
In the example below, the Bank can issue a Bank.CreditCard, which has a private constructor, and can change a credit card's limit according to the current bank policy using the private setLimit(...) instance method of Bank.CreditCard. (A direct field access to the instance variable limit would also work in this case). From any other class only the public methods of Bank.CreditCard are accessible.
public class Bank {
// maximum limit as per current bank policy
// is subject to change
private int maxLimit = 7000;
// ------- PUBLIC METHODS ---------
public CreditCard issueCard(
final String firstName,
final String lastName
) {
final String number = this.generateNumber();
final int expiryDate = this.generateExpiryDate();
final int CVV = this.generateCVV();
return new CreditCard(firstName, lastName, number, expiryDate, CVV);
}
public boolean setLimit(
final CreditCard creditCard,
final int limit
) {
if (limit <= this.maxLimit) { // check against current bank policy limit
creditCard.setLimit(limit); // access private method Bank.CreditCard.setLimit(int)
return true;
}
return false;
}
// ------- PRIVATE METHODS ---------
private String generateNumber() {
return "1234-5678-9101-1123"; // the numbers should be unique for each card
}
private int generateExpiryDate() {
return 202405; // date is YYYY=2024, MM=05
}
private int generateCVV() {
return 123; // is in real-life less predictable
}
// ------- PUBLIC STATIC NESTED CLASS ---------
public static final class CreditCard {
private final String firstName;
private final String lastName;
private final String number;
private final int expiryDate;
private final int CVV;
private int balance;
private int limit = 100; // default limit
// the constructor is final but is accessible from outer class
private CreditCard(
final String firstName,
final String lastName,
final String number,
final int expiryDate,
final int CVV
) {
this.firstName = firstName;
this.lastName = lastName;
this.number = number;
this.expiryDate = expiryDate;
this.CVV = CVV;
}
// ------- PUBLIC METHODS ---------
public String getFirstName() {
return this.firstName;
}
public String getLastName() {
return this.lastName;
}
public String getNumber() {
return this.number;
}
public int getExpiryDate() {
return this.expiryDate;
}
// returns true if financial transaction is successful
// otherwise false
public boolean charge(final int amount) {
final int newBalance = this.balance - amount;
if (newBalance < -this.limit) {
return false;
}
this.balance = newBalance;
return true;
}
// ------- PRIVATE METHODS ---------
private int getCVV() {
return this.CVV;
}
private int getBalance() {
return this.balance;
}
private void setBalance(final int balance) {
this.balance = balance;
}
private int getLimit() {
return limit;
}
private void setLimit(final int limit) {
this.limit = limit;
}
}
}
Static nested classes access PRIVATE class-level static variables of the class they are defined in. That can be huge from an architectural standpoint (i.e. Service Locator pattern employing nested static helper classes in Services), and may help OP see why they exist along with inner classes.
The difference is that a nested class declaration that is also static can be instantiated outside of the enclosing class.
When you have a nested class declaration that is not static, also known as an inner class, Java won't let you instantiate it except via the enclosing class. The object created out of the inner class is linked to the object created from the outer class, so the inner class can reference the fields of the outer.
But if it's static, then the link does not exist, the outer fields cannot be accessed (except via an ordinary reference like any other object) and you can therefore instantiate the nested class by itself.
I have illustrated various possible correct and error scenario which can occur in java code.
class Outter1 {
String OutStr;
Outter1(String str) {
OutStr = str;
}
public void NonStaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// below static attribute not permitted
// static String tempStatic1 = "static";
// below static with final attribute not permitted
// static final String tempStatic1 = "ashish";
// synchronized keyword is not permitted below
class localInnerNonStatic1 {
synchronized public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
public static void StaticMethod(String st) {
String temp1 = "ashish";
final String tempFinal1 = "ashish";
// static attribute not permitted below
//static String tempStatic1 = "static";
// static with final attribute not permitted below
// static final String tempStatic1 = "ashish";
class localInnerNonStatic1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// static method with final not permitted
public static void innerStaticMethod(String str11) {
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
}
// static class not permitted below
// static class localInnerStatic1 { }
}
// synchronized keyword is not permitted
static class inner1 {
static String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
public void innerMethod(String str11) {
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
public static void innerStaticMethod(String str11) {
// error in below step
str11 = temp1 +" india";
//str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
//}
}
//synchronized keyword is not permitted below
class innerNonStatic1 {
//This is important we have to keep final with static modifier in non
// static innerclass below
static final String temp1 = "ashish";
String tempNonStatic = "ashish";
// class localInner1 {
synchronized public void innerMethod(String str11) {
tempNonStatic = tempNonStatic +" ...";
str11 = temp1 +" sharma";
str11 = str11+ tempNonStatic +" sharma";
System.out.println("innerMethod ===> "+str11);
}
/*
// error in below step
public static void innerStaticMethod(String str11) {
// error in below step
// str11 = tempNonStatic +" india";
str11 = temp1 +" india";
System.out.println("innerMethod ===> "+str11);
}*/
//}
}
}
I would like to understand a strange behavior I faced dealing with anonymous classes.
I have a class that calls a protected method inside its constructor (I know, poor design but that's another story...)
public class A {
public A() {
init();
}
protected void init() {}
}
then I have another class that extends A and overrides init().
public class B extends A {
int value;
public B(int i) {
value = i;
}
protected void init() {
System.out.println("value="+value);
}
}
If I code
B b = new B(10);
I get
> value=0
and that's expected because the constructor of the super class is invoked before the B ctor and then value is still.
But when using an anonymous class like this
class C {
public static void main (String[] args) {
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
}
}
I would expect to get value=0 because this should be more or less equal to class B: the compiler automatically creates a new class C$1 that extends A and creates instance variables to store local variables referenced in the methods of the anonymous class, simulating a closure etc...
But when you run this, I got
> java -cp . C 42
> value=42
Initially I was thinking that this was due to the fact that I was using java 8, and maybe, when introducing lamdbas, they changed the way anonymous classes are implemented under the hood (you no longer need for final), but I tried with java 7 also and got the same result...
Actually, looking at the byte code with javap, I can see that B is
> javap -c B
Compiled from "B.java"
public class B extends A {
int value;
public B(int);
Code:
0: aload_0
1: invokespecial #1 // Method A."<init>":()V
4: aload_0
5: iload_1
6: putfield #2 // Field value:I
9: return
...
while for C$1:
> javap -c C\$1
Compiled from "C.java"
final class C$1 extends A {
final int val$v;
C$1(int);
Code:
0: aload_0
1: iload_1
2: putfield #1 // Field val$v:I
5: aload_0
6: invokespecial #2 // Method A."<init>":()V
9: return
....
Could someone tell me why this difference?
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
EDIT:
to clarify the question: why does the initialization of the anonymous classes break the rules for initializing of any other class (where super constructor is invoked before setting any other variable)?
Or, is there a way to set instance variable in B class before inovking super constructor?
This question applies to all inner classes, not just anon classes. (Anon classes are inner classes)
JLS does not dictates how an inner class body accesses outer local variable; it only specifies that the local variables are effectively final, and definitely assigned before the inner class body. Therefore, it stands to reason that the inner class must see the definitely assigned value of the local variable.
JLS does not specify exactly how the inner class sees that value; it is up to the compiler to use whatever trick (that is possible on the bytecode level) to achieve that effect. In particular, this issue is completely unrelated to constructors (as far as the language is concerned).
A similar issue is how an inner class accesses the outer instance. This is a bit more complicated, and it does have something to do with constructors. Nevertheless, JLS still does not dictate how it is achieved by the compiler; the section contains a comment that "... compiler can represent the immediately enclosing instance how ever it wishes. There is no need for the Java programming language to ... "
From JMM point of view, this under-specification might be a problem; it is unclear how writes were done in relation to reads in inner class. It is reasonable to assume that, a write is done on a synthetic variable, which is before (in programming order) the new InnerClass() action; the inner class reads the synthetic variable to see the outer local variable or the enclosing instance.
Is there a way to replicate the behavior of the anonymous class using "normal" classes?
You may arrange the "normal" class as outer-inner class
public class B0
{
int value;
public B0(int i){ value=i; }
public class B extends A
{
protected void init()
{
System.out.println("value="+value);
}
}
}
It will be used like this, which prints 10
new B0(10).new B();
A convenience factory method can be added to hide the syntax ugliness
newB(10);
public static B0.B newB(int arg){ return new B0(arg).new B(); }
So we split our class into 2 parts; the outer part is executed even before the super constructor. This is useful in some cases. (another example)
( inner anonymous access local variable enclosing instance effective final super constructor)
Your anonymous class instance behaves differently than your first code snippet since you are using a local variable whose value is initialized before the anonymous class instance is created.
You can get a similar behavior to the first snippet with an anonymous class instance if you use an instance variable in the anonymous class :
class C {
public static void main (String[] args) {
A a = new A() {
int avalue = 10;
void init() { System.out.println("value="+avalue); }
}
}
}
This will print
value=0
since init() is executed by A's constructor before avalue is initialized.
The variable capture in anonymous classes is allowed to break the rules of normal constructors (super constructor call must be the first statement) because this law is only enforced by the compiler. The JVM allows any bytecode to be ran before invoking the super constructor, which is utilized by the compiler itself (it breaks it's own rules!) for anonymous classes.
You can mimic the behavior either with inner classes as shown in bayou.io's answer, or you can use an anonymous in a static B factory method:
public class B extends A
{
public static B create(int value)
{
return new B() {
void init() { System.out.println("value="+value);
};
}
}
The limitation is actually rather pointless and can be annoying in some situations:
class A
{
private int len;
public A(String s)
{
this.len = s.length();
}
}
class B extends A
{
private String complexString;
public B(int i, double d)
{
super(computeComplexString(i, d));
this.complexString = computeComplexString(i, d);
}
private static String computeComplexString(int i, double d)
{
// some code that takes a long time
}
}
In this example, you have to do the computeComplexString computation twice, because there is no way to both pass it to the super constructor and store it in an instance variable.
The two examples are not related.
In the B example:
protected void init() {
System.out.println("value="+value);
}
the value being printed is the value field of the instance of B.
In the anonymous example:
final int avalue = Integer.parsetInt(args[0]);
A a = new A() {
void init() { System.out.println("value="+avalue); }
}
the value being printed is the local variable avalue of the main() method.
The term inner class is conventionally taken to mean "a nested class which requires an enclosing instance". However, the JLS states as follows:
8.1.3. Inner Classes and Enclosing Instances
[...]
Inner classes include local (§14.3), anonymous (§15.9.5) and non-static member classes (§8.5).
[...]
An instance of an inner class whose declaration occurs in a static context has no lexically enclosing instances.
Also,
15.9.5. Anonymous Class Declarations
[...]
An anonymous class is always an inner class (§8.1.3); it is never static (§8.1.1, §8.5.1).
And it is well-known that an anonymous class may be declared in a static context:
class A {
int t() { return 1; }
static A a = new A() { int t() { return 2; } };
}
To describe it poignantly,
new A() {} is a nested class without an enclosing instance, defined in a static context, but it is not a static nested class—it is an inner class.
Are we all assigning inappropriate meanings to these terms in day-to-day usage?
As a related point of interest, this historical specification document defines the term top-level as the opposite of inner:
Classes which are static class members and classes which
are package members are both called top-level classes. They differ from inner
classes in that a top-level class can make direct use only of its own instance
variables.
Whereas in the common usage top-level is taken to be the opposite of nested.
The distinctions laid out in the question make perfect sense from the specification's standpoint:
an inner class has restrictions applied to it, which have nothing to do with the question of enclosing instances (it may not have static members, for example);
the concept of a static nested class is basically just about namespacing; these classes might rightfully be termed top-level, together with what we usually assume as top-level classes.
It just so happens that removing static from a nested class declaration does two separate things at once:
it makes the class require an enclosing instance;
it makes the class inner.
We rarely think about inner as entailing restrictions; we only focus on the enclosing instance concern, which is much more visible. However, from the specification's viewpoint, the restrictions are a vital concern.
What we are missing is a term for a class requiring an enclosing instance. There is no such term defined by the JLS, so we have (unaware, it seems) hijacked a related, but in fact essentially different, term to mean that.
Well, doesn't the anonymous class have an enclosing instance in your case as well? It is the reference that's static, not the instance of the anonymous class. Consider:
class A {
int t() { return 1; }
static A a = new A() { { System.out.println(t()); } };
}
There is no difference between static inner class and no static. i don't understand why they should be considered separately. Have a look at the following code:
public class Outer {
public static class StaticInner{
final Outer parent;
public StaticInner(Outer parent) {
this.parent = parent;
}
};
public class Inner{}
public static void main(String[] args) {
new StaticInner(new Outer());
new Outer().new Inner();
}
}
And then at StaticInner and Inner classes bytecode:
public class so.Outer$Inner extends java.lang.Object{
final so.Outer this$0;
public so.Outer$Inner(so.Outer);
Code:
0: aload_0
1: aload_1
2: putfield #1; //Field this$0:Lso/Outer;
5: aload_0
6: invokespecial #2; //Method java/lang/Object."<init>":()V
9: return
}
public class so.Outer$StaticInner extends java.lang.Object{
final so.Outer parent;
public so.Outer$StaticInner(so.Outer);
Code:
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: aload_1
6: putfield #2; //Field parent:Lso/Outer;
9: return
}
Actually there is no difference between them at all. I'd say non-static inner class is just a syntactic sugar. A shorter way to write a common thing, no more. The only slight difference is that in no-static inner class, reference to the enclosing class is assigned before calling parent constructor, this might affect some logic, but I don't think that it's so much critical, to consider them separately.
P.S. One more question on a related topic, which might be interesting.
How can I make something like this work:
class Outer {
int some_member;
abstract class InnerBase {
abstract void method();
}
}
class OuterExtendsInner extends Outer.InnerBase {
OuterExtendsInner(Outer o) { o.super(); }
void method() {
// How do I use some_member here?
// Writing Outer.this.some_member -> error about Outer not being an enclosing class
// Writing just some_member -> no-go, either
}
}
The workaround is to have a method in InnerBase that returns Outer.this and call THAT from derived classes, but is there another way?
I primarily want to extend the InnerBase from outside in order to have better code-organization, but I could move all derived classes into Outer.
The problem here is that the synthetic field which links InnerBase to Outer is a private field. Thus, we can only access the outer object from within InnerBase, or if some method or field there provides a reference to the same object.
You could do this in OuterExtendsInner:
class OuterExtendsInner extends Outer.InnerBase {
Outer o;
OuterExtendsInner(Outer o) {
o.super();
this.o = o;
}
void method() {
// now you can reference o.some_member
int x = o.some_member;
}
}
The answer is: you can't, because it would break encapsulation. Only InnerBase can have access to attributes of Outer, not OuterExtendsInner. It is not direct inheritance. InnerBase does not inherit of Outer.
I haven't tried WhiteFang34's answer. It might work, but I'm not clear on it ...
If you really want to define an extension of your inner class elsewhere than in the outer class, the most natural thing would be to define it as an extension of the inner class in another outer extending your outer class as follows:
class Outer {
int some_member;
abstract class InnerBase {
abstract void method();
}
}
class OuterExtendsOuter extends Outer {
class InnerExtendsInner extends Outer.InnerBase {
void method() {
System.out.println(some_member);
}
}
}
I haven't actually run this code either, but it should work.
Update:
Based on the comment thread, I have now compiled and run both my code above and WhiteFang34's code.
Both in fact work, but as noted in the comments by Paŭlo Ebermann, both create two copies of the outer inside the instantiated inner class.
I'm going to upvote Paŭlo's answer, and would advocate just not trying to do this by either tactic, as it's really an abuse of the inner class mechanism.
Just make your extended inner classes live inside the same outer class!
Update 2:
What happens in my code, based on runtime examination using a debugger and on examining the output from javap inspections of the classes, is that both InnerBase and OuterExtendsOuter$InnerExtendsInner have synthetic private final fields named this$0. Because no constructors are explicitly defined, the default constructors are used, and the code snippet
OuterExtendsOuter outer = new OuterExtendsOuter();
Outer.InnerBase inner = outer.new InnerExtendsInner();
causes these two fields to both reference outer.
In other words, Paŭlo's comment is entirely correct.
By further experimentation, the same actually happens if you extend InnerBase in another inner class of Outer, so it has little to do with it being defined in the same outer class or an extension of it, but is in fact an outcome of how non-static inner classes are handled generally.
I suspect this is documented somewhere, but I haven't seen that.
Probably best to mix inheritance and inner classes as little as possible!
Just have a getter method in the InnerBase?
class Outer {
int some_member;
abstract class InnerBase {
abstract void method();
protected int getSome_Member() // This is possible, because Abstract classes can have non-abstract methods.
{
return some_member;
}
}
}
class OuterExtendsInner extends Outer.InnerBase {
OuterExtendsInner(Outer o) { o.super(); }
void method() {
// you can access "some_member" now
int myNumber = getSome_Member();
}
}
Well your problem is that every instance of InnerBase (I know it's abstract) has to have a reference to an Outer object. That is part of the semantics of nested classes. Instantiating OuterExtendsInner would need such a reference.
You can avoid that making InnerBase a static nested class.
The outer class can extend the inner class iff the inner class is compiled to ".class".
Now, every time you compile the outer class it encounters the "extends innerclass" which is
not yet compiled and the compiler will throw a NoClassDefException or ClassNotFoundException.
Isn't it ? So you will never get that inner class compiled. If you can overcome this problem
then you can also extend the inner class :) .
I'm having a hard time wrapping my head around non-static nested classes in Java. Consider the following example, which prints "Inner" and then "Child".
class Outer {
class Inner {
Inner() { System.out.println("Inner"); }
}
}
public class Child extends Outer.Inner {
Child(Outer o) {
o.super();
System.out.println("Child");
}
public static void main(String args[]) {
new Child(new Outer());
}
}
I understand that instances of Inner always have to be associated with an Outer instance, and that that applies to Child too since it extends Inner. My question is what the o.super() syntax means - why does it call the Inner constructor?
I've only seen a plain super(args) used to call the superclass constructor and super.method() to call the superclass version of an overridden method, but never something of the form instance.super().
It's called a "qualified superclass constructor invocation".
Citing from here:
Explicit constructor invocation statements can be divided into two kinds:
Alternate constructor invocations begin with the keyword this (possibly prefaced with explicit type arguments). They are used to invoke an alternate constructor of the same class.
Superclass constructor invocations begin with either the keyword super (possibly prefaced with explicit type arguments) or a Primary expression. They are used to invoke a constructor of the direct superclass. Superclass constructor invocations may be further subdivided:
Unqualified superclass constructor invocations begin with the keyword super (possibly prefaced with explicit type arguments).
Qualified superclass constructor invocations begin with a Primary expression . They allow a subclass constructor to explicitly specify the newly created object's immediately enclosing instance with respect to the direct superclass (§8.1.3). This may be necessary when the superclass is an inner class.
Inner Classes (non-static child classes) are essentially Nested Classes (static child classes) with implicit links back to their parent objects. Here is your above code, written instead using a static nested class:
class Outer {
static class Inner {
final Outer outer;
Inner(Outer outer) {
this.outer = outer;
System.out.println("Inner");
}
}
}
public class Child extends Outer.Inner {
Child(Outer o) {
super(o); // o.super();
System.out.println("Child");
}
public static void main(String args[]) {
new Child(new Outer());
}
}
Looking at this, you should be able to understand what o.super() was doing.
Why does o.super() in Child ends up invoking Outer.Inner constructor? It's simple: because Child extends Outer.Inner, and constructor calls are always chained up the hierarchy.
Here's a slight expansion to your snippet to illustrate:
class Outer {
Outer() {
System.out.println("Outer");
}
void outerMethod() { }
class Inner {
Inner() {
System.out.println("OuterInner");
outerMethod();
}
String wealth;
}
}
class OuterChild extends Outer {
OuterChild() {
System.out.println("OuterChild");
}
}
public class OuterInnerChild extends Outer.Inner {
OuterInnerChild(Outer o) {
o.super();
System.out.println("OuterInnerChild");
this.wealth = "ONE MILLION DOLLAR!!!";
}
public static void main(String args[]) {
System.out.println(new OuterInnerChild(new Outer()).wealth);
new OuterChild();
}
}
This prints:
Outer
OuterInner
OuterInnerChild
ONE MILLION DOLLAR!!!
Outer
OuterChild
Some key observations:
Because OuterInnerChild extends Outer.Inner, it inherits wealth, just like normal subclass semantics
And just like normal subclass semantics, the constructor of OuterInnerChild chains to the constructor of Outer.Inner
Because OuterChild extends Outer, its constructor chains, even when not invoked explicitly
Whether implicitly or explicitly, the constructor chains up the hierarchy
But why does the compiler demand that OuterInnerChild constructor takes an Outer o, and that o.super() is invoked?
Now that is specific to inner class semantics: it's done to ensure that all instances of OuterInnerChild has an enclosing Outer instance for Outer.Inner, the super class of OuterInnerChild. Otherwise, the constructor of Outer.Inner would not have an enclosing instance of Outer to invoke outerMethod() on.
Conceptually, a non-static inner class “belongs” to a particular object. It's sorta like each one gets its own version of the class, much like a non-static field or method belongs to a particular object.
So that's why we have funny syntax like instance.new Inner() and instance.super() — for contexts where the answer to the question “but whose Inner?” isn't immediately obvious. (In a non-static method of the outer class, you can just say new Inner(), and as usual that's short for this.new Inner().)
Always not to forget basic principles, in process of calling a sub class constructor it's always the parent class is instantiated first irrespective of inner/outer classes. In your scenario, as you are extending inner class and your inner class is a member of parent class which needs to be instantiated then followed by calling the actual inner class constructor.