代码1
public class T {
public static void main(String[] args) {
System.out.println(Single.counter1);
System.out.println(Single.counter2);
}
}
class Single{
public static int counter1;
public static int counter2=0;
private static Single single=new Single();//1 1
private Single(){
counter1++;
counter2++;
}
public static Single getInstance(){
return single;
}
}
代码执行结果:
1
1
加载过程:
1.首先主线程T进来首先会对T进行加载
2.Single.counter1调用类的静态属性,属于主动加载。
2.首先在准备阶段counter1和counter2的值都设置为初始值为0.
private static int counter1=0;//分配内存,设置int的默认值
private static int counter1=0;//分配内存,设置int的默认值
private static Single single=null;
3.初始化阶段
- 对于counter1没有赋值依然是0.
- 对于counter2赋值为1
- 将new Single()赋值给single,会调用构造方法。这个时候会调用构造方法将counter1 counter2 进行加上1
4.输出counter1和counter2都为1
代码2
将代码private static Single single=new Single();换个位置
public class T {
public static void main(String[] args) {
System.out.println(Single.counter1);
System.out.println(Single.counter2);
}
}
class Single{
private static Single single=new Single();
public static int counter1;
public static int counter2=0;
private Single(){
counter1++;
counter2++;
}
public static Single getInstance(){
return single;
}
}
加载过程:
1.首先主线程T进来首先会对T进行加载
2.Single.counter1调用类的静态属性,属于主动加载。
3.首先在编译阶段counter1和counter2的值都设置为初始值为0.按照顺序进行设置默认值
private static Single single=null;
private static int counter1=0;//分配内存,设置int的默认值
private static int counter1=0;//分配内存,设置int的默认值
4.初始化阶段:
- 执行new Single()赋值给single,会调用构造方法。这个时候会调用构造方法将counter1 counter2 进行加上1。counter的值都为1
- 没有对counter1赋值,依然为1
- 对counter2进行赋值变为0
所以最后的结果是 1 0
代码3
public class SSClass
{
static
{
System.out.println("SSClass");
}
}
public class SuperClass extends SSClass
{
static
{
System.out.println("SuperClass init!");
}
public static int value = 123;
public SuperClass()
{
System.out.println("init SuperClass");
}
}
public class SubClass extends SuperClass
{
static
{
System.out.println("SubClass init");
}
static int a;
public SubClass()
{
System.out.println("init SubClass");
}
}
public class NotInitialization
{
public static void main(String[] args)
{
System.out.println(SubClass.value);
}
}
对于静态字段,只有直接定义这个字段的类才会被初始化,因此通过其子类来引用父类中定义的静态字段,只会触发父类的初始化而不会触发子类的初始化。
代码4
public class Test2 {
public static void main(String[] args) {
//调用静态常量不会导致类的初始化,所以结果为:3
//这里代码块的代码没有执行,因为在准备阶段常量已经确定了
System.out.println(Test3.x);
}
}
class Test3{
//因为加上了final关键字,所以在准备阶段将其赋值为3,并且表明为final
public static final int x=3;
static {
System.out.println("代码块1");
}
}
代码5:
public class Test2 {
public static void main(String[] args) {
System.out.println(Test3.x);
/**
* 结果:
代码块1
881789502
*/
}
}
class Test3{
//虽然加了关键字final,但是这里没有确定x的取值,
//所以需要进行在准备阶段首先赋值为0,然后再初始化阶段再赋值为随机数,然后再进行代码块初始化
public static final int x=new Random().nextInt();
static {
System.out.println("代码块1");
}
}
}
上面就是对于常量的调用的时候,一定要注意,是否在准备阶段已经确定常量的值,如果确定则在调用常量的时候,值已经被确定了不进行类的初始化,如果不确定将进行类的初始化
代码6
/**
* Created by qianyi on 2017/10/4.
*/
public class NotInitialization
{
public static void main(String[] args) {
System.out.println(SuperClass.value);
}
}
class SSClass
{
static
{
System.out.println("SSClass");
}
}
class SuperClass extends SSClass
{
static
{
System.out.println("SuperClass init!");
}
public static final int value = 123;
public SuperClass()
{
System.out.println("init SuperClass");
}
}
结果:123
对于final修饰的静态变量(常量),无论是本身自己调用常量或者是子类调用常量都不会导致类的初始化。