首页 新闻 会员 周边 捐助

关于abstract class,子类对象实例化的问题,请教大家!

0
悬赏园豆:5 [已解决问题] 解决于 2017-01-11 15:54
public abstract class Demo {
    public Demo()
    {
        this.print();
    }
    
    public abstract void print();
}

public class DemoImple extends Demo{
    private int x = 10;
    public DemoImple(int x)
    {
        this.x = x;
    }

    public void print() {
        System.out.println("x=" + this.x);
    }
}

public class CaseDemo09 {
    public static void main(String[] args) {
        new DemoImple(100);
    }

}

这个case里面,最后的结果是:x=0
给出的解释是:通过子类对象来进行实例化。

不清楚的地方:

1、 new DemoImple(100); //这里不是传递了数值100吗?为什么会是0呢 ?
2、之所以有输出,是不是调用了父类,即抽象类Demo的构造方法?实际调用的子类的print() 方法?中间调用机制或是过程是怎样的?

烦请大牛路过解释一下,谢谢了O(∩_∩)O~

问题补充:

鉴于有同学用C#测试了,结果为10,我以为:

1、new DemoImple(100); 这句首先调用了父类的构造方法 Demo(),由于多态,Demo 中实际调用的是子类 DemoImple 中重写过的 print() 方法,而此时 this.x 值为 DemoImple 中的 private int x=10,所以输出为:x=10

2、new DemoImple(100);中将 100 赋值给 this.x 但是并没有输出。

不知道以上对 c# 理解正不正确. 至于 Java ,x = 0,待大牛解答一下..

xuefenhu的主页 xuefenhu | 初学一级 | 园豆:199
提问于:2014-01-21 19:57
< >
分享
最佳答案
1

用java做了下试验,说一下我得到的结论,不过我也不是很确定:

调用子类的构造器的时候,首先会调用父类构造器,所以这个时候x的值还没有变成100;

然后,为什么不是10而是0呢,我在子类构造器中显式调用了super()来调用父类构造器,然后在这个地方断点,发现在调用父类构造器的时候x的值是0,而不是10,所以这个时候我觉得成员变量还没有初始化(这个就是我说的不确定的地方,虽然试验结果证明了我的说法,但没理解原理),

我把我测试的代码贴给你,你拿去测试试一试,

package abstractClass;

abstract class AbstractDemo {
    {
        System.out.println("execute super block");
    }
    static{
        System.out.println("execute static super block");
    }
    
    public AbstractDemo(){
        System.out.println("call super constractor");
        this.print();
    }
    
    public abstract void print();
}

class DemoImpl extends AbstractDemo{
    {
        System.out.println("execute block");
    }
    static{
        System.out.println("execute static block");
    }
    private int x = 10;
    public DemoImpl(int x){
        super();   //断点
        System.out.println("call constractor");
        System.out.println("before init in constractor this.x="+this.x);
        this.x = x;
    }
    
    @Override 
    public void print(){
        System.out.println("this.x="+x);
    }
}

public class TestAbstractDemo{
    public static void main(String[] args) {
        new DemoImpl(100);
    }
}


结果如下:

execute static super block
execute static block
execute super block
call super constractor
this.x=0
execute block
call constractor
before init in constractor this.x=10



收获园豆:5
苍枫露雨 | 小虾三级 |园豆:1027 | 2014-03-19 18:57

刚刚又试了一下,执行完super()之后,执行了初始化this.x,此时this.x才变成了10,然后才执行构造器。

我把结论写了个博客,感兴趣的话可以看看,顺便帮我看看有没有什么问题,:)

http://www.cnblogs.com/chrischennx/p/3612295.html

苍枫露雨 | 园豆:1027 (小虾三级) | 2014-03-19 19:07
其他回答(4)
0

最后结果应该是x=10才对吧。你这是Java吗?Java我不是很了解,反正对于C#来说,x=10,因为首先首先被调用的是抽象类的构造函数,然后这个时候x还是10,当print后才调用DemoImpl的构造函数,这个时候虽然将x设置为100,但是已经没有print了。

ocean | 园豆:824 (小虾三级) | 2014-01-22 08:47

是Java,不过Java 运行结果确实是 x=0,C#环境下,你运行了吗?

支持(0) 反对(0) xuefenhu | 园豆:199 (初学一级) | 2014-01-22 09:11

@疯子也疯狂: 呃,以我对C#的了解,不用运行我也知道肯定是10啊。

支持(0) 反对(0) ocean | 园豆:824 (小虾三级) | 2014-01-22 21:59
0

public class DemoImple extends Demo{
    private int x = 10;
    public DemoImple(int x)
    {
        this.x = x;
    }

    public void print() {
        System.out.println("x=" + this.x);
    }
}
在子类中没有重写抽象类的 print的方法 java中是否有重写关键字??

wolfy | 园豆:2636 (老鸟四级) | 2014-01-22 10:27

java 中函数重写,只要将函数体重写就可以了,没有关键字.源程序中已经进行了重写了.

支持(0) 反对(0) xuefenhu | 园豆:199 (初学一级) | 2014-01-22 10:40

@疯子也疯狂: 我刚才用c#测试了 结果是10

支持(0) 反对(0) wolfy | 园豆:2636 (老鸟四级) | 2014-01-22 10:43

@wolfy: 谢谢帮忙用 c# 测试.

支持(0) 反对(0) xuefenhu | 园豆:199 (初学一级) | 2014-01-22 11:10
0

    这个和类的加载机制有关,在构造子类对象new DemoImpl(100)时,先调用父类的构造方法public Demo() { this.print(); },根据java的运行时多态性,子类对实现了父类的print()方法,此时调用子类的print();

由于构造子类时会先构造父类;而构造父类时,其所用的静态成员和非静态属性是父类的,但非静态方法却是子类的; 
由于构造父类时,子类并未加载;如果此时所调用的非静态方法里有成员,则这个成员是子类的,且非静态属性是默认初始值的。

这里由于子类的x属性并未加载,初始值为0.

要理解这个问题需要清楚类的加载顺序,可以参考这篇文章:http://hi.baidu.com/linyongboole/item/74c32815dbe5c10fd1d66d04

李己铭 | 园豆:205 (菜鸟二级) | 2014-05-18 23:50

学习了.

支持(0) 反对(0) masque | 园豆:210 (菜鸟二级) | 2014-06-26 10:14
0

实例化DemoImple时,执行顺序是:

1、先执行父类的构造方法: public Demo(),里面有print();而现在x还没有值,所以打印“0”;

2、执行本类的构造方法:public DemoImple(int x);为本类中的x赋值为100;此时x为100;但是你没有打印!

 public DemoImple(int x)
    {
        this.x = x;
        this.print();
    }

这样就看到打印的100了

吕展辉 | 园豆:202 (菜鸟二级) | 2014-10-31 19:13
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册