博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Class.forName杂谈
阅读量:7199 次
发布时间:2019-06-29

本文共 4079 字,大约阅读时间需要 13 分钟。

  hot3.png

既然是杂谈,那么肯定会比较杂乱,都是点到为止,不回做过多的原理分析,如果对于原理,可能需要深入了解JVM内部的东西了。<br/> 首先,我来展示一下几个现象,然后对这几个现象进行分析。<br/> 相关几个类的定义

package com.bieber.gc;public class Super {static{ System.out.println("super static block");}public Super(){ System.out.println("super init");}public void test(){ System.out.println("invoke test");}}public class Main extends Super{ public Main() { System.out.println("main init");}static{ System.out.println("sub static block");}public void test(){ System.out.println("main test");}}

这里涉及到两个类,下面针对这两个类来写几个测试用例。<br/> ####用例一

用例代码

public static void main(String[] args) throws Exception { try { System.out.println("#########start load class##########"); Thread.currentThread().getContextClassLoader().loadClass("com.bieber.gc.Main"); System.out.println(); System.out.println("#########start init class#########"); Main main = new Main(); System.out.println(); System.out.println("#########invoke#########"); main.test(); } catch (ClassNotFoundException e) { e.printStackTrace(); }}

#####输出结果

#########start load class###################start init class#########super static blocksub static blocksuper initmain init#########invoke#########main test

#####结果分析 可以看到通过Classloader加载类的时候,并没有执行static代码块,而static代码块却放到了调用构造函数的时候执行了,并且static代码块是在构造函数之前执行的。同时在调用在子类重写的方法时候,父类方法没有执行(这点是毫无疑问的)。 ####用例二 #####用例代码

public static void main(String[] args) throws Exception { try { System.out.println("#########start load class##########"); Class.forName("com.bieber.gc.Main", true, Thread.currentThread().getContextClassLoader()); System.out.println(); System.out.println("#########start init class#########"); Main main = new Main(); System.out.println(); System.out.println("#########invoke#########"); main.test(); } catch (ClassNotFoundException e) { e.printStackTrace(); }}

#####执行结果

#########start load class##########super static blocksub static block#########start init class#########super initmain init#########invoke#########main test

#####结果分析 发现这个时候子类和父类的static代码块在调用构造函数之前执行的,这点说明此处的Class.forNameClassLoader执行效果一样。其他部分和上面基本一致。 ####用例三 #####用例代码

public static void main(String[] args) throws Exception { try { System.out.println("#########start load class##########"); Class.forName("com.bieber.gc.Main", false, Thread.currentThread().getContextClassLoader()); System.out.println(); System.out.println("#########start init class#########"); Main main = new Main(); System.out.println(); System.out.println("#########invoke#########"); main.test(); } catch (ClassNotFoundException e) { e.printStackTrace(); }

#####执行结果

#########start load class###################start init class#########super static blocksub static blocksuper initmain init#########invoke#########main test

#####结果分析 这个执行结果和和用例一的结果一样。

####总结 上面列举了三个测试用例,用例二和用例三的却别就是 Class.forName("com.bieber.gc.Main", true, Thread.currentThread().getContextClassLoader());Class.forName("com.bieber.gc.Main", false, Thread.currentThread().getContextClassLoader());的区别,这个很容易理解,其实第一个是在加载类的时候是初始化了类(Class)的其他信息,而第二个是延迟初始化。如果是延迟初始化从执行结果上来看和hread.currentThread().getContextClassLoader().loadClass("com.bieber.gc.Main");是一样的。<br/> 通过上面可以理解为,类的加载分为两个步骤:<br/>

  1. 只是装载类,类似将类的字节码加载到JVM中<br/>
  2. 解析类的结构,并初始化类的相关信息,比如static代码块<br/>

并且可以得到父类的加载总是在子类之前,不管是static代码执行,还是构造函数的调用。这也很容易理解,因为子类中可能会调用父类的信息,所以先需要将父类准备好了,子类调用的时候,才没问题。<br/>

此处给一个建议:谨慎在父类中定义protected(public) static的属性,因为这个时候,是所有子类共用一份内存,很容导致读写冲突。<br/>

针对上面的测试,下面列举出几个其他的测试,大家看看会得到什么结果?

package com.bieber.gc;public class Field {static{ System.out.println("field static block");}}public class Main extends Super{private static Field field=new Field();public Main() { System.out.println("main init");}static{ System.out.println("sub static block");}public void test(){ System.out.println("main test");}}或者public class Main extends Super{private static Field field;public Main() { System.out.println("main init");}static{ System.out.println("sub static block");}public void test(){ System.out.println("main test");}}

我把Main类做了上面的调整,看看执行上面的测试用例,会得到什么结果。欢迎讨论交流,也希望大家也能分享一下你们在开发过程中的一些东西。

转载于:https://my.oschina.net/bieber/blog/286893

你可能感兴趣的文章
ant中copy操作学习心得(转)
查看>>
aspx中的表单验证 jquery.validate.js 的使用 以及 jquery.validate相关扩展验证(Jquery表单提交验证插件)...
查看>>
$.data(elem, key, val) 和 elem.data(key, val)
查看>>
NAND Flash Bad Block Table
查看>>
nohup启动命令(转)
查看>>
富有哲理性的一句话,敌人和朋友
查看>>
教你如何查看一款App里面所包含的图片
查看>>
GDB高级使用方法
查看>>
YII页面显示trace
查看>>
安装时出现——没有定义根文件系统,请到分区菜单修改
查看>>
KPROCESS IDT PEB Ldr 《寒江独钓》内核学习笔记(3)
查看>>
数据结构图之三(最短路径--迪杰斯特拉算法)
查看>>
手机的RAM和ROM
查看>>
C++ 访问控制 public, protected, private, 友元
查看>>
Javascript Ajax异步读取RSS文档
查看>>
Web service是什么?
查看>>
工作线程AfxBeginThread的使用
查看>>
lsof命令
查看>>
迟到的13总结,14展望
查看>>
KL距离,Kullback-Leibler Divergence
查看>>