请看下面两个程序:
(1)
public class InitPuzzle {
      private static boolean initialized = false;
      private static Thread t = new Thread(new Runnable() {
                  public void run() {
                      System.out.println(Thread.currentThread());
                      initialized = true;
                  }
      });      static {
          t.start();
          System.out.println(Thread.currentThread());
  
          try{
            Thread.sleep(1000);
            System.out.println(initialized);
          }catch (InterruptedException e){
              throw new AssertionError(e);
          }
      }      public InitPuzzle(){
         System.out.println("Initialization is finished!");
      }      public static void main(String[] args){
         new InitPuzzle();
      }
}=============================================(2)public class InitPuzzle {
      private boolean initialized = false;
      private Thread t = new Thread(new Runnable() {
                  public void run() {
                      System.out.println(Thread.currentThread());
                      initialized = true;
                  }
      });      {
          t.start();
          System.out.println(Thread.currentThread());
  
          try{
             Thread.sleep(1000);
             System.out.println(initialized);
          }catch (InterruptedException e){
              throw new AssertionError(e);
          }
      }      public InitPuzzle(){
          System.out.println("Initialization is finished!");
      }      public static void main(String[] args){
          new InitPuzzle();
      }
}这两个类的差别只在前者多了static,但是运行输出结果为什么不一样呢?

