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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 完美恋爱 高级黑马   /  2013-12-5 18:22  /  2502 人查看  /  22 人回复  /   1 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 完美恋爱 于 2013-12-6 06:20 编辑

class Super
{
        int i=0;

        public Super()
        {
                i+=2;
        }
}
class Demo extends Super
{
        public Demo()
        {
                i+=5;                                
        }
        public static void main(String[] args)
        {
                int i=4;
                Super d=new Demo();
                System.out.println(d.i);
        }
}
为什么输出的结果是7呢?调用的成员变量i 应该是父类的啊!那应该是2才对啊!

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

22 个回复

倒序浏览
Super d=new Demo();Demo为Super的子类,创建对象时,先调用父类的构造方法i+=2;,再调用子类的构造方法i+=5;  最终结果是7

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
sorry,你好像解答错了
回复 使用道具 举报
本帖最后由 ily521125 于 2013-12-5 20:54 编辑

继承中的构造器调用:


  • 子类一定调用父类的构造器
  • 子类默认调用父类无参构造器
因此在创建一个Demo()对象时,无论Demo类中有无构造方法,都会去调用Super中的构造方法,并继承了Super的成员属性i
如果Demo类中无构造方法即没有语句 public Demo(){ i+=5}; 则在创建Demo()对象时,默认调用Super类的构造方法,得到 i 的结果为2;
如果Demo类中有构造方法即有语句 public Demo(){ i+=5 }; 则在创建Demo()对象时,也会调用Super类的构造方法,此时代码相当
  1. public Demo()
  2. {
  3.               // Super(); 该语句是默认产生的去调用父类构造方法
  4.                i+=5;
  5. }
复制代码

在调用父类构造方法后,i=2,就继续执行 i+=5 所以在完成Demo()对象创建后成员变量 i 结果是7


评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
ily521125 发表于 2013-12-5 20:32
继承中的构造器调用:

可是在子类中的i和父类中的i不是一个i吧!而且不是只能调用父类本身的成员变量吗?那为什么还会把子类中的算进去呢!请再详细说明一下
回复 使用道具 举报
本帖最后由 ily521125 于 2013-12-5 21:13 编辑
完美恋爱 发表于 2013-12-5 20:56
可是在子类中的i和父类中的i不是一个i吧!而且不是只能调用父类本身的成员变量吗?那为什么还会把子类中 ...


具体的说,就是若果你没有继承Super类的话,你Demo类中的构造方法中写的i+=5是不对的会报错,因为Demo类中并没有成员变量i,你主方法中定义的int i=4,是作用在主方法中的,和成员变量没有任何关系。Demo类继承了Super类会也会继承Super类的成员变量i,因此i+=5中的i就是继承来的

也就是说,你是先继承类Super类中的成员变量 i ,才可以在Demo类构造方法中写i+=5这这句话,不然你都没有定义i,何来的i+=5呢
回复 使用道具 举报
刘敏 中级黑马 2013-12-5 21:32:34
7#
Super d=new Demo();这句话内涵很丰富:
1. 先在堆内存中分配一个Demo对象,初始化 i=0。
2. 执行父类的构造函数   i+=2;//此时i=2
3. 执行自己的构造函数  i+=5;// 此时i=7。

注意:Demo自己在内存中并没有自己的i,这个变量i是Super的,Demo继承Super就自动拥有了这个i。

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
ily521125 发表于 2013-12-5 21:05
具体的说,就是若果你没有继承Super类的话,你Demo类中的构造方法中写的i+=5是不对的会报错,因为Demo类 ...

原来如此,我懂啦!谢谢了哈!
回复 使用道具 举报
ily521125 发表于 2013-12-5 21:05
具体的说,就是若果你没有继承Super类的话,你Demo类中的构造方法中写的i+=5是不对的会报错,因为Demo类 ...

还有一个疑惑,确实,i是继承过来的,可是d是父类的引用,所以调用的d.i的i应该是在父类范围内的i,就是说i的值应该是在父类范围内的,i+=5是在 子类范围内的,照常的话不应该算上去才对啊!
回复 使用道具 举报
刘敏 发表于 2013-12-5 21:32
Super d=new Demo();这句话内涵很丰富:
1. 先在堆内存中分配一个Demo对象,初始化 i=0。
2. 执行父类的构 ...

还有一个疑惑,确实,i是继承过来的,可是d是父类的引用,所以调用的d.i的i应该是在父类范围内的i,就是说i的值应该是在父类范围内的,i+=5是在 子类范围内的,照常的话不应该算上去才对啊!
回复 使用道具 举报
完美恋爱 发表于 2013-12-5 21:38
还有一个疑惑,确实,i是继承过来的,可是d是父类的引用,所以调用的d.i的i应该是在父类范围内的i,就是 ...

