Java 的加载与反射机制
一、 Java 程序运行的过程(加载机制)
好了,让我们简单了解下 Class 和 ClassLoader 这两个类吧!
程序开始时, ClassLoader 会把包含主函数的 .class 文件 Load 到内存中的代码区,并为这个 .class 文件创建一个 Class 对象来描述这个类的一些特征 ( 类的属性和方法 ) 。然后把需要的类逐步加载 ( 可以在运行时通过加入虚拟机运行参数: -verbose:class 来显示类加载的过程 ) ,静态语句块和动态语句是在类被 ClassLoader 加载到内存虚拟机时,执行的,它们要先于构造函数而执行的,区别时静态语句块只加载一次, 那么在内存中存在多少个 ClassLoader 呢,有一点我们先明确下,那就是一个 class 对象肯定对应一个 ClassLoader, 也就是说我们可以通过这个对象找到它所对应的 ClassLoader.
二、 JDK 内置 ClassLoader
Bootstrap class loader
☆ Implemented by native language
☆ Load the core classes of jdk
Extesion class loader
☆ loader the class from jre/lib/ext
application class loader
☆ load user-define classes
☆ ClassLoader.getSystemClassLoader()
Other class loader
☆ Secure class loader
☆ URLClassLoader
过程是 boot class loader 首先把其它的 class loader l 和一些核心类 load 到内存中,其它的 class loader 再把我们需要的类 load 到虚拟机中。这样就开始运行啦 1 呵呵,明白了吗?
JDK Class Loader 的层次关系 ( 对象之间不是继承 )
二、 Java 的反射机制
首先:什么是 Java 反射机制呢?
Java 的反射机制 是在运行状态中,对于任意一个类,都知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法;这种动态获取的信息以及动态调用对象方法的功能成为 Java 语言的反射机制。
Java 反射机制主要提供了以下功能;在运行时判断一个对象所属的类,在运行时构造任意一个类的对象,在运行时判断任意一个类所有的成员变量和成员方法。在运行时调用任意一个对象的方法,生成动态代理。
下面具体介绍下上面的功能如何实现:
1. 得到对象的某个属性
public Object getProperty(Object owner, String filedName) throws Exception {
Class ownerClass = owner.getClass(); // 得到该对象的 Class
Field field = ownerClass.getField(fileName); // 通过 Class 得到声明的属性 ( 注:如果该属性是私有的会抛出 java.lang.NoSuchFieldException )
Object property = field.get(owner); // 通过对象得到该属性的实例,
return property;
}
2. 得到某个类的静态属性
public Object getStaticProperty(String className, String fieldName) throws Exception {
Class ownerClass = Class.forName(className);// 得到这个类的 Class
Field field = ownerClass.getField(fieldName); // 通过 Class 得到类声明的属性
Object property = field.getProperty(ownerClass); // 因为该属性是静态属性,所以直接从类的 Class 里取。
return property;
}
3. 执行某对象的方法
public Object invokeMethod(Object owner, String methodName, Object[] args) throws Exception {
Class ownerClass = owner.getClass(); // 得到这个对象的 Class
Class[] argsClass = new Class[args.length];// 配置参数的 Class 数组,作为寻找 Method 的条件。
for (int i = 0, j = args.length; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Method method = ownerClass.getMethod(methodName, argsClass);
return method.invoke(owner, args); 执行该 Method,invoke 方法的参数是执行这个方法的对象和参数数组,返回值是 Object, 也即是该方法的返回值。
}
4. 执行某个类的静态方法
public Object invokeStaticMehod(String className,
String methodName, Object[] args) throws Exception {
Class ownerClass = Class.forName (className);
Class [] argsMethod = new Class[args. length ];
for ( int i = 0, j = args. length ; i < j; i++) {
argsMethod[i] = args[i].getClass();
}
Method method = ownerClass.getMethod(methodName, argsMethod);
return method.invoke( null , argsMethod) ; // 因为它是一个静态类不需要借助于实体运行,故传递一个 null.
}
5. 新建实例 :
public Object newInstance(String className, Object[] args) throws Exception {
Class newoneClass = Class.forName (className);
Class[] argsClass = new Class[args. length ];
for ( int i = 0, j = args. length ; i < j; i++) {
argsClass[i] = args[i].getClass();
}
Constructor cons = newoneClass.getConstructor(argsClass);
return cons.newInstance(args);
}
6. 判断是否为某个类的实例
public boolean isInstance(Object obj, Class cls) {
return cls.isInstance(obj); // 注意你也可以用关键字 instanceof 来实现
}
7. 得到数组中的某个元素
public Object getByArray(Object array, int index) {
return Array.get(array,index);
}