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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 雷丹 中级黑马   /  2013-10-23 23:20  /  882 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class Parent {
        int x = 10;
        public Parent() {
                add(2);
        }
        void add(int j) {
                this.x += j;
        }
}
class Child extends Parent {
        int x = 9;

        void add(int j) {
                System.out.println("==+++=="+x);//为什么这里输出的x是0
                x += j;
                System.out.println("===="+x)
        }
        public Child(){
                super();
                System.out.println(">>>>>>"+x);
        }
}
public class Test {
        public static void main(String args[]) {
                Parent p = new Child();
                System.out.println(p.x);//为什么结果是10,不是说多态父类引用指向子类对象吗?

               
        }
}

评分

参与人数 1技术分 +1 收起 理由
杨增坤 + 1

查看全部评分

7 个回复

倒序浏览
因为Person类中的int x = 10;x是个常量,所以户随着类的加载而在内存中创建。
当然子类中虽然也有int x=9,也会随着Child类的加载而加载,
虽然父类接收了子类的创建的对象,但是还是Fu的声明的对象,所以还会现在父类中查找,没找到才起子类中找,但是此时已经在父类中找到,所以会输出父类中的x.

还有一种情况就是static修饰的方法,当Fu f=new Child();那么用  f  调用静态方法,那么也会执行父类中的静态方法,道理和上面的一样。


除了非静态成员,那么使用多态调用的话,会调用子类中重写的方法或者成员变量!

希望对你有帮助!

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 赞一个!

查看全部评分

回复 使用道具 举报
首先看Parent p = new Child();建立了一个新的Child对象,先访问其构造方法
public Child(){
                super();//调用父类构造方法
                System.out.println(">>>>>>"+x);
        }
父类构造方法add(2),需要指出调用add方法的是p对象,也就是p.add(2).而子父类同时存在add方法。根据多态,常量看左面,方法看右面。所以会调用子类的add方法。
而这时,x并没有初始化,在调用完super后内存中才会存在x变量。System.out.println("==+++=="+x) x是this.x所以输出为0,下面的为2. super()语句执行完毕。子类内存中
产生变量int x =9.输出 System.out.println(">>>>>>"+x);
p.x不多说 多态时常量看左面。

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 赞一个!

查看全部评分

回复 使用道具 举报
本帖最后由 我能学编程吗 于 2013-10-24 00:25 编辑

我个人觉得:
//为什么结果是10,不是说多态父类引用指向子类对象吗?
答:因为多态只适用于方法,对成员变量不管用,父类引用能访问的只能是父类的成员变量,而方法的话,父类引用能调用子类覆盖的方法,这叫多态。


public Child(){
        super();
        System.out.println(">>>>>>"+x); //为什么这里输出的x是0
}
//为什么这里输出的x是0
这个问题问遇到的好啊,之前看张孝详老师的基础视频对这个有点印象,但是当时老师没有模拟出来这个,你现在遇到了,我一想,如果没听过那个原理,还真不知道怎么回事。
答:
要解答这个问题,首先,你要知道一个对象的初始化过程:
当执行new Child();创建对象的时候,首先执行super()方法
1、在Child的所有父类的super()没有执行完之前,Child对象的成员变量的x初始化为默认值0
2、执行构造函数Child(),这里会调用的父类的无参构造函数,你调不调用super();都会调用父类的构造函数的,也就是调用了Parent的public Parent(),那么在Parent的第一行,默认也会调用父类的构造函数,虽然你没有写super(),但是Java会默认先调用父类的无参构造函数,一直这样循环的把所有父类的构造函数都调用完了,再会执行构造函数后面的代码。(当然你这里Parent就只有一个父类了,就是Object),
所以的类都会调到object的无参构造函数。
3、你于你的代码,因为继承关系很少,我给你说全了,在Object的构造函数执行完后,然后执行Parent的构造函数的代码:add(2); ,准确的说应该是执行super后面的代码,如下:// 这是Parent 类的构造器,在这个构造器中的 super(); 语句没有执行完前,Parent.x的值默认始化为0,super();  执行完后Parent.x 显示初始化为10;
public Parent() {
        super(); // 虽然你没有写这句,代Java编译时会自动加上
        add(2);
}执行add(2)的方法,因为你的子类覆写了这个方法,按照多态特性,实质上调用的是子类Child的add方法,如下:
void add(int j) {
                System.out.println("1Child.x = "+x);//为什么这里输出的x是0       // 因为调用 的是Child的add方法,所以这里的x访问的就是Child对象的成员x,从上面3个步骤可知,x的值目前还是0呢
                x += j;
                System.out.println("2Child.x = "+x);
}

4、Parent的构造函数执行完后,开始执行Child构造函数中super();后面的代码:System.out.println(">>>>>>"+x);,如下:
//  这是 Child 类的构造器,在这个构造器中的  super(); 语句没有执行完前, Child.x的值默认始化为0, super();  执行完后 Child.x 显示初始化为9;
public Child(){
      super();
      System.out.println(">>>>>>"+x);
}


哇,感觉自己好写的好乱啊,不知道你能否明白?

评分

参与人数 1技术分 +1 收起 理由
周志龙 + 1 赞一个!

查看全部评分

回复 使用道具 举报
补充一下,所以会调用子类的add方法。
而这时,x并没有初始化,在调用完super后内存中才会存在x变量。说的片面了,是这时候子类中的x并没有初始化。因为所有构造函数不添加super()或this();虚拟机都会自动对其添加super();
再执行add方法时,父类的变量x已经存在。
楼主把子类的x注释掉就很好理解了。
void add(int j) {
                 //因为本类定义了变量x,所以这里x是this.x。如果本类没有x变量,虚拟机添加的是super.x。打印结果就是10.
                System.out.println("==+++=="+x);//为什么这里输出的x是0
                x += j;
                System.out.println("===="+x)
        }
回复 使用道具 举报
本帖最后由 我能学编程吗 于 2013-10-24 00:41 编辑

个人觉得:
我反对上述各楼说:在调用完super()后x变量才存在的说法。我认为没调用之前就存在了,并且所有的类,一旦加载进内存成员变量就存在了,并且进行了默认的始化,int型变量默认初始化为0。换句句总结说:
super()执行完之前,x已经存在,并且默认初始化为0
super()执行完之后,x进行显示初始化,即x = 9;

上面代码中很明显,add方法执行完之后才会返回Child类的super()方法,这时super()方法才算执行完,而当add方法在执行时Child类的super()方法 还没有执行完,而add方法中访问的x变量就是Child对象中的,如果不存在的话,就会报错了。也打印不出x=0
回复 使用道具 举报
我能学编程吗 发表于 2013-10-24 00:30
个人觉得:
我反对上述各楼说:在调用完super()后x变量才存在的说法。我认为没调用之前就存在了,并且所有 ...

同意你说的,在没执行完super()语句时,变量x存在,但是没有初始化,俺说错了,是没初始化,不是不存在。
回复 使用道具 举报
乔兵 高级黑马 2013-10-25 08:19:56
8#
楼主你好,如果问题已解决请将帖子状态修改为提问结束,

如果未解决请继续提问,谢谢合作

修改方法请看解释帖:http://bbs.itheima.com/thread-89313-1-1.html
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马