本篇文章说一下java虚拟机类的加载过程。
手先我们看一下下面的代码:
package mytest;
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A {
public static int m = 300;
static {
System.out.println("class A 静态代码块");
m=100;
}
public A(){
System.out.println("class A 无参构造方法");
}
public void a(){
System.out.println("class A内部方法");
}
}
一个很简单的Test A:我们执行一下
class A 静态代码块
class A 无参构造方法
100
从结果上面我们可以看出来m=100
,类的静态方法,是要优先于构造方法初始化的。
下面我们将 public static int m = 300;
放到静态代码快下面:
package mytest;
public class Test {
public static void main(String[] args) {
A a = new A();
System.out.println(A.m);
}
}
class A {
static {
System.out.println("class A 静态代码块");
m=100;
}
public static int m = 300;
public A(){
System.out.println("class A 无参构造方法");
}
public void a(){
System.out.println("class A内部方法");
}
}
class A 静态代码块
class A 无参构造方法
300
我们可以发现m=300
:只要是类的静态区域,无论是代码块还是变量,初始化的顺序是按照代码顺序的。
下面我们创建B类,并继承A。
package mytest;
public class Test {
public static void main(String[] args) {
B b = new B();
System.out.println(B.m);
}
}
class A {
static {
System.out.println("class A 静态代码块");
m=100;
}
public static int m = 300;
public A(){
System.out.println("class A 无参构造方法");
}
public void a(){
System.out.println("class A内部方法");
}
}
class B extends A{
static {
System.out.println("class B 静态代码块");
m=500;
}
public B(){
System.out.println("class B 无参构造方法");
}
}
看下结果:
class A 静态代码块
class B 静态代码块
class A 无参构造方法
class B 无参构造方法
500
结论:
- 静态代码块(包括静态变量)优先于构造方法执行,并且按照先父类,再子类的顺序执行;
- 构造方法执行在静态代码块(包括静态变量)之后,也是按照先父类,再子类的顺序执行;
- 在当前类里面静态代码块执行有先后顺序,按照代码由上而下顺序执行。
补充:如果仅仅使用子类调用父类的静态变量,子类不会初始化。
public static void main(String[] args) {
//只是用子类调用父类的静态变量,子类不会初始化
System.out.println(B.m);
}
class A 静态代码块
300
创建数组对象,也不会引起类的加载。
B [] b = new B[0];
class B extends A{
static {
System.out.println("class B 静态代码块");
m=500;
}
//常量
public final static int Final = 300;
public B(){
System.out.println("class B 无参构造方法");
}
}
我们在子类创建一个常量 public final static int Final = 300;
public static void main(String[] args) {
//只是用子类常量,子类不会初始化
System.out.println(B.Final);
}
300
仅仅打印了一下常量的值,也不会引起类的初始化。