How many external ** this ** will this inner class have?

I have the following example of inner classes.

class Outer {
   private class Inner1 extends InnerBase {
   }
   private class Inner2 extends InnerBase {
   }
   private class InnerBase {
   }
}

I usually considered the inner class to have an additional, hidden "this" outer class.

However, but what will happen, the inner class is derived from another inner class?

All inner classes (Inner1, Inner2, InnerBase) must have an additional value.

Will Inner1, Inner2 have their own external links? Or just reuse one of InnerBase, causing a slightly different behavior?

(Hid this == link pointing to an instance of an outer class)

+3
source share
4 answers

this. javap

$ javap -private Outer.Inner1
Compiled from "Outer.java"
class Outer$Inner1 extends Outer$InnerBase{
    final Outer this$0;
    private Outer$Inner1(Outer);
}

$ javap -private Outer.InnerBase
Compiled from "Outer.java"
class Outer$InnerBase extends java.lang.Object{
    final Outer this$0;
    private Outer$InnerBase(Outer);
    Outer$InnerBase(Outer, Outer$1);
}

, , java, this$0 . :

public class Outer {
    class InnerBase {
        Outer innerBaseOuter() { return Outer.this; }
    }

    class Inner1 extends InnerBase {
        public Inner1() {}
        public Inner1(Outer parentOuter) {
            parentOuter.super(); // set a different super in InnerBase
        }
        Outer innerOuter() { return Outer.this; }
    }

    public static void main(String[] args) {
        Outer outer1 = new Outer();
        Outer outer2 = new Outer();

        Inner1 a = outer1.new Inner1();
        System.out.println("Checking (a.base == a.inner) => "+
            (a.innerBaseOuter() == a.innerOuter()));

        Inner1 b = outer1.new Inner1(outer2);
        System.out.println("Checking (b.base == b.inner) => "+
            (b.innerBaseOuter() == b.innerOuter()));
    }
}

, :

Checking (a.base == a.inner) => true
Checking (b.base == b.inner) => false
+2

Outer. Outer, Outer. , Outer .

class Outer {
    private class Inner1 extends InnerBase {
        Outer getOuter() {
            return Outer.this;
        }
    }

    private class Inner2 extends InnerBase {
        Outer getOuter() {
            return Outer.this;
        }
    }

    private class InnerBase {
        Outer getOuter() {
            return Outer.this;
        }
    }

    public static void main(String[] args) {
        new Outer().test();
    }
    public void test() {
        System.out.println((new Inner1()).getOuter());
        System.out.println((new Inner2()).getOuter());
        System.out.println((new InnerBase()).getOuter());
    }
}
+1

:

public class Outer 
{
    public Outer() {}
    class Inner1 extends Outer 
    {
        public Inner1() 
        {
            super(); // invokes Object() constructor
        }
    }

    class Inner2 extends Inner1 
    {
        public Inner2() 
        {
            super(); // invokes Inner1() constructor
        }
    }
}

.

Outer.java:12: cannot reference this before
supertype constructor has been called
super(); // invokes Inner1() constructor

Inner2 , . , , Inner1, , - . , , expression.super(args)

, : , . , , , , . Inner1. , Inner2, , Inner1 . , - . , this.super.

Inner2 this , .

:

public class Outer
{
    class Inner1 extends Outer { }
    class Inner2 extends Inner1 
    {
        public Inner2() 
        {
            Outer.this.super();
        }
    }
}

, . : , -, : ? , . , , . , . Inner1 , . Inner2 , , .

Thus, for one class it is rarely both an inner class and a subclass of another. More generally, it is rarely advisable to expand the inner class; if you must, think long and hard about the host. Most member classes can and should be declared static.

+1
source

In your example, there is only one level of "inner", so each inner class will have access to the class Outer, as you mentioned.

Here is an example of fun:

public class Test {

    public static void main(String[] args) {
        Level1 l1 = new Level1();
        Level1.Level2 l2 = l1.new Level2();
        Level1.Level2.Level3 l3 = l2.new Level3();
    }

    public static class Level1 {

        private String s = "Level1";

        public Level1() {
            System.out.println(this + ": " + s);
        }

        public class Level2 {

            private String s = "Level2";

            public Level2() {
                System.out.println(this + ": " + s);
                System.out.println("Level1: " + Level1.this);
            }

            public class Level3 extends OtherLevel {

                private String s = "Level3";

                public Level3() {
                    System.out.println(this + ": " + s);
                    System.out.println("Level1: " + Level1.this);
                    System.out.println("Level2: " + Level2.this);

                    System.out.println("super: " + super.toString());
                }
            }
        }

        public class OtherLevel {

            private String s = "OtherLevel";

            public OtherLevel() {
                System.out.println(this + ": " + s);
            }
        }
    }
}

Conclusion:

javaapplication4.Test$Level1@70284ac3: Level1
javaapplication4.Test$Level1$Level2@74a14fed: Level2
Level1: javaapplication4.Test$Level1@70284ac3
javaapplication4.Test$Level1$Level2$Level3@88d00c6: OtherLevel
javaapplication4.Test$Level1$Level2$Level3@88d00c6: Level3
Level1: javaapplication4.Test$Level1@70284ac3
Level2: javaapplication4.Test$Level1$Level2@74a14fed
super: javaapplication4.Test$Level1$Level2$Level3@88d00c6
0
source

All Articles