当前位置:编程学习 > JAVA >>

java 多态陷阱

照原来,先考考大家,在不运行的情况下说出下面程序的输出结果(请先注意这是关于多态的啊)

package acm; 
 
//例一 
class Test extends Main { 
    private void write() { 
        System.out.println("Test"); 
    } 

 
public class Main { 
    private void write() { 
        System.out.println("Main"); 
    } 
 
    public static void main(String[] args) { 
        Main main = new Test(); 
        main.write(); 
    } 

 
//我们所期望的是 输出Test,但由于private方法被自动认为是final方法。而且对导出的类是屏蔽的。因此 
//在这种情况下,Test下的write就是一个全新的方法,Main中的方法在子类中方法不可见,因此也不能被重载 
//只有非private 方法才可以被覆盖 。因此结果是:Main 
 
//例二 
class Super { 
    public int field = 0; 
 
    public int getField() { 
        return field; 
    } 

 
class Sub extends Super { 
    public int field = 1; 
 
    public int getField() { 
        return field; 
    } 
 
    public int getSuperField() { 
        return super.field; 
    } 

 
public class Main { 
    public static void main(String[] args) { 
        Super sup = new Sub(); 
        System.out.println("sup.field= " + sup.field + ",sup.getField()=" 
                + sup.getField()); 
        Sub sub = new Sub(); 
        System.out.println("sub.field= " + sub.field + ",sub.getField()=" 
                + sub.getField() + ",sub.getSuperField()=" 
                + sub.getSuperField()); 
 
    } 

 
//当Sub对象转型为Super引用时,任何域访问操作都将由编译器解析,因此不是多态的。 
//在本例中,为Super.field和Sub.field分配了不同的存储空间。这样,Sub实际上包含两个称为field的域: 
//它自己的和它从Super处得到的。结果: 
//sup.field= 0,sup.getField()=1 
//sub.field= 1,sub.getField()=1,sub.getSuperField()=0 
 
 
//例三 
class Glyph { 
    void draw() { 
        System.out.println("Glyph.draw()"); 
    } 
 
    Glyph() { 
        System.out.println("Glyph() before draw()"); 
        draw(); 
        System.out.println("Glyph() after draw()"); 
    } 
 

 
class RoundGlyph extends Glyph { 
    private int radius = 1; 
 
    RoundGlyph(int r) { 
        radius = r; 
        System.out.println("RoundGlyph.RoundGlyph(),radius=" + radius); 
    } 
 
    void draw() { 
        System.out.println("RoundGlyph.draw(),radius=" + radius); 
    } 

 
public class Main { 
    public static void main(String[] args) { 
        new RoundGlyph(5); 
    } 

 
//当Glyph 的构建器调用draw()时,radius 的值甚至不是默认的初始值1,而是 0。 
//上一篇文章的所述初始化顺序是不全面的,实际过程是这样的:  
//(1) 在采取其他任何操作之前,为对象分配的存储空间初始化成二进制零。  
//(2) 调用基础类构建器。此时,被覆盖的draw()方法会得到调用(的确是在RoundGlyph构建器调用之前), 
//此时会发现radius的值为 0,这是由于步骤(1)造成的。  
//(3) 按照原先声明的顺序调用成员初始化代码。  
//(4) 调用衍生类构建器的主体。  
//结果: 
//Glyph() before draw() 
// RoundGlyph.draw(),radius=0 
// Glyph() after draw() 
// RoundGlyph.RoundGlyph(),radius=5 
以上均由近期读Thinking in Java所得

摘自 一路向北

补充:软件开发 , Java ,
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,