读书人

JVM装载种的顺序

发布时间: 2012-12-24 10:43:14 作者: rapoo

JVM装载类的顺序

这几天看了下j2se基础,看到这个题目

class B {private int radius = 10;public void draw() {        System.out.println("B.draw(), radius = " + radius);}public B() {        System.out.println("B constructor");        draw();}}public class A extends B {private int radius = 1;public void draw() {        System.out.println("A.draw(), radius = " + radius);}public A(int radius) {        this.radius = radius;        System.out.println("A constructor");}public static void main(String[] args) {        A a = new A(5);}}结果是B constructorA.draw(), radius = 0A constructor

?首先是JVM装载类,如果有基类,则先装载基类,直到继承体系的根--Object,在装载类的时候会初始化所有static定义的成员变量;如果碰到有通过new来实例化的代码,则先为该类分配内存空间,所有的对象成员变量都赋予初值(所有基础数据类型都是赋值为0,对象类型都是null),然后执行构造方法,同样,会根据继承体系从根开始调用构造方法,调用每个类的构造方法时都会生成一个实例,会执行成员变量的初始化操作。

这里:当执行到A的构造方法时

public A(int radius) {this.radius = radius;System.out.println("A constructor");}

?先执行父类B的构造方法,此时A的成员变量都没有初始化,全部是默认的0,在B中调用draw时,根据运行时动态绑定,会执行A的draw()方法,所以打印的radius为0,执行完B的构造方法之后,才执行A的成员变量初始化,radius=1,然后再执行构造方法中的代码,此时A中的radius才被赋值为5。

?

把A(int radius)改成这样:public A(int radius) { System.out.println("radius = " + radius);this.radius = radius; System.out.println("A constructor"); }那么输出应该是B constructorA.draw(), radius = 0radius =1A constructor可是输出确是B constructorA.draw(), radius = 0radius =5A constructor

?改成这样的话,当执行System.out.println("radius = " + radius); 这句话的时候,这里的radius的值是指形参的值(此时的radius不是指的A中的radius,而是把离他最近的radius的值赋给他),如果你要看A中的radius的值的话,应该使用this.radius,这样的话它的值才是1。

?

A(int radius){System.out.println("radius = " + radius); this.radius = radius; System.out.println("A constructor");}
radius会使A中定义的radius在这个构造函数中失效(即被形参作用域覆盖)。要是把第一条输出语句中的radius改为this.radius就会输出1了。

读书人网 >编程

热点推荐