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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 李新辉 中级黑马   /  2013-11-4 23:13  /  2976 人查看  /  35 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 李新辉 于 2013-11-5 11:44 编辑

复制代码
  1. class Super
  2. {
  3.         int i = 20;
  4.         public Super(String a)
  5.         {                  
  6.                 i=1;
  7.         }
  8.         public Super()
  9.         {
  10.                 System.out.println("b  "+i);//b  20
  11.                 i += 2;
  12.                 System.out.println("c  "+i);//c  22
  13.         }
  14. }
  15. class Demo extends Super
  16. {
  17.         public Demo (String a)
  18.         {
  19.                 System.out.println("d  "+i);//d  22
  20.                 i = 5;
  21.                 System.out.println("e  "+i);//e  5
  22.         }
  23.         public static void main(String[] args)
  24.         {
  25.                 int i = 4;
  26.                 System.out.println("a  "+i);//a  4
  27.                 Super d=new Demo("A");
  28.                 System.out.println("f  "+i);//f  4
  29.                 System.out.println(d.i);//5
  30.         }
  31. }
复制代码
  1. class Super
  2. {
  3.         int i = 20;
  4.         public Super(String a)
  5.         {                  
  6.                 i=1;
  7.         }
  8.         public Super()
  9.         {
  10.                 System.out.println("a  "+i);//a  20
  11.                 i += 2;
  12.                 System.out.println("b  "+i);//b  22
  13.         }
  14. }
  15. class Demo extends Super
  16. {
  17.         static int i = 4;
  18.         public Demo (String a)
  19.         {
  20.                 System.out.println("c  "+i);//c  4
  21.                 i = 5;
  22.                 System.out.println("d  "+i);//d  5
  23.         }
  24.         public static void main(String[] args)
  25.         {
  26.                 Super d=new Demo("A");
  27.                 System.out.println("e  "+i);//e  5
  28.                 System.out.println(d.i);//22
  29.         }
  30. }
复制代码
一个结果是5
一个结果是22

求高人指点,这结果怎么来的
我很迷惑…………

评分

参与人数 1技术分 +2 收起 理由
To + 2 赞一个!

查看全部评分

35 个回复

倒序浏览
第一个程序的运行结果是22,这个因为static和成员变量存储在不同区域有关,Demo类中的i是static的,包括i=5,建立对象后,访问的就是堆内存中的i,结果就是20+2=22

第二个程序结果是5,因为都是堆内存中的i,最后执行到i=5,所以i的最终值就是5

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
class Super
{
        int i = 20;
        public Super(String a)
        {                  
                i=1;
        }
        public Super()
        {
                i += 2;
        }
}
class Demo extends Super
{
                //这个相当于复写了变量i
        static int i = 4;
        public Demo (String a)
        {
                                //这里隐式的有super();所以父类i初始化后为22
                i = 5;//这个i,因为本类有,相当于this.i
        }
        public static void main(String[] args)
        {
                Super d=new Demo("A");
                                //多态,常量看左面
                System.out.println(d.i);
        }
}
-------------------------------------------------
class Super
{
        int i = 20;
        public Super(String a)
        {                  
                i=1;
        }
        public Super()
        {
                i += 2;
        }
}
class Demo extends Super
{

        public Demo (String a)
        {
                                ////这里隐式的有super();所以父类i初始化后为22
                i = 5;//这个i相当于super.i,在父类初始化后又对i重新赋值5
        }
        public static void main(String[] args)
        {
                int i = 4;
                Super d=new Demo("A");
                System.out.println(d.i);
                                //还是调用的父类的i,你写这两个调用的都是父类的i,关键是你没搞懂赋值过程
        }

}

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
  1. class Super
  2. {
  3.         int i = 20;
  4.         public Super(String a)
  5.         {                  
  6.                 i=1;
  7.         }
  8.         public Super()          //第二步,初始化父类并且执行构造方法, i=22
  9.         {
  10.                 i += 2;
  11.         }
  12. }
  13. class Demo extends Super
  14. {
  15.               static int i = 4;      //在这里,子类和父类具有同名变量,如果没

  16. //这里没有定义   static int i = 4;  下面这个语句将给父类变量赋值
  17. //由于在子类中定义了 这个变量,所以下面语句赋值给本类中的i 而最后
  18. //打印的是父类中的 i.
  19.         public Demo (String a)
  20.         {
  21.                 i = 5;
  22.         }
  23.         public static void main(String[] args)
  24.         {
  25.                 Super d=new Demo("A"); //第一步  
  26.                 System.out.println(d.i);  //第三步,打印父类中变量
  27.         }
  28. }
复制代码

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 Clare0621 于 2013-11-5 12:57 编辑

顺序反了,根据你重新编辑的代码,下面程序一指楼主第二个程序,程序二指第一个程序:

