一、内容提要:
1、反射机制是什么
2、反射机制能做什么
3、反射机制相关的API
4、通过一个对象获得完整的包名和类名
5、实例化Class类对象
6、获取一个对象的父类与实现的接口
7、获取某个类的全部构造函数
8、通过反射机制实例化一个类的对象
9、获取某个类的全部属性
10、获取某个类的全部方法
11、通过反射机制调用某个类的方法
12、通过反射机制操作某个类的属性
13、反射机制的动态代理
14、反射机制的应用实例
15、在范型为Integer的ArrayList中存放一个String类型的对象
16、通过反射取得并修改数组的信息
17、通过反射机制修改数组的大小
18、将反射机制应用于工厂模式
1、反射机制是什么?
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取信息以及动态调用对象的方法的功能称为java语言的反射机制。
2、反射机制能做什么?
反射机制主要提供了以下功能:
1、在运行时判断任意一个对象所属的类
2、在运行时构造任意一个类的对象
3、在运行时判断任意一个类所具有的成员变量和方法
4、在运行时调用任意一个对象的方法
5、生成动态代理
3、反射机制相关的API
通过一个对象获得完整的包名和类名
1package com.wangjun.ThinkingInJava.java_14.third.java_10; 2 3public class TestReflect { 4 5 public static void main(String[] args) { 6 TestReflect testReflect=new TestReflect(); 7 System.out.println(testReflect.getClass().getName()); 8 9 } 10 11}
输出结果:
1 com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
实例化Class类对象
1 1 package com.wangjun.ThinkingInJava.java_14.third.java_10; 2 2 3 3 public class TestReflect { 4 4 5 5 public static void main(String[] args) throws ClassNotFoundException { 6 6 Class<?> class1=null; 7 7 Class<?> class2=null; 8 8 Class<?> class3=null; 9 9 1010 //一般采用这种形式 1111 class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect"); 1212 class2=new TestReflect().getClass(); 1313 class3=TestReflect.class; 1414 System.out.println("类名称: "+class1.getName()); 1515 System.out.println("类名称: "+class2.getName()); 1616 System.out.println("类名称: "+class3.getName()); 1717 1818 } 1919 2020 }
输出结果:
11 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect 22 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect 33 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
获取一个对象的父类与实现的接口:
1 1 package com.wangjun.ThinkingInJava.java_14.third.java_10; 2 2 3 3 import java.io.Serializable; 4 4 5 5 public class TestReflect1 implements Serializable { 6 6 7 7 public static void main(String[] args) throws ClassNotFoundException { 8 8 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect1"); 9 9 //取得父类 1010 Class<?> parentClass=clazz.getSuperclass(); 1111 System.out.println("clazz的父类为: "+parentClass.getName()); 1212 //clazz的父类为:java.lang.Object 1313 //获取所有的接口 1414 Class<?> intes[]=clazz.getInterfaces(); 1515 System.out.println("clazz实现的接口有:"); 1616 for(int i=0;i<intes.length;i++){ 1717 System.out.println((i+1)+":"+intes[i].getName()); 1818 } 1919 } 2020 2121 }
输出结果:
11 clazz的父类为: java.lang.Object 22 clazz实现的接口有: 33 1:java.io.Serializable
通过反射机制实例化一个类的对象
1 1 public class TestReflect2 { 2 2 3 3 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { 4 4 Class<?> class1=null; 5 5 class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.User"); 6 6 //第一种方法,实例化默认构造方法,调用set赋值 7 7 User user=(User) class1.newInstance(); 8 8 user.setAge(20); 9 9 user.setName("Rollen"); 1010 System.out.println(user); 1111 1212 //第二种方法 取得全部的构造函数 使用构造函数赋值 1313 Constructor<?> cons[]=class1.getConstructors(); 1414 //查看每个构造方法需要的参数 1515 for(int i=0;i<cons.length;i++){ 1616 Class<?>clazzs[]=cons[i].getParameterTypes(); 1717 System.out.print("cons["+i+"]("); 1818 for(int j=0;j<clazzs.length;j++){ 1919 if(j==clazzs.length-1){ 2020 System.out.print(clazzs[j].getName()); 2121 }else { 2222 System.out.print(clazzs[j].getName()+","); 2323 } 2424 } 2525 System.out.println(")"); 2626 } 2727 2828 user=(User) cons[1].newInstance("Rollen"); 2929 System.out.println(user); 3030 user = (User) cons[0].newInstance(20, "Rollen"); 3131 System.out.println(user); 3232 } 3333 3434 } 35 36 1 package com.wangjun.ThinkingInJava.java_14.third.java_10; 37 2 38 3 public class User { 39 4 private int age; 40 5 private String name; 41 6 public User(){} 42 7 public User(String name){ 43 8 super(); 44 9 this.name=name; 4510 } 4611 public User(int age,String name){ 4712 super(); 4813 this.age=age; 4914 this.name=name; 5015 } 5116 public int getAge() { 5217 return age; 5318 } 5419 public void setAge(int age) { 5520 this.age = age; 5621 } 5722 public String getName() { 5823 return name; 5924 } 6025 public void setName(String name) { 6126 this.name = name; 6227 } 6328 6429 6530 public String toString(){ 6631 return "User [age=]"+age+",name="+name+"]"; 6732 } 6833 6934 }
输出结果:
11 User [age=]20,name=Rollen] 22 cons[0](int,java.lang.String) 33 cons[1](java.lang.String) 44 cons[2]() 55 User [age=]0,name=Rollen] 66 User [age=]20,name=Rollen]
获取某个类的全部属性:
1 1 import java.io.Serializable; 2 2 import java.lang.reflect.Field; 3 3 import java.lang.reflect.Modifier; 4 4 5 5 public class TestReflect3 implements Serializable{ 6 6 private String name="main"; 7 7 public static void main(String[] args) throws ClassNotFoundException{ 8 8 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect3"); 9 9 System.out.println("======本类属性========"); 1010 Field[] fields=clazz.getDeclaredFields(); 1111 for(int i=0;i<fields.length;i++){ 1212 //权限修饰符 1313 int mo=fields[i].getModifiers(); 1414 String priv=Modifier.toString(mo); 1515 //属性类型 1616 Class<?> type=fields[i].getType(); 1717 System.out.println(priv+" "+type.getName()+" "+fields[i].getName()+";"); 1818 } 1919 System.out.println("==========实现的接口或者 父类的属性=============="); 2020 //取得实现的接口或者父类的属性 2121 Field[] filed1=clazz.getFields(); 2222 for(int j=0;j<filed1.length;j++){ 2323 // 权限修饰 2424 int mo=filed1[j].getModifiers(); 2525 String priv=Modifier.toString(mo); 2626 2727 //属性类型 2828 Class<?> type=filed1[j].getType(); 2929 System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";"); 3030 3131 } 3232 3333 } 3434 3535 }
输出结果:
11 ======本类属性======== 22 private java.lang.String name; 33 ==========实现的接口或者 父类的属性==============
获取某个类的全部方法
1 1 package com.wangjun.ThinkingInJava.java_14.third.java_10; 2 2 3 3 import java.io.Serializable; 4 4 import java.lang.reflect.Method; 5 5 import java.lang.reflect.Modifier; 6 6 7 7 public class TestReflect4 implements Serializable { 8 8 9 9 public static void main(String[] args) throws Exception{ 1010 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect4"); 1111 Method method[]=clazz.getMethods(); 1212 for (int i = 0; i < method.length; ++i) { 1313 Class<?> returnType = method[i].getReturnType(); 1414 Class<?> para[] = method[i].getParameterTypes(); 1515 int temp = method[i].getModifiers(); 1616 System.out.print(Modifier.toString(temp) + " "); 1717 System.out.print(returnType.getName() + " "); 1818 System.out.print(method[i].getName() + " "); 1919 System.out.print("("); 2020 for (int j = 0; j < para.length; ++j) { 2121 System.out.print(para[j].getName() + " " + "arg" + j); 2222 if (j < para.length - 1) { 2323 System.out.print(","); 2424 } 2525 } 2626 Class<?> exce[] = method[i].getExceptionTypes(); 2727 if (exce.length > 0) { 2828 System.out.print(") throws "); 2929 for (int k = 0; k < exce.length; ++k) { 3030 System.out.print(exce[k].getName() + " "); 3131 if (k < exce.length - 1) { 3232 System.out.print(","); 3333 } 3434 } 3535 } else { 3636 System.out.print(")"); 3737 } 3838 System.out.println(); 3939 } 4040 4141 } 4242 4343 }
输出结果:
11 public boolean equals (java.lang.Object arg0) 22 public java.lang.String toString () 33 public native int hashCode () 44 public final native java.lang.Class getClass () 55 public final native void notify () 66 public final native void notifyAll ()
通过反射机制调用某个类的方法
1 1 public class TestReflect5 { 2 2 3 3 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { 4 4 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect5"); 5 5 //调用TestReflect类中的reflect1方法 6 6 Method method=clazz.getMethod("reflect1"); 7 7 method.invoke(clazz.newInstance()); 8 8 //Java 反射机制-调用某个类的方法1. 9 9 //调用TestReflect的reflect2方法 1010 method=clazz.getMethod("reflect2", int.class,String.class); 1111 method.invoke(clazz.newInstance(), 20,"张三"); 1212 1313 } 1414 1515 public void reflect1(){ 1616 System.out.println("Java 反射机制 - 调用某个类的方法1."); 1717 } 1818 public void reflect2(int age, String name) { 1919 System.out.println("Java 反射机制 - 调用某个类的方法2."); 2020 System.out.println("age -> " + age + ". name -> " + name); 2121 } 2222 2323 }
运行结果:
11 Java 反射机制 - 调用某个类的方法1. 22 Java 反射机制 - 调用某个类的方法2. 33 age -> 20. name -> 张三
通过反射机制调用某个类的方法
1 1 package net.xsoftlab.baike; 2 2 import java.lang.reflect.Method; 3 3 public class TestReflect { 4 4 public static void main(String[] args) throws Exception { 5 5 Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect"); 6 6 // 调用TestReflect类中的reflect1方法 7 7 Method method = clazz.getMethod("reflect1"); 8 8 method.invoke(clazz.newInstance()); 9 9 // Java 反射机制 - 调用某个类的方法1. 1010 // 调用TestReflect的reflect2方法 1111 method = clazz.getMethod("reflect2", int.class, String.class); 1212 method.invoke(clazz.newInstance(), 20, "张三"); 1313 // Java 反射机制 - 调用某个类的方法2. 1414 // age -> 20. name -> 张三 1515 } 1616 public void reflect1() { 1717 System.out.println("Java 反射机制 - 调用某个类的方法1."); 1818 } 1919 public void reflect2(int age, String name) { 2020 System.out.println("Java 反射机制 - 调用某个类的方法2."); 2121 System.out.println("age -> " + age + ". name -> " + name); 2222 } 2323 }
通过反射机制调用某个类的属性
1 1 package net.xsoftlab.baike; 2 2 import java.lang.reflect.Field; 3 3 public class TestReflect { 4 4 private String proprety = null; 5 5 public static void main(String[] args) throws Exception { 6 6 Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect"); 7 7 Object obj = clazz.newInstance(); 8 8 // 可以直接对 private 的属性赋值 9 9 Field field = clazz.getDeclaredField("proprety"); 1010 field.setAccessible(true); 1111 field.set(obj, "Java反射机制"); 1212 System.out.println(field.get(obj)); 1313 } 1414 }
反射机制的动态代理
1 1 // 获取类加载器的方法 2 2 TestReflect testReflect = new TestReflect(); 3 3 System.out.println("类加载器 " + testReflect.getClass().getClassLoader().getClass().getName()); 4 4 package net.xsoftlab.baike; 5 5 import java.lang.reflect.InvocationHandler; 6 6 import java.lang.reflect.Method; 7 7 import java.lang.reflect.Proxy; 8 8 //定义项目接口 9 9 interface Subject { 1010 public String say(String name, int age); 1111 } 1212 // 定义真实项目 1313 class RealSubject implements Subject { 1414 public String say(String name, int age) { 1515 return name + " " + age; 1616 } 1717 } 1818 class MyInvocationHandler implements InvocationHandler { 1919 private Object obj = null; 2020 public Object bind(Object obj) { 2121 this.obj = obj; 2222 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this); 2323 } 2424 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 2525 Object temp = method.invoke(this.obj, args); 2626 return temp; 2727 } 2828 } 2929 /** 3030 * 在java中有三种类类加载器。 3131 * 3232 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 3333 * 3434 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类 3535 * 3636 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 3737 * 3838 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。 3939 * 4040 * @author xsoftlab.net 4141 * 4242 */ 4343 public class TestReflect { 4444 public static void main(String[] args) throws Exception { 4545 MyInvocationHandler demo = new MyInvocationHandler(); 4646 Subject sub = (Subject) demo.bind(new RealSubject()); 4747 String info = sub.say("Rollen", 20); 4848 System.out.println(info); 4949 } 5050 }
二、反射机制的应用实例
在泛型为Integer的ArrayList中存放一个String类型的对象
1 1 package net.xsoftlab.baike; 2 2 import java.lang.reflect.Method; 3 3 import java.util.ArrayList; 4 4 public class TestReflect { 5 5 public static void main(String[] args) throws Exception { 6 6 ArrayList<Integer> list = new ArrayList<Integer>(); 7 7 Method method = list.getClass().getMethod("add", Object.class); 8 8 method.invoke(list, "Java反射机制实例。"); 9 9 System.out.println(list.get(0)); 1010 } 1111 }
通过反射取得并修改数组的信息
1 1 package net.xsoftlab.baike; 2 2 import java.lang.reflect.Array; 3 3 public class TestReflect { 4 4 public static void main(String[] args) throws Exception { 5 5 int[] temp = { 1, 2, 3, 4, 5 }; 6 6 Class<?> demo = temp.getClass().getComponentType(); 7 7 System.out.println("数组类型: " + demo.getName()); 8 8 System.out.println("数组长度 " + Array.getLength(temp)); 9 9 System.out.println("数组的第一个元素: " + Array.get(temp, 0)); 1010 Array.set(temp, 0, 100); 1111 System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0)); 1212 } 1313 }
通过反射机制修改数组的大小
1 1 package net.xsoftlab.baike; 2 2 import java.lang.reflect.Array; 3 3 public class TestReflect { 4 4 public static void main(String[] args) throws Exception { 5 5 int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; 6 6 int[] newTemp = (int[]) arrayInc(temp, 15); 7 7 print(newTemp); 8 8 String[] atr = { "a", "b", "c" }; 9 9 String[] str1 = (String[]) arrayInc(atr, 8); 1010 print(str1); 1111 } 1212 // 修改数组大小 1313 public static Object arrayInc(Object obj, int len) { 1414 Class<?> arr = obj.getClass().getComponentType(); 1515 Object newArr = Array.newInstance(arr, len); 1616 int co = Array.getLength(obj); 1717 System.arraycopy(obj, 0, newArr, 0, co); 1818 return newArr; 1919 } 2020 // 打印 2121 public static void print(Object obj) { 2222 Class<?> c = obj.getClass(); 2323 if (!c.isArray()) { 2424 return; 2525 } 2626 System.out.println("数组长度为: " + Array.getLength(obj)); 2727 for (int i = 0; i < Array.getLength(obj); i++) { 2828 System.out.print(Array.get(obj, i) + " "); 2929 } 3030 System.out.println(); 3131 } 3232 }
将反射应用于工厂模式
1 1 package net.xsoftlab.baike; 2 2 interface fruit { 3 3 public abstract void eat(); 4 4 } 5 5 class Apple implements fruit { 6 6 public void eat() { 7 7 System.out.println("Apple"); 8 8 } 9 9 } 1010 class Orange implements fruit { 1111 public void eat() { 1212 System.out.println("Orange"); 1313 } 1414 } 1515 class Factory { 1616 public static fruit getInstance(String ClassName) { 1717 fruit f = null; 1818 try { 1919 f = (fruit) Class.forName(ClassName).newInstance(); 2020 } catch (Exception e) { 2121 e.printStackTrace(); 2222 } 2323 return f; 2424 } 2525 } 2626 /** 2727 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。 2828 * Java 工厂模式可以参考 2929 * http://baike.xsoftlab.net/view/java-factory-pattern 3030 * 3131 * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。 3232 * 3333 * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。 3434 * 3535 * java 读取 properties 配置文件 的方法可以参考 3636 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file 3737 * 3838 * @author xsoftlab.net 3939 */ 4040 public class TestReflect { 4141 public static void main(String[] args) throws Exception { 4242 fruit f = Factory.getInstance("net.xsoftlab.baike.Apple"); 4343 if (f != null) { 4444 f.eat(); 4545 } 4646 } 4747 }