解决方案 »

  1.   

      static 是静态的意思,也就是说它修饰的值是改变不了的,下面的第二个类里修饰属性时候没有用static,所以它的值是可以改变的!
      

  2.   

    static 修饰的值是改不了的?????
      

  3.   

    static 段在初始化的时候是先执行的.
      

  4.   

    static字段在是对象初始化之前就已经初始化的。
      

  5.   

    当类被加载的时候首先运行STATIC块内的东东
      

  6.   

    类加载时先运行static代码块;再调用构造器
      

  7.   

    在Java编程思想这本书中,有初始化顺序的详细说明,仔细阅读一下就有答案
      

  8.   

    类初始化会先加载static 的
      

  9.   

    各位,我问的是为什么一个输出是false而另一个输出的是true。
      

  10.   

    做些一些测试,也不是很明白第一个程序的结果。。第一个程序public class InitPuzzle {
    private static boolean initialized = false;
    private static Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println("1");
    initialized = true;
    System.out.println("2");
    }
    }); static {
    t.start();
    System.out.println("3"); try{
    Thread.sleep(1000);
    System.out.println(initialized);

    }catch (InterruptedException e){
    throw new AssertionError(e);
    }
    } public InitPuzzle(){
    System.out.println("Initialization is finished!");
    } public static void main(String[] args){
    new InitPuzzle();
    }
    }
    //运行多次会有输出结果顺序会不同:
    //3
    //1
    //false
    //2
    //Initialization is finished!虽然不明白,但运行多几次就可以看出 是先打印System.out.println(initialized) 再执行initialized = true的第二个程序public class InitPuzzle2 {
    private boolean initialized = false;
    private Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println("1");
    initialized = true;
    System.out.println("2");
    }
    }); {
    t.start();
    System.out.println("3"); try{
    Thread.sleep(1000);
    System.out.println(initialized);
    }catch (InterruptedException e){
    throw new AssertionError(e);
    }
    } public InitPuzzle2(){
    System.out.println("Initialization is finished!");
    } public static void main(String[] args){
    new InitPuzzle2();
    }
    }
    输出结果为
    3
    1
    2
    true
    Initialization is finished!前面312一下就执行打印了可见initialized 已被设为true
      

  11.   

    我理解是同是static的,先会执行{},然后才去初始化同是static的变量,因为我直接把
    private static boolean initialized = true;
    这样每次都是true还是期待高人说明
      

  12.   

    Thinking in Java 中文第四版
    书94页
    5.7.1初始化顺序中提到:
    在类的内部,变量定义的先后顺序决定了初始化的顺序。即使变量定义散步于方法定义之间,它们仍旧会在任何方法(包括构造器)被调用之前得到初始化。5.7.2静态数据的初始化中提到:
    书96页第三自然段
    初始化的顺序是先静态对象,而后是非静态对象。class Window
    {
    Window(int er)
    {
    System.out.println("Window(" + er + ")");
    }
    }class House
    {
    Window w1 = new Window(1);
    House()
    {
    System.out.println("House()");
    w3 = new Window(33);
    }
    Window w2 = new Window(2);
    void f()
    {
    System.out.println("f()");
    }
    Window w3 = new Window(3);
    }public class OrderOfInitialization {        //这里换成static Window w = new Window(4);楼主试试
    //Window w = new Window(4);
    public static void main(String[] args) {
    House h = new House();
    h.f();
    }}
      

  13.   

    (1)Thread[main,5,main]
    Thread[Thread-0,5,main]
    false
    Initialization is finished!
    (2)Thread[main,5,main]
    Thread[Thread-0,5,main]
    true
    Initialization is finished!
    没有差别的地方我就不说了,被标示的是有差别的地方,原因:
    staitc是静态方法,也就是说程序已被创建就调用static,所以第一个程序你一创建InitPuzzle的对象,程序就自动先执行一遍static方法体中的方法,由于没有执行private static Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println(Thread.currentThread());
    initialized = true;
    }
    });
    所以当执行t.start()方法时,参数还是false;
    当你去掉static时“{}”在java中叫做实例初始化块(instance initializer block),是除了static之外第二优先级的方法体,所以这时你调用t.start()时程序已经先执行static方法的run方法将参数变成true了,注意:此处“{}”不能去掉,否则就产生编译错误,另外我给出的运行结果不一定是虚拟机执行的顺序,因为当第一种情况是虚拟机是先执行打印false,在执行打印Thread[main,5,main] Thread[Thread-0,5,main] Initialization is finished!(这个是根据不同机器的运行效率决定的,你可以再你的机器上实验下,此处涉及线程)
      

  14.   

    我知道被执行了,不过是后执行的,先执行的static,然后在对函数初始化
      

  15.   

        private static Thread t = new Thread(new Runnable() {
            public void run() {
                System.out.println("before");
                initialized = true;
                System.out.println("after");
            }
        });
    你将t的定义改成如上所示,就会发现在打印false之前一定会打印出before,这就说明你说的“不过是后执行的”是错误的。
    还有“然后在对函数初始化”,java里面没有“函数初始化”这个概念。
      

  16.   

    1 类被加载的时候首先运行STATIC块内的语句,也就是先于构造器的调用
    2 静态修饰的变量,是指该变量被所有的该类的对象共享。其存储的位置是在 内存的方法区。
    注意 静态变量在类加载的时候初始化的
      

  17.   

    (1)before
    Thread[main,5,main]
    false
    Initialization is finished!
    after
    (2)before
    after
    Thread[main,5,main]
    true
    Initialization is finished!
    这是你改了之后的结果,如果像你说的那after的打印顺序你怎么解释,java的结果输出顺序不能只看代码的书写顺序,特别是线程这个地方,如果你想凭着人脑就分析虚拟机那是痴心妄想,这个地方不同机器的运行结果是不一样的。后面我说函数初始化实际上就是指类初始化函数
      

  18.   


    你还是没有正面回答我的问题呢,我问的是既然
    System.out.println("before");
    被执行到了,那么initialized = true;
    为什么没有被执行呢?别跟我说什么线程执行顺序不可控制,你别忘记了static代码块中有Thread.sleep(1000); 1秒钟对于jvm来说是很长的一段时间了,主线程sleep了1秒钟足够t线程跑完了。如果你觉得1秒不够,你可以改成主线程休眠10秒,1分钟,看看结果如何呢?
      

  19.   

    public class InitPuzzle {public static void main(String[] args){
    new InitPuzzle1();
    }
    }
    class InitPuzzle1{
    private static boolean initialized = false;
       private static Thread t = new Thread(new Runnable() {
            public void run() {
               
                initialized = true;
                System.out.println("before");
                System.out.println("after");

            }
        });
    static{
    t.start();
    System.out.println(Thread.currentThread()); try{
    t.sleep(5000);
    System.out.println(initialized);
    }catch (InterruptedException e){
    throw new AssertionError(e);
    }
    } public InitPuzzle1(){
    System.out.println("Initialization is finished!");

         }
    }你可以看看上面的输出结果,是不是更没有顺序
    Thread[main,5,main]
    false
    Initialization is finished!
    before
    after
      

  20.   

    哥们, 你设一下断点看应该就明白了,当我在第二个例子的initialized = true;这一句前设置了断点后,打印出来的是false,此时我的断点还没有放过,而是刚刚到这个断点。  我没学过线程,不知道什么意思。 我正在研究着呢。   估计你用这个方法应该能知道原因了!
      

  21.   

    用static 定义的话 下一次直接能使用,而不会再重新初始化
    而且改变也是 相当于 加锁一样处于 同步状态
      

  22.   

    我自己加了一些断点测了一下;
    由于是Thread
    所以在 t.start()之后不一定立刻执行t.run();执行顺序:
    static {
    1 ======= t.start();
    2 ========System.out.println(Thread.currentThread());try{
    3==========Thread.sleep(1000);
    4==========System.out.println(initialized);
    }catch (InterruptedException e){
    throw new AssertionError(e);
    }
    }public void run() {
    5 =========System.out.println(Thread.currentThread());
    6 ==========initialized = true;
    }
    所以是和执行顺序有关的。你也可以试一下下面代码:private static Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println(Thread.currentThread());
    initialized = true;
    System.out.println("Thread -- t : " + InitPuzzle.initialized);
    t_2.start();
    }
    }
    );
    private static Thread t_2 = new Thread(new Runnable() {
    public void run() {
    System.out.println(Thread.currentThread()); System.out.println("Thread t2: " + InitPuzzle.initialized);
    }
    }
    );
    t_2中的System.println中的InitPuzzle.initialized值为true;
      

  23.   


    "所以在 t.start()之后不一定立刻执行t.run();" 这没有问题,可是你别忘记了static代码块中有Thread.sleep(1000); 1秒钟对于jvm来说是很长的一段时间了,主线程sleep了1秒钟足够t线程跑完了。如果你觉得1秒不够,你可以改成主线程休眠10秒,1分钟,看看结果如何呢?
      

  24.   

    我想LZ困惑的是第一个事例代码,因为初始线程等待1000毫秒的目的是让t先执行
    完毕。并且从结果来看t确实很快的启动了(初始线程的打印后立即出现了t线程的
    打印,然后大概1秒的时间打印出“false”。看起来t线程对“initialized”的
    修改无效。首先要说明这个地方和对象的初始化无关,如果我们把main函数中的代码改为如下:
    try{
    Class.forName("InitPuzzle");
    }catch (Exception e){

    }这里没有实例化对象,只是加载了类,执行的结果除了没有构造函数里面的打印外其他都一样为了找到问题,把t线程修改一下,在修改 initialized 后加一个打印 private static Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println("t:" + Thread.currentThread());
    initialized = true;
    System.out.println("u:" + initialized);
    }
    });执行结果为 Thread[main,5,main]
    t:Thread[Thread-0,5,main]
    false
    u:true“U:true”说明t线程的修改是成功的,但它却出现了在“false”后面。
    所以执行流程变成了 “初始线程” -〉t线程 -〉“初始线程” -〉t线程,看来t线程在执行
    initialized = true;时被阻塞住了。你可以增大初始线程sleep的时间,结果不受影响。
    只是为什么被“阻塞”我也不能解释。
      

  25.   

    把程序改成这样试了一下public class InitTest {
    private static boolean initialized = false;
    private static int initI = 0;
    private static Thread t = new Thread(new Runnable() {
    public void run() {
    System.out.println("1");
    initI = 2;
    System.out.println(initI);
    }
    }); static {
    t.start();
    try {
    Thread.sleep(10000);
    } catch (InterruptedException e) {
    throw new AssertionError(e);
    }
    System.out.println(initialized); } public InitTest() {
    System.out.println("Initialization is finished!");
    } public static void main(String[] args) {
    new InitTest();
    }
    }怀疑是不是static块对static变量是同步的?
      

  26.   


    不是。而且没有“static块对static变量”这种提法
      

  27.   

    static 是类内的静态区域,当你用到或构造对象的时候首先第一触发的就是它
      

  28.   


    static的叫类初始化块,构造对象那叫实例初始化。你搞混了
      

  29.   

    public class InitPuzzle {
      private static boolean initialized = false;
      private static Thread t = new Thread(new Runnable() {
      public void run() {
      System.out.println(Thread.currentThread());
      initialized = true;
      }
      });  static {
      t.start();
      System.out.println(Thread.currentThread());
       
      try{
      Thread.sleep(1000);
      System.out.println(initialized);
      }catch (InterruptedException e){
      throw new AssertionError(e);
      }
      }  public InitPuzzle(){
      System.out.println("Initialization is finished!");
      }  public static void main(String[] args){
      new InitPuzzle();
      }
    }=============================================(2)public class InitPuzzle {
      private boolean initialized = false;
      private Thread t = new Thread(new Runnable() {
      public void run() {
      System.out.println(Thread.currentThread());
      initialized = true;
      }
      });  {
      t.start();
      System.out.println(Thread.currentThread());
       
      try{
      Thread.sleep(1000);
      System.out.println(initialized);
      }catch (InterruptedException e){
      throw new AssertionError(e);
      }
      }  public InitPuzzle(){
      System.out.println("Initialization is finished!");
      }  public static void main(String[] args){
      new InitPuzzle();
      }
    }这两个类的差别只在前者多了static,但是运行输出结果为什么不一样呢? 
     
     
     
    对我有用[0] 丢个板砖[0] 引用 举报 管理 TOP 回复次数:48  
     
    sunboylg
     
    (sunboylg) 等 级: 
     #1楼 得分:0回复于:2010-03-25 17:17:11static 是静态的意思,也就是说它修饰的值是改变不了的,下面的第二个类里修饰属性时候没有用static,所以它的值是可以改变的! 
     
     
      

  30.   

    我想匿名类要使用外部类,必须等类的初始化完成吧。所以t thread is blocked at initialized=true