// 程序一:子类中并未定义成员变量。因此子类构造函数里面的i操作的是父类的属性i,可理解为:super.i = 5;在子类实例化过程中会先调用父类构造函数,在调用子类构造函数,最后打印的d.i是父类的属性i,因此为5.


//程序2:static int i = 4,定义了一个静态成员变量变量或叫类变量。因为子类有了属性i,则子类构造函数里面的i = 5,可理解为this.i = 5;而最后打印d.i的值同样为父类的i,但与程序一不同的就是子类构造函数里面的语句 i = 5,操作的是子类变量与父类无关,因而d.i只经过父类构造函数初始化为22.
另:可在输出d.i语句后面,加上一句:System.out.println(this.i)加以验证,输出的值应为5

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
成员函数在多态调用时,编译看左边,运行看右边。Demo2中i是成员函数中的局部变量,所以调用的是子的i,先初始值i=4,new Demo2("A")后变为5
我对程序一的简化
  1. class Super
  2. {
  3.         int i = 20;
  4.    
  5. }
  6. class Demo2 extends Super
  7. {
  8.         public Demo2 (String a)
  9.         {
  10.                
  11.                 i = 5;
  12.                
  13.         }
  14.         public static void main(String[] args)
  15.         {
  16.                 int i = 4;

  17.                 Super d=new Demo2("A");

  18.                 System.out.println(d.i);
  19.         }
  20. }
复制代码
在多态中成员变量,无论编译和运行,都参考左边的,即引用型变量所属的类型。也就是说父类中有自己的变量,则先找父类自己的成员。所以造成第二个程序结果为22
我把第二个程序简化了,意思一样的
  1. class Fu
  2. {
  3.         int i = 22;

  4. }
  5. class Demo extends Fu
  6. {
  7.         static int i = 4;
  8.         public static void main(String[] args)
  9.         {
  10.                 Fu d=new Demo();
  11.                 System.out.println(d.i);
  12.         }
  13. }
复制代码
总结:因为当调用静态方法时,只要建立子类对象,父类与子类中的静态方法都会随之加载入内存,是不需要调用就可直接用类名.方法名的,而不需要对象。只要引用还存在,就看引用变量的类型。

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1

查看全部评分

回复 使用道具 举报
1.子类继承必须调用父类构造函数
2.默认调用无参构造函数
3.子类和父类都只有有参构造函数,而子类没有显示调用super(参数),会报错
4.两个程序实际返回的都是父类的变量,可以在Demo1中添加super.i测试
class Super
{
        int i = 20;
        public Super(String a)
        {                  
                i=1;
        }
        public Super()
        {
                System.out.println("b  "+i);//b  20
                i += 2;
                System.out.println("c  "+i);//c  22
        }
}
class Demo extends Super
{
        public Demo (String a)
        {
                System.out.println("d  "+i);//d  22
                i = 5;
                System.out.println("e  "+i);//e  5
                                System.out.println(super.i);
        }
        public static void main(String[] args)
        {
                int i = 4;
                System.out.println("a  "+i);//a  4
                Super d=new Demo("A");
                System.out.println("f  "+i);//f  4
                System.out.println(d.i);//5
        }
}

评分

参与人数 1技术分 +1 收起 理由
黄炳期 + 1 赞一个!

查看全部评分

回复 使用道具 举报
帖子已重新分类,如果问题还没有解决,可重新提问
回复 使用道具 举报
黄炳期 发表于 2013-11-5 08:34
帖子已重新分类,如果问题还没有解决,可重新提问

经常打不开论坛……
烦死了……


Bad Request

Your browser sent a request that this server could not understand.
Size of a request header field exceeds server limit.
Cookie: Ms5p_2132_saltkey=BHEmdzgs; Ms5p_2132_lastvisit=1383212933; Ms5p_2132_client_created=1383216576; Ms5p_2132_client_token=33DD081EE214AEB049FEB7D65EAC0598; Ms5p_2132_auth=25fal8heQEC

360总是出这毛病
其他浏览器就没事……
回复 使用道具 举报
李新辉 发表于 2013-11-5 11:06
经常打不开论坛……
烦死了……

不会啊,我就是用360浏览器的,正常的
回复 使用道具 举报
黄炳期 发表于 2013-11-5 11:11
不会啊,我就是用360浏览器的,正常的

