Today I stumbled about some strange inner (non-static) class behaviour.
If I have the following classes ...
class B { String val = "old"; void run(){ val = "new"; System.out.println(val); // outputs: new new InnerB().printVal(); // outputs: new } private class InnerB { void printVal(){ System.out.println(val); } } } new B().run();
... everything seems to be clear. The instance of InnerB belongs to the instance of B so if it should output val it prints the already replaced value 'new'.
BUT if the inner class extends the outer class this doesn't work.
class B { String val = "old"; void run(){ val = "new"; System.out.println(val); // outputs: new new InnerB().printVal(); // outputs: new new InheritedB().printVal(); // outputs: old new } private class InnerB { void printVal(){ System.out.println(val); } } private class InheritedB extends B{ void printVal(){ System.out.println(val + " "+ B.this.val); } } } new B().run(); // outputs: new new old!
If I have a look at the constructors I also see that a new instance of B will be created if instance of InheritedB is created.
I find this very strange... Can somebody explain why there is this difference?
Inner class can extend it's outer class. But, it does not serve any meaning. Because, even the private members of outer class are available inside the inner class. Even though, When an inner class extends its outer class, only fields and methods are inherited but not inner class itself.
You can access any field of outer class from inner class directly. Even Outer class can access any field of Inner class but through object of inner class. Show activity on this post. "A nested class is a class defined within another class.
Advantages. The main advantages of a nested (inner) class are: It shows a special type of relationship, in other words, it has the ability to access all the data members (data members and methods) of the main class including private. They provide easier code because it logically groups classes in only one place.
In Java programming, nested and inner classes often go hand in hand. A class that is defined within another class is called a nested class. An inner class, on the other hand, is a non-static type, a particular specimen of a nested class.
This line:
new InheritedB().printVal();
creates a new instance of InheritedB
, whose containing instance is the existing instance of B
(where val is "new"
). But at this point there are two val
variables:
B
InheritedB
, which has a separate val
fieldThe value of the second variable is "old"
because that's effectively the default value of the field.
This statement in InheritedB
:
System.out.println(val + " "+ B.this.val);
prints out the value of val
inherited from B
, followed by the value of val
in the "containing instance".
It might be simpler to think of it being refactored to:
public class B { String val = "old"; } public class InheritedB extends B { B other; public InheritedB(B other) { this.other = other; } void printVal() { System.out.println(val + " "+ other.val); } }
Then you're basically running:
B original = new B(); original.val = "new": InheritedB inherited = new InheritedB(original); inherited.printVal();
Hopefully you can follow exactly what's going on there. The compiler is roughly performing your original code into that code.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With