A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

本帖最后由 蔡增辉 于 2013-5-15 17:12 编辑

代码如下,请帮忙分析下输出结果和原理,多谢;

1.PNG (14.95 KB, 下载次数: 1)

1.PNG

评分

参与人数 1技术分 +1 收起 理由
殇_心。 + 1

查看全部评分

22 个回复

正序浏览
xuemeng 发表于 2013-5-15 14:12
做这道题,首先要明白类加载时执行顺序::

new 子类对象时的执行顺序:Ø 当new子类对象, 的执行顺序(省去了 ...

非常给力,学习了。我用其他代码验证的结果也是这样的。
回复 使用道具 举报
黑马一刘昭 发表于 2013-5-18 16:58
你好,我去搜了下,有的说可以,有的说不行。说可以的也说的是这种情况。但是我添加了一行代码打印出Stud ...

因为你这样调用, 就不是隐式继承了啊!
回复 使用道具 举报
xuemeng 发表于 2013-5-18 14:44
如果笔试, 你说子类可以继承父类私有属性, 肯定不通过, 但是面试就可以说能够继承,因为你可以给面试官解 ...

你好,我去搜了下,有的说可以,有的说不行。说可以的也说的是这种情况。但是我添加了一行代码打印出Student的name,它就报错,显示必须到Person类里面去访问。

所以我想,即便是真的执行隐式继承,也不可以高调的去显示执行(比如我说的打印不出)。这是我的想法,你认为呢?

class Person   
{
        private String name;
        private int age;
        //已经完成了给name和age赋值的功能
        public Person(String name, int age)
        {
                this.name = name;
                this.age = age;
        }
}

class Student extends Person
{
        private String sn;//学号
        public Student(String name,int age,String sn)
        {
                super(name,age);//调用父类的构造方法,必须放在第一行,否则错误SuperDemo2.java:24: 错误: 对super的调用必须是构造器中的第一个语句
                this.sn = sn;
        }
}        

class SuperDemo21
{
        public static void main(String[] args)
        {
                //想创建Student对象的时候,就给name和age赋值
                Student p = new Student("Will",17,"007");
                System.out.println(p.name);//只是新加了这一行代码,想打出Student的name
        }
}

报错:SuperDemo21.java:29: 错误: name可以在Person中访问private!
回复 使用道具 举报
黑马一刘昭 发表于 2013-5-18 12:56
求看下这个super的问题,super(name,age);在这里是调用什么的?它这句能起什么作用?父类的name和age不是 ...

如果笔试, 你说子类可以继承父类私有属性, 肯定不通过, 但是面试就可以说能够继承,因为你可以给面试官解释,
     事实上, 父类的私有属性, 是可以隐式继承, 就如你的这个代码, 就隐式继承了父类的私有属性!!!
回复 使用道具 举报
xuemeng 发表于 2013-5-15 16:07
大家互相帮助!!

求看下这个super的问题,super(name,age);在这里是调用什么的?它这句能起什么作用?父类的name和age不是用private修饰了吗?别的不就继承不了。
谢谢


class Person   
{
        private String name;
        private int age;
        //已经完成了给name和age赋值的功能
        public Person(String name, int age)
        {
                this.name = name;
                this.age = age;
        }
}

class Student extends Person
{
        private String sn;//学号
        public Student(String name,int age,String sn)
        {
                super(name,age);//调用父类的构造方法,必须放在第一行,否则错误SuperDemo2.java:24: 错误: 对super的调用必须是构造器中的第一个语句
                this.sn = sn;
        }
}       

class SuperDemo2
{
        public static void main(String[] args)
        {
                //想创建Student对象的时候,就给name和age赋值
                new Student("Will",17,"007");
        }
}
回复 使用道具 举报
xuemeng 发表于 2013-5-15 16:07
大家互相帮助!!

求回复我的问题,内存地址的问题!谢谢
http://bbs.itheima.com/thread-50070-1-1.html
回复 使用道具 举报
黑马一刘昭 发表于 2013-5-15 16:05
学了半个月给您跪了,以后希望您多指点!!

大家互相帮助!!:D
回复 使用道具 举报
xuemeng 发表于 2013-5-15 16:00
我是菜鸟, 学了几年了吧!!!

学了半个月给您跪了,以后希望您多指点!!:'(
回复 使用道具 举报
黑马一刘昭 发表于 2013-5-15 15:56
大神学习Java多久了?

我是菜鸟, 学了几年了吧!!!
回复 使用道具 举报
xuemeng 发表于 2013-5-15 15:46
很多人在这里遇到困难, 其实是因为老毕在这里没有着重讲这一块!!

大神学习Java多久了?
回复 使用道具 举报
黑马一刘昭 发表于 2013-5-15 15:34
真心厉害,希望知道你是怎么学习的,理解如此深刻!!求回复,求告诉,求指引!! ...

很多人在这里遇到困难, 其实是因为老毕在这里没有着重讲这一块!!
回复 使用道具 举报
xuemeng 发表于 2013-5-15 14:12
做这道题,首先要明白类加载时执行顺序::

new 子类对象时的执行顺序:Ø 当new子类对象, 的执行顺序(省去了 ...

真心厉害,希望知道你是怎么学习的,理解如此深刻!!求回复,求告诉,求指引!!:hug:
回复 使用道具 举报
这样的题,主要从主函数的代码怎么写来入手。
FatherClass f = new ChildrenClass();
f.show();
这部分就是多态啊。FatherClass(父类)的f(引用)指向了ChildrenClass(子类)的对象(new出来的)。
既然f指向了子类对象。调用的show方法当然是子类的show方法,打印的就是10啦。

Children z = new ChildrenClss();
z.show();
这部分就是子类(ChildrenClass)的引用(z)指向子类的对象。那z指向的是子类对象当然调用的是子类的show方法了。打印的也是10.
回复 使用道具 举报
JinnyZh 来自手机 中级黑马 2013-5-15 14:27:18
10#
xuemeng 发表于 2013-5-15 14:14:26

楼上的, 答案没错, 但似乎理解有问题的!!

应该是我错了,谢谢来自: Android客户端
回复 使用道具 举报
本帖最后由 xuemeng 于 2013-5-15 14:20 编辑

刚出去,, 看了下楼主的标题, 其实楼主你理解错了, 这个题主要考的是new 子类对想的时候, 对象的初始化顺序, 虽然本题中也用到了多态, 但是这个在本题中不是重点!!
回复 使用道具 举报
JinnyZh 发表于 2013-5-15 13:08
答案应该是 10
                10
不好意思,忘记说了~

楼上的, 答案没错, 但似乎理解有问题的!!
回复 使用道具 举报
做这道题,首先要明白类加载时执行顺序::

new 子类对象时的执行顺序:
Ø 当new子类对象, 的执行顺序(省去了加载)
Ø 所有属性 (父类和子类) 都赋值为默认值;
Ø 父类的构造代码块和父类的显示初始化语句;
Ø 父类构造器的代码;
Ø 子类的构造代码块和子类的显示初始化语句;
Ø 子类的构造器代码.

有了上面的说明, 我们再来看代码:
class FatherClass {
int field = 0;
FatherClass() {
  field++;
}
public void show() {
  System.out.println(field);
}
}
class ChildClass extends FatherClass {
{
  field = 10;
}
ChildClass() {
  super();
  field = super.field;
}
public void show() {
  System.out.println(field);
}
}
class Demo {
public static void main(String[] args) {
//这里是用的是多态,创建的是一个子类对象, 即父类的引用指向子类对象, 那么既然对象是子类, 我们就结合我上面面说的, 当new 子类对象是, 程序做了些什么?
1,   首先就是Field属性, 默认初始化值,那么Filed的值就是0, 至于这里为什么要这样执行, 首先在new子类对象时, 因为子类对象总会隐式调用父类的无参构造器,你这里的代码没有隐式调用,自己写出来了, 是显示调用, 但是不管是显示,还是隐式,都会调用, 那么当调用父类的构造器的时候, 那么就要对父类进行初始化, 所以,这也是为什么要说每个子类都有一个父类对象的原因
2,执行父类构造代码块和父类显示初始化语句, 这里因为没有构造代码块, 那么就没有执行,仅仅执行了显示初始化语句, 也就是 int Field = 0;第二步执行完成;
3,执行父类构造器的代码,Filed++, 那么这个时候Filed的值是1;
4, 父类初始化动作完成, 接着执行子类的构造代码块, Filed = 10. 这个时候Filed的值就是10了, 这里要注意,在执行这句代码的时候Field的值已经是10了, 因为继承的关系,每个子类都有一个父类对象,先是父类执行初始化,然后是子类, 但是它们的属性用的都是同一个, 所以当子类做初始化动作的时候, 属性值被改变, 那么父类的属性值也跟着改变了,, 所以在做完这个动作后, 不论是父类还是子类的Field的值都是10, 其实本来就只有一个Filed, 只是父类先Fild++, Filed变为1, 然后子类再 Filed = 10, Filed的值为10
5,执行子类构造器的代码  Filed = super.Filed, 既然这样,Filed的值当然是10了, 因为super.Filed的值就是父类的值, 而父类的值因为子类的重新赋值而变成了10

  FatherClass f = new ChildClass();
//这个简单了,多态调用, 多态调用只需知道, 能不能调用看左边, 具体调用那个看右边,(不过注意属性和静态方法不包括在此列,他们调用只看属性), 具体解释下, 左边引用f是FatherClass类,那么这个类到底有没有show()方法了, 有,能调用, 没有肯定就会出错, 事实上我们的代码在FatherClass类中是有show()方法,那么就说明f引用能够调用show方法,接下来具体调用哪一个show()方法呢? 具体调用看右边, 因为右边是子类对象, 那么调用的方法就是子类的show()方法, 所以最后打印结果为10
  f.show();
//这个执行过程和上面的完全一样,所以结果也是一样 , 最后打印结果为10
  ChildClass c = new ChildClass();
  c.show();
}
}

评分

参与人数 1技术分 +1 收起 理由
殇_心。 + 1

查看全部评分

回复 使用道具 举报
JinnyZh 发表于 2013-5-15 13:07
关于多态中的父类引用指向之类对象~
成员函数:
编译时:要查看引用变量所属的类中是否有所调用的成员。

答案应该是 10
                10
不好意思,忘记说了~
回复 使用道具 举报
关于多态中的父类引用指向之类对象~
成员函数:
编译时:要查看引用变量所属的类中是否有所调用的成员。
在运行时:要查看对象所属的类中是否有所调用的成员。如果父子出现同名的方法,会运行子类中的方法,因为方法有覆盖的特性
编译看左边运行看右边!
////////////////////////////////////////////////////////////////
首先创建FatherClass f = new ChildClass(); 父类引用指向之类对象,
然后利用构造代码块初始化,此时子类中, field = 10 ,接着利用子类的构造函数初始化,这是会调用父类的空参的构造函数,
然后父类中的field有于自增会变成1,此时若在父类构造函数中System.out.pringln(field);会输出是1,然后将子类中的filed= 10 指向父类,父类中的field变成 10
由于如果父子出现同名的方法,会运行子类中的方法,因为方法有覆盖的特性,会调用子类的show方法,输出子类的field =10~
ChildClass z 的话也是一样的道理..........
我是这么理解的,不知道答案对么

评分

参与人数 1技术分 +1 收起 理由
殇_心。 + 1

查看全部评分

回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马