public class Singleton {

   public static Singleton singleton=new Singleton();
   public static int a;
   public static int b=0;
   public static int c=2;
   
   
   private Singleton()
   {
   super();
   a++;
   b++;
           c++;
   }
   public static Singleton getInstance()
   {
   return singleton;
   }
   
   public static void main(String [] args)
   {
   Singleton sl=Singleton.getInstance();
   System.out.println("a="+sl.a);
   System.out.println("b="+sl.b);
   System.out.println("c="+sl.c);
   }
}找牛人解决以上一道题!在线等待回答

解决方案 »

  1.   

    public static int a;
    public static int b = 0;
    public static int c = 2;
    public static Singleton singleton = new Singleton();
      

  2.   


    嗯,我也认为是初始化的顺序问题,不过我还想问一下
    public static int a;
    public static int b=0;
    初始化时有什么区别吗?
      

  3.   

    public static Singleton singleton=new Singleton();这时a,b ,c, 都是1.  为什么a 再被默认初始化成0,而保留了1? 
      

  4.   


    因为a没有显式地赋予初始化值啊...
    可以尝试使用lazy方式初始化单例,看下结果的区别...
      

  5.   

    这时a,b ,c, 都是1. 为什么a 不再被默认初始化成0,而保留了1? 
      

  6.   


    你可以debug一下,我发现是又区别的,在这个例子中,先是a,b,c都变成1,接着初始化a,b,c,JVM发现a已经有值了(已经初始化)所以不赋默认值0,但是b,c无论是否已经初始化都赋值成程序指定的值。所以他们的区别是,对于"int a;"这种写法,如果a已经有值,那么不会被赋值0,否者会。
    对于“int a=0”,必需被赋值0,因为是你自己指定的。
      

  7.   

      
      public static Singleton singleton=new Singleton();
      public static int a;
      public static int b=0;
      public static int c=2;先初始化Singleton类对象singleton,此时a,b,c都是0,在构造函数中都变为1,然后再进行赋值。此时a已经有值了,所以a=1,然后再给b,c赋值,结果a=1,b=0,c=2.如果  public static int a;
      public static int b=0;
      public static int c=2;
      public static Singleton singleton=new Singleton();的话,a=0,b=0,c=2,执行完构造函数中,a=1,b=1,c=3
      

  8.   

    类初始化我一直还是没彻底弄明白,不知理解的是否对,请给指教:1 变量a,b,c,singleton 在调用构造函数的时候,先进行了默认的初始化,a=0,b=0,c=0,singleton=null;(a,b,c 在构造函数里加一输出可以验证).
    2 程序转而去追溯父类的构造函数(Object()).
    3 追溯完父类的构造函数,回来再到本类的构造函数。执行(a++,b++,C++).
    4 执行完构造函数后,在对4个变量进行显示初始化。b,c,singleton 都将赋新值。 a 没有显示初始化,默认从构造函数返回的了。(我理解的核心思想是: 变量初始化分两次进行,1 默认初始化(刚执行构造函数时),2 显示初始化(构造函数结束前)。
      

  9.   

    还有个问题,程序用到singleton 对象时,直接调用getInstance(),(没有"new"的过程了),说明对象已经存在了。
    那么这个对象是什么时候存在的? 
    是编译后就存在了? 还是引用时产生的?
    有点想不明白。请讲得具体一些。
      

  10.   

    又是这个问题
    要知道,定义和赋值是两个语句
    int a = 0; 相当于 int a; a = 0;两条语句,int a是定义,用于分配内存,即方法栈生成的时候,在数据区的a的相对地址里留出一定的空间(int长度),作为a的内存空间,a = 0;是赋值语句,在语句被执行的时候的,往a的内存地址保存一个0,所以定义语句是在栈生成的时候就决定,赋值语句是在程序执行的时候决定的。而对于成员变量,int定义的时候,系统会自动初始化变量为0//所以
    public static Singleton singleton=new Singleton(); //此时a,b,c被定义,在栈中分配空间,然后出初始化为0,然后掉用构造方法,分别执行相应的赋值语句
      public static int a;
      public static int b=0; //然后 这里 相当于 int b; b=0; 即b=0语句被执行,所以b有重新变为0
      public static int c=2; //同理,这里把c又变成2
      

  11.   

    看一下程序都干了些什么就清楚了呗。
    PS:在下也是刚接触字节码不久,只能给点简单的说明:
    第一种情况:class Test9 {
    public static Test9 singleton = new Test9();
    public static int a;
    public static int b = 0;
    public static int c = 2;
    //public static Test9 singleton = new Test9();
    ……
    }对应字节码:
    public class com.codetest.test.Test9 {
      public static com.codetest.test.Test9 singleton;  public static int a;  public static int b;  public static int c;  static {};
        Code:
           0: new           #17                 // class com/codetest/test/Test9
           3: dup           
           4: invokespecial #18                 // Method "<init>":()V      // 这里应该是调用构造函数
           7: putstatic     #5                  // Field singleton:Lcom/codetest/test/Test9;
          10: iconst_0      
          11: putstatic     #3                  // Field b:I         // 这里对应 b = 0
          14: iconst_2      
          15: putstatic     #4                  // Field c:I         // 这里对应 c = 2
          18: return        
    }第二种情况:class Test9 {
    //public static Test9 singleton = new Test9();
    public static int a;
    public static int b = 0;
    public static int c = 2;
    public static Test9 singleton = new Test9();
    ……
    }对应字节码:
    public class com.codetest.test.Test9 {
      public static int a;  public static int b;  public static int c;  public static com.codetest.test.Test9 singleton;  static {};
        Code:
           0: iconst_0      
           1: putstatic     #3                  // Field b:I        // 这里对应 b = 0
           4: iconst_2      
           5: putstatic     #4                  // Field c:I        // 这里对应 c = 2
           8: new           #17                 // class com/codetest/test/Test9
          11: dup           
          12: invokespecial #18                 // Method "<init>":()V        // 这里是调用构造函数
          15: putstatic     #5                  // Field singleton:Lcom/codetest/test/Test9;
          18: return        
    }为了减少篇幅,在下只节选了类声明部分和静态块。
    可见,关于静态区的初始化Java编译器会自动生成一个静态块进行处理,初始化的顺序为自上而下。
    由于变量a没有初始化,所以在静态区内没对它进行处理。
    经过实验得知,LZ的代码与以下代码生成的字节码是一致的:public class Test9 {
    public static Test9 singleton;
    public static int a;
    public static int b;
    public static int c;
    // public static Test9 singleton = new Test9(); static {
    singleton = new Test9();
    b = 0;
    c = 2;
    }
    }
      

  12.   

    首先new Singleton
    初始化 a = 0;b=0;c=2;
    接着调用构造函数
    a++=1;b++=1;c++=3;
    然后继续赋值
    a=1;b=0;c=2
    所以结果应该是a=1;b=0;c=2
      

  13.   

    这个说法不对,可以通过下面的程序验证.
       private Singleton()
       {
    super();
    a++;
    b++;
       c++;
    System.out.println("a is   "+a+"b is   "+b+"c is    "+c);   }结果都是1.
      

  14.   

    这个话题蛮有意思,说说我的看法:
    初始化:
    可以看到所有变量都非对象变量,所以在运行时,执行main方法之前运行。
    就通用编译器来讲,基本都是顺序执行,java解析器也不例外。
    所以所有的成员变量都顺序执行下来执行main方法:
    在所有成员变量执行完后main方法,开始执行,调用代码执行验证:
    掉换static变量顺序注:

    方法和普通的变量不同,只有在调用才执行,就如main方法和static变量的关系
    参考:http://blog.csdn.net/madding/article/details/6451983
      

  15.   

    我觉得这道题的难点和最令人迷惑的地方是: 在类Singleton的static块中实例化一个Singleton(), 应该是先顺序执行完static的所有statements后再调用Singleton的实例初始化块(或构造方法)? 还是在类的static块没有执行完的情况下, 调用类的实例初始化块(或构造方法), 然后再完成类的静态初始化...实践了一下, 看来是后者
      

  16.   

    没明白LZ的意思,按照我的意思实现了下:
    public class Singleton {  public static Singleton singleton=null;
      public static int a;
      public static int b=0;
      public static int c=2;
       
       
      public Singleton()
      {
      a++;
      b++;
      c++;
      }
      public static Singleton getInstance()
      {
     if(singleton==null){
     singleton=new Singleton();
     }
     return singleton;
      }
       
      public static void main(String [] args)
      {
      Singleton single=Singleton.getInstance();
      System.out.println("a="+single.a);
      System.out.println("b="+single.b);
      System.out.println("c="+single.c);
      }
    }
      

  17.   

    这是在讨论JVM初始化类的细节么...
      

  18.   

    public class Singleton{
      public static Singleton singleton=new Singleton();
       public static int a;
       public static int b=0;
       public static int c=2;
      private Singleton()
       {
        super();
        System.out.println("a="+ this.a);
        System.out.println("b="+  this.b);
        System.out.println("c="+  this.c);
        System.out.println("**************");
        a++;
        b++;
        c++;
        System.out.println("a="+ this.a);
        System.out.println("b="+  this.b);
        System.out.println("c="+  this.c);
        System.out.println("**************");
       }
       public static Singleton getInstance()
       {
          return singleton;
       } 
      public static void main(String [] args)
       {
         Singleton sl=Singleton.getInstance();
         System.out.println("a="+sl.a);
         System.out.println("b="+sl.b);
         System.out.println("c="+sl.c);
         System.out.println("**************");
       }
    }
    运行结果:
    a=0
    b=0
    c=0
    **************
    a=1
    b=1
    c=1
    **************
    a=1
    b=0
    c=2
    **************
      

  19.   

    这个问题其实很简单,就是初始化顺序问题静态域按声明顺序初始化所以程序首先执行public static SingleTon singleton=new SingleTon();好像是说java域空间在编译时就分配,int型默认为O;然后执行构造函数;
    a,b,c各加1;然后按顺序初始化 a,b,c 。。
    所以
    a=1
    b=0
    c=2