2 czkerl czKerl_ 于 2016.04.14 16:03 提问

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行
以及什么原因
感谢各位

13个回答

chenhchen1994
chenhchen1994   2016.04.14 16: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

chenhchen1994
chenhchen1994 回复June君: 因为第一次走的时候,没有给name赋值,所以是null啊
一年多之前 回复
czKerl_
czKerl_ 回复June君: 父类的name是私有的
一年多之前 回复
qq_32224861
qq_32224861 为什么会是null呢?
一年多之前 回复
u010368406
u010368406   2016.04.14 16:16

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

maowei117
maowei117   2016.04.15 13: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方法,
因为它们不会被重写。

czKerl_
czKerl_ 十分感谢,看了收获很大
一年多之前 回复
qq_26971803
qq_26971803   2016.04.14 16:11

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

CSDNXIAOD
CSDNXIAOD   2016.04.14 16:12

JAVA 面试题<基础>
面试题之java基础
常见JAVA基础面试题有哪些
----------------------biu~biu~biu~~~在下问答机器人小D,这是我依靠自己的聪明才智给出的答案,如果不正确,你来咬我啊!

JTPower
JTPower   2016.04.14 16:16

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

stargazer1989
stargazer1989   2016.04.14 16:41

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

li301928
li301928   2016.04.14 17:42

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

u012768347
u012768347   2016.04.14 17: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
  • 可以参考

内存中对象实例化细节

u012768347
u012768347 回复li301928: 实际上时子类空间的tellName(),此时子类name是String类型,系统初始化是null 然后2.同样调用printName(),此时name还是null,输出Apple print name: null,然后3.父类初始化完毕,此时才到子类显示初始化,name被赋值apple,此时调用的两个方法就是子类方法,输出Apple tell name: apple Apple print name:apple
一年多之前 回复
u012768347
u012768347 回复li301928: 是我弄错了,子类覆盖了父类方法,所以1.虽然先初始化父类,但是在父类里的tellName()调用的
一年多之前 回复
u012768347
u012768347 回复li301928: 是我弄错了,子类覆盖了父类方法,所以1.虽然先初始化父类,但是在父类里的tellName()调用的
一年多之前 回复
li301928
li301928 你的输出结果不对Apple tell name: null Apple print name: null Apple tell name: apple Apple print name: apple
一年多之前 回复
qq_34108945
qq_34108945   2016.04.14 22: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);
}
}

共13条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!