还写了个姊妹篇参考:Java 类加载机制(阿里)-何时初始化类
类加载
类加载的五个过程
eg: class Test{ static{ i = 4; //正常 System.out.println(i)//报错,因为不能访问,只能赋值 } static int i = 2; }
2、扩展类加载器,Extension ClassLoader,加载libext,或者被java.ext.dirs系统变量指定的类
3、应用程序类加载器,Application ClassLoader,加载ClassPath中的类库
4、自定义类加载器,通过继承ClassLoader实现,一般是加载我们的自定义类
Field c = cls.getDeclaredField("a"); c.setAccessible(true);//这里如果不设置的话,会抛出IllegalAccessException()异常 c.set(car, 888); ...
下面是代码:
package com.ioc; public class Car { private String brant; private String color; private int maxSpeed; private int a; public String getBrant() { return brant; } public void setBrant(String brant) { this.brant = brant; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getMaxSpeed() { return maxSpeed; } public void setMaxSpeed(int maxSpeed) { this.maxSpeed = maxSpeed; } public Car(){} public Car(String brant,String color,int max) { this.brant = brant; this.color = color; this.maxSpeed = max; } public String toString(){ String a = brant+color+maxSpeed; return a; } public void print(){ System.out.println(brant+color+maxSpeed+a); } }
反射调用的代码:
验证一下:
验证:
1)当类被初始化时,其静态代码块会执行。
class ClassLoadTime{ static{ System.out.println("ClassLoadTime类初始化时就会被执行!"); } public ClassLoadTime(){ System.out.println("ClassLoadTime构造函数!"); } } class ClassLoadDemo{ public static void main(String[] args){ ClassLoadTime clt = new ClassLoadTime(); } }
输出结果:
ClassLoadTime类初始化时就会被执行!
ClassLoadTime构造函数!
2) 读取一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)
class ClassLoadTime{ static{ System.out.println("ClassLoadTime类初始化时就会被执行!"); } public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符) public ClassLoadTime(){ System.out.println("ClassLoadTime构造函数!"); } } class ClassLoadDemo{ public static void main(String[] args){ int value = ClassLoadTime.max; System.out.println(value); } }
输出:
ClassLoadTime类初始化时就会被执行!
200
3)设置一个类的静态字段(被final修饰、已在编译期把结果放在常量池的静态字段除外)
class ClassLoadTime{ static{ System.out.println("ClassLoadTime类初始化时就会被执行!"); } public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符) public ClassLoadTime(){ System.out.println("ClassLoadTime构造函数!"); } } class ClassLoadDemo{ public static void main(String[] args){ ClassLoadTime.max = 100; } }
输出:
ClassLoadTime类初始化时就会被执行!
4)调用一个类的静态方法
class ClassLoadTime{ static{ System.out.println("ClassLoadTime类初始化时就会被执行!"); } public static int max = 200; (防止测试类和此类不在一个包,使用public修饰符) public ClassLoadTime(){ System.out.println("ClassLoadTime构造函数!"); } public static void method(){ System.out.println("静态方法的调用!"); } } class ClassLoadDemo{ public static void main(String[] args){ ClassLoadTime.method(); } }
输出:
ClassLoadTime类初始化时就会被执行!
静态方法的调用!
被final修饰静态字段在操作使用时,不会使类进行初始化,因为在编译期已经将此常量放在常量池。
测试:
class ClassLoadTime{ static{ System.out.println("ClassLoadTime类初始化时就会被执行!"); } public static final int MIN = 10; (防止测试类和此类不在一个包,使用public修饰符) } class ClassLoadDemo{ public static void main(String[] args){ System.out.println(ClassLoadTime.MIN); } }
输出:
10
子类调用或者设置父类的静态字段或者调用父类的静态方法时仅仅初始化父类,而不初始化子类。同样读取final修饰的常量不会进行类的初始化。
class Fu{ public static int value = 20; static{ System.out.println("父类进行了类的初始化!"); } } class Zi{ static{ System.out.println("子类进行了类的初始化!"); } } class LoadDemo{ public static void main(String[] args){ System.out.println(Zi.value); } }
输出:
父类进行了类的初始化!
20
java类中各种成员的初始化时机,此处不一一测试:
类变量(静态变量)、实例变量(非静态变量)、静态代码块、非静态代码块 的初始化时机:
* 由 static 关键字修饰的(如:类变量[静态变量]、静态代码块)将在类被初始化创建实例对象之前被初始化,而且是按顺序从上到下依次被执行;
public static int value =34; static{ System.out.println("静态代码块!"); } public 类名(){ System.out.println("构造函数!"); }
一旦这样写,在类被初始化创建实例对象之前会先初始化静态字段value,然后执行静态代码块,当实例化对象时会执行构造方法中的代码
* 没有 static 关键字修饰的(如:实例变量[非静态变量]、非静态代码块)初始化实际上是会被提取到类的构造器中被执行的,但是会比类构造器中的
代码块优先执行到,其也是按顺序从上到下依次被执行。
public int value =34; { System.out.println("非静态代码块!"); } public 类名(){ System.out.println("构造函数!"); }
在使用构造函数实例化一个对象时,会先初始化value,然后执行非静态代码块,最后执行构造方法里面的代码。
*在存在父类的时候,调用子类的构造时,会先调用父类的默认构造(空参构造),进行父类的初始化。
参考:java中类加载时机