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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 潘星 中级黑马   /  2012-8-10 15:40  /  2707 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

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",问当创建子类对象的时候
是不是也同时创建了父类的对象,而如果创建子类对象指向父类的引用的话
是不是就没有创建对象?
                                                               
                                                               
                                                               
                                                       
                                                               
                                                               
                                                               

评分

参与人数 1技术分 +1 收起 理由
杨志 + 1

查看全部评分

8 个回复

正序浏览
先说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,才能调用到子类;
        子类当父类建立对象,即使子类类中有相同的函数都只会调用到子类中对象的构造函数。
注:构造代码块是建立几个对象就会执行几次,而静态代码块无论建立多少个对象都只会执行一次。
回复 使用道具 举报
潘星 中级黑马 2012-8-10 17:55:16
8#
是我看错了,现在明白了,此问题以解决,谢谢
回复 使用道具 举报
潘星 发表于 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 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 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");
        }
}


评分

参与人数 1技术分 +1 收起 理由
张_涛 + 1 赞一个!

查看全部评分

回复 使用道具 举报
王少岩 发表于 2012-8-10 15:59
首先我感觉Zi z=new Zi(); Fu f=new Zi();这两句执行后输出的结果应该是一样的,他们都是创建了子类对象, ...

可是结果是不一样的啊
回复 使用道具 举报
加载子类时会先加载父类
创建子类对象时,会先加载父类对象
关于静态代码块,代码块,构造函数加载顺序是:,
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",问当创建子类对象的时候
是不是也同时创建了父类的对象,而如果创建子类对象指向父类的引用的话
是不是就没有创建对象?
                                                               
                                       

评分

参与人数 1技术分 +1 收起 理由
杨志 + 1

查看全部评分

回复 使用道具 举报
首先我感觉Zi z=new Zi(); Fu f=new Zi();这两句执行后输出的结果应该是一样的,他们都是创建了子类对象,只不过引用变量不同而已。

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

个人理解,欢迎指正
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马