当前位置: 技术问答>java相关
///////////////一个很简单的问题,只要有道理就有分。不够还可以再加!//////////////////
来源: 互联网 发布时间:2015-10-25
本文导语: 源码:PolyConstructors.java文件 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(in...
源码:PolyConstructors.java文件
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);
}
}
结果是:
java PolyConstructors
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
结果输出第2行为什么不是RoundGlyph.draw(), radius = 1?
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);
}
}
结果是:
java PolyConstructors
Glyph() before draw()
RoundGlyph.draw(), radius = 0
Glyph() after draw()
RoundGlyph.RoundGlyph(), radius = 5
结果输出第2行为什么不是RoundGlyph.draw(), radius = 1?
|
你们看看这段代码:
/*
* @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
/*
* @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
|
我觉得是这样的:
jvm在装入类的时候,并未对变量进行初始化。而在字节代码执行之前进行的初始化,只是调用静态变量和静态初始化器进行初始化,例如,定义 static int radius = 1;则运行结果就与现在的不同了,这是因为radius为static,所以就先初始化了。
而上面这段代码,是先执行父类Glyph的构造方法,并未涉及到对radius的初始化,所以此时它的值还是默认的初始值0。
也可以这样理解:在字节代码中的执行顺序,Glyph()是在int radius = 1所对应的字节代码之前的。
一家之言,仅供参考。
jvm在装入类的时候,并未对变量进行初始化。而在字节代码执行之前进行的初始化,只是调用静态变量和静态初始化器进行初始化,例如,定义 static int radius = 1;则运行结果就与现在的不同了,这是因为radius为static,所以就先初始化了。
而上面这段代码,是先执行父类Glyph的构造方法,并未涉及到对radius的初始化,所以此时它的值还是默认的初始值0。
也可以这样理解:在字节代码中的执行顺序,Glyph()是在int radius = 1所对应的字节代码之前的。
一家之言,仅供参考。
|
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) {
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。就这么简单,不知道我说的你明白否???
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。就这么简单,不知道我说的你明白否???
|
我看了一下你的原代码:
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,这样才能调用类的属性。
|
那是因为你将Glyph定义为抽象类,抽象类的机制就是:使用它的时候必须要继承抽象类后才能被实例化。而原先的构造器也会被继承下来。也就是说,在你的RoundGlyph类里的构造器是在Glyph里定义的Glyph(),所以你在main()里实例化的RoundGlyph类时应首先执行RoundGlyph的构造器,也就是在Glyph里定义的Glyph()方法(其中的draw()方法已经在RoundGlyph类里面定义了,应此你可以把抽象类机制中的继承看成是将抽象类完善的结果)RoundGlyph类实例化的时候已经将你在Glyph()中所写的构造器部分执行过了,形成了输出的前三行,而你在RoundGlyph类中初始化的radius=1并没有被用到。另外,由于你在实例化的时候,构造器中并没有初始化radius,java编译器就自动给他初始化为“0”了。
|
调用过程是:
父类的变量定义和初始化
父类的构造方法
子类的变量定义和初始化
子类的构造方法
如果在父类的构造中调用需要在子类中初始化的变量时,实际上那时候这个变量还没有初始化。对于 int 型来说,结果就是 0
父类的变量定义和初始化
父类的构造方法
子类的变量定义和初始化
子类的构造方法
如果在父类的构造中调用需要在子类中初始化的变量时,实际上那时候这个变量还没有初始化。对于 int 型来说,结果就是 0
|
楼上几位说的都有道理,不知 Iforgot(清风雨)有什么观点?大家共同研究!
|
先父类初始化,再子类初始化
在调用父类构造为函数时,i没有被付初值1,而只是int型默认初始化为0
在调用父类构造为函数时,i没有被付初值1,而只是int型默认初始化为0
|
在Thinking in Java里面有详细的叙述,当你初始化class RoundGlyph的
时候,由于关键字extends的存在,知道有class Glyph的存在,于是载入
class Glyph。在实例化class Glyph之前,因为有抽象方法的存在
于是调用子类的方法,这时候,还没有给i赋值,所以是0
后面都很简单,我就不说了
时候,由于关键字extends的存在,知道有class Glyph的存在,于是载入
class Glyph。在实例化class Glyph之前,因为有抽象方法的存在
于是调用子类的方法,这时候,还没有给i赋值,所以是0
后面都很简单,我就不说了
|
声明的时候还没有分配内存空间
|
严重同意编程狂人的观点,大家知道执行顺序就行了。先从理论上来分析阿。哈哈
|
只是你不知道代码的执行顺序摆了,懂得了执行的顺序就知道结果了,
这些在SCJP上说得很清楚,你多看看SCJP就OK了。
这些在SCJP上说得很清楚,你多看看SCJP就OK了。
|
这是一个多态,继承和构造顺序的问题,充分体现了OOP的特点..
public static void main(String[] args) {
new RoundGlyph(5);
}
中1首先构在父类
2执行父类的构造函数,输出第一行,执行draw(),由于是在子类中写的main函数,并且父类是抽象函数,所以执行子类的draw的具体方法,但此时还没轮到子类RoundGlyph去给自己的成员变量radius去赋值为1,所以用默认的出使值0,就有了那个结果,让后在执行下一行输出
3让后构造子类RoundGlyph,此时就为1了..
具体再说里面还有好多细节...
public static void main(String[] args) {
new RoundGlyph(5);
}
中1首先构在父类
2执行父类的构造函数,输出第一行,执行draw(),由于是在子类中写的main函数,并且父类是抽象函数,所以执行子类的draw的具体方法,但此时还没轮到子类RoundGlyph去给自己的成员变量radius去赋值为1,所以用默认的出使值0,就有了那个结果,让后在执行下一行输出
3让后构造子类RoundGlyph,此时就为1了..
具体再说里面还有好多细节...
|
因为super()语句默认在子构造函数的第一行,那时候还没执行
radius = r;
radius没有系统初始为0
radius = r;
radius没有系统初始为0
|
不知道你懂了没有。如果你还不明白,可给我发邮件:qasdew765@sohu.com
|
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);
}
}再补充:
其实上边这段代码跟下面是一样的效果:
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);
}
}
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);
}
}
|
BenLadeng5225(Ladeng) 的话听起来是有点道理但是加了this还是和原来的结果一样
|
up
|
up
|
我也要些当晚饭!