Java基础

 在编程的江湖上,总有这样一群人,他们赋有敏锐的嗅觉,能犀利地嗅出代码的bad smell.我们暂且称他们为“犀利哥”。有江湖的地方,总有犀利哥的传说。
 昨日编程碰到一问题,苦苦鏖战2个时辰,没有结果。无奈之下请犀利哥出山,不到一根烟的功夫,问题解决,我第一次见识了犀利哥的魅力!
 用一个demo来模拟我的问题,有3个类:
 第一个:Cheese类:

 class Cheese {  }
 


第二个:Father类:
public class Father {
    public Father() {
        getCheese();
    }
     protected Cheese getCheese(){
            return null;
        }
}

public class Father {
    public Father() {
        getCheese();
    }
     protected Cheese getCheese(){
            return null;
        }
}
 

第三个:Son类:

public class Son extends Father{
    private Cheese cheese=null;//-----1-----关键就在这!
    //private Cheese cheese;   //-----2-----
    public Son() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Cheese getCheese(){
        if(cheese==null){
            cheese=new Cheese();
        }
        return cheese;
    }
    public static void main(String[] args) {
        Son son=new Son();
        Cheese ch=son.getCheese();//-------3--------
        System.out.println(ch.toString());
    }
}
 


我们把Son类中的标注的1语句换成2语句,会发现在debug状态下,最后打印的Cheese对象的地址是不一样的。谁动了我的奶酪?原因何在?
原因分析:当是语句1时,它执行的逻辑是这样的:首先调用子类Son的构造器,然后调用父类Father的构造器,根据多态机制,在这个构造器里面调用子类的
getCheese()方法,得到一个Cheese对象。然后退出父类构造器,进而退出子类构造器,关键是下面接下来又执行了子类实例变量cheese的初始化,导致了Cheese对象又为null。
这样再执行3语句的时候,又new了一个新的Cheese对象。结果导致上面的结果。
           当执行语句2时,执行的逻辑是:首先调用子类Son的构造器,然后调用父类Father的构造器,根据多态机制,在这个构造器里面调用子类的
getCheese()方法,得到一个Cheese对象。然后退出父类构造器,进而退出子类构造器,因为子类实例变量只是声明,没有初始化,所以执行语句3的时候,Cheese对象仍为原来的对象。

一点思考:为什么在运行环境下 地址却是一样的???
撰此小文,旨在提醒各位不要犯我这样的低级错误。
哦,最后忘记了介绍犀利哥啦,他就是集美貌与才华于一身的我们开发经理(名字就不说了)。

你可能感兴趣的:(java,编程)