黑马程序员技术交流社区

标题: 静态代码块,构造代码块和构造函数 [打印本页]

作者: 黎志文    时间: 2013-5-29 17:18
标题: 静态代码块,构造代码块和构造函数
本帖最后由 黎志文 于 2013-5-29 18:45 编辑

class StaticCode
{
          private static StaticCode tt = new StaticCode();
          static
         {
                System.out.println("StaticCode类的静态代码块");
         }
         private InstanceCode In = new InstanceCode();
         private StaticCode()
         {
                System.out.println("StaticCode类的构造函数");
         }

        {
                System.out.println("StaticCode类的构造代码块");
        }
         public static void main(String[] args){}
}


class InstanceCode
{
          static
         {
               System.out.println("Instance类的静态代码块");
         }
         {
               System.out.println("Instance类的构造代码块");
          }
         InstanceCode()
        {
               System.out.println("Instance类的构造函数");
         }
}
执行后的结果竟然是:
Instance类的静态代码块
Instance类的构造代码块
Instance类的构造函数
StaticCode类的构造代码块
StaticCode类的构造函数
StaticCode类的静态代码块                                 

StaticCode类的静态代码块竟然最后才执行,这是为啥???

作者: 王林涛    时间: 2013-5-29 17:57
本帖最后由 王林涛 于 2013-5-29 17:59 编辑

楼主请发全码!
静态代码块,构造代码块,构造函数,首先你要先了解他们的具体作用是干什么的!
1 静态代码块,是给类名初始化用的,优先于对象存在,所以它肯定优先于构造代码块.静态代码块存在于内存的方法区
2 构造代码块,是给类中的所有对象初始化用的,对象一建立,构造函数代码块就会运行,类实例构造代码块优先于构造函数运行.
3 构造函数,构造函数是给类中指定的对象初始化用的.
作者: 黎志文    时间: 2013-5-29 18:04
王林涛 发表于 2013-5-29 17:57
楼主请发全码!
静态代码块,构造代码块,构造函数,首先你要先了解他们的具体作用是干什么的!
1 静态代码块,是 ...

