求助,如何解释这段代码?

Vurteon 2014-03-26 06:53:25

public class Problem {
public static void main(String[] args) {
//创建子类对象
new extendsBase();
}
}

class Base{
public Base(){
test();
}
public void test(){
System.out.println("Base!");
}
}

//继承Base,重写test方法
class extendsBase extends Base{
@Override
public void test() {
System.out.println("Why????");
}
}


求解释,为什么会是输出Why???。可以从高层分析,也可以从内存方面来分析。。
...全文
549 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
lliiqiang 2014-06-24
  • 打赏
  • 举报
回复
方法被覆盖了啊。有些方法应该在构造函数完成之前不能被调用.属性也一样. 其实什么好名誉都是次要的,要的是利益
yuhouqingchen_2648 2014-06-23
  • 打赏
  • 举报
回复
每一个对象都有自己的方法表,由于子类继承父类,所以在new子类对象的时候,子类默认构造器会调用父类的无参构造器。 由于子类重写了父类的test方法,所以子类的方法表中存的是重写之后的test方法的地址,所以调用子类重写之后的test方法
机器学习之禅 2014-03-27
  • 打赏
  • 举报
回复
重载的函数与原函数完全一致,是覆盖了。而且你创建的又是继承类的对象,所以它就直接调用继承类的函数。
Vurteon 2014-03-27
  • 打赏
  • 举报
回复
引用 13 楼 u013652613 的回复:
多态 飘过
多态的范围很广,详细可以参考这篇文章 http://developer.51cto.com/art/201009/225990_all.htm 这样回答太过于。。。
Vurteon 2014-03-27
  • 打赏
  • 举报
回复
引用 12 楼 foolishdault 的回复:
子类构造时会先调用父类的构造方法,当然是调用了父类的test()方法
你先把这个程序运行一下看看结果再考虑这个问题
油头小兄妹 2014-03-27
  • 打赏
  • 举报
回复
首先是子类的构造函数继承了父类的,所以可以调用test方法,然后因为子类重写了父类的test的方法,new子类对象的时候,会调用子类test方法,实现多态,所以打印的是why??
灰太狼A代 2014-03-27
  • 打赏
  • 举报
回复
多态 飘过
树哥 2014-03-27
  • 打赏
  • 举报
回复
引用 22 楼 Vurteon 的回复:
[quote=引用 21 楼 slowwind2007_lishu 的回复:] Test是在构造函数里调用的,此时对象的虚函数表还没有建立起来,即对象还没有完全构造完,此时调用此对象自己的函数,即ExtendBase的Test函数。
Java的表区具体的我现在还不太明白,但是你说这个即使是在C++里面也是有问题的。 你可以参考下面的文章。 http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx[/quote] ---------------------------------------------------------------------------------------------------------------------- 我的意思是对象构造函数里最好不要有虚函数。因为构造期间,虚函数表是没有建立起来的,对象只能调用自己的函数,而不是虚函数表里的函数指针。
Vurteon 2014-03-27
  • 打赏
  • 举报
回复
谢谢大家,其实我的主要目的是想了解一些这方面的原理。待我彻底解决了此问题再来结贴。
sunbo624 2014-03-27
  • 打赏
  • 举报
回复
默认的构造函数 就是 类名() { super(); }
yanjingrong 2014-03-27
  • 打赏
  • 举报
回复
应为调用了父类Base 的构造方法,而Base 的构造方法有test()方法,test方法被子类复写,改成了System.out.println("Why????");,所以输出why了
xiejin90314 2014-03-27
  • 打赏
  • 举报
回复
这个没啥好说的。。。
路边一青蛙 2014-03-27
  • 打赏
  • 举报
回复

    public class Problem {
        public static void Main(String[] args) {
            //创建子类对象
            new extendsBase();
            Console.ReadLine();
        }
    }
 
    class Base{
        public Base(){
            test();
        }
        public virtual void test(){
            Console.WriteLine("Base!");
        }
    }
 
    //继承Base,重写test方法
    class extendsBase : Base{
        public extendsBase():base() //注意此处显示的调用父类的构造函数,但输出结果仍然是:Why????
        {
        }

        public override void test() {
            Console.WriteLine("Why????");
        }
    }
我们再看另一种情况,输出就是Base!:

public class Problem {
        public static void Main(String[] args) {
            //创建子类对象
            new extendsBase();
            Console.ReadLine();
        }
    }
 
    class Base{
        public Base(){
            test();
        }
        public  void test(){ //此处我把virtual 关键词去掉了
            Console.WriteLine("Base!");
        }
    }
 
    //继承Base,重写test方法
    class extendsBase : Base{
        public extendsBase():base()
        {
        }
       //由于父类存在一个test方法,那么在C#中函数前面不加new关键词的话,是编译不过去的。
       //这是java虚函数和C#实体函数的区别
        public new void test() {  
            Console.WriteLine("Why????");
        }
    }
其实你的代码,就等同于上面第一种情况的代码是一样的!不知道能不能给你一点思路
sixbusy 2014-03-27
  • 打赏
  • 举报
回复
就C++而言new extendsBase的时候,先调用的Base的构造函数,而Base的虚表中test指向的是子类的方法。这就是多态。 在构造函数中调用虚函数不是个很好的习惯,如果extendsBase的test使用extendsBase的变量呢?变量是有的,但没有初始化呀。
bobo928843007 2014-03-27
  • 打赏
  • 举报
回复
new 一个对象时要先构造父类,但是test()被覆盖了,调用的是子类的test()。

package test;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
 
public class TestTime {

	    public static void main(String[] args) {
	        //创建子类对象
	        new extendsBase();
	        new Base();
	    }
	 
 
}
class Base{
    public Base(){
        test();
    }
    public void test(){
        System.out.println("Base!");
    }
}
 
//继承Base,重写test方法
class extendsBase extends Base{
    @Override
    public void test() {
        System.out.println("in children");
    }
    public extendsBase()
    {
    	System.out.println("in children ctr");
    }
}
输出结果: in children in children ctr Base!
路边一青蛙 2014-03-27
  • 打赏
  • 举报
回复
引用 24 楼 TreeNode_2012 的回复:
java中所有的函数默认都是虚函数...这是和C#不同的地方之一
当然静态函数除外
路边一青蛙 2014-03-27
  • 打赏
  • 举报
回复
java中所有的函数默认都是虚函数...这是和C#不同的地方之一
放纵的青春 2014-03-27
  • 打赏
  • 举报
回复
这样理解 子类重写了test方法 继承了构造方法 然后你调用的时候是new的子类 所以是用的子类的test方法 因为继承了父类的构造方法 所以会执行test方法
Vurteon 2014-03-27
  • 打赏
  • 举报
回复
引用 21 楼 slowwind2007_lishu 的回复:
Test是在构造函数里调用的,此时对象的虚函数表还没有建立起来,即对象还没有完全构造完,此时调用此对象自己的函数,即ExtendBase的Test函数。
Java的表区具体的我现在还不太明白,但是你说这个即使是在C++里面也是有问题的。 你可以参考下面的文章。 http://www.cppblog.com/dawnbreak/archive/2009/03/10/76084.aspx
树哥 2014-03-27
  • 打赏
  • 举报
回复
Test是在构造函数里调用的,此时对象的虚函数表还没有建立起来,即对象还没有完全构造完,此时调用此对象自己的函数,即ExtendBase的Test函数。
加载更多回复(15)

62,616

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