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);
}
}找牛人解决以上一道题!在线等待回答
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);
}
}找牛人解决以上一道题!在线等待回答
public static int b = 0;
public static int c = 2;
public static Singleton singleton = new Singleton();
嗯,我也认为是初始化的顺序问题,不过我还想问一下
public static int a;
public static int b=0;
初始化时有什么区别吗?
因为a没有显式地赋予初始化值啊...
可以尝试使用lazy方式初始化单例,看下结果的区别...
你可以debug一下,我发现是又区别的,在这个例子中,先是a,b,c都变成1,接着初始化a,b,c,JVM发现a已经有值了(已经初始化)所以不赋默认值0,但是b,c无论是否已经初始化都赋值成程序指定的值。所以他们的区别是,对于"int a;"这种写法,如果a已经有值,那么不会被赋值0,否者会。
对于“int a=0”,必需被赋值0,因为是你自己指定的。
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
2 程序转而去追溯父类的构造函数(Object()).
3 追溯完父类的构造函数,回来再到本类的构造函数。执行(a++,b++,C++).
4 执行完构造函数后,在对4个变量进行显示初始化。b,c,singleton 都将赋新值。 a 没有显示初始化,默认从构造函数返回的了。(我理解的核心思想是: 变量初始化分两次进行,1 默认初始化(刚执行构造函数时),2 显示初始化(构造函数结束前)。
那么这个对象是什么时候存在的?
是编译后就存在了? 还是引用时产生的?
有点想不明白。请讲得具体一些。
要知道,定义和赋值是两个语句
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
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;
}
}
初始化 a = 0;b=0;c=2;
接着调用构造函数
a++=1;b++=1;c++=3;
然后继续赋值
a=1;b=0;c=2
所以结果应该是a=1;b=0;c=2
private Singleton()
{
super();
a++;
b++;
c++;
System.out.println("a is "+a+"b is "+b+"c is "+c); }结果都是1.
初始化:
可以看到所有变量都非对象变量,所以在运行时,执行main方法之前运行。
就通用编译器来讲,基本都是顺序执行,java解析器也不例外。
所以所有的成员变量都顺序执行下来执行main方法:
在所有成员变量执行完后main方法,开始执行,调用代码执行验证:
掉换static变量顺序注:
方法和普通的变量不同,只有在调用才执行,就如main方法和static变量的关系
参考:http://blog.csdn.net/madding/article/details/6451983
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);
}
}
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
**************
a,b,c各加1;然后按顺序初始化 a,b,c 。。
所以
a=1
b=0
c=2