我看了一下你的原代码:
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}class RoundGlyph extends Glyph {
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 PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
在你的MAIN方法中,有new RoundGlyph(5);jvm在执行这条语句的时候,在执行自己的构造方法RoundGlyph(int r) {}之前,由于继承关系先执行父类的无参数的构造方法打印出第一条语句Glyph() before draw(),在调用draw()方法,打印出RoundGlyph.draw(), radius = 0,然后再执行 System.out.println("Glyph() after draw()");打印出Glyph() after draw(),最后调用自身的RoundGlyph(int r){}打印出 RoundGlyph.RoundGlyph(), radius = 5。这就是程序的整个流程。 你问结果输出第2行为什么不是RoundGlyph.draw(), radius = 1?我们可以这样认为:这里的radius是一个局部变量,如果想让它为1的话,必须是
this.radius,这样才能调用类的属性。
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}class RoundGlyph extends Glyph {
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 PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
在你的MAIN方法中,有new RoundGlyph(5);jvm在执行这条语句的时候,在执行自己的构造方法RoundGlyph(int r) {}之前,由于继承关系先执行父类的无参数的构造方法打印出第一条语句Glyph() before draw(),在调用draw()方法,打印出RoundGlyph.draw(), radius = 0,然后再执行 System.out.println("Glyph() after draw()");打印出Glyph() after draw(),最后调用自身的RoundGlyph(int r){}打印出 RoundGlyph.RoundGlyph(), radius = 5。这就是程序的整个流程。 你问结果输出第2行为什么不是RoundGlyph.draw(), radius = 1?我们可以这样认为:这里的radius是一个局部变量,如果想让它为1的话,必须是
this.radius,这样才能调用类的属性。
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}class RoundGlyph extends Glyph {
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 PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}再补充:
其实上边这段代码跟下面是一样的效果:
abstract class Glyph {
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}class RoundGlyph extends Glyph {
int radius = 1;
RoundGlyph(){
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
} RoundGlyph(int r) {
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = "+ radius);
}
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}public class PolyConstructors {
public static void main(String[] args) {
new RoundGlyph(5);
}
}
jvm在装入类的时候,并未对变量进行初始化。而在字节代码执行之前进行的初始化,只是调用静态变量和静态初始化器进行初始化,例如,定义 static int radius = 1;则运行结果就与现在的不同了,这是因为radius为static,所以就先初始化了。
而上面这段代码,是先执行父类Glyph的构造方法,并未涉及到对radius的初始化,所以此时它的值还是默认的初始值0。
也可以这样理解:在字节代码中的执行顺序,Glyph()是在int radius = 1所对应的字节代码之前的。
一家之言,仅供参考。
父类的变量定义和初始化
父类的构造方法
子类的变量定义和初始化
子类的构造方法如果在父类的构造中调用需要在子类中初始化的变量时,实际上那时候这个变量还没有初始化。对于 int 型来说,结果就是 0
* @file Test.java
* @author Fancy
*/class TestBase { int b = Toolkit.test("TestBase"); void test() {
} TestBase() {
System.out.println("TestBase Constructor");
test();
}}public class Test extends TestBase { int x = Toolkit.test("Test"); void test() {
System.out.println("Test.test, x = " + x);
} Test() {
System.out.println("Test Constructor");
} public static void main(String[] args) {
new Test();
}
}
class Toolkit {
static int test(String s) {
System.out.println("Toolkit.test(), s = " + s);
return 1;
}
}
运行结果Toolkit.test(), s = TestBase
TestBase Constructor
Test.test, x = 0
Toolkit.test(), s = Test
Test Constructor这就说明了我上面的说法,再抄一次:调用过程是:
父类的变量定义和初始化
父类的构造方法
子类的变量定义和初始化
子类的构造方法如果在父类的构造中调用需要在子类中初始化的变量时,实际上那时候这个变量还没有初始化。对于 int 型来说,结果就是 0
在调用父类构造为函数时,i没有被付初值1,而只是int型默认初始化为0
声明同时付值实际上实在构造器调用完毕付的值呢?猜想,我回去试试看。
时候,由于关键字extends的存在,知道有class Glyph的存在,于是载入
class Glyph。在实例化class Glyph之前,因为有抽象方法的存在
于是调用子类的方法,这时候,还没有给i赋值,所以是0
后面都很简单,我就不说了
new对象时,解析父类并调用相应的构造器。也就是说构造最上层父类对象属性,第2层父类对象属性,...最后是本对象属性,构造出对象。但是在构造父类对象(属性)时他调用本对象函数使用本对象的局部变量,但那时还没解析啊,或者算解析了,为什么不是一并负值呢?尽请指教,错误和思路不当之处请指正。:)
总觉得应该声明和付值一起才是,这里却不是这样,难到是解析了所有的声明后才付值?我也去试试看。要是被也推翻了,那就不知怎么解释了。
abstract void draw();
Glyph() {
System.out.println("Glyph() before draw()");
draw();
System.out.println("Glyph() after draw()");
}
}class RoundGlyph extends Glyph {
int radius = 1;
RoundGlyph(int r) {
draw();//这里调用draw,你看看输出就有启发了。
radius = r;
System.out.println("RoundGlyph.RoundGlyph(), radius = "+ radius);
}
void draw() {
System.out.println("RoundGlyph.draw(), radius = " + radius);
}
}public class PolyConstructors {
public static void main(String[] args) {
RoundGlyph a= new RoundGlyph(5);
}
}
第2行没有输出 radius=1,是因为,draw是在父类里面调用的,这时int radius = 1;还没有被初始化,而int型的变量在未被初始化时,默认值是零,假如你在RoundGlyph 里面调用,就不一样了,因为当你执行到RoundGlyph 类里面是,静态变量和成员变量都被初始化了,说仪输出为1。就这么简单,不知道我说的你明白否???
这些在SCJP上说得很清楚,你多看看SCJP就OK了。
public static void main(String[] args) {
new RoundGlyph(5);
}
中1首先构在父类
2执行父类的构造函数,输出第一行,执行draw(),由于是在子类中写的main函数,并且父类是抽象函数,所以执行子类的draw的具体方法,但此时还没轮到子类RoundGlyph去给自己的成员变量radius去赋值为1,所以用默认的出使值0,就有了那个结果,让后在执行下一行输出
3让后构造子类RoundGlyph,此时就为1了..
具体再说里面还有好多细节...
radius = r;
radius没有系统初始为0