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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 逍遥小seng 中级黑马   /  2014-10-20 16:08  /  1555 人查看  /  9 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文



结果不是B C 2吗,成员变量不是随着类加载吗?答案却是 B C 5。下面这道就对
class lianxi2
{
        public static void main(String[] args)
        {
                A a= new B();
                a.method();
                System.out.println(a.x);

        }
}
class A
{
        int x = 5;
        void method ()
        {
                System.out.println("A");
        }
}
class B extends A
{
        int x=6;
        void method ()
        {
                System.out.println("B");
        }
}

答案就是B 5

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1 淡定

查看全部评分

9 个回复

倒序浏览
class lianxi2
{
        public static void main(String[] args)
        {
                A a= new B();
       
                System.out.println(a.x);

        }
}
class A
{
        int x;
        A ()
        {       
                x=5;
               
        }
}
class B extends A
{
       
        B ()
        {        x = 6;
               
        }
}
这个结果又是 6.我去怎么回事。
回复 使用道具 举报
先说答案为B 5 的情况:
类B是类A的直接子类,且这两个类同时都定义了成员变量 int x = ?,也就是这句话在两个类中写了两边,在创建实例对象的时候,这两个对象的成员变量x会存在不同的内存空间,一个是a.x 一个是b.x,所以当你答应a.x的时候得到的是5,实际上输出的结果应该是:
B
5
输出B是方法的Override体现的多态性,这个是方法的覆盖的概念,这里不多说。
以上的情况举一个例子:
“假设父类叫father,son是father的直接子类, 两个类里面都有一个叫age的成员变量。创建实例对象后,这两个age其实是在不同的内存空间里的,是分别独立的。比如在father中可以对age赋值50,在son中可以对age赋值25。那么在son类中,这样的语句 int a = age, 那么这个a是25,如果写 int a = father.age 或者 int a = super.age, 那么a是50.”
后一个直接输出6的情况:
同样的类B是类A的直接子类,但是和上面不同的是成员变量x只是在父类A中做了定义,类B中只是在构造方法中做了引用,所以类B构造方法中的x实际上继承的父类A的x,所以在new B()的时候根据子类的构造顺序,先调用父类A的构造方法赋值给x=5,然后再调用子类的B的构造方法赋值给x=6,所以打印的结果是6.
这个例子有两个重点,一个是成员变量只在父类定义了一次,一个改变成员变量的位置在构造方法中,主要考察子类在实例化的时候构造方法的调用顺序。

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1 很给力!

查看全部评分

回复 使用道具 举报
  1. class lianxi2
  2. {
  3.          public static void main(String[] args)
  4.         {
  5.                          //多态父类的引用指向子类对象
  6.                  A a= new B();
  7.                                  //调用方法,因为子类中有这个方法,所以覆盖父类得出B5
  8.                  a.method();
  9.                  System.out.println(a.x);
  10.          }
  11. }
  12. class A
  13. {
  14.          int x = 5;
  15.          void method ()
  16.          {
  17.                  System.out.println("A");
  18.          }
  19. }
  20. class B extends A
  21. {
  22.          int x=6;
  23.          void method ()
  24.          {
  25.                  System.out.println("B");
  26.          }
  27. }
复制代码
第一个是应为静态绑定,多态的体现,

评分

参与人数 1技术分 +1 收起 理由
杨佳名 + 1 赞一个!

查看全部评分

回复 使用道具 举报
  1. class lianxi2
  2. {
  3.          public static void main(String[] args)
  4.         {
  5.                          //这个函数中X是在成员位置只用一个引用,值为0,建立B时构造函数首先调用A的构造函数对X进行初始化为5,
  6.                          //子类的构造函数中有一条隐性的super(),之后会子类的构造函数初始化,那就是6了
  7.                  A a= new B();
  8.          
  9.                 System.out.println(a.x);

  10.         }
  11. }
  12. class A
  13. {
  14.          int x;
  15.          A ()
  16.          {        
  17.                 x=5;
  18.                  
  19.         }
  20. }
  21. class B extends A
  22. {
  23.          
  24.         B ()
  25.          {        x = 6;
  26.                  
  27.         }
  28. }
复制代码
回复 使用道具 举报
liuqingqian 发表于 2014-10-20 16:46
先说答案为B 5 的情况:
类B是类A的直接子类,且这两个类同时都定义了成员变量 int x = ?,也就是这句话在 ...

大致明白点,还想问你下,拿第二个例子来说,改变成员变量在构造方法中,而这样编译说下面的x没有标识符,难道只能构造方法中修改x吗?x不是classB从classA中继承下来的吗,怎么不能改变?
class A
{
        int x;
        A ()
        {        
                x=5;
               
        }
}
class B extends A
{
        x=6;
        B ()
        {        
               
        }
}
回复 使用道具 举报

谢谢了,帮我解释下x不在构造函数修改就不通过编译,怎么回事?
回复 使用道具 举报
如果x是成员变量,那它就是静态绑定,你用父类的引用打印肯定是打印父类的x,如果是构造函数的话,在初始化时肯定要先知道父类是怎么初始化的,之后在进行子类的初始化
回复 使用道具 举报

这个问题是成员变量的初始化位置的知识点,对于非静态的变量初始化有三个位置:1,定义的时候直接赋值、2,初始化块中 3,构造方法中。具体的讲解你看一下这个blog:http://blog.csdn.net/hawksoft/article/details/8441083
回复 使用道具 举报
wf111sxwf 来自手机 中级黑马 2014-10-20 19:51:57
10#
多态中 同名成员变量看左边,同名成员函数看右边 手机党就不用代码解释了见谅哈
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马