【Java学习笔记】关于默认值

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

JVM将为类的instance和static变量赋上缺省值(默认值),包括数组array中的每一个元素--而不用再写初始化赋值语句。

切记:局部变量是没有缺省值的,必须手动初始化!并且这一缺省赋值过程是在对象的构造函数调用之前完成的。

我们看下边的程序:

public class Test {
    public static void main(String[] args){
        SubClass subClass = new SubClass();
        System.out.println(subClass.getObj());   
    }
}
class SuperClass {
    public SuperClass() {
        init();
    }
    protected void init() {
    }
}
class SubClass extends SuperClass {
private Object obj;// 如果换成obj = null 呢?
    protected void init() {
        obj = "abcdefg";
    }
    public Object getObj() {
        return obj;
    }
    public void setObj(Object obj) {
        this.obj = obj;
    }
}

这个的输出为abcdefg,而换成obj=null则输出为null。

这个子类覆盖了父类的init()方法。

其实在子类运行构造函数的时候就使用了super()调用父类的构造函数,而在父类的构造函数中调用了init()方法,而此时子类已经有init()方法覆盖了父类的init()方法,所以此时调用的实际上是子类的init()方法.(这也告诉我们,一般不要再构造方法中调用可能被重写的方法,这可能会给程序带来很多问题。)

而修改后却输出null,追寻这个的原因又引出了一个Java初始化顺序的问题:

新建一java对象(上面main方法中new SubClass())时,它的内部初始化顺序为:

1. 父类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

2. 子类静态成员和静态初始化块 ,按在代码中出现的顺序依次执行

3. 父类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

4. 父类构造方法

5. 子类实例成员和实例初始化块 ,按在代码中出现的顺序依次执行

6. 子类构造方法

我们分析一下:

那么在private Object obj;中,依次执行了3(无操作)、4(赋值abcdefg)、5(无操作)、6(无操作)=>输出为abcdefg

那么在private Object obj=null;中,依次执行了3(无操作)、4(赋值abcdefg)、5(修改引用为null)、6(无操作)=>输出为null

这就是add()方法的多态性体现。要是将add()方法的权限修改为private,则两个程序的输出都是null,因为类中所有的private方法都隐式地指定是final的。

 

作者:gnuhpc
出处:http://www.cnblogs.com/gnuhpc/

posted @ 2012-12-17 21:10  gnuhpc  阅读(661)  评论(0编辑  收藏  举报