czKerl_
2016-04-14 08:03
采纳率: 100%
浏览 2.3k
已采纳

Java一个很基础的面试题【求助】

 public class Apple extends Fruit  {
    private String name = "apple";
    public Apple () {
        tellName();
        printName();
    }
    public void tellName() {
        System.out.println("Apple tell name: " + name);
    }
    public void printName() {
        System.out.println("Apple print name: " + name);
    }
    public static void main(String[] args){
        new Apple();    
    }
}
class Fruit {
    private String name = "fruit";
    public Fruit () {
        tellName();
        printName();
    }
    public void tellName() {
        System.out.println("fruit tell name: " + name);
    }
    public void printName() {
        System.out.println("fruit print name: " + name);
    }
}

我想知道为什么会输出4行
以及什么原因
感谢各位

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

12条回答 默认 最新

  • On_the_orad 2016-04-14 08:19
    已采纳

    1.先走第三行代码进tellName()方法。打印输出 Apple tell name: null
    2.进入Class Fruit 进入public Fruit()方法中的tellName
    3.再走第三行代码进printName()方法。打印输出 Apple print name: null
    4.进入Class Fruit 进入public Fruit()方法中的printName
    5.走第二行代码 给name赋值apple
    6.重复走1-打印输出 Apple tell name: apple -2-3 -打印输出 Apple print name:apple

    打赏 评论
  • Brioal 2016-04-14 08:11

    我觉得在继承的时候就默认调用了父类的构造方法。所以会多出两行。这就好比你继承Jbutton。就算你啥都不写调用之后还是会显示一个button。个人理解。错了勿喷

    打赏 评论
  • TF_Power 2016-04-14 08:16

    应该是调用了父类的构造方法,你可以把父类的构造方法里面的方法注释掉一个看下效果

    打赏 评论
  • 暗影修罗 2016-04-14 08:16

    创建子类实体时,在执行构造方法时会先执行父类的构造方法,所以会先输出父类的两行,在输入子类的两行

    打赏 评论
  • stargazer1989 2016-04-14 08:41

    实例化子类对象时,父类对象也会相应的被实例化,也就是说实例化子类对象时,Java编译器会在子类的构造方法中调用父类的的**无参构造函数**。

    打赏 评论
  • li301928 2016-04-14 09:42

    继承并不继承构造,其他构造方法什么的都继承,而父类的两个方法在子类中重写。所以实际上就只有子类的两个方法。
    注释掉父类构造里面的方法就出现只有两个结果的情况,可以说明执行父类构造的时候调用了子类的方法,但是并没法传递name值,所以为空。
    大家可以试试把父类中的两个狗杂哦方法改为private类型,这样不满足继承中重写条件,那么执行父类构造时只会调用父类方法值不为空。吓试的不一定正确,求改

    打赏 评论
  • z犬夜叉 2016-04-14 09:43

    http://blog.csdn.net/u012768347/article/details/51009724

    当创建一个子类实例时,在对象初始化过程中会依据继承体系向上初始化父类。

    其实在子类构造器其中,有一个隐式语句是Java虚拟机自动加上的,比如在Apple类默认构造函数的第一句,有super();
    这样会先初始化Fruit类,所以有输出

    • fruit tell name: fruit
    • fruit print name:fruit
    • Apple tell name: apple
    • Apple print name:apple
    • 可以参考

    内存中对象实例化细节

    打赏 评论
  • ActualMental 2016-04-14 14:42

    java新手,亲手试验补充,实践证明父类的name属性即使是public结果一样;顺序如数字所标从大到小,若父类中的name属性为private则跳过4
    public class Apple extends Fruit {
    private String name = "apple";//9
    public Apple () {//2
    tellName();//10
    printName();//12
    }
    public void tellName() {//6 //11
    System.out.println("Apple tell name: " + name);
    }
    public void printName() {//8 //13
    System.out.println("Apple print name: " + name);
    }
    public static void main(String[] args){
    new Apple(); //1
    }
    }
    class Fruit {
    public String name = "fruit";//4
    public Fruit () {//3
    tellName();//5
    printName();//7
    }
    public void tellName() {
    System.out.println("fruit tell name: " + name);
    }
    public void printName() {
    System.out.println("fruit print name: " + name);
    }
    }

    打赏 评论
  • maowei117 2016-04-15 05:44

    这个问题在Thinking in java中有比较好的一个解释,我们要知道在new子类对象的过程中发生了些什么:
    1、在其他任何事物发生之前,将分配给对象的存储空间初始化为二进制的零,也就是说,我现在要new Apple对象了,我先要分配好内存,而且内存全部初始化为0
    2、调用基类构造器。子类构造器在调用的时候必须调用基类的构造器(有可能你没写,也成功了,那是因为java默认帮你调用了,但是最好还是自己显式写出来)
    重点就在于第二步:在这个例子里面,Fruit的构造器调用了tellName(),printName().而子类又重写了这两个方法,所以在这里就已经存在了多态。因为在加载类的
    时候发现我的子类已经重写了这两个方法,所以基类中的tellName(),printName()实际上是子类重写之后的方法。所以执行代码你会发现,前两行输出的是
    Apple tell name: null
    Apple print name: null
    说明这个方法是子类的方法,而不是基类的
    至于为什么是null:因为这里的name指向的是子类的私有成员name,而这个时候子类的私有成员还没有被初始化,只有父类的私有成员name被初始化了
    所以这里当然显示null
    3、按照声明的顺序调用成员的初始化方法。执行完父类的构造方法,才会转到子类对子类的name进行初始化,这也解释了null的问题。
    4、调用子类的构造方法。这个时候再调用子类的构造方法,这时候因为name已经初始化了name="Apple"。所以这时候显示的就是
    Apple tell name: apple
    Apple print name: apple

    总结:这个问题的关键就是,如果基类的构造器调用了基类的方法,而恰好这个方法又被子类重写了,那么实际上基类构造器在执行的时候
    是执行的子类重写后的方法。
    因为这样的特性,有时会导致很多问题,所以建议构造方法里面的内容要尽可能简单,构造器里面唯一能安全调用的方法是基类中的final方法,
    因为它们不会被重写。

    打赏 评论
  • Yee_XU 2016-04-16 06:13

    new子类时会走父类的构造方法,再走自己的构造,所有一共就是4行啦

    打赏 评论
  • you种放学别跑 2016-04-26 17:24

    创建子类对象时候会默认调用系统的无参数构造器,也就是fruit类中的无参数构造器,fruit的无参数构造器里面调用了两个他的方法,这两个方法会先执行,然后执行Apple的无参数构造器,Apple的无参数构造器里面调用了他自己的两个方法,因此就会执行这两个方法

    打赏 评论
  • you种放学别跑 2016-04-26 17:25

    不好意思,刚才打错字了,第一句是 创建子类对象时候会默认调用父类的无参数构造器

    打赏 评论

相关推荐 更多相似问题