我们知道,如果要使用类里面的实例变量,那么是必须要类初始化的,但是如果我们使用静态变量呢,如果静态变量还使用final修饰呢。我们下面就来讲一下这个问题:
public class Test {
public static void main(String[] args) {
System.out.print(A.hello);
}
}
class A {
public static String hello="java";
static {
System.out.println("A");
}
}
我们知道,如果类初始化了,那么一定会执行静态代码块,如上,我们之间使用A类
里面的静态变量hello
就会初始化类A
使用final static修饰:
当我们使用final static修饰时,会发现A类没有初始化:
public class Test {
public static void main(String[] args) {
System.out.print(A.hello);
}
}
class A {
public final static String hello="java";
static {
System.out.println("A");
}
}
因为这里是直接就把变量hello当成了常量,
但如果我们使用new String()方法创建:
此时 A类会被初始化:
public class Test {
public static void main(String[] args) {
System.out.print(A.hello);
}
}
class A {
public final static String hello=new String("java");
static {
System.out.println("A");
}
}
继承碰到初始化:
每个类是否初始化是由上面的各种情况决定,然后子类初始化必定要先初始化父类,这就是规则。
总结;
1、如果一个 static final 变量是"编译期常量",就像 public static final String a = “java”;那样,那么这个值不需要对 Test2 类进行初始化就可以读取。
2、但是,如果只是将一个变量的域设置为 static 和 final 的,那不足以确保这种行为。例如,对 public static final String a = new String(“java”);的访问将强制对 Test2 类进行初始化,因为它不是一个"编译期常量"。
3、如果一个 static 变量域不是 final,那么在对它进行访问时,总是要求在它被读取之前,要先进行链接 (为这个域分配存储空间) 和初始化(初始化该存储空间) 就像 public static String a = “JD”。