这就是全码了!你所说的我能理解,按照这样的逻辑,首先private static StaticCode tt = new StaticCode();
这条语句就应该是先加载StaticCode这个类,所有先打印StaticCode这个类的静态代码块,接着打印它的构造代码块,最后是打印它的构造函数里面的内容;紧接着private InstanceCode In = new InstanceCode();这条语句创建一个InstanceCode类,那么再依次执行该类的静态代码块、构造代码块和构造函数里的内容;可是打印出来的结果是想发的,先打印InstanceCode这个类的相关内容,最后才执行StaticCode类的静态代码块。有点匪夷所思
作者: 王林涛    时间: 2013-5-29 18:29
黎志文 发表于 2013-5-29 18:04
这就是全码了!你所说的我能理解,按照这样的逻辑,首先private static StaticCode tt = new StaticCode( ...

你的Test类在哪?
作者: Super_Class    时间: 2013-5-29 18:37
       
                        |--静态代码块和构造代码块
                                静态代码块:随着类的加载二执行,而且只执行一次
                                构造代码块:每次创建对象就可以执行。
作者: 黎志文    时间: 2013-5-29 18:42
王林涛 发表于 2013-5-29 18:29
你的Test类在哪?

不好意思,刚开始StaticCode这个类我是起名叫Test类,但是后来编译的时候发现,该类的java名称是StaticCode,即StaticCode.java,为了保持一致性,我把后来就把Test改成了StaticCode,但没再去重新执行,所有造成了打印结果和原码有一点不一致,sorry!
作者: 黎志文    时间: 2013-5-29 18:47
Super_Class 发表于 2013-5-29 18:37
|--静态代码块和构造代码块
                                静态代码块:随着类的加载二执行,而且只执行一次
                                构造代码块:每 ...

谢谢,这个我能明白,那请问:静态代码块、静态成员变量和静态成员函数,这三个执行的先后顺序又是什么?
作者: 王林涛    时间: 2013-5-29 18:51
Super_Class 发表于 2013-5-29 18:37
|--静态代码块和构造代码块
                                静态代码块:随着类的加载二执行,而且只执行一次
                                构造代码块:每 ...

先运行InstanceCode方法没错,这个当然知道,随着类的加载而加载,且只运行一次.
但是,关键在StaticCode方法中为什么先输出的是"StaticCode构造代码块"而不是先输出的"StaticCode静态代码块"呢?
作者: 王林涛    时间: 2013-5-29 18:55
黎志文 发表于 2013-5-29 18:42
不好意思,刚开始StaticCode这个类我是起名叫Test类,但是后来编译的时候发现,该类的java名称是StaticCo ...

前者输出我明天,程序一进来直接加载InstanceCode方法,但是我也有些费解,为什么在Static方法中,先输出的是"StaticCode构造代码块呢"?你如果懂了麻烦也告诉我一声吧!,然后我给你发一个也是这样的执行程序.你看看
希望对你有帮助!
class Fu
{
        static
        {
                System.out.println("父类静态代码块");
        }

        {
       
                System.out.println("父类构造代码块");
        }

        Fu()
        {
                System.out.println("父类构造方法");
          
        }
}

class Zi extends Fu
{
        static
        {
                System.out.println("子类静态代码块");
        }

        {
       
                System.out.println("子类构造代码块");
        }
       
        Zi()
        {
                System.out.println("子类构造方法");
          
        }
}



class  ExtendsDemo
{
        public static void main(String[] args)
        {
                Zi z = new Zi();
        }
}
/*
  父类静态代码块
  子类静态代码块

  父类构造代码块
  父类构造函数

  子类构造代码块
  子类构造函数



  代码走向:
        父类静态代码块
        子类静态代码块

        子类构造函数super()
        父类构造函数

        父类构造代码块
        父类构造方法


        子类构造代码块
        子类构造放

    必选先走父亲静态,子静态

        走父类构造,构造方法

        走子类构造,构造方法

*/
作者: Super_Class    时间: 2013-5-29 19:03
静态代码块 最先被调用。

静态成员变量和静态成员函数按照你调用顺序执行。


class A{
static{
sop("static code..")
}


public A(){
sop("A Instance code..");


}


public static x = 2;


public static void method(){

sop("x = "+x);
}
}
作者: 神之梦    时间: 2013-5-29 19:19
把楼主的代码顺序稍微改变下,结果是这样的
  1. class StaticCode
  2. {


  3.             static
  4.           {
  5.                  System.out.println("StaticCode类的静态代码块");
  6.           }

  7.                  private static StaticCode tt = new StaticCode();
  8.                        
  9.                 private InstanceCode In = new InstanceCode();

  10.           private StaticCode()
  11.           {
  12.                  System.out.println("StaticCode类的构造函数");
  13.           }

  14.          {
  15.                  System.out.println("StaticCode类的构造代码块");
  16.          }
  17.           public static void main(String[] args){

  18.                   }
  19. }


  20. class InstanceCode
  21. {
  22.            static
  23.           {
  24.                 System.out.println("Instance类的静态代码块");
  25.           }
  26.           {
  27.                 System.out.println("Instance类的构造代码块");
  28.            }
  29.           InstanceCode()
  30.          {
  31.                 System.out.println("Instance类的构造函数");
  32.           }
  33. }
复制代码


我想这里肯定牵涉到了一个特殊的地方,楼主把private static StaticCode tt = new StaticCode();把这句加上了静态的修饰符。
加上这个之后,代码的执行顺序就变成了先执行静态代码块或者上面的这句,看谁在前面就执行谁,也就是说他两的优先级在这里已经相等了,只是位置的问题了。
当执行者句话时,因为在这个类里边还有另一个InstanceCode类的对象创建,就跑到InstanceCode这个类中去进行初始化,完了之后,再回来执行自己的初始化。
如果楼主把private static StaticCode tt = new StaticCode();这句中的static去掉,结果就只有("StaticCode类的构造函数");
其中的原因,只有等大神了,但可以肯定的是,之所以没有按照楼主的想法执行的原因:
一是private static StaticCode tt = new StaticCode();这句加上了static。
二是去执行上面这句时,会先跑到InstanceCode类去初始化,是因为楼主把这个InstanceCode类的实例对象放在 StaticCode这个类的成员变量位置上,而不是在主方法中。

其中的奥秘我也很想知道,大神快来吧.....



作者: 精彩生活向钱看    时间: 2013-5-30 09:34
看不懂啊




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