jdk version:1.8.0_241
There is a class extending a inner class. Code as follows:
class WithInner {
class Inner {
}
}
public class ExtendInnerClass extends WithInner.Inner {
ExtendInnerClass(WithInner withInner) {
withInner.super();
}
}
To connect WithInner class's object and Inner class's object, we have to use super() method.
But when i decompiled the class file, i find something interesting.
public class ExtendInnerClass extends Inner {
ExtendInnerClass(WithInner withInner) {
withInner.getClass();
super(withInner);
}
}
I find that compiler not only use super() method but also withInner.getClass().
why he do this?
An inner class object usually need to hold a reference to its outer class object.
Inner class has loaded before outer class without getClass(), it doesn't meet the principle of jvm, so use getclass() to load outer class in jvm before inner one.
Related
I know I can access methods of outer class from within the inner class.
Like the below class:
class outer {
void outerMethod() {}
class inner {
void innerMethod() {
outerMethod();
}
}
}
I want to know how can I do this if I extended the inner class?
I want to do the following:
class newClass extends outer.inner {
void innerMethod() {
outerMethod();
}
}
I want to be able to access method() from newClass
Instance of non-static inner class requires existence of outer class instance which it will belong to.
So to make class newClass extends outer.inner { compile you either need to
make inner class static, and remove requirement of existence of outer class instance (but this will also limit your class a little)
or ensure that inner will belong to some outer instance, which you can do by calling outerInstance.super() inside your constructor of your class which extends this inner class.
In case of option 2, probably simplest solution would be explicitly passing instance of outer to your class like
class newClass extends outer.inner {
private outer o;
public newClass(outer outerInstance) {
outerInstance.super();
this.o = outerInstance;
}
void innerMethod() {
o.outerMethod();
}
}
Now you can simply call your outerMethod() on passed instance of outer class.
But remember that calling outerMethod is possible only when this method has proper visibility for your newClass. So despite the fact that inner is able to use any method of its outer class your newClass may not have access to it.
When a nested class in instantiated how does it reference the outer class? Does it always extend the outer class or reference it another way? I was told that the inner extends the outer but then why doesn't the following example work?
For Example:
public class OuterClass {
public String fruit = "apple";
public class InnerClass {
public String fruit = "banana";
public void printFruitName(){
System.out.println(this.fruit);
System.out.println(super.fruit);
}
}
}
The above does not compile with an error for super.fruit saying that 'fruit' cannot be resolved. However if the inner class is specified to extend the outer class then it works:
public class OuterClass {
public String fruit = "apple";
public class InnerClass extends OuterClass {
public String fruit = "banana";
public void printFruitName(){
System.out.println(this.fruit);
System.out.println(super.fruit);
}
}
}
This seems to show that the inner class does not extend the outer class unless specifically specified.
There is no implicit sub-type relationship: your observation/conclusion is correct. (In the first case, super has the type of "Object" and "Object.fruit" does indeed not exist.)
An inner class (as opposed to "static nested class"), as shown, must be created within context of an instance of the outer class; but this is orthogonal to sub-typing.
To access a member of the outer class, use OuterClass.this.member or, if member is not shadowed, just member will resolve; neither super.member nor this.member will resolve to the outer class member.
Extending the outer class "fixes" the compiler error, but the code with this.fruit doesn't access the member of the enclosing OuterClass instance - it simply accesses the member of the InnerClass instance inherited from the superclass it extends.
I was learning about Nested and Inner classes and this led me to think whether it is possible to extend an Inner class to be a Nested class or not. For example.
public class Outer{
public class Inner{
// notice the lack of static keyword
}
}
public class ExtendedOuter extends Outer{
public static class ExtendedInner extends Inner{
// notice the static keyword
}
}
I did try to compile the code above and I couldn't, but the compile time error I received made me believe that there may be a work around. I can however extend a Nested class to be an Inner class.
This is the compile time error I received.
no enclosing instance of type Outer is in scope
An inner class has a reference to the outer class. You cannot remove it in a subclass. This would be like removing a field in a sub-class.
Actually you can extend the inner class. You just have to provide an instance of Outer that the class will be bound to. To do so, you have to explicitly call the super constructor with the instance.
public class Outer {
public class Inner{
// notice the lack of static keyword
}
}
public class ExtendedOuter extends Outer {
private static Outer outer = new ExtendedOuter(); // or any other instance
public static class ExtendedInner extends Inner {
public ExtendedInner() {
outer.super(); // this call is explicitly required
}
}
}
This also works if you have a nested class that extends another nested class from a different enclosing class.
Your question doesn't make sense. An inner class is already a nested class, and so is any other class defined inside another one. Evidently you don't know what these words mean:
nested class: a class declared inside another one
inner class: a nested class that isn't declared 'static'.
Note that 'static nested' and 'inner' are mutually exclusive. Note also that an inner class can extend a static nested class, but not vice versa.
What your code is actually trying to do is extend the inner class as a static class, which is what causes the error. Not because the extending class is nested.
So, I ran into a wall earlier. If I have a class Parent with an inner class SubParent like this:
public class Parent
{
public class SubParent
{
}
public Parent(SubParent sp)
{
}
}
Then I have a Child class which extends Parent like this:
public class Child extends Parent
{
public Child()
{
super(new SubParent());
}
}
Then I get a "error: cannot reference this before supertype constructor has been called" with an arrow pointing at the SubParent constructor.
Now, if I have SubParent as a separate class in it's own file, everything is fine. But I would like to have it as an inner class. Is there any way to do that?
An inner class instance requires an outer class instance to exist. At the point you are calling
super(new SubParent());
the SubParent constructor would have been called before an outer class instance has been created. You can't do this.
Either declare SupParent in its own file or make it static. What relationship are you trying to achieve anyway?
Since your SubParent is not a static nested class, there's an implicit relationship between it and the Parent object it belongs to (in this case, also a Child object). It sounds like you're not needing the relationship an inner class provides; try making SubParent a public static class.
Note that there's a distinction between an inner class, which is not static (has a reference to an instance of its containing class), and a nested class, which is any class contained inside another class, whether static or not.
Your problem is that you are trying to create a SubParent very early in construction of the Child, before it is ready to use as "this" in an inner class creation. In addition to earlier suggestions, you could change Parent to have a parameterless constructor and a setter for its SubParent reference:
public Parent(){
}
public void setSub(SubParent sp){
}
The Child constructor can wait until after the super call to create the SubParent:
class Child extends Parent
{
public Child()
{
setSub(new SubParent());
}
}
Consider the below code:
class abstract Normal1 extends Something
{
}
class Outer
{
class abstract Inner extends Normal1
{
}
}
class General extends Outer.Inner // Problem occurs at this
{
}
The error I am getting is "No enclosing instance of type PerfHelper is available due to some intermediate constructor invocation"
My question is can I extend the inner class like above ?
Declare the inner class as static and you should be able to extend it:
class outer {
static abstract class inner extends normal1 { }
}
If inner is not abstract, it's tied to outer, and can only exist when an instance of outer exists. Check to see if this is what you really want.
Nested class are like(in sense ) Property of a class.
As in case of instance variable it only when available when its object is created as same as inner class also available when outer's object will created.
So if you want to extend this then make your inner class as static inner class
As jordao suggest above
Try this, (Read nested class inheritance rules).
abstract class normal1 extends something { }
class outer
{
abstract class inner extends normal1{}
}
class Outer1 extends outer
{
class General extends inner {}
}
In your class General modify its constructor a to call super inner class constructor. here is the code..
public General(){
new outer().super();
}