Reputation: 15416
I am learning inner class . Out of curiosity i extended the inner class which has a parameterized constructor. But when i write super(int i) to call it the code does not compile.
class Outer{
class Inner{
private int a;
Inner(int i){
this.a=i;
}
public void inheritFromInner(){
System.out.println("Inherited from inner");
}
}
}
class Test extends Outer.Inner{
Test(int r){
super(r);// This line does not compile.
}
}
As inner classes are part(member) of the outer class and they have to be accessed through the outer class. How the super constructor of Test class can be called.
The compile error is: No enclosing instance of type Outer is available due to some intermediate constructor invocation
Upvotes: 1
Views: 1124
Reputation: 10084
The existing answers do not expound upon the differences among the kinds of member classes.
A member class is any class that is declared within another class. They are sometimes called nested classes. Of the kinds of member classes, anonymous inner classes and local classes will not be mentioned here. The remaining kinds of member classes are inner classes and static member classes.
Inner Class. An inner class instance must be instantiated with the context of an existing outer class instance. Inner classes contain an implicit reference to the outer class instance (a fact which can cause inner class instances to lead to memory leaks). Although uncommon, you can instantiate an inner class instance as follows:
Outer out = new Outer();
Outer.Inner inner = out.new Inner();
Because the super()
keyword must be the 1st line to execute within a subclass constructor, you would have to declare your constructor like this if it really does need to be in an inner class:
class Test extends Outer.Inner{
Test(Outer out, int r) {
out.super(r);
}
}
Static Member Class. A static member class is declared with the modifer static
in the class declaration. In almost every way that matters, a static member class is a top level class. Like top level classes (and unlike inner classes), they do not require any other object instances for instantiation. Static member class objects are commonly intantiated as:
Outer.Inner inner = new Outer.Inner();
Whenever possible, you should strongly favor the use of static member classes over inner classes. Use inner classes only when your member class objects really must have a superclass instance (which should be uncommon).
Upvotes: 4
Reputation: 620
The error actually has nothing to do with that specific line of code, nor with the superclass constructor taking a parameter. You can reproduce the error with a simpler example:
class Outer {
class Inner {
}
}
class Test extends Outer.Inner {
}
This gives an error such as:
Outer.java:6: error: an enclosing instance that contains Outer.Inner is required
class Test extends Outer.Inner {
^
1 error
There are two type of inner classes, non-static (the default) and static (which requires the keyword static
). Static inner classes are just like top-level classes (which are always static), but non-static inner classes require an instance of their enclosing class in order to be instantiated. Since Outer.Inner
is a non-static inner class, it can only be instantiated "in the context of" an instance of Outer
, which means either inside of a instance method of Outer
, or via code such as:
Outer outer = new Outer();
outer.new Inner();
(This syntax is not commonly encountered.)
Since Test
is a top-level class, it's static, and so it can't subclass a non-static inner class, because when creating an instance via new Test()
, there won't be an instance of Outer
provided.
Note however that this code compiles without error:
class Outer {
class Inner {
}
class Test extends Outer.Inner {
}
}
In this case, Test
is also a non-static inner class of Outer
, so instances of Test
must be created in the context of an instance of Outer
, which satisfies the requirements of its superclass.
Of course, modifying the original code to make Inner
static will also allow it to compile. In real-world code, you create a non-static inner class because you need an instance of that class to have access to the associated instance of the enclosing class. In that case, you don't have the option of making it static. But if it doesn't need such access, then you should make your inner class static (or, make it a top-level class instead).
Edit: Apparently it is possible to create a static subclass of a non-static inner class, by explicitly passing an instance of the necessary enclosing class as a constructor parameter to the subclass and invoking super()
on it. See scottb's answer here.
Upvotes: 1
Reputation: 14217
You need to state your Inner class to public static
class Outer{
public static class Inner{
private int a;
Inner(int i){
this.a=i;
}
public void inheritFromInner(){
System.out.println("Inherited from inner");
}
}
}
class Test extends Outer.Inner{
Test(int r){
super(r);// This line does not compile.
}
}
Upvotes: 1