赛迪网 > IT技术 Java > (最新更新)Java基础
  IT资讯搜索
 
IT产品搜索
[程序开发][网管世界][网络安全][数据库技术]
[操作系统][嘉宾聊天·在线访谈][活动集锦]
[精彩专题][Symantec专区][订阅IT技术周刊]
[开发论坛][网管论坛][安全论坛][数据库论坛]
[操作系统论坛][Sybase专区][IBM dW技术专区]
[病毒求助][病毒与漏洞播报][文档·源码下载]

内部类的一个例子展示java的可访问特性

发布时间:2007.11.29 05:02     来源:赛迪网技术社区    作者:执木

java的访问修改符(access modifier)包括:Default-Access、public、private、protected四种。并不是所有的情况都可以使用全部四种访问修改符,有的情况下使用某些访问修改符是没有意义的,例如:如果一个类不是内部类,则不能使用private作为该类的访问修改符,编译下面的代码: private class test { ... } jdk编译器将给出“modifier private not allowed here”错误提示。因为private特性只能由定义它的那个类使用,如果上面的代码通过编译,则不会有任何情况可以使用test 类,那么也就不会有任何意义。 如果一个类没有定义任何构造函数,则编译器将生成一个缺省的构造函数,该构造函数的访问修改符和类的访问修改符相同,例如: class test将生成test()构造函数 public class test将生成public test()构造函数。在使用内部类的情况,上述的特性将使编译器表现出一个特别现象。需要说明的是,下面的例子仅针对 Windows系统下jdk编译器,作者并没有尝试使用其他的编译器的情况。但由于java编译器生成的是class 文件这种中间形式的代码,所以下面的讨论应该适用于任何符合java标准的编译器。编译下面的代码: public class Wrapper { private class InnerClass {} private void testInnerClass() { InnerClass inner = new InnerClass(); } public static void main(String[] args) { Wrapper wrapper = new Wrapper(); wrapper.testInnerClass(); } } 将产生三个class文件:Wrapper、Wrapper$InnerClass和Wrapper$1。对于前两个文件,了解内部类的读者都会理解,但第三个类Wrapper$1的作用是什么呢?使用java的反射机制,或者使用javap反汇编器,将发现Wrapper$1类没有任何成员变量和方法,而Wrapper$InnerClass则除了有一个private Wrapper$InnerClass()构造方法外,还有一个 Wrapper$InnerClass(Wrapper$1)构造方法,使用javap,你将发现Wrapper$InnerClass(Wrapper$1) 并没有使用Wrapper$1类型的参数,而只是直接调用了private Wrapper$InnerClass()。如果读者仔细思考一下创建一个新的类实例的过程,大概已经明白了产生上述现象的原因:当程序试图创建一个Wrapper$InnerClass的类实例时,却不能使用其缺省的构造函数,因为 Wrapper$InnerClass()是private的,不能由外部使用。因此编译器不得不再生成一个可访问的构造函数,由于这里只有Wrapper类的private void testInnerClass()方法使用了 new InnerClass(),所以编译器只(需)为这个新的构造函数生成了Default-Access的访问修改符。同时,为了和已有的缺省构造函数有所区别,就加入了一个Wrapper$1类型的参数,为此,编译器还要生成一个Wrapper$1类。 为了更简单,(也许)更清晰的看到编译器生成的class代码工作的原理,读者可以使用java反编译器,来看看class反编译后生成的java源程序,下面是作者使用Jad反编译后生成的Wrapper类的代码: // Decompiled by Jad v1.5.7d. Copyright 2000 Pavel Kouznetsov. // Jad home page: http://www.geocities.com/SiliconValley/Bridge/8617/jad.html // Decompiler options: packimports(3) // Source File Name: Wrapper.java public class Wrapper { private class InnerClass { private InnerClass() { } InnerClass(_cls1 _pcls1) { this(); } } public Wrapper() { } private void testInnerClass() { InnerClass innerclass = new InnerClass(null); } public static void main(String args[]) { Wrapper wrapper = new Wrapper(); wrapper.testInnerClass(); } // Unreferenced inner classes: /* anonymous class */ class _cls1 { } } 显然,Wrapper$1类不会有任何实际的作用。那么为什么编译器一定要生成Wrapper$1类,而不使用随便一个基本类型(例如byte)来作为占位符呢?我想,大概是因为使用Wrapper$1可以使用更少的内存吧,因为一个空类是不会占用任何内存的(Wrapper$1类没有任何成员变量,也就不会需要任何指向它的指针变量,事实上,即使删除Wrapper$1.class文件,也不会影响程序运行,jvm将不会给出任何错误提示。),而任何一个可以有实际值的参数都会要求开辟一些内存来存放它。那么java的编译器不会做优化吗?问题是java编译器最终产生的只是class代码,在class代码的层次,无法向虚拟机表达这样的优化。而java虚拟机恐怕也不宜加入这种优化特性,所以sun就采用了现在的这种解决方法。需要说明的是,这只是我的猜测,由于我没有详细的阅读过jvm的全部文档,所以不能确定。

   (责任编辑:包春林)


[ 发表评论 ] 字体[  ] [ 打印 ] [ 进入博客 ] [ 进入论坛 ]  [ 推荐给朋友 ]
  相关文章
· 如何在JBuilder2007中配置MyEclipse (11-28) · 开发JAVA编程中字符串分割的两种方法 (11-28)
· 超线程多核心下Java多线程编程彻底分析 (11-28) · Java程序多进程运行模式的详细实例分析 (11-28)
· JAVA高级:Java中限时线程回调方式的实现 (11-28) · 框架不是框框--应用框架的基本思想 (11-28)
· 设计模式:如何用Java动态代理实现AOP (11-28) · JAVA基础:详细介绍什么是Java的虚拟机 (11-28)
· Java进阶:Java中的类装载器和命名空间 (11-28) · Java语言中的ClassLoader与Package机制 (11-28)
  客户需求反馈表
* 姓  名:
更多资料  了解方案  认识厂商
* 单位名称:
* 联系电话:
* 电子邮件:
  赛迪推荐  
  手机·资费 ·新品·导购·评测·手机资费·宽带
手机搜索  诺基亚 N73 MOTO Z6
  IT产品 ·笔记本·台式机·服务器·打印·投影
IT产品搜索 
  IT技术 ·开发·网管·安全·数据库·操作系统
  信息化 ·热点·专题·访谈·周刊·方案案例
· 工信部“三定”公布 总编制731名设24司局
· 北京发电子商务监管意见 营利性网店须办照
· 直播 08中国城市信息化高峰论坛 案例点评
· 烽火网络校园解决方案 移民安置信息管理系统
  IT博客 ·曾剑秋·项立刚·Java学习·网管
  IT技术论坛 ·开发·网管·安全·数据库·系统