java允许父类的引用变量引用它的子类的实例
Super d=new Demo();这种类型转换时自动完成的,父类转换成了子类,所以d.i就是demo类中的
回复 使用道具 举报
完美恋爱 发表于 2013-12-5 21:38
还有一个疑惑,确实,i是继承过来的,可是d是父类的引用,所以调用的d.i的i应该是在父类范围内的i,就是 ...

你的父类的i是没有设权限的,如果设置为private,子类是没办法修改的;但是你的是默认,父类是可以修改的。你想要的那个结果应该这样写:class Super
{
        int i=0;

        public Super()
        {
                i+=2;//这个修改的是子类的i
        }
}
class Demo extends Super
{
        int i;//这个是子类自己的


        public Demo()
        {
                i+=5;  //这个修改的是父类的i,这个i=5; 如果没有上面的定义,这里就是修改父类的        
        }
        public static void main(String[] args)
        {
                int i=4;
                Super d=new Demo();
                System.out.println(d.i); //d.i 子类和父类都有i,编译器会让d调用父类的i;。
        }
}

回复 使用道具 举报
完美恋爱 发表于 2013-12-5 21:38
还有一个疑惑,确实,i是继承过来的,可是d是父类的引用,所以调用的d.i的i应该是在父类范围内的i,就是 ...

哥们  有一点关键的你没有搞明白   Super d=new Demo();这句话是在堆内创建一个Demo对象  并没有Super对象 d引用的是Demo对象     理解了这点就不疑惑了
回复 使用道具 举报
ily521125 发表于 2013-12-5 21:47
java允许父类的引用变量引用它的子类的实例
Super d=new Demo();这种类型转换时自动完成的,父类转换成了 ...

class Super
{
        int i=0;
       
        public Super()
        {
                i+=2;
        }
}
class Demo extends Super
{
        public Demo()
        {
                i+=5;
        }
        public static void main(String[] args)
        {
                int i=4;
                Super d=new Demo();
                Demo a = (Demo)d;
                i++;
                System.out.println(a.i);
        }
}
这个结果为什么还是7啊?

评分

参与人数 1技术分 +1 收起 理由
滔哥 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 刘敏 于 2013-12-5 22:10 编辑

其实,你要知道,你的代码中,不管是父类对象.i, 还是子类对象.i,实际在内存中只有一个i,修改i就会改变它的值。需要补下对象的内存分布啊!                int i=4; //这个是main()函数的局部变量,不是Demo的成员变量!!
                Super d=new Demo();
                Demo a = (Demo)d;
                i++;
                System.out.println(a.i);

回复 使用道具 举报
四五六七八 发表于 2013-12-5 22:01
哥们  有一点关键的你没有搞明白   Super d=new Demo();这句话是在堆内创建一个Demo对象  并没有Super对 ...

你说的我知道,父类引用指向子类对象,这跟我问的 那个没关系
回复 使用道具 举报
完美恋爱 发表于 2013-12-5 22:02
class Super
{
        int i=0;


那你认为是几呢?你把父类引用子类的实例有转换成子类,它还是具有父类和子类的属性啊,这块儿我建议你看看关于多态的内容
回复 使用道具 举报
ily521125 发表于 2013-12-5 22:12
那你认为是几呢?你把父类引用子类的实例有转换成子类,它还是具有父类和子类的属性啊,这块儿我建议你看 ...

我感觉应该是5啊!因为向下转型后调用的就是自身的i了啊!
回复 使用道具 举报
完美恋爱 发表于 2013-12-5 22:17
我感觉应该是5啊!因为向下转型后调用的就是自身的i了啊!

如果你非要让它输出是主函数里的i的话,就直接输出i
  1. class Super
  2. {
  3.         int i=0;
  4.         
  5.         public Super()
  6.         {
  7.                 i+=2;
  8.         }
  9. }
  10. class Demo extends Super
  11. {
  12.         public Demo()
  13.         {
  14.                 i+=5;
  15.         }
  16.         public static void main(String[] args)
  17.         {
  18.                 int i=4;
  19.                 Super d=new Demo();
  20.                 Demo a = (Demo)d;
  21.                 i++;
  22.                 System.out.println(i);
  23.         }
  24. }
复制代码
这样结果就是5了
回复 使用道具 举报
完美恋爱 发表于 2013-12-5 22:10
你说的我知道,父类引用指向子类对象,这跟我问的 那个没关系

那个i不是父类范围  是子类继承父类之后属于子类自己的  你可以理解为父类也有一个i 只是在内存中只有一个Demo对象(只有子类范围的i)
如果还不理解     那可能就是你认为   调用父类构造方法会创建父类对象  实际上调用构造方法并不一定会创建对象                 
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马