内部类

1.普通内部类

普通内部类,不能有静态代码块、不能有静态方法、静态变量、静态内部类

原因如下:

我们不妨用反证法来证明:假设现在有一个普通内部类A,里面有一个静态变量B(其实其他几个都是同个道理,所以这里只用静态变量来举例子),普通内部类的加载,是需要依靠其对应的外部类。如果外部类仅仅只是加载到jvm,没有实例化,内部类是没有被加载到内存中的。因为普通内部类仅仅只是一个普通的成员属性,只有实例化了外部类,对应的内部类才会被加载到jvm中。假设我们现在没实例化A的外部类,然后我们直接通过A来调用B,又因为A还没加载到内存中,故而A的静态变量肯定也没加载到内存中,所以肯定访问不成功,这就是原因。

 

非静态内部类并不随外部类一起加载,只有在实例化外部类之后才会加载。
 现在考虑这个情况:在外部类并没有实例化,内部类还没有加载,这时候如果                                                          
 调用内部类的静态成员或方法,内部类还没有加载,却试图在内存中创建该内
 部类的静态成员,这明显是矛盾的。所以非静态内部类不能有静态成员变量或
 静态方法。

 

注意:java中有一种东西叫做静态常量,静态常量。首先他是一个静态的变量,意味着它需要在雷家在的时候马上初始化,这个说法上是错误的,我们继续向下看。然后他是一个常量,常量意味着啥?意味着不能改变!那么又是静态,又是常量,换句话说这个变量,他在你写出来的时候,就是确定下来的,不可以改变的,既然在写出来的时候就能确定的,为什么还要费劲在加载类的时候做什么操作呢?直接编译期就能读取到对应的数据,并且把常量存放起来。【注意的是 => 普通常量不具有这个功能,普通常量是随着类的参数而初始化的】

 

实例化普通内部类语法

首先要实例化出一个外部类,再实例化出内部类,写法有点怪异,可以当作是普通变量来使用,只不过多了一个new字段。

内部类是如何依附于外部类的?

    编译器编译时,是把外部类与成员内部类编译成两个独立的文件的;

    但会给成员内部类默认添加一个类型为外部类对象引用的成员变量并为构造方法默认传入一个类型为外部类对象引用的参数,并以该参数值来初始化该成员变量;

    如下所示:

        final Person this$0;

        InnerClass(Person per){

    ...

    this$0 = per;

    ...

  }

    也就是说,成员内部类的对象保存了一个外部类对象的引用,通过这个引用,内部类就可以无限制的访问外部类的成员了。

    从这里也可以看出,创建成员内部类对象之前必须要存在一个外部类对象,即,成员内部类是依附于外部类的。

 

 

2.静态内部类

内部类外部类能够互相访问,加了private依然能。

只是静态的需要有所区分把,静态能访问静态。非静态能访问非静态+静态。

 

内部类编译出来,实际上是另外一份文件,但是我们访问一个内部类,依然需要通过外部类来访问。

     =》   

 

3.局部内部类

局部内部类是定义在一个方法或者一个作用域里面的类,它和成员内部类的区别在于局部内部类的访问仅限于方法内或者该作用域内。

class People{
    public People() {
         
    }
}
 
class Man{
    public Man(){
         
    }
     
    public People getWoman(){
        class Woman extends People{   //局部内部类
            int age =0;
        }
        return new Woman();
    }
}

 

注意,局部内部类就像是方法里面的一个局部变量一样,是不能有public、protected、private以及static修饰符的。

也就是说,对应的局部内部类不能再其他任何地方被引用,它的作用域仅限于当前所在的作用域,当然你可以把它return。

 

局部内部类不能用权限修饰符,也不能用static。具体原因不得而知,大概是因为方法是即时运行,运行完马上销毁对应的栈,把static加载这里没什么意义。因为不能用static,所以也不能用interface。

只能是普通的类或者抽象类。

方法区中的内部类,如果引用到方法中的变量,必须是final。

原因:内部类编译出来,实际上是另外一个独立的class文件,和外部类无关,只是他能够持有外部类的一个引用。同理,方法区里面的内部类,我们肯定不能说什么持有方法的引用的,java没有这种机制。所以在编译的时候,jvm实际上是吧方法的变量直接搞进内部里面。这样的话,就要求是final了,因为内部类无法检测到方法区里面的变量的随时变化。而且还有一个很重要的点,局部内部类引用了方法中的变量,如果方法中最后return了这个局部内部类,然后这个方法执行完销毁了,那么这个局部内部类就无法去继续持有这个方法里面的变量了,这也是为什么局部内部类要copy一份方法中的变量出来的原因。

 

 

4.匿名内部类

有一个抽象类,AnonymousTest,或者接口,直接new出来,无需搞一个去继承或者实现。

anstract AnonymousTest{}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值