黑马程序员技术交流社区

标题: 子类继承父类函数调用问题 [打印本页]

作者: 潘星    时间: 2012-8-10 15:40
标题: 子类继承父类函数调用问题
class StaticDemo
{
        public static void main(String[] args)
        {               
                Zi z=new Zi();                
                //Fu f=new Zi();
        }
}
class  Fu
{
        static
        {
                System.out.println("aa");
        }
        {
                System.out.println("bb");
        }
        Fu()
        {
                System.out.println("cc");
        }
       
}
class Zi extends Fu
{
        static
        {
                System.out.println("11");
        }
        {
                System.out.println("22");
        }
        Zi()
        {
                System.out.println("33");
        }
}
以上代码中Zi z=new Zi();的结果是"aa" "bb" "cc" "11"        "bb" "cc" "22" "33",
而Fu f=new Zi(); 的结果是"aa" "11" "bb" "cc" "22" "33",问当创建子类对象的时候
是不是也同时创建了父类的对象,而如果创建子类对象指向父类的引用的话
是不是就没有创建对象?
                                                               
                                                               
                                                               
                                                       
                                                               
                                                               
                                                               

作者: 王少岩    时间: 2012-8-10 15:59
首先我感觉Zi z=new Zi(); Fu f=new Zi();这两句执行后输出的结果应该是一样的,他们都是创建了子类对象,只不过引用变量不同而已。

在创建子类对象的时候,子类构造函数会隐式的执行super()调用父类的构造函数,所以在创建子类对象的时候也会创建父类对象,以代码为例执行顺序是:父类的静态代码块-->子类静态代码块-->父类构造代码块-->父类构造函数-->子类构造代码块-->子类构造函数

个人理解,欢迎指正
作者: 胡刚涛    时间: 2012-8-10 16:27
加载子类时会先加载父类
创建子类对象时,会先加载父类对象
关于静态代码块,代码块,构造函数加载顺序是:,
1,静态代码块;2,代码块;3,构造函数。
静态代码块的加载不需要创建对象,类一加载就执行,且只执行一次。
代码块和构造函数依赖对象加载。

class StaticDemo
{
        public static void main(String[] args)
        {               
                Zi z=new Zi();
        }
}
class  Fu
{
        static
        {
                System.out.println("aa");
        }
        {
                System.out.println("bb");
        }
        Fu()
        {
                System.out.println("cc");
        }
        
}
class Zi extends Fu
{
        static
        {
                System.out.println("11");
        }
        {
                System.out.println("22");
        }
        Zi()
        {
                System.out.println("33");
        }
}
以上代码中Zi z=new Zi();的结果是"aa" "bb" "cc" "11"        "bb" "cc" "22" "33",结果也是"aa" "11" "bb" "cc" "22" "33"吧,因为静态代码会随类的加载先加载
而Fu f=new Zi(); 的结果是"aa" "11" "bb" "cc" "22" "33",问当创建子类对象的时候
是不是也同时创建了父类的对象,而如果创建子类对象指向父类的引用的话
是不是就没有创建对象?
                                                               
                                       
作者: 潘星    时间: 2012-8-10 16:36
王少岩 发表于 2012-8-10 15:59
首先我感觉Zi z=new Zi(); Fu f=new Zi();这两句执行后输出的结果应该是一样的,他们都是创建了子类对象, ...

可是结果是不一样的啊
作者: 张雪磊    时间: 2012-8-10 16:49
本帖最后由 张雪磊 于 2012-8-10 16:52 编辑

在对子类对象进行初始化时,父类的构造函数也会运行,
那是因为子类的构造函数默认第一行有一条隐式的语句 super();
super():会访问父类中空参数的构造函数。而且子类中所有的构造函数默认第一行都是super();

