当前位置:  技术问答>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?

|
你们看看这段代码:

/*
 * @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所对应的字节代码之前的。
一家之言,仅供参考。

|
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 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

|
楼上几位说的都有道理,不知  Iforgot(清风雨)有什么观点?大家共同研究!

|
先父类初始化,再子类初始化
在调用父类构造为函数时,i没有被付初值1,而只是int型默认初始化为0

|
在Thinking in Java里面有详细的叙述,当你初始化class RoundGlyph的
时候,由于关键字extends的存在,知道有class Glyph的存在,于是载入
class Glyph。在实例化class Glyph之前,因为有抽象方法的存在
于是调用子类的方法,这时候,还没有给i赋值,所以是0
后面都很简单,我就不说了

|
声明的时候还没有分配内存空间

|
严重同意编程狂人的观点,大家知道执行顺序就行了。先从理论上来分析阿。哈哈

|
只是你不知道代码的执行顺序摆了,懂得了执行的顺序就知道结果了,
这些在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了..
具体再说里面还有好多细节...


|
因为super()语句默认在子构造函数的第一行,那时候还没执行
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);
}
}


|
BenLadeng5225(Ladeng) 的话听起来是有点道理但是加了this还是和原来的结果一样

|
up

|
up

|
我也要些当晚饭!

    
 
 

您可能感兴趣的文章:

  • 新手问题给十分不知够不够,不够再给。
  • 一个基本问题,但需要高手指点。。水平不够者勿误导
  • 紧急求救 我用freebsd通过smbfs连接win2000的一些问题 (分不够可加)
  • 关于crontab问题(若分不够,可加)
  • 硬盘空间不够的问题
  • JB5安装问题,分不够可以在加!
  • 关于截分文件的问题?分不够可再加
  • 关于red hat 8.0的问题,不够再给,(在线等)
  • 关于写文件报磁盘空间不够的错的问题
  • 刷新率问题!分不够可以再加!在线等待!!
  • 急!急!100分问题求解(不够可加)输入中文到oracle数据库乱码的问题
  • 使用shell在文本文件中进行字符串搜索问题?shell高手请进,分不够可以再加
  • 硬盘空间不够的问题!
  • gtk+GUI问题,100分!!!不够再开贴给分!!!在线等!!!!!!!跟贴就有分!!!!!
  • 字符集的问题,请大家帮忙了!分不够再加
  • 各位高手请指点:cvs的安装问题!!!在线等待,分不够可再加!!
  • 请教这里的高手一个巨麻烦的问题,分不够另加。
  • JRE1.3.1的字体问题,分不够可再加。
  • 高分请教输入法的问题,分不够可以再给.
  • c 语言和shell 混合编程问题?(分不够可以另加)
  •  
    本站(WWW.)旨在分享和传播互联网科技相关的资讯和技术,将尽最大努力为读者提供更好的信息聚合和浏览方式。
    本站(WWW.)站内文章除注明原创外,均为转载、整理或搜集自网络。欢迎任何形式的转载,转载请注明出处。












  • 相关文章推荐
  • 菜鸟问题:请问在哪里可以下载Gcc和Glade还有Glade怎么安装?还有在KDE环境下可以用Glade吗?Thanks!
  • 一个想不明白的问题,为什么在windows中可以ping 通域名,但在linux却不可以 ??
  • 生产者消费者问题为什么不可以共用一个信号量,如果这个信号量可以设置取值固定为0到N,即当信号量取值为N的时候阻塞进程,是否也可以?
  • linux修改用户密码出现问题,当密码修改为2011042109时,我可以用2011042108或2011042112等只要前8位一样后面任意输入都可以登录
  • 哪位朋友正在使用红旗的桌面版3.0???可以不可以进来讨论几个问题呢???
  • redhat linux7.3下面ping域名不通,ping ip可以!怎么回事啊!直接访问域名也不行,访问ip可以!什么问题啊
  • 网络问题: 两台相同的Linux主机a,b;从a 可以telnet 到 b ,从b 可以ping 通 a ,但从b不能telnet a
  • 装完fc1后,设置后可以上网了,网页,链接都可以,可是却不能收邮件,不能登陆,为什么,还有一个小问题,装完系统后,有什么特别好用的
  • 你是否可以回答Socket的问题?数据先后问题
  • 关于连接池 connection pool!!!!!!(37分的问题,不够还可以加分!要多少分可以自己提)
  • 用Jbuilder3 遇到问题不能运行把可疑代码注掉后可以运行但是重新使用可疑代码时又可以运行了多次重复都是如此
  • Linux下显示问题。暂时没分了,如果能解决问题,我可以去换分来给你。
  • 一个初级问题.用jbuilder可以编jsp吗?
  • 问一个crontab中不能运行手动可以运行的问题
  • 用Java可以解决这个问题吗?急!!!
  • 请问这里可以讨论MINIX的问题吗?
  • 50分!两个简单问题。.jsp文件中可以插入javascript代码吗?是否可以通过某框架中链接的target属性将.jsp文件在另一框架中显示?
  • (在线等)这样的window 和linux问题可以实现吗?
  • gcc新手新问题,在windows下有可以编译??
  • 一个初学者问题:看6.2的书,使用7.0的Redhat是否可以?
  • 修改配置真正解决php文件上传大小限制问题(nginx+php)
  • 简单问题简单问题简单问题简单问题
  • 修改配置真正解决php文件上传大小限制问题(apache+php)
  • 小问题,急问题,重大问题!!!
  • sharepoint 2010中item.Update()和item.SystemUpdate 修改数据版本问题解决
  • 弱弱的一问,linux下的中文问题及网络问题,分不是问题
  • 八个问题帮你快速了解Docker
  • 请教两个小问题:一个cgywin下使用vi的问题,另一个socket的问题
  • 错误:将'const x'作为'x'的'this'实参时丢弃了类型限定问题解决
  • 网页的编码问题!或者java的编码问题,由此引出一条解决中文问题的思路
  • nginx Windows版相关问题及使用说明


  • 站内导航:


    特别声明:169IT网站部分信息来自互联网,如果侵犯您的权利,请及时告知,本站将立即删除!

    ©2012-2021,,E-mail:www_#163.com(请将#改为@)

    浙ICP备11055608号-3