那就不知道了  
也没上乱七八糟的网站   就是第二次出这问题了
回复 使用道具 举报
寻丶丶觅 发表于 2013-11-4 23:39
class Super
{
        int i = 20;

静态变量能覆盖父类非静态变量???
不能吧……

主函数定义的    i   呢???
回复 使用道具 举报
Clare0621 发表于 2013-11-5 00:15
程序一:子类中并未定义成员变量,static int i = 4,定义了一个静态变量或叫类变量。因此子类构造函数里面 ...

d.i
调用不是类变量   i  吗?
代码我加上了打印语句
还有  输出结果   
麻烦再帮我看看
回复 使用道具 举报
李新辉 发表于 2013-11-5 11:43
d.i
调用不是类变量   i  吗?
代码我加上了打印语句

我原回复说错了,根据你重新编辑的代码看:
程序一:子类未定义成员变量,因此子类构造函数Demo里面的i可看成:super.i = 5,因而后面打印的 d.i 值也为5;
程序二:子类定义了静态成员变量,所以子类构造函数里面的 i=5可看成是:this.i = 5;操作的是子类成员变量i,与父类无关
最后,俩个程序打印的 d.i 值都是父类的成员变量 i ,因为多态时,成员变量并不具备多态性。也即不管编译还是运行,都参考左边即引用的类型,这里是父类。
回复 使用道具 举报
本帖最后由 李新辉 于 2013-11-5 15:00 编辑
Clare0621 发表于 2013-11-5 00:15
顺序反了,根据你重新编辑的代码,下面程序一指楼主第二个程序,程序二指第一个程序:

// 程序一:子类中 ...

顺序反了,根据你重新编辑的代码,下面程序一指楼主第二个程序,程序二指第一个程序:

// 程序一:子类中并未定义成员变量。因此子类构造函数里面的i操作的是父类的属性i,可理解为:super.i = 5;在子类实例化过程中会先调用父类构造函数,在调用子类构造函数,最后打印的d.i是父类的属性i,因此为5.


                System.out.println("f  "+i);  //那么这个位置打印这个     i   又是怎么回事呢?
                System.out.println("   "+d.i);//5


//程序2:static int i = 4,定义了一个静态成员变量变量或叫类变量。因为子类有了属性i,则子类构造函数里面的i = 5,可理解为this.i = 5;而最后打印d.i的值同样为父类的i,但与程序一不同的就是子类构造函数里面的语句 i = 5,操作的是子类变量与父类无关,因而d.i只经过父类构造函数初始化为22.
另:可在输出d.i语句后面,加上一句:System.out.println(this.i)加以验证,输出的值应为5
                                                      //主函数为静态,不可能有this引用!!!我已经验证过……

System.out.println("   "+d.i);//22我认为此处打印的是对象中    i    ,对象中还是父类继承来的i     
                                           //如果没有对象的存在,那么打印   i   就是静态的类变量   i=4

回复 使用道具 举报
    System.out.println("f  "+i);  //那么这个位置打印这个     i   又是怎么回事呢?——————>这个  i   是主函数里面的 i 啊,那是个局部变量,在主函数有效,所以打印a和f都是4.
    System.out.println("   "+d.i);//5

//主函数为静态,不可能有this引用!!!我已经验证过…——————对的

System.out.println("   "+d.i);//22我认为此处打印的是对象中    i    ,对象中还是父类继承来的i     
                                           //如果没有对象的存在,那么打印   i   就是静态的类变量   i=4————————>听不懂,如果不建立对象,构造函数根本不会被调用,那里根本执行不到啊

评分

参与人数 1技术分 +1 收起 理由
乔兵 + 1

查看全部评分

回复 使用道具 举报
Clare0621 发表于 2013-11-5 16:36
System.out.println("f  "+i);  //那么这个位置打印这个     i   又是怎么回事呢?——————>这个   ...

不建立对象   类加载  静态变量已经存在   这时候直接打印   i   就是  静态变量 而已
静态给类 初始化的嘛……

对不??
回复 使用道具 举报
李新辉 发表于 2013-11-5 16:54
不建立对象   类加载  静态变量已经存在   这时候直接打印   i   就是  静态变量 而已
静态给类 初始化的 ...

恩,对程序而如此
回复 使用道具 举报
heke 发表于 2013-11-5 00:57
成员函数在多态调用时,编译看左边,运行看右边。Demo2中i是成员函数中的局部变量,所以调用的是子的i,先初 ...

1     总结:因为当调用静态方法时,只要建立子类对象,父类与子类中的静态方法都会随之加载入内存,是不需要调用就可直接用类名.方法名的,而不需要对象。        
2     只要引用还存在,就看引用变量的类型。

1和2有关系么  为什么我看半天看不出来关系···1我知道 但是在这个程序里好像没体现啊
2是什么意思  说的是 父类引用指向子类对象么      !!!


回复 使用道具 举报
heke 发表于 2013-11-5 00:57
成员函数在多态调用时,编译看左边,运行看右边。Demo2中i是成员函数中的局部变量,所以调用的是子的i,先初 ...

第一个结果为5的程序  最后 d.i 不是应该看父类的  i 么  前面也是父类引用指向子类对象  成员变量应该看父类里面的啊  跟 主函数里定义了一次  i  有什么关系   求告知!!!
回复 使用道具 举报
12下一页
您需要登录后才可以回帖 登录 | 加入黑马