对于下面的代码执行顺序如下
        当创建了子类对象的时候会先执行构造方法的隐式语句super(),调用父类的构造方法,所以加载子类的时候会自动加载父类,  这时候就加载了两个类
        由于两个类中都有静态代码块所以会先执行静态代码块里的代码,而且是父类先加载,所以会先打印“aa”(父类静态代码块)   然后是   “11”(子类静态代码块) 。
        静态代码块执行完后,就会 执行父类构造函数里的数据,而父类里有构造代码块,构造代码块是先于构造方法执行的的,且只执行一次,所以,接着就打印了
         “bb”(父类构造代码块)  “cc”(父类构造方法)。最后执行完了父类里的操作,自然会会到子类执行子类的构造代码块和构造方法,你创建的是子类对象嘛,
        所以又打印了“22”(子类构造代码块)  “33”(子类构造方法)。Zi z=new Zi();  的结果就是aa 11 bb cc 22 33,不知道你的"aa" "bb" "cc" "11"        "bb" "cc" "22" "33"
        怎么得来的?你的结果应该是错误的,Fu f=new Zi(); 这个跟 Zi z=new Zi(); 的结果是相同的。因为没有涉及的方法的调用问题,都是在对象初始化,所以没有不同。

        
class StaticDemo
{
        public static void main(String[] args)
        {               
                Zi z=new Zi();                 
                //Fu f=new Zi();
        }
}
class  Fu
{
        static
        {
                System.out.println("aa");
        }
        {
                System.out.println("bb");
        }
        Fu()
        {
                System.out.println("cc");
        }
        
}
class Zi extends Fu
{
        static
        {
                System.out.println("11");
        }
        {
                System.out.println("22");
        }
        Zi()
        {
      
                     
                System.out.println("33");
        }
}



作者: 尤洋    时间: 2012-8-10 16:58
本帖最后由 尤洋 于 2012-8-10 16:59 编辑

“以上代码中Zi z=new Zi();的结果是"aa" "bb" "cc" "11"        "bb" "cc" "22" "33",
而Fu f=new Zi(); 的结果是"aa" "11" "bb" "cc" "22" "33",问当创建子类对象的时候
是不是也同时创建了父类的对象,而如果创建子类对象指向父类的引用的话
是不是就没有创建对象?    ”

楼主你提的问题本身 就有问题
首先    无论是只运行 Zi z=new Zi();      还是只运行Fu f=new Zi();    或者两个同时运行
结果的  前6个肯定都是一样的  aa    11       bb      cc       22       33,只不过当创建两个对象时,非静态的初始化过程需要再运行一遍,后面再多
加上bb  cc    22     33
作者: 王少岩    时间: 2012-8-10 17:06
潘星 发表于 2012-8-10 16:36
可是结果是不一样的啊

单独执行Zi z=new Zi();的结果是"aa" "11" "bb" "cc" "22" "33",
单独执行Fu f=new Zi();的结果是"aa" "11" "bb" "cc" "22" "33".
同时执行Zi z=new Zi();Fu f=new Zi();的结果是"aa" "11" "bb" "cc" "22" "33" "bb" "cc" "22" "33".

创建子类对象时首先加载静态代码块且只加载一次,然后加载父类,构造代码块优先于构造函数执行
作者: 潘星    时间: 2012-8-10 17:55
是我看错了,现在明白了,此问题以解决,谢谢
作者: 黑马-王泽斌    时间: 2012-8-10 19:27
先说Zi z = new Zi():静态代码块随类加载而加载,肯定会先执行所有的,无论建多少个对象都只执行一次,而构造代码块会随对象的建立而先执行。 当建立子类的对象后,先打印aa、11,然后去子类中调用这个对象的相同参数的构造函数,而每个构造函数里的第一行如果没定义super()都会有一个隐式的super(),这时它会先去调用父类中的相同参数的构造函数,同时建立父类构造函数的对象,然后执行父类中的构造代码块,打印bb,然后执行此父类构造函数,打印cc,执行完父类再回来执行自己,先打印构造代码块22,然后打印33。
所以打印:aa,11,bb,cc,22,33.
再说Fu f = new Zi():这个是子类当做父类建立对象,在这个程序中跟Zi z = new Zi()执行结果一样。
不同是:如果调用到子类中特有的函数(即父类中没有的函数,而子类中有)这时就需要强转:Zi z =(Zi)f,才能调用到子类;
        子类当父类建立对象,即使子类类中有相同的函数都只会调用到子类中对象的构造函数。
注:构造代码块是建立几个对象就会执行几次,而静态代码块无论建立多少个对象都只会执行一次。




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2