转自:类加载时是否会执行静态代码块?静态代码块的骚操作。_胡歌粉丝的博客-CSDN博客_类加载会执行静态代码块吗
问
类加载时是否会执行静态代码块?
答
不一定。类加载的方式有多种,并不是每一种方式都能执行静态代码块
解
常见类加载的方式
1 类名.Class
2 new 对象
3 Class.forName(“类的全路径”) ps(有个点注意一下)
在执行的时候加上以下一句JVM的运行参数,可以观看类加载过程
-XX:+TraceClassLoading
例,用idea就这样添加
来吧,小伙子们,上代码~
第一种形式,类名.Class
class ClassTest{
static {
System.out.println("执行了静态代码块");
}
}
public class ClassLoderTest {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass2 = ClassTest.class;
}
}
运行结果如下
ClassTest 这个类有被加载器加载,但是并没有输出语句,所以并没有被执行。
第二种形式, new 对象
new 一个对象,以及利用这个对象调用成员变量方法等,就不在一一赘述。
class ClassTest{
static {
System.out.println("执行了静态代码块");
}
}
public class ClassLoderTest {
public static void main(String[] args) throws ClassNotFoundException {
new ClassTest();
}
}
运行结果如下
ClassTest 这个 类有被加载,并且静态块语句有被输出,所以,这种方式会执行静态代码块。
第三种形式 ,Class.forName(“类的全路径”)
class ClassTest{
static {
System.out.println("执行了静态代码块");
}
}
public class ClassLoderTest {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass3 = Class.forName("com.management.JavassistTest.ClassTest");
}
}
运行结果如下
ClassTest 这个 类有被加载,并且静态块语句有被输出,所以,这种方式会执行静态代码块。
第三种形式的特殊用法
但是第三种的形式有另一种方式使得它不执行。如下:
class ClassTest{
static {
System.out.println("执行了静态代码块");
}
}
public class ClassLoderTest {
public static void main(String[] args) throws ClassNotFoundException {
Class<?> aClass3 = Class.forName("com.management.JavassistTest.ClassTest",
false,//true的时候会执行
ClassLoader.getSystemClassLoader());
}
}
运行结果如下
总结
类加载时是否会执行静态代码块取决于加载的方式。
扩展:
如果对类加载有兴趣的,并不是新鲜出炉的菜鸟,可以去了解一下 双亲委派 和 热替换 有意思的哦~
扩展
上面讲述了类加载的时候是否会执行静态代码块这一问题的通俗解答,我觉得用来回答初级程序员的面试是没问题的。
扩展一下瞎琢磨出来的知识点,O(∩_∩)O哈哈~
问: 当子类调用父类的成员变量或者方法时,父类和子类的静态代码块是否会被加载? ps(成员变量不可为被 static final 修饰的基本数据类型和字符串,否则类不会被加载)
代码如下
class ClassTest{
static final Integer a = 666;
static {
System.out.println("执行了父类静态代码块");
}
}
class ClassTestSon extends ClassTest{
static {
System.out.println("执行了子类静态代码块");
}
}
public class ClassLoderTest {
public static void main(String[] args) throws ClassNotFoundException {
Integer a = ClassTestSon.a;
}
}
此时通过子类调用了父类的一个成员变量。运行结果如下:
此时子类和父类都有被加载,但是只执行了父类的静态代码块,为什么呢?
(…•˘_˘•…)大家准备好,我要装X了!
是因为~
我们是通过子类访问了父类的成员变量,子类属于被动加载,而父类属于主动加载,被动加载的类是不会执行静态代码块的,而主动加载的类会执行静态代码块。
关于静态代码块的补充说明:
静态属性和静态代码块的初始化顺序由定义决定。
如下:
class ClassTest {
static final ClassTest instance = new ClassTest();
static {
System.out.println("执行了静态代码块");
}
public ClassTest() {
System.out.println("执行了构造方法");
}
}
先执行构造方法再执行静态代码块,因为初始化顺序由定义决定。