补疑(关于内部类)

    技术2022-05-11  67

    内部类就是一种链关系,就好像C++当中的指针一样,或者这是一个指向具体内容的指针,或者这是一个指向指针的指针,看看下面的代码:class Outer1{    class Inner11{        class Inner111{            int var111 = 100;            }        }     class Inner12{        class Inner121{            int var121 = 10;            class Inner1211{                int var1211 = Outer1.Inner12.Inner121.this.var121;            }        }    }}

    public class OutClass1{    public static void main(String[] args){        int var1 = new Outer1().new Inner11().new Inner111().var111;        int var2 = new Outer1().new Inner12().new Inner121().new Inner1211().var1211;          System.out.println(var1);        System.out.println(var2);    }}这里的内部类嵌套了内部类,一层层的,很容易看出来就好像一种链接关系,就好像数据结构当中的树,层次分明。要注意的一个地方就是关于var1211的赋值,首先要说的就是要

    找到上一级的变量,只要逐层找就可以了,还有就是因为上一层变量在赋值的时候要加上this.var121,因为要赋值的是上一层变量的实例变量。而this的使用则是,this放在哪个

    类后,就说明该this是该类的实例。如果内部类是static的,那么就不需要这样一层一层的new了,它的使用方法,就好像普通的static一样,如果是逐层的static,那么要到最里层的静态变量,就好像普通的静态变

    量一样,只不过多了一些指向的标识符而已。如果静态变量中间夹杂了非静态变量,那么该new的时候,就实例化,该直接用的时候,就直接用就可以了。

    内部类的继承要调用父类的外层类的super(),下面看一下下面的代码:class Outer2{    class Inner21{         }}

    class Outer3{    class Inner31 extends Outer2.Inner21{        Inner31(Outer2 o2){            o2.super();        }    }}试试把构造函数注释掉,或者只注释o2.super(),看看是否能编译过去。

    内部类可以使用外层类,但是,如果需要生成一个实例才有内部类,就不能通过编译了。也可以这样说,内部类可以写在外部类的函数中,但是,如果写到函数中,就不能在外层

    类使用了,下面看一个例子:class Outer3{    void prtOuter3(){        System.out.println("Outer3");    }     class Inner31{        Inner31(){            class Inner311{                void prtInner31(){                    System.out.println("Inner311");                }                void prtprtInner31(){                    Outer3.this.prtOuter3();                }            }        }    }}

    public class OuterClass3{    public static void main(String[] args){        Outer3.Inner31.Inner311 inner = new Outer3().new Inner31().new Inner311();        inner.prtprtInner31();    }}上面这段代码是不能通过编译的,就是因为它把内部类写到了外层类的函数中之后,还想在外部使用它,想要通过编译(这里说的只是通过编译,没有说使用的意图),有两个方法

    可以,一个是将内部类移到构造方法外,另外一个就是不要在main方法当中实例该内部类。

    又是外层,又是同层,又是内部类,写着写着万一重名了字母办(只是假设,很少有机会写这么多内部类,还有内部类嵌套内部类吧,如果出现这样的情况,首先要想的应该是,我

    的设计是不是有问题?)?那么到底该调用哪个类呢,通过下面的例子,就能说明这样的情况。class Outer4{    {        new Inner42();    }     class Inner41{        {            System.out.println("Outer4.Inner41");        }    }     class Inner42{        {            new Inner41();        }          class Inner41{            {                System.out.println("Outer4.Inner42.Inner41");            }        }    }}

    public class OuterClass4{    public static void main(String[] args){        new Outer4();    }}这时候出现了两个同名的类,一个是Inner42的内部类Inner41,一个是它的同级别的类,那么这时候要在Inner42里面实例化Inner41,会出现什么样的结果呢,是不会通过编译,

    还是什么,运行一下,可以通过编译,得出的是Outer4.Inner42.Inner41,所以得出结论,如果同名,内部类优先,那么如果我想使用的是同级类呢,这也很简单,加上前面讲的

    链new Outer4.Inner41()就可以了。所以也可以看出来,在链接的过程,不要出现同名,也就是说内部类的名字可以与该类的同级别类同名,但是不能在该链上出现同名。比如:class Outer{    class Inner1{        class Inner11{            //class Outer{}如果去掉注释就会出错        }    }}这时候就不允许出现重名。

    下面就是包含了一个内部类,内部接口,匿名类的例子,首先要说明的是,匿名内部类不像内部类那样,可以有构造函数,它不能有构造函数,所以只能通过块{}来初始化:interface OuterInterface{    int varInterface = 1;    void pt();}

    class Outer51{    Outer51(){      }     int get(){        return 100;    }}

    class Outer52{    /*interface OuterInterface{        void pt();    }*/     class Inner521{        OuterInterface testMthodInterface(){            final int i = 2;            int j = 3;            return new OuterInterface(){                int k;                {                    k = i+k;                }                    public void pt(){                    System.out.println(k);                }            };        }          Outer51 testMethodClass(){            return new Outer51(){                public int get(){                    return super.get()*10;                }            };        }    }}

    public class OuterClass5{    public static void main(String[] args){        int v1 = new Outer52().new Inner521().testMethodClass().get();        System.out.println(v1);        new Outer52().new Inner521().testMthodInterface().pt();    }}从这里,就可以看出,继承接口内部优先。匿名内部类同普通类一样,可以继承自接口,也可以继承自类,继承自类的构造函数中,可以有参数。

    接口可以嵌套在接口中,也可以嵌套在类的顶层中,但是不能嵌套在内部类中,看一下下面的代码:class OuterClass{    interface InnerInterface{}    class InnerClass{        //interface InnerInterface{}    }}如果去掉注释,就不能通过编译了。

    ps:看到一篇关于内部类的总结(http://www.newasp.net/tech/java/14908.html),觉得总结的不错,揣摩了一下,用自己的话总结了一下。 


    最新回复(0)