1、反射:在程序运行时通过一个类的对象获取这个类的信息的方法。
2、Class类:在java里万事万物皆对象,可以理解为是Class类的对象,Class有一些方法可以由类的对象获取类的信息。获取一个class的Class实例有三种办法,如下:
package reflection;
public class ReflectionDemo {
public static void main(String args[]) {
// 实例对象如何表示
ClassDemo classDemo = new ClassDemo();
// ClassDemo是类,其实也是一个实例对象是基于Class的。
//方法1:(任何一个类都有一个隐含的成员变量class)
Class c1 = ClassDemo.class;
//方法2:(通过getClass()方法获取一个对象的类信息)
Class c2 = classDemo.getClass();
// 两种表达式相同的
System.out.println(c1 == c2);
//方法3:通过Class的forName()方法
Class c3 = null;
try {
c3 = Class.forName("reflection.ClassDemo");
} catch (Exception e) {
// TODO: handle exception
}
// 也是相等的
System.out.println(c2 == c3);
// 可以通过c1,c2, c3创建该类的对象
try {
ClassDemo classDemo2 = (ClassDemo)c1.newInstance(); // 根据实际情况进行强制类型转换
classDemo2.print();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
// classdemo 类
class ClassDemo{
void print() {
System.out.println("class demo");
}
}
3、静态加载和动态加载:静态加载时值程序在编译期的时候就完成了加载编译,比如new对象就是编译时加载的,已经创建好了对象实例。而动态加载时指在运行时需要使用的时候才进行加载,绕过编译且不报错。
4、通过反射API获取类信息:使用Class的提供的方法可以获取一个对象的类的信息,包括成员变量,成员方法,构造方法,甚至包括接口信息,继承关系等。Java的反射API提供的Field
类封装了成员变量的所有信息,Method
对象封装了方法的所有信息,Constructor
对象封装了构造方法的所有信息。
5、动态代理:JDK提供的动态创建接口对象的方式,即没有实现类但是在运行期动态创建了一个接口对象的方式。
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
// 定义一个InvocationHandler实例,它负责实现接口的方法调用;
// 通过Proxy.newProxyInstance()创建interface实例,它需要3个参数:(使用的`ClassLoader`;需要实现的接口数组;用来处理接口方法调用的`InvocationHandler`实例。)
//将返回的`Object`强制转型为接口。
public class Main {
public static void main(String args[]) {
InvocationHandler handler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method);
if (method.getName().equals("morning")) {
System.out.println("Good morning, " + args[0]);
}
return null;
}
};
Hello hello = (Hello) Proxy.newProxyInstance(
Hello.class.getClassLoader(), // 传入ClassLoader
new Class[] { Hello.class }, // 传入要实现的接口
handler); // 传入处理调用方法的InvocationHandler
hello.morning("Bob");
}
}
interface Hello {
void morning(String name);
}
6、代理模式和反射机制:动态代理是设计模式当中代理模式的一种(为其他对象提供一种代理以控制这个对象的访问),JDK的动态代理主要是使用的是反射机制。常应用于AOP(面向切面编程)、RPC(远程过程调用),反编译,EventBus 2.x,动态生成类框架等。
优点:运行期类型的判断,动态类加载,动态代理使用反射;
缺点:性能是一个问题,反射相当于一系列解释操作,通知jvm要做的事情,性能比直接的java代码要慢很多。