类加载优先级 博客分类: JsonLiang's Java demo java
程序员文章站
2024-03-18 17:45:46
...
笔者将通过本文向大家介绍一下Java中的类加载顺序,既然是一门编程语言,那么纯说理论是不行的,应该通过实践来验证理论,理论来指导实践。下面笔者就来写一个验证类加载优先级的Java demo供大家学习和参考。
下面是控制台输出结果:
我是静态代码块:B:2
我是构造代码块!A:3
我是构造方法A:4,B:10
我是main方法A:4,B:10
偶然间笔者在网上看到有人写了关于类加载顺序的文章,并贴出了Java demo,最后得出了加载顺序的结论。但是笔者发现文章的作者写的代码并不严谨,得出的结论并不完全正确。因为光看在控制台输出的顺序,并不能完全说明Java的类加载顺序。比如,在加载优先级为同级时,加载和输出结果的顺序是根据代码的上下文顺序来决定的,这并不能说明优先级的高低。所以笔者在这里加以说明,以此做个提醒。笔者在代码中特意将优先级高的放在比它优先级低的代码后面,以此更为直观的证明它的优先级更高,而不是因为代码顺序导致。本Java demo纯属笔者原创,根据自己思路所写。为了方便大家代码阅读,笔者将RunTest类和TestJava类放在同一个.java文件中(为新手朋友稍作解释,老手无视即可)。
年后回来有个小伙伴问了我个问题(如果你是一个细心的、爱思考的读者,相信你也会发现这个问题,但是并没有读者在笔者的博文下留言提问,笔者有点小小的失落,不知大家是浅尝辄止没有注意到,还是自己知道其中的道理,好了,言归正传),正好适合放在这里做引申:
1.声明与赋值的关系(或顺序)
2.初始化加载和创建对象时加载,以及方法调用时加载
先对第一点作出解释:在上面的代码中静态变量A,似乎是先被静态代码块赋值了,再声明的变量类型,为何该代码能通过编译呢?其实不然,虽然在上面我们已经得出了类的加载顺序,静态变量和静态代码块的优先级是相同的,此时根据代码顺序加载,但是变量(属性)的声明是先于赋值的,这是由类加载机制决定的,类的加载机制可参考:http://blog.csdn.net/boyupeng/article/details/47951037。
再解释第二点:静态变量、静态代码块、静态方法是在类被加载时就初始化加载,但静态方法作为一个函数(方法)不会直接执行,同样需要被调用才执行,只不过不需要创建一个新的对象,因为它是先于对象存在的,而构造代码块和构造函数(方法)是在创建对象时加载,普通方法在被调用时才加载。
另外注意:静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问。结合笔者给的demo,在上述代码中,静态代码块中给A赋值(A = 2)是可以编译通过的,而如果要引用变量A(例如输出语句改为打印A的值)则会报错:不能在定义字段之前引用字段(报错信息的中文翻译)。 --2017/2/3引申补充
原文永久地址:http://jsonliangyoujun.iteye.com/blog/2348180
/** * * @author Liangyj *加载优先级:1.静态变量和静态代码块(类加载时执行,只加载一次并且常驻内存)、静态方法(只加载一次并且常驻内存,直接使用类名调用时才执行) *-->2.构造代码块(创建对象时执行)-->3.构造方法(创建对象时执行)-->4.普通方法(创建对象并调用时执行) */ public class TestJava { public static void main(String[] args) { System.out.println("我是main方法A:"+A+",B:"+B); } //构造方法 public TestJava(){ B = 10; A = 4; System.out.println("我是构造方法A:"+A+",B:"+B); } //构造代码块 { A = 3 ; B = 3; System.out.println("我是构造代码块!A:"+A); } //静态变量 private static int B = 1; //静态代码块 static { A = 2 ; B = 2; System.out.println("我是静态代码块:"+"B:"+B); } //静态变量 private static int A = 1; } class RunTest{ @SuppressWarnings("static-access") public static void main(String[] args) { TestJava testJava = new TestJava(); testJava.main(args); } }
下面是控制台输出结果:
我是静态代码块:B:2
我是构造代码块!A:3
我是构造方法A:4,B:10
我是main方法A:4,B:10
偶然间笔者在网上看到有人写了关于类加载顺序的文章,并贴出了Java demo,最后得出了加载顺序的结论。但是笔者发现文章的作者写的代码并不严谨,得出的结论并不完全正确。因为光看在控制台输出的顺序,并不能完全说明Java的类加载顺序。比如,在加载优先级为同级时,加载和输出结果的顺序是根据代码的上下文顺序来决定的,这并不能说明优先级的高低。所以笔者在这里加以说明,以此做个提醒。笔者在代码中特意将优先级高的放在比它优先级低的代码后面,以此更为直观的证明它的优先级更高,而不是因为代码顺序导致。本Java demo纯属笔者原创,根据自己思路所写。为了方便大家代码阅读,笔者将RunTest类和TestJava类放在同一个.java文件中(为新手朋友稍作解释,老手无视即可)。
年后回来有个小伙伴问了我个问题(如果你是一个细心的、爱思考的读者,相信你也会发现这个问题,但是并没有读者在笔者的博文下留言提问,笔者有点小小的失落,不知大家是浅尝辄止没有注意到,还是自己知道其中的道理,好了,言归正传),正好适合放在这里做引申:
1.声明与赋值的关系(或顺序)
2.初始化加载和创建对象时加载,以及方法调用时加载
先对第一点作出解释:在上面的代码中静态变量A,似乎是先被静态代码块赋值了,再声明的变量类型,为何该代码能通过编译呢?其实不然,虽然在上面我们已经得出了类的加载顺序,静态变量和静态代码块的优先级是相同的,此时根据代码顺序加载,但是变量(属性)的声明是先于赋值的,这是由类加载机制决定的,类的加载机制可参考:http://blog.csdn.net/boyupeng/article/details/47951037。
再解释第二点:静态变量、静态代码块、静态方法是在类被加载时就初始化加载,但静态方法作为一个函数(方法)不会直接执行,同样需要被调用才执行,只不过不需要创建一个新的对象,因为它是先于对象存在的,而构造代码块和构造函数(方法)是在创建对象时加载,普通方法在被调用时才加载。
另外注意:静态语句块中只能访问到定义在静态语句块之前的变量,定义在它之后的变量,在前面的静态语句块可以赋值,但是不能访问。结合笔者给的demo,在上述代码中,静态代码块中给A赋值(A = 2)是可以编译通过的,而如果要引用变量A(例如输出语句改为打印A的值)则会报错:不能在定义字段之前引用字段(报错信息的中文翻译)。 --2017/2/3引申补充
原文永久地址:http://jsonliangyoujun.iteye.com/blog/2348180
推荐阅读
-
类加载优先级 博客分类: JsonLiang's Java demo java
-
类加载优先级 博客分类: JsonLiang's Java demo java
-
java中子类与父类中的静态代码块、非静态代码块和构造函数的加载顺序 博客分类: JAVA基础 静态代码块非静态代码块加载顺序
-
java中子类与父类中的静态代码块、非静态代码块和构造函数的加载顺序 博客分类: JAVA基础 静态代码块非静态代码块加载顺序
-
类的加载ClassLoader 博客分类: Java
-
类的加载ClassLoader 博客分类: Java
-
java 类文件加载 博客分类: jvm classloaderjvm热部署
-
Java 类的热替换 —— 概念、设计与实现 博客分类: java核心 javaclassload热加载热部署
-
Junit 4 博客分类: JsonLiang's Java demo junit单元测试java