java内部类的一些细节

从JDK1.1开始,我们引入了内部类这样的概念,无疑这样一种机制给我们带来了不少便利,它使我们的代码结构层次更好,可读性更强。

很多初学者对内部类不是很熟悉,或者会使用内部类,但并不是很清楚在java底层的机制中到底做了什么。

让我们一起来看下java实现内部类的细节:

public class outter{

      private int field;

      class  Inner{

           private int field1;

           private int field2;

      }

}

可以看到在外围类outter的内部定义了一个类Inner。我们管Inner这个类就叫做内部类。

值得注意的是:在外围类初始化的时候,并不意味这每一个outter的实例都有一个Inner作为实例域。Inner类的实例化往往在外围类的方法里完成,在java中,内部类的实例化,并不是作为外围类的一个实例,而是生成另外一个名字类似于这样 outter$Inner.class的.class文件,这是一个与常规类翻译的的文件没什么两样的文件,所以其实jvm压根不知道什内部类的存在。

但是我们知道,内部类可以像外围类的其他方法一样自由的访问外围类的私有域,java在编译的时候又做了什么呢?其实如果懂反射机制的朋友可以写一个反射类来测试一下outter$Inner这个类所有域和方法,我们可以看到编译器给他增加了一个用final声明的outter的引用field,这个引用指向它的外围类的对象,也就是说内部类的对象拥有一个外围类对象的引用!

而如果我们继续使用反射类测试一下外围类的所有域和方法,我们实际上也可以发现,外围类outter多了一个 static int access$0(outter)这样一个静态方法,这个方法专门用来返回给内部类自己的int类型的field这个域的值。

java编译就是通过这样一个机制,实现了内部类来访问外围类的私有域。

比如当Inner中的方法这样写:if(field  == 1),其实编译器会翻译为if(access$0(outter))。

不过不得不说sun公司当年这样的设计也确实有一定的风险,如果一个对java编译和java虚拟机足够熟悉的人,甚至可以把在一个自己写的类里用类似于access$0(outter)这种形式去访问外围类中的域。不过java还有很多安全机制,比如基于包的访问权限等,可以帮助弥补这些缺陷。再退一步说,想通过这种手段来访问外部类的私有域来实现一些非法的目的,是需要相当高的技巧和运气的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值