专栏合集(一):Java深度历险 pdf已上传115 ebook
1. blog learning .... 深入探讨 Java 类加载器
blog.... 写道
类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。
jdk 1.6 写道
Class
类的实例表示正在运行的 Java 应用程序中的类和接口。
Class 没有公共构造方法。Class 对象是在加载类时由 Java 虚拟机以及通过调用类加载器中的 defineClass 方法自动构造的。
以下示例使用 Class 对象来显示对象的类名:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
还可以使用一个类字面值(JLS Section 15.8.2)来获取指定类型(或 void)的 Class 对象。例如:
System.out.println("The name of class Foo is: "+Foo.class.getName());
以下示例使用 Class 对象来显示对象的类名:
void printClassName(Object obj) {
System.out.println("The class of " + obj +
" is " + obj.getClass().getName());
}
还可以使用一个类字面值(JLS Section 15.8.2)来获取指定类型(或 void)的 Class 对象。例如:
System.out.println("The name of class Foo is: "+Foo.class.getName());
2011-10-1 update
以下命令可以查看,JVM是如何将二进制文件(*.class)载入内存的。
java -verbose ABClient
测试代码:
public class A{
public void printInfo(){
System.out.println(" class A printInfo...");
}
}
public class B{
public void printInfo(){
System.out.println(" class B printInfo...");
}
}
public class ABClient{
public void printInfo(){
System.out.println(" class ABClient printInfo...");
}
public static void main(String args[]){
new A().printInfo();
//只有new 出是实例的时候 ,才会被load 进 内存中。声明则不会。
B b;
}
}
结果:
[Loaded java.security.cert.Certificate from shared objects file]
[Loaded ABClient from file:/E:/coding/20111001_java/classLoader/]
---------static block code loader finished------------
[Loaded A from file:/E:/coding/20111001_java/classLoader/]
class A printInfo...
[Loaded java.util.AbstractList$Itr from shared objects file]
###初始化对象的3种方法:
为ABClient类添加静态代码块:
static{
System.out.println("========run static code========");
}
public class InstanceObject{
public void printTest(String info){
System.out.println("----------run----------:" + info);
}
public static void main(String args[]){
// 隐式 实例化方法
InstanceObject io = new InstanceObject();
io.printTest("隐式实例化");
//显式 实例化方法
//1 Class.forName
try{
Class clazz = Class.forName("InstanceObject");
InstanceObject io2 = (InstanceObject)clazz.newInstance();
io2.printTest("显式实例化 forName");
}catch(java.lang.InstantiationException ie){
ie.printStackTrace();
}catch(java.lang.ClassNotFoundException cnfe){
cnfe.printStackTrace();
}catch(java.lang.IllegalAccessException iae){
iae.printStackTrace();
}
//2 ClassLoader
try{
ClassLoader clazzLoader = InstanceObject.class.getClassLoader();
System.out.println("begin to load the ABClient class");
Class clazz2 = clazzLoader.loadClass("ABClient");
//静态区域块 是在第一次实例化时才被载入的。
System.out.println("begin to instance the ABClient object");
ABClient abObject = (ABClient)clazz2.newInstance();
}catch(java.lang.InstantiationException ie){
ie.printStackTrace();
}catch(java.lang.ClassNotFoundException cnfe){
cnfe.printStackTrace();
}catch(java.lang.IllegalAccessException iae){
iae.printStackTrace();
}
//API中 获取 Class 实体的方法有2种, 推荐使用 类名.class ;另外一种是instance.getClass()
}
}
测试Class.forName 第二个参数为 true or false时的 载入静态代码块的区别。
测试结果为 无论是true还是false,对象实例化之后静态代码块还是没有被执行,在实例调用某个方法后才执行。这点有待验证。
至于 classLoader 载入.class文件后,静态代码块不会被执行;初始化(newInstance)后,静态代码块被执行,且仅执行一次。