反射是学高新技术遇到的最大的难点,也不知道怎么说,总之刚开始各种听不懂,后来不知道为什么想起了关于太极的那句两仪生四象什么的,感觉反射不就那回事,反射就一句话,给一个类的字节码,可以对那个类为所欲为。
反射是Java的特征之一,它不仅可以列举类的成员、方法,还可以创建对象、调用方法、访问成员。
反射的成员有:
Class类:它的实例表示java中类和接口
Field类:它是类和接口里的属性
Constructor类:它封装了反射类的构造方法
Method类:它封装了反射类的方法
Array类:提供了动态创建数组和访问数组的静态方法,里面所有方法都是静态的。
1、Class类
Java在运行时,系统会对所有对象进行运行时类型标识,用来保存这些信息的类就是Class类。
每一个Class对象都是独一无二的,在创建某个类的实例时,Jvm会先查看对应的CLass对象是否存在。如果不存在,JVM会根据类名查找对应的字节码文件并通过类加载器加载,创建Class对象,最后才创建这个类的实例。
创建Class对象有3种方法
public static void main(String[] args)
{//方法一
类型 x=new 类型();
Class x类型=x.getClass();
//方法二:
Class a=Class.forName(className);
//方法三:
Class b=classname.class;
}
而获取Class对象只是第一步,利用Java的反射机制,可以用Class对象获取类的Field,Constructor、Method。里面提供了非常多的方法。
1、public Field[] getFields(); 获取所有 public成员属性
2、get DeclareField():获取所有成员,包括private的
3、get Construtors():获取所有public构造方法
4、get DeclareConstrutors():获取所有构造方法
....................
1、获取成员
public class ReflectPoint {
private int x;
public int y;
public String toString(){
return str1+";" + str2 + ";" + str3;
}
}
public class FieldTest(){
ReflectPoint pt1 = new ReflectPoint(3,5);
//fieldX和fieldY并不是对象身上的变量,而是类上的
//要用它去取某个对象上的对应的值,传入什么对象,就取相应对象的值。
Field fieldY = pt1.getClass().getField("y");
System.out.println(fieldY.get(pt1));
//获取私有的成员变量
Field fieldX = pt1.getClass().getDeclaredField("x");
fieldX.setAccessible(true);
System.out.println(fieldX.get(pt1));
}
2、获取方法
private static void methodTest(String [] args) throws Exception {
String str1 = "abc";
//一般方法:
System.out.println(str1.charAt(1));
//反射方法 :
Method methodCharAt =
Class.forName("java.lang.String").getMethod("charAt",int.class);
System.out.println(methodCharAt.invoke(str1,1));
//用反射方式执行某个main方法
//一般方式:
Test.main(new String[]{"111","222","333"});
System.out.println("-------");
//反射方式:
String startingClassName = args[0];
Method methodMain =
Class.forName(startingClassName).getMethod("main",String[].class);
methodMain.invoke(null,(Object)new String[]{"111","222","333"});
}
//定义一个测试类
class Test{
public static void main(String [] args){
for(String arg : args){
System.out.println(arg);
}
}
}
这到底有什么用呢“?
就是框架。
而以下就要讲一个应用:代理
代理模式是Java中很常用的设计模式,很多框架都经常用到,它的原理就用到了反射。
二、反射应用:代理
1、静态代理
静态代理严格来讲还不是代理模式,它只是阐述了代理是什么。
下面有一个例子:一个客户想做一批衣服,但他找不到厂家,只能通过中介公司,中介公司帮他找了厂家做这批衣服,而中介要收代理费用。
interface Factory{
void productClothing();
}
class ProxyCompany implements Factory{
private Factory ft;
ProxyCompany(Factory ft){
this.ft=ft;
}
public void productClothing(){
ft.productClothing();
System.out.println("收取中介费10000");
}
}
这就是静态代理,也是代理的理解。可是这种代理并没有用到放射的技术,而且如果要用到其他的功能就要重新代理非常的麻烦。
我们可以利用动态代理技术来根据需要的功能来根据反射来添加。
这也是AOP设计模式,面向方面
如果程序存在交叉业务,就可以使这交叉业务模块化,用代理去实现,而反射就是核心技术。
要动态代理,需要实现一个InvocationHandler接口,可以把需要代理的类设为target参数,共同的业务设置为advice参数,总之看下面的例子
class ProxyHandle implements InvocationHandler{
private Object target;
public Object newProxyInstance(Object target){
this.target=target;
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(),
this.target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy,Method method,Object[] args)throws Throwable{
Object result=null;
try {
result = method.invoke(this.target, args);
} catch (Exception e) {
// TODO: handle exception
}
return result;
}
}
这就是动态代理。可以把代理类通过反射来得到而不用通过实际的对象来得,这样也算一个小小的框架把。