`
unbounder
  • 浏览: 174744 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

java继承扫盲1

    博客分类:
  • java
阅读更多
继承是OOP语言的必备功能,其功能强大,并且又是OO另一个重量级功能——多态——的基础,所以理解继承包括开发平台如何具体实现继承的机制至关重要。 
   
   对于java语言的继承机制本来没有想太多,因为教科书或语言规范都写的很清楚了,大概的:base   class中的public和protected成员会被derived   class自动接收,成为其成员。而base   class中的private和包访问(默认访问级别)成员则不会被继承。你可以在derived   class中直接使用继承到的成员或者覆写(override)它。 
   
   上面这句话理解起来不困难,但很多教科书(反正我一本都没看到)没有谈到在derived   class中对继承的成员的两种不同操作——直接使用和覆写后再使用——jdk是如何实现的。不要小看这个问题,他很重要! 
           在《Think   in   Java,2nd   edition》(侯捷中文版)的第六章有这么一个程序,源代码如下: 
  
//:   c06:Detergent.java  
    
   class   Cleanser   {  
       private   String   s   =   new   String("Cleanser");  
       public   void   append(String   a)   {   s   +=   a;   }  
       public   void   dilute()   {   append("   dilute()");   }  
       public   void   apply()   {   append("   apply()");   }  
       public   void   scrub()   {   append("   scrub()");   }  
       public   void   print()   {   System.out.println(s);   }  
       public   static   void   main(String[]   args)   {  
           Cleanser   x   =   new   Cleanser();  
           x.dilute();   x.apply();   x.scrub();  
           x.print();  
       }  
   }  
    
   public   class   Detergent   extends   Cleanser   {  
       //   Change   a   method:  
       public   void   scrub()   {  
           append("   Detergent.scrub()");  
           super.scrub();   //   Call   base-class   version  
       }  
       //   Add   methods   to   the   interface:  
       public   void   foam()   {   append("   foam()");   }  
       //   Test   the   new   class:  
       public   static   void   main(String[]   args)   {  
           Detergent   x   =   new   Detergent();  
           x.dilute();  
           x.apply();  
           x.scrub();  
           x.foam();  
           x.print();  
           System.out.println("Testing   base   class:");  
           Cleanser.main(args);  
       }  
   }   ///:~  

   这里面,Cleanser类中有一个private实例变量s,五个普通public方法,和一个main()方法。根据规范,除了private实例变量s外,五个普通方法和那个mian()方法都会被Detergent类继承。再来看Detergent类,Detergent类中新添了一个方法 foam(),另外有两个继承的方法被覆写了,一个是scrub()方法,还有一个,千万要注意,继承自Cleanser类的main()方法也被覆写了!不信你可以试验下,注释掉Detergent类中的mian()方法,编译后用java   Detergent执行,照样可以,说明main()方法被继承下来了,不过我又用自己的main()方法覆写了它,这样我就可以执行自己的代码了。 
   
   仔细观察上述代码,不要先用jdk执行它,而是在脑子里想它的执行过程,你会发现,当我们在Detergent的实例中调用直接继承的方法,如 dilute(),   apply()时,他们要调用append()方法,OK没问题,append()方法也是public的,已经被继承了,调用自己的方法这很天经地义,思考上没什么障碍,但,问题出现了,append()方法的实现是要使用String   s,而s是Cleancer的private成员,按规定它是不能被继承的,也就是说在Detergent实例里面根本就没有s这个变量! 
   
   可是,程序是可以编译执行的,没有任何问题。那么问题当然出在我们自己,是我们没有彻底理解jdk对java继承的实现机制! 
   
   经过反复琢磨,反复修改,写测试代码,总算对这个问题有了个比较深入的了解,请大家先看我的结论:jdk把derived   class编译成字节代码时,对直接继承和覆写实现的成员,操作是不同的!对于直接继承的成员,并不把其代码加到derived   class的代码中,但会保留一个引用(我不知道,我自己的理解和设想),用来指向base   class中相应的成员;而对于被覆写过的成员来说,则象对待derived   class中的其他自有成员一样,在分配空间是给他们分配自己的空间,也就是说,在编译后的字节代码中会有这些成员的代码。 
   
   所以,上面的问题就可以解决了。先看看上面的程序执行后的结果: 
   Cleanser   dilute()   apply()   Detergent.scrub()   scrub()   foam() 
   Testing   base   class: 
   Cleanser   dilute()   apply()   scrub() 
   注意,一定要这样执行:java   Detergent,因为Cleanser也有main()方法,你用java   Cleanser,也是能执行的,但那只能执行Cleanser类了。 
   
   这个程序在进行一系列动作之后分别打印了两次String   s的值。第一次是用Detergent类的实例的print()方法打印的,第二次是用Cleanser类的实例的print()方法打印的。对于打印的对象s来说,她只有一个,属于Cleanser类,那为什么Detergent类的方法也能访问到s呢?根据我上面的结论,因为print()方法是直接继承来的,在Detergent类中没有覆写它(也就是说没有把它明示的写出来),所以,这个方法只保留一份,在Cleanser类中,不过,由于 Detergent类是Cleanser类的派生类,所以,在Detergent类中有个引用可以让它访问Cleanser类的print()方法,并且在使用的时候就好像使用自己的方法一样。而执行的时候,其实真正的执行都是在Cleanser类的空间里执行的,只不过执行完后把结果返回到 Detergent类中而已!所以,因为真正的执行是在Cleanser类的实例中执行的,那么String   s就当然可以被访问到啦,所以,结果中的第一行(在Detergent中打印s的内容)的结果其实是Cleanser中的s内容,至于为什么在 Cleanser中打印s却不一样?呵呵,这很简单,因为之前新生成了一个Cleanser实例,不一样的实例,数据当然不一样,不信,你在源代码的最后再添一行:x.print(); 
   结果保证是: 
   Cleanser   dilute()   apply()   Detergent.scrub()   scrub()   foam() 
   Testing   base   class: 
   Cleanser   dilute()   apply()   scrub() 
   Cleanser   dilute()   apply()   Detergent.scrub()   scrub()   foam() 
   
   至此,jdk对java继承的实现机制我已经有了自己的理解了,我认为它就是正确的,你认为呢?
分享到:
评论

相关推荐

    java扫盲初级知识

    1. **JAVA_HOME**: 指向J2SDK的安装路径,例如`C:\j2sdk1.4.2`。 2. **CLASSPATH**: 配置类路径,确保Java虚拟机能正确找到类文件。例如`.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar`。 3. **Path**: 添加J...

    Java 最新面试宝典 java 面试宝典 java 最新面试宝典 Java面试Java 工程师进阶知识完全扫盲

    1.面试官箴言 无论什么行业,实际上在面试之前,我们都会去思考一个问题,究竟什么样的求职者才会获得面试官的青睐?作为求职者,在面试前需要做什么准备,才能应对形形色色的面试官呢?现在竞争如此激烈,如何在一...

    Java 工程师进阶知识完全扫盲

    Java 工程师进阶知识完全扫盲 本文将从 Java 工程师的视角,深入探讨消息队列(Message Queue)技术的知识点,并对面试官的提问进行解答。 一、使用消息队列的原因 面试官:你在系统里用过消息队列吗? 候选人:...

    Java 工程师进阶知识完全扫盲.zip

    1. **Java基础巩固**:熟练掌握Java语法是进阶的基础,包括类、对象、封装、继承、多态等面向对象特性。此外,对异常处理、集合框架(如ArrayList、LinkedList、HashMap、TreeMap等)的深入理解和使用,以及IO流、...

    互联网 Java 工程师进阶知识完全扫盲

    "互联网 Java 工程师进阶知识完全扫盲"是一个全面的学习资源,旨在帮助Java开发者提升技能,掌握在高并发、分布式、高可用、微服务以及海量数据处理等关键领域的专业知识。 首先,我们要讨论的是高并发处理。在...

    JAVA面试题,基础入门知识,学习从扫盲开始

    Java 面试题中涵盖了 Java 的基础知识点,包括继承、多态、数组、列表、运行时异常、线程和同步机制、垃圾回收器、面向对象编程原则、反射、泛型、Java 8 新特性和大文件处理等方面。以下是对这些知识点的详细解释:...

    PCIe扫盲,pcie扫盲系列博文

    本文将对PCIe总线的基础知识进行扫盲,涵盖其物理层结构、中断机制等方面。 首先,PCIe的物理层(PHY Layer),也称为PIPE接口,是PCIe通信的基石。它负责将数据转换为电信号,通过电缆或连接器传输,并在接收端...

    Java 工程师进阶知识完全扫盲.pdf

    Java 工程师进阶知识完全扫盲.pdf 本资源摘要信息涵盖了 Java 工程师进阶知识的多个方面,包括消息队列的使用、优点和缺点、高可用性、消息消费的幂等性、消息队列的顺序性、消息队列的延时和过期失效问题等。 一...

    渗透测试 行业术语扫盲.pdf

    渗透测试 行业术语扫盲-来源-公众号-moonsec

    互联网 Java 工程师进阶知识完全扫盲.rar

    众所周知,Java开发人员的生存环境可谓是与以前大相径庭,以IT行业发展来说,在十几年前的时候,IT行业的技术人才是稀缺的,程序员最初的招聘行情,只要你会敲“holle world”、会点技术,能做出点东西,就能入职...

    hadoop基础知识扫盲

    大数据hadoop基础知识扫盲,初步了解什么是hadoop

    计算机扫盲知识pdf

    1. **计算机基本构成**:介绍计算机硬件组成部分,如中央处理器(CPU)、内存(RAM)、硬盘(HDD/SSD)、显示器、键盘和鼠标等,以及它们各自的作用。 2. **操作系统基础**:讲解操作系统的基本概念,如Windows、...

    Java基础核心总结+面试宝典,涵盖Java面试的方方面

    《Java工程师进阶知识完全扫盲》这份文档可能会深入到一些进阶主题,如JVM调优、Spring框架的应用、微服务架构、数据库设计等,这些都是一个资深Java工程师需要掌握的知识。 最后,《JAVA面试知识点总结》是对前面...

    互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识

    互联网 Java 工程师进阶知识完全扫盲:涵盖高并发、分布式、高可用、微服务、海量数据处理等领域知识。

    Java入门基础.pdf

    * 封装、继承、多态 * 抽象类与接口 * 接口回调、闭包、内部类 * 异常处理 多线程 * 多线程基础 * 线程池 * volatile关键字 * HandlerThread、Callable、Future * Java中的Runnable、Callable、Future、FutureTask...

    PCIe扫盲系列附目录

    文章“PCIe扫盲系列附目录”是对PCIe标准的一个基础介绍,而部分内容主要通过一个Memory Read操作的例子,对PCIe总线的数据传输过程进行了详细说明。 ### PCIe总线的结构 PCIe总线结构主要分为三层:事务层...

Global site tag (gtag.js) - Google Analytics