class Singleton {  
private static Singleton obj = new Singleton();  
public static int counter1;  
public static int counter2 = 0;  
private Singleton() {  
    counter1++;  
    counter2++;  
}  
public static Singleton getInstance() {  
    return obj;  
}  
}  
  
// 程序2  
public class MyMain {  
public static void main(String[] args) {  
    Singleton obj = Singleton.getInstance();  
    System.out.println("obj.counter1=="+obj.counter1);  
    System.out.println("obj.counter2=="+obj.counter2);  
}  
}  

解决方案 »

  1.   

    执行结果是:  
    obj.counter1==1  
    obj.counter2==0  
    大家讨论,说对了理由给分.
      

  2.   

    前几天刚回过的
    http://community.csdn.net/Expert/topic/4275/4275850.xml?temp=.1619379
      

  3.   

    我修改了一下程序,你看一下,应该就可以明白了!
    class Singleton {  
    private static Singleton obj = new Singleton();
    public static   String s = obj.print();
    public static int counter1;  
    public static int counter2=0;  
    private Singleton() {  
        counter1++;  
        counter2++;  
    }
    public String print(){
    return counter1+" "+counter2;
    }public static Singleton getInstance(){  
        return obj;  
    }  
    }  
      
    // 程序2  
    public class MyMain {  
    public static void main(String[] args) {  
        Singleton obj = Singleton.getInstance();  
        System.out.println("obj.counter1=="+obj.counter1);  
        System.out.println("obj.counter2=="+obj.counter2); 
        System.out.println(obj.s); 
    }  
    }  
      

  4.   

    //次序问题
    //对Java还不是很了解,不知道有没有规定static成员的
    //初始化关系,如果没有,那就变成编辑器有关了.
    //不过从程序可推测static的声明和初始化是分两遍来
    //完成的.
    //调整一下次序,就能更好的表达语义了.
    ---初学者class Singleton {    public static int counter1;
        public static int counter2 = 0;    private static Singleton obj = new Singleton();
           
        private Singleton() {
            counter1++;
            counter2++;
            System.out.println("counter1= " + counter1);
            System.out.println("counter2= " + counter2);
        }    public static Singleton getInstance() {
            return obj;
        }
    }public class Single {
        public static void main(String[] args) {
            System.out.println("obj.counter1==" + Singleton.counter1);
            System.out.println("obj.counter2==" + Singleton.counter2);
        }
    }
      

  5.   

    呵呵 wlmmlw兄,
    执行结果是:
    counter1= 1
    counter2= 1
    obj.counter1==1
    obj.counter2==1你上面的这个程序说明了类初始化的时候的关系,就是
    Singleton.counter1的时候是先调用构造函数的.
    调用构造函数的时候,是先执行
    counter1++和2++,
    这个时候还没有执行
    public static int counter1;
    public static int counter2 = 0;
    只是看在static的面子上给他在内存里面分配了一个地址并且初始化为0.
    而调用
     System.out.println("obj.counter1==" + Singleton.counter1);
            System.out.println("obj.counter2==" + Singleton.counter2);
    的时候,还是没有执行赋值,这样后面的两个也是1了!
    呵呵 interhanchi(闭关修练中!) 兄
    你的例子很不错,也很经典,问题一目了然.
    佩服,俺学习的榜样哈!keiy() 兄,你的帖子看过了 呵呵 感觉问题没有弄的太清楚了就结贴了哈 呵呵还有啊 无名兄,前面有个兄弟点名让你回帖呢  估计你没有看到.
      

  6.   

    暂不结贴 呵呵
    哪个兄弟给个好点的java的群啊???
      

  7.   

    interhanchi(闭关修练中!) 
    的例子的确很不错,学习!
      

  8.   

    这段程序主要说明的问题是:静态数据成员初始化的顺序,初始化顺序依次为obj,counter1,counter2.但是我不明白在初始obj的时候应该初始counter1和counter2,如果这样的counter2就初始了两次。还是请楼主解答吧这段代码太经典了!
    如果
    private static Singleton obj = new Singleton();  
    public static int counter1;  
    public static int counter2 = 0; 
    的顺序改为:obj的的申明放在counter2的申明之后结果就是counter1=1,counter2=1;
      

  9.   

    看楼主代码的意思是想让
    obj.counter1==1
    obj.counter2==1
    准确的说是
    Singleton.counter1==1
    Singleton.counter2==1初始化的值是用被覆盖的.我是这样理解的.
    不过最好不要写这样的代码.---初学者
      

  10.   

    菜鸟也来发个言:我看执行结果的确是:
    Singleton.counter1==1
    Singleton.counter2==1
    counter1和counter2是静态成员.会比类优先这初始化.而这时,他们两个分别就有了一个初始化值了,即0;接着就是类的构造方法的执行.即:private static Singleton obj = new Singleton(); 
    所以,两个值分别增1.就得到了
    Singleton.counter1==1
    Singleton.counter2==1总的来说:这个题无非就是一个静态数据初始化与类的初始化问题. 
      

  11.   

    zxbjlu1983(晚风长街)
    初始化了一次,static初始化的时候,只是分配在内存里面的地址,然后分一个默认值0,
    赋值的事情,是在后来++后.
    wlmmlw(吴铭) 
    我的意思,只是想咱讨论讨论代码初始化和执行的顺序 呵呵
      

  12.   

    楼主说法我不赞同当第一次访问静态数据或方法的时候加载器开始启动并找出Singleton类的编译代码(即Singleton.class)后,有关静态初始化的所有动作都会执行。而不是你所说的“只是分配在内存里面的地址,然后分一个默认值”,这种说法对于非静态数据适合——先设缺省值然后执行所有出现在子段的初始化动作。
    上述说法引自java编程思想第三版
      

  13.   

    楼主的例子可以这样改一下:
    public class Test1
    {
    public static void main(String[] args)
    {
    Myclass myclass = Myclass.CreateMyclass();
    System.out.println(myclass.counter1);
    System.out.println(myclass.counter2);
    }
    }class Myclass
    {
    private static final Myclass obj = new Myclass();
    public static int counter1;
    public static int counter2=3; private Myclass()
    {
       counter1++;
       counter2++;
       System.out.println("Myclass () 里的 counter1 = "+counter1);
       System.out.println("Myclass () 里的 counter2 = "+counter2);
    }
    public static Myclass CreateMyclass()
    {
    return obj;
    }
    }可见执行private static final Myclass obj = new Myclass();前,语句 public static int counter1;  public static int counter2=3;还没有被执行。这时系统就当counter = 0;counter=0看待。 执行完构造涵数后再执行后两条语句,这时因为counter1没有明确的值,所以把构造函数的结果给了它。 因为counter2有确定的值3, 所以把3赋给了它。不知我说得对不, 请楼主说明。继续关注。
      

  14.   

    楼主说法我不赞同当第一次访问静态数据或方法的时候加载器开始启动并找出Singleton类的编译代码(即Singleton.class)后,有关静态初始化的所有动作都会执行。而不是你所说的“只是分配在内存里面的地址,然后分一个默认值”,这种说法对于非静态数据适合——先设缺省值然后执行所有出现在子段的初始化动作。
    上述说法引自java编程思想第三版
    我不这样认为,我觉得还是有static修饰的int变量如果在构造函数里面应用的时候,值绝对是0
    昨天上课的时候我还专门问了我们老师的,她也是这么说的,而且程序的执行结果也表明是这样.
    呵呵 把你应用哪儿的话贴上来看看吧.
     lgh2008(ar_guang)可见执行private static final Myclass obj = new Myclass();前,语句 public static int counter1;  public static int counter2=3;还没有被执行。
    呵呵 ,基本上就是这个意思.
    执行构造函数的时候,用到了变量,而变量在构造函数下面,所以只能用默认的int变量的值.
    这里注意,static类型的变量是在类被加载的时候先分配内存的,也就是没有执行构造函数的时候就先搜索static关键字的变量,然后分配内存.
    所以说,你说没有执行是不全对的 呵呵
      

  15.   

    类装载持续问题, 确实很能说明问题. 在scjp开始中有很多这样的题目
      

  16.   

    //大哥,我怎么记得程序是这么写的?一个是静态属性,一个是非静态的,你是不是写错了class Singleton {  
    private static Singleton obj = new Singleton();  
    public int counter1;  
    public static int counter2 = 0;  
    private Singleton() {  
        counter1++;  
        counter2++;  
    }  
    public static Singleton getInstance() {  
        return obj;  
    }  
    }  
      
    // 程序2  
    public class MyMain {  
    public static void main(String[] args) {  
        Singleton obj = Singleton.getInstance();  
        System.out.println("obj.counter1=="+obj.counter1);  
        System.out.println("obj.counter2=="+obj.counter2);  
    }  
    }
      

  17.   

    //我想大家看一下这个代码就会知道是一回事情了,这个和JDK没有关系
    //只是初始化次序问题
    class Singleton {
        private static Singleton obj;         //其实在JDK编译的时候都是先将属性定义出来。写在方法外的int类型默认为 "0"
        public static int counter1;
        public static int counter2;
        static{                                             //静态变量是在静态块中初始化的,先实例obj,调用构造函数两个数字都为"1";现在要调用counter2负值(因为counter1没有附值还等于"1")
            obj  = new Singleton();
            counter2=0;
        }    private Singleton() {
            counter1++;
            counter2++;
        }
        public static Singleton getInstance() {
            return obj;
        }
        public static void main(String[] args) {
            Singleton obj = Singleton.getInstance();
            System.out.println("obj.counter1=="+obj.counter1);
            System.out.println("obj.counter2=="+obj.counter2);
        }
    }
      

  18.   

    楼主啊,确实是没有被执行啊,类加载的时候JVM只是给它们分配了内存空间,并一个0 给了它们。分配完内存空之后,再执行赋值语句,那才是真正的执行。
    如果将private static Singleton obj = new Singleton();  往后写两行,这个程序就没有任何悬念了。 即。
    class Singleton {  
    public static int counter1;  
    public static int counter2 = 0; 
    private static Singleton obj = new Singleton(); 
    private Singleton() {  
        counter1++;  
        counter2++;  
    }  
    public static Singleton getInstance() {  
        return obj;  
    }  
    }  
      
    // 程序2  
    public class MyMain {  
    public static void main(String[] args) {  
        Singleton obj = Singleton.getInstance();  
        System.out.println("obj.counter1=="+obj.counter1);  
        System.out.println("obj.counter2=="+obj.counter2);  
    }  
    }  
      

  19.   

    当第一次访问静态数据或方法的时候加载器开始启动并找出Singleton类的编译代码(即Singleton.class)后,有关静态初始化的所有动作都会执行。而不是你所说的“只是分配在内存里面的地址,然后分一个默认值”,这种说法对于非静态数据适合——先设缺省值然后执行所有出现在子段的初始化动作。
    上述说法引自java编程思想第三版可见执行private static final Myclass obj = new Myclass();前,语句 public static int counter1;  public static int counter2=3;还没有被执行。是真是假,就设public static int counter2=5,看看结果就一目了然。
      

  20.   

    让我们先来简化一下这题:
    class Singleton {  
    public static Singleton obj = new Singleton();  
    public static int counter1;  
    public static int counter2=0;  
    private   Singleton() {
        counter1++;  
        counter2++;  
    }  
    }  
    // 程序2  
    public class MyMain {  
    public static void main(String[] args) {  
        System.out.println("obj.counter1=="+Singleton.obj.counter1);  
        System.out.println("obj.counter2=="+Singleton.obj.counter2);  
     
    }  
    }
    相信对于这一题,这样简化不会有什么影响吧。
    小弟认为:由于静态变量是在程序运行前初始化的,如果存在多个静态成员,必然有个顺序问题,如果各个静态成员互不相干还好,如果有了牵连(本例中obj初始化的时候对counter2进行了操作!),本来大家平起平坐的,你凭什么干涉我(counter2很不满,我还没初始化呢!)。于是,counter2在obj初始化后依然毅然重新初始化了自己(public static counter2=0)。
    嘿嘿,小弟愚见,望楼主赏点分花花!
      

  21.   

    jiaxiang131(小白) 兄:
    呵呵,有没有static执行的机理可是大不一样哈强烈建议大家看看 jiaxiang131(小白) 兄发的第二贴,
    此贴经典之极,世所罕见!俺强烈怀疑你是不是反编译class出来的 要不怎么对运行的 内在顺序了如的这么指掌?
    恩,再次推荐一下.lgh2008(ar_guang)兄,
    呵呵,你明白我的意思,我也明白你指的是啥,哈,这才叫交流嘛,不必拘泥与语言形式上的偏差误会 
    呵呵,听说神交是交流的最高形式哈,估计就是这样吧 呵呵luyisir2(小小程序员) 兄,
    花花会有的,没有想到我的一个帖子居然这么多兄弟关注,呵呵,给分的一定不会手软
      

  22.   

    总结了一下,把大家的帖子汇集了一下,然后得出了下面的一个程序,
    里面的几个问题弄清楚了这个问题算玩玩全全彻底搞清楚了
    //powered by kestrel@byhh,MyMain.javaclass Singleton { 
     
    private static Singleton obj = new Singleton();
    public static String s=obj.print();
    //public static   String s =new String(counter1+" "+counter2);
    //为什么这里这样写会产生不能引用没有定义变量的错误?郁闷!public static int counter1;  
    public static int counter2=0;  
    public static String t=new String(counter1+" "+counter2);private Singleton() {  
        counter1++;  
        counter2++;  
        System.out.println("counter1="+counter1);
        System.out.println("counter2="+counter2);
        
    }
    public String print(){
    return counter1+" "+counter2;
    }public static Singleton getInstance(){  
        return obj;  
    }  
    }  
      public class MyMain {  
    public static void main(String[] args) {  
        Singleton obj = Singleton.getInstance();  
         //这里obj是新生成的一个另外分配了内存的对象吗?还是初始化Singleton而产生的一个静态的对象? 
        //期待高人指点ing...    
        System.out.println("s="+ obj.s); 
        System.out.println("t="+ obj.t);
        //为什么这里会输出1,0??
        System.out.println("obj.counter1=="+obj.counter1);  
        System.out.println("obj.counter2=="+obj.counter2); 
        System.out.println(obj.s); 
    }  
    }  
      

  23.   

    运行结果是:counter1=1
    counter2=1
    s=1 1
    t=1 0
    obj.counter1==1
    obj.counter2==0
    1 1呵呵 大家如果看明白了上面的帖子,基本上差不多了
      

  24.   

    lizi02(冬虫夏草)兄,
     很高兴和你一起讨论这个程序,它确实很有挑战性,我整整调试了一个上午,当我明白它的那一刻,心里有说不出的高兴。谢谢你为大家提供这样的乐趣。在这里我就不向你要分了(虽然我现在的分还很少),但你要答应我一个条件,把我加为好友,QQ:15271295。 这一点不过份吧。
      

  25.   

    今天在书上看到这样一句话:“在其他任何事物发生之前,将分配给对象的存储空间初始化为2进制0”
    对应楼主代码:
      程序首先初始化static Singleton obj静态变量,此时分配空间给obj后obj的存储空间初始化为2进制0,也就是说此时counter1,counter2的值都是0。执行构造函数后都变为1。
      接着初始化static counter1但是没有初始化语句,所以counter1仍然是1。
      同理counter2由于执行初始化语句就成为0了。
    楼主问题很有启发性,学到不少东西
      

  26.   

    呵呵,昨天就准备把qq贴上来的qq.121498129昨天晚上反编译了一下,看的更明白了.
      

  27.   

    问一下楼主,关于你最后一贴中:
    最后行代码:
    System.out.println(obj.s); //结果是1 1是不是因为静态字符串s在
    public static String s=obj.print();初始化了,字符串是不变的.所以才输出1 1开始以为是1 0
      

  28.   

    public static String s=obj.print();恩
    它在赋值的时候,counter1和counter2还没有执行赋值语句,也就是如果把这句放到
    public static int counter1=0; 
    public static int counter2;
    后面结果就不一样了 呵呵
      

  29.   

    我来说句话啊
    程序文件在编译时扫描类的所有成员变量字段,包括静态的,并以0值来初始化(对象的引用初始化为null),并分配内存
    而类加载时,将会严格按照声明顺序进行初始化。
    不知道是不是这个意思呢?
      

  30.   

    对不起,我在JB9上执行的结果是
    obj.counter1==1obj.counter2==0不是
    obj.counter1==1obj.counter2==1
    为什么?这些是不是要涉及JDK底层