JAVA : 反射机制
2017-01-19 23:10
435 查看
反射机制
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。JAVA反射(放射)机制:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。从这个观点看,Perl,Python,Ruby是动态语言,C++,Java,C#不是动态语言。但是JAVA有着一个非常突出的动态相关机制:Reflection,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。
功能
java反射机制主要提供了以下功能: 在运行时判断任意一个对象所属的类;在运行时构造任意一个类的对象;在运行时判断任意一个类所具有的成员变量和方法;在运行时调用任意一个对象的方法;生成动态代理。它有着一个非常突出的动态相关机制:Reflection。这个字的意思是“反射、映象、倒影”,用在Java身上指的是我们可以于运行时加载、探知、使用编译期间完全未知的classes。换句话说,Java程序可以加载一个运行时才得知名称的class,获悉其完整构造(但不包括methods定义),并生成其对象实体、或对其fields设值、或唤起其methods。这种“看透class”的能力(the ability of the program to examine itself)被称为introspection(内省、内观、反省)。Reflection和introspection是常被并提的两个术语。
动态绑定
要想深入研究java的反射机制,首先要了解什么是动态绑定。动态是相对于静态来说的。二者的区别主要在于创建对象的时间不一同,静态绑定是编译时创建对象,而动态绑定是在运行时创建对象。public class TestReflect { public static void main(String[] args) throws Exception { String message = null; ManPerson m1 = new ManPerson(); message = m1.eat("aaa");//静态方式调用 System.out.println(message); Class<?> clazz = Class.forName("com.kblsoft.reflect.one.ManPerson"); ManPerson m2 = (ManPerson) clazz.newInstance();//动态方式创建对象调用 message = m2.eat("bbbb"); System.out.println(message); } } interface Person{ public abstract String eat(String food); } class ManPerson implements Person{ @Override public String eat(String food) { return "man eat " + food; } }
通过一个对象获得完整的包名和类名
public class TestReflect { public static void main(String[] args) { TestReflect testReflect = new TestReflect(); System.out.println(testReflect.getClass().getSimpleName());//类名 System.out.println(testReflect.getClass().getName());//包名+类名 //output: //TestReflect // com.kblsoft.reflect.one.TestReflect } }
实例化Class类对象
public class TestReflect { public static void main(String[] args) throws Exception { Class<?> class1 = null; Class<?> class2 = null; Class<?> class3 = null; class1 = Class.forName("com.kblsoft.reflect.one.TestReflect"); // 一般采用这种形式 class2 = new TestReflect().getClass();//可用下面这种代替 class3 = TestReflect.class; System.out.println("类名称 " + class1.getName()); System.out.println("类名称 " + class2.getName()); System.out.println("类名称 " + class3.getName()); //output //类名称 com.kblsoft.reflect.one.TestReflect //类名称 com.kblsoft.reflect.one.TestReflect //类名称 com.kblsoft.reflect.one.TestReflect } }
获取某个类中的全部构造函数
public class TestReflect { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.kblsoft.reflect.one.Student"); //第一种方法,实例化 Student student = (Student) clazz.newInstance(); student.setAge(24); student.setName("black"); System.out.println(student.getAge() + "::" + student.getName()); //output 24::black //第二种 获取所有构造函数,逐个分析 Constructor<?> cons[] = clazz.getConstructors(); for (Constructor<?> con : cons) { Parameter[] paras = con.getParameters(); System.out.println(con); for (Parameter para : paras) { System.out.println(para.getType().getName()); } } //output // public com.kblsoft.reflect.one.Student(int,java.lang.String) // int // java.lang.String // public com.kblsoft.reflect.one.Student(java.lang.String) // java.lang.String // public com.kblsoft.reflect.one.Student() } } class Student { public int age; public String name; public Student() { } public Student(String name) { this.name = name; } public Student(int age, String name) { this.age = age; this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
获取某个类的全部属性
权限修饰符在这里有用public class TestReflect extends Param { private int iSelf = 0; public static void main(String[] args) throws ClassNotFoundException { Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect"); System.out.println("===============本类属性:getDeclaredFields==============="); // 取得本类的全部属性 Field[] field = clazz.getDeclaredFields(); for (Field f : field) { // 权限修饰符 int mo = f.getModifiers(); String priv = Modifier.toString(mo); // 属性类型 Class<?> type = f.getType(); System.out.println(priv + " " + type.getName() + " " + f.getName() + ";"); } System.out.println("==========实现的接口或者父类的属性:getFields=========="); // 取得实现的接口或者父类的属性 Field[] filed1 = clazz.getFields(); for (Field f : filed1) { // 权限修饰符 int mo = f.getModifiers(); String priv = Modifier.toString(mo); // 属性类型 Class<?> type = f.getType(); System.out.println(priv + " " + type.getName() + " " + f.getName() + ";"); } } }
获取某个类的全部方法
public class TestReflect extends Param { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect"); Method[] methods = clazz.getMethods();//获取全部方法,然后循环信息 for (Method method : methods) { Class<?> returnType = method.getReturnType(); Class<?> paras[] = method.getParameterTypes(); int temp = method.getModifiers(); //获取方法修饰符和名称 //output public static void main System.out.print(Modifier.toString(temp) + " "); System.out.print(returnType.getName() + " "); System.out.print(method.getName() + " "); //获取方法参数 for (Class<?> para : paras) { System.out.print(para.getName()); } //获取方法的异常 Class<?> exces[] = method.getExceptionTypes(); for (Class<?> exce : exces) { System.out.println(exce.getName()); } System.out.println(); } } public static void testMethod(String param1,int param2) { } public String testMethod2(){ return "SUCCESS"; } }
通过反射机制调用某个类的方法
public class TestReflect extends Param { public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect"); Method method1 = clazz.getMethod("reflect1"); method1.invoke(clazz.newInstance()); Method method2 = clazz.getMethod("reflect2",int.class,String.class); method2.invoke(clazz.newInstance(),22,"black");//invoke 反射 //output //Java 反射机制 - 调用某个类的方法1. //Java 反射机制 - 调用某个类的方法2. //age -> 22. name -> black } public void reflect1() { System.out.println("Java 反射机制 - 调用某个类的方法1."); } public void reflect2(int age, String name) { System.out.println("Java 反射机制 - 调用某个类的方法2."); System.out.println("age -> " + age + ". name -> " + name); } }
通过反射机制操作某个类的属性
private String proprety = null; public static void main(String[] args) throws Exception { Class<?> clazz = Class.forName("com.kblsoft.reflect.one.TestReflect"); Object obj = clazz.newInstance(); // 可以直接对 private 的属性赋值 Field field = clazz.getDeclaredField("proprety");//获取指定的属性值 field.setAccessible(true);//设置是否允许访问,而不是修改原来的访问权限修饰词。 field.set(obj, "Java反射机制");//set值 System.out.println(field.get(obj));//get值 }
反射机制的动态代理
代理设计模式 : 定义:为其他对象提供一种代理以控制对这个对象的访问。一个典型的动态代理创建对象过程可分为以下四个步骤:
1、通过实现InvocationHandler接口创建自己的调用处理器 IvocationHandler handler = new InvocationHandlerImpl(…);
2、通过为Proxy类指定ClassLoader对象和一组interface创建动态代理类
Class clazz = Proxy.getProxyClass(classLoader,new Class[]{…});
3、通过反射机制获取动态代理类的构造函数,其参数类型是调用处理器接口类型
Constructor constructor = clazz.getConstructor(new Class[]{InvocationHandler.class});
4、通过构造函数创建代理类实例,此时需将调用处理器对象作为参数被传入
Interface Proxy = (Interface)constructor.newInstance(new Object[] (handler));
为了简化对象创建过程,Proxy类中的newInstance方法封装了2~4,只需两步即可完成代理对象的创建。
生成的ProxySubject继承Proxy类实现Subject接口,实现的Subject的方法实际调用处理器的invoke方法,而invoke方法利用反射调用的是被代理对象的的方法(Object result=method.invoke(proxied,args))
public class TestReflect { public static void main(String[] args) throws Exception { MyInvocationHandler demo = new MyInvocationHandler(); Person sub = (Person) demo.bind(new RealPerson()); String info = sub.eat("children"); System.out.println(info); } } interface Person{ public String eat(String food); } class RealPerson implements Person{ @Override public String eat(String food) { return "eat " + food; } } class MyInvocationHandler implements InvocationHandler{//定义一个InvocationHandler接口的子类 private Object obj = null; public Object bind(Object obj){//具体的实现 this.obj = obj; return Proxy.newProxyInstance(obj.getClass().getClassLoader(),obj.getClass().getInterfaces(),this);//创建动态代理 } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return method.invoke(this.obj,args);//对接口的调用重定向为对代理的调用 } }
通过反射取得并修改数组的信息
Array的使用public class TestReflect { public static void main(String[] args) throws Exception { int[] temp = { 1, 2, 3, 4, 5 }; Class<?> demo = temp.getClass().getComponentType(); System.out.println("数组类型: " + demo.getName()); System.out.println("数组长度 " + Array.getLength(temp)); System.out.println("数组的第一个元素: " + Array.get(temp, 0)); Array.set(temp, 0, 100); System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0)); //output //数组类型: int //数组长度 5 //数组的第一个元素: 1 //修改之后数组第一个元素为: 100 } }
通过反射机制修改数组的大小
public class TestReflect { public static void main(String[] args) throws Exception { int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int[] newTemp = (int[]) arrayInc(temp, 15); print(newTemp); String[] atr = { "a", "b", "c" }; String[] str1 = (String[]) arrayInc(atr, 8); print(str1); //output //数组长度为: 15 //1 2 3 4 5 6 7 8 9 0 0 0 0 0 0 //数组长度为: 8 //a b c null null null null null } // 修改数组大小 public static Object arrayInc(Object obj, int len) { Class<?> arr = obj.getClass().getComponentType(); Object newArr = Array.newInstance(arr, len); int co = Array.getLength(obj); System.arraycopy(obj, 0, newArr, 0, co); return newArr; } // 打印 public static void print(Object obj) { Class<?> c = obj.getClass(); if (!c.isArray()) { return; } System.out.println("数组长度为: " + Array.getLength(obj)); for (int i = 0; i < Array.getLength(obj); i++) { System.out.print(Array.get(obj, i) + " "); } System.out.println(); } }
将反射机制应用于工厂模式
//现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。 //但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。 public class TestReflect { public static void main(String[] args) throws Exception { Person p = Factory.getInstance("com.kblsoft.reflect.one.ManPerson");//接口接收,创建的是子类 if (null != p) { System.out.println(p.eat("children")); } } } interface Person{ public abstract String eat(String food); } class ManPerson implements Person{ @Override public String eat(String food) { return "man eat " + food; } } class WomanPerson implements Person{ @Override public String eat(String food) { return "woman eat " + food; } } class Factory { public static Person getInstance(String className){ Person person = null; try { person = (Person) Class.forName(className).newInstance(); } catch (Exception e) { e.printStackTrace(); } return person; } }
参考
1. http://www.cnbl/lzq198754/p/5780331.html
2. java编程思想
相关文章推荐