补疑(关于内部类)

内部类就是一种链关系,就好像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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值