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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

class Super
{
        int i = 0;
        public Super(String a)
        {
                System.out.println("A");
                i = 1;
        }
        public Super()
        {
                System.out.println("B");
                i+=2;
        }
}

class  Demo extends Super
{
        public Demo(String a)
        {
                System.out.print("c");
                i=5;
        }
        public static void main(String[] args)
        {
                int i = 4;
                Super d = new Demo("A");
                System.out.println(d.i);
        }
}
疑问1: 这道题的结果是什么?
疑问2:main函数中的 int i = 4 是不是存在地方区,为什么子类继承了int i = 0而没有用到 int i =
5?
疑问3:最后的d.i是什么意思?

4 个回复

倒序浏览
1: 结果是
B
c5
2:main中的int i=4 只在main方法里有效属于main方法。
3:d.i是子类重父类继承的属性。由于 i 没有被访问修饰符private修饰 子类可以直接使用作为本类的属性。
Super d = new Demo("A");创建一个子类对象,创建子类对象时会先创建父类对象所以先执行super类的构造器输出 System.out.println("B");然后在执行子类的构造器System.out.print("c");并把继承的 i  的值=5,  System.out.println(d.i);输出的时候就是5了。

评分

参与人数 1技术分 +1 收起 理由
房宝彬 + 1

查看全部评分

回复 使用道具 举报
结果是 B c 5
在对子类对象进行初始化时,父类的构造函数也会运行,
那是因为子类的构造函数默认第一行有一条隐式的语句 super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();

为什么子类一定要访问父类中的构造函数。

因为父类中的数据子类可以直接获取。所以子类对象在建立时,需要先查看父类是如何对这些数据进行初始化的。
所以子类在对象初始化时,要先访问一下父类中的构造函数。
如果要访问父类中指定的构造函数,可以通过手动定义super语句的方式来指定。

注意:super语句一定定义在子类构造函数的第一行。



子类的实例化过程。

结论:
子类的所有的构造函数,默认都会访问父类中空参数的构造函数。
因为子类每一个构造函数内的第一行都有一句隐式super();

当父类中没有空参数的构造函数时,子类必须手动通过super语句形式来指定要访问父类中的构造函数。

当然:子类的构造函数第一行也可以手动指定this语句来访问本类中的构造函数。
子类中至少会有一个构造函数会访问父类中的构造函数。

评分

参与人数 1技术分 +1 收起 理由
房宝彬 + 1

查看全部评分

回复 使用道具 举报
本帖最后由 丁佼 于 2012-3-18 00:30 编辑

1、答案是:
B
c5
2、mian方法中的i存在于堆内存,方法区存放的是静态变量和方法代码。
3、实际执行过程中mian方法里定义的int i = 4属于局部变量,而d.i 调用的是能作为d的成员变量使用的 i ,即不是定义在方法的语句块里的,而是定义在class语句块里的变量,本例里面也就是从Super类继承的 i

最后分析一下语句的执行过程,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a、首先是mian方法执行   Super d = new Demo("A");
/*即调用Demo的Demo(String a){}构造函数来产生对象。而子类构造函数执行时会首先执行一句super();这里调用的是调用父类的空参数构造函数*/

b、即执行了  Super(){    System.out.println("B");                i+=2;  }  
/*也就是在控制台上打印了B ,同时 d 在建立对象的时候也继承了Super类的 i,初始值为0,在Super()执行后 i 经运算改为 2 。
至此,Demo(String a)的第一句的super();执行完毕*/

c、代码返回到下一句开始执行  {   System.out.print("c");                i=5; }
/*也就是在控制台打印c ; 并且将 i 直接赋值成为 5。
至此Demo(String a)执行完毕*/

d、返回到mian方法执行下一句  System.out.println(d.i);
/*这里的d.i前面已经说了,调用的是可以作为d的成员属性使用的i,也就是Super类里继承来的i,在上面一步中已经被赋值成为了 5 ,所以在控制台打印 5 , 由于上一条打印语句打印完c 之后没有换行,所以c和5是连起打印的。
函数执行结束*/

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
注意,语句的大小写,a 步里面的super在java里表示调用父类,而不是自定义的那个Super类(虽然例子里的Super是作为父类存在,但是不能代替super使用),super();语句作用是调用父类的空参数构造函数,在子类的每一个构造函数里都作为第一句语句存在,不管你有没有显式的写出来,java默认就是有的。
回复 使用道具 举报
结果:   B
          C5
因为在调用子类的构造方法的时会首先调用父类的空构造在这是没有写出来而已,但是肯定是调用了父类空构造的。至于5则是对象d的成员变量i的值了。
d.i在这里用到了多态了在父类中有成员变量i子类通过继承得到成员变量i,main方法中是父类引用指向子类对象,在实际中应用中会根据这个对象实际是什么来进行相应的调用的。
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马