一、内容提要:
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
通过一个对象获得完整的包名和类名
package com.wangjun.ThinkingInJava.java_14.third.java_10;
public class TestReflect {
public static void main(String[] args) {
TestReflect testReflect=new TestReflect();
System.out.println(testReflect.getClass().getName());
}
}
输出结果:
1 com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
实例化Class类对象
1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
2
3 public class TestReflect {
4
5 public static void main(String[] args) throws ClassNotFoundException {
6 Class<?> class1=null;
7 Class<?> class2=null;
8 Class<?> class3=null;
9
10 //一般采用这种形式
11 class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect");
12 class2=new TestReflect().getClass();
13 class3=TestReflect.class;
14 System.out.println("类名称: "+class1.getName());
15 System.out.println("类名称: "+class2.getName());
16 System.out.println("类名称: "+class3.getName());
17
18 }
19
20 }
输出结果:
1 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
2 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
3 类名称: com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect
获取一个对象的父类与实现的接口:
1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
2
3 import java.io.Serializable;
4
5 public class TestReflect1 implements Serializable {
6
7 public static void main(String[] args) throws ClassNotFoundException {
8 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect1");
9 //取得父类
10 Class<?> parentClass=clazz.getSuperclass();
11 System.out.println("clazz的父类为: "+parentClass.getName());
12 //clazz的父类为:java.lang.Object
13 //获取所有的接口
14 Class<?> intes[]=clazz.getInterfaces();
15 System.out.println("clazz实现的接口有:");
16 for(int i=0;i<intes.length;i++){
17 System.out.println((i+1)+":"+intes[i].getName());
18 }
19 }
20
21 }
输出结果:
1 clazz的父类为: java.lang.Object
2 clazz实现的接口有:
3 1:java.io.Serializable
通过反射机制实例化一个类的对象
1 public class TestReflect2 {
2
3 public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
4 Class<?> class1=null;
5 class1=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.User");
6 //第一种方法,实例化默认构造方法,调用set赋值
7 User user=(User) class1.newInstance();
8 user.setAge(20);
9 user.setName("Rollen");
10 System.out.println(user);
11
12 //第二种方法 取得全部的构造函数 使用构造函数赋值
13 Constructor<?> cons[]=class1.getConstructors();
14 //查看每个构造方法需要的参数
15 for(int i=0;i<cons.length;i++){
16 Class<?>clazzs[]=cons[i].getParameterTypes();
17 System.out.print("cons["+i+"](");
18 for(int j=0;j<clazzs.length;j++){
19 if(j==clazzs.length-1){
20 System.out.print(clazzs[j].getName());
21 }else {
22 System.out.print(clazzs[j].getName()+",");
23 }
24 }
25 System.out.println(")");
26 }
27
28 user=(User) cons[1].newInstance("Rollen");
29 System.out.println(user);
30 user = (User) cons[0].newInstance(20, "Rollen");
31 System.out.println(user);
32 }
33
34 }
1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
2
3 public class User {
4 private int age;
5 private String name;
6 public User(){}
7 public User(String name){
8 super();
9 this.name=name;
10 }
11 public User(int age,String name){
12 super();
13 this.age=age;
14 this.name=name;
15 }
16 public int getAge() {
17 return age;
18 }
19 public void setAge(int age) {
20 this.age = age;
21 }
22 public String getName() {
23 return name;
24 }
25 public void setName(String name) {
26 this.name = name;
27 }
28
29
30 public String toString(){
31 return "User [age=]"+age+",name="+name+"]";
32 }
33
34 }
输出结果:
1 User [age=]20,name=Rollen]
2 cons[0](int,java.lang.String)
3 cons[1](java.lang.String)
4 cons[2]()
5 User [age=]0,name=Rollen]
6 User [age=]20,name=Rollen]
获取某个类的全部属性:
1 import java.io.Serializable;
2 import java.lang.reflect.Field;
3 import java.lang.reflect.Modifier;
4
5 public class TestReflect3 implements Serializable{
6 private String name="main";
7 public static void main(String[] args) throws ClassNotFoundException{
8 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect3");
9 System.out.println("======本类属性========");
10 Field[] fields=clazz.getDeclaredFields();
11 for(int i=0;i<fields.length;i++){
12 //权限修饰符
13 int mo=fields[i].getModifiers();
14 String priv=Modifier.toString(mo);
15 //属性类型
16 Class<?> type=fields[i].getType();
17 System.out.println(priv+" "+type.getName()+" "+fields[i].getName()+";");
18 }
19 System.out.println("==========实现的接口或者 父类的属性==============");
20 //取得实现的接口或者父类的属性
21 Field[] filed1=clazz.getFields();
22 for(int j=0;j<filed1.length;j++){
23 // 权限修饰
24 int mo=filed1[j].getModifiers();
25 String priv=Modifier.toString(mo);
26
27 //属性类型
28 Class<?> type=filed1[j].getType();
29 System.out.println(priv + " " + type.getName() + " " + filed1[j].getName() + ";");
30
31 }
32
33 }
34
35 }
输出结果:
1 ======本类属性========
2 private java.lang.String name;
3 ==========实现的接口或者 父类的属性==============
获取某个类的全部方法
1 package com.wangjun.ThinkingInJava.java_14.third.java_10;
2
3 import java.io.Serializable;
4 import java.lang.reflect.Method;
5 import java.lang.reflect.Modifier;
6
7 public class TestReflect4 implements Serializable {
8
9 public static void main(String[] args) throws Exception{
10 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect4");
11 Method method[]=clazz.getMethods();
12 for (int i = 0; i < method.length; ++i) {
13 Class<?> returnType = method[i].getReturnType();
14 Class<?> para[] = method[i].getParameterTypes();
15 int temp = method[i].getModifiers();
16 System.out.print(Modifier.toString(temp) + " ");
17 System.out.print(returnType.getName() + " ");
18 System.out.print(method[i].getName() + " ");
19 System.out.print("(");
20 for (int j = 0; j < para.length; ++j) {
21 System.out.print(para[j].getName() + " " + "arg" + j);
22 if (j < para.length - 1) {
23 System.out.print(",");
24 }
25 }
26 Class<?> exce[] = method[i].getExceptionTypes();
27 if (exce.length > 0) {
28 System.out.print(") throws ");
29 for (int k = 0; k < exce.length; ++k) {
30 System.out.print(exce[k].getName() + " ");
31 if (k < exce.length - 1) {
32 System.out.print(",");
33 }
34 }
35 } else {
36 System.out.print(")");
37 }
38 System.out.println();
39 }
40
41 }
42
43 }
输出结果:
1 public boolean equals (java.lang.Object arg0)
2 public java.lang.String toString ()
3 public native int hashCode ()
4 public final native java.lang.Class getClass ()
5 public final native void notify ()
6 public final native void notifyAll ()
通过反射机制调用某个类的方法
1 public class TestReflect5 {
2
3 public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
4 Class<?> clazz=Class.forName("com.wangjun.ThinkingInJava.java_14.third.java_10.TestReflect5");
5 //调用TestReflect类中的reflect1方法
6 Method method=clazz.getMethod("reflect1");
7 method.invoke(clazz.newInstance());
8 //Java 反射机制-调用某个类的方法1.
9 //调用TestReflect的reflect2方法
10 method=clazz.getMethod("reflect2", int.class,String.class);
11 method.invoke(clazz.newInstance(), 20,"张三");
12
13 }
14
15 public void reflect1(){
16 System.out.println("Java 反射机制 - 调用某个类的方法1.");
17 }
18 public void reflect2(int age, String name) {
19 System.out.println("Java 反射机制 - 调用某个类的方法2.");
20 System.out.println("age -> " + age + ". name -> " + name);
21 }
22
23 }
运行结果:
1 Java 反射机制 - 调用某个类的方法1.
2 Java 反射机制 - 调用某个类的方法2.
3 age -> 20. name -> 张三
通过反射机制调用某个类的方法
1 package net.xsoftlab.baike;
2 import java.lang.reflect.Method;
3 public class TestReflect {
4 public static void main(String[] args) throws Exception {
5 Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
6 // 调用TestReflect类中的reflect1方法
7 Method method = clazz.getMethod("reflect1");
8 method.invoke(clazz.newInstance());
9 // Java 反射机制 - 调用某个类的方法1.
10 // 调用TestReflect的reflect2方法
11 method = clazz.getMethod("reflect2", int.class, String.class);
12 method.invoke(clazz.newInstance(), 20, "张三");
13 // Java 反射机制 - 调用某个类的方法2.
14 // age -> 20. name -> 张三
15 }
16 public void reflect1() {
17 System.out.println("Java 反射机制 - 调用某个类的方法1.");
18 }
19 public void reflect2(int age, String name) {
20 System.out.println("Java 反射机制 - 调用某个类的方法2.");
21 System.out.println("age -> " + age + ". name -> " + name);
22 }
23 }
通过反射机制调用某个类的属性
1 package net.xsoftlab.baike;
2 import java.lang.reflect.Field;
3 public class TestReflect {
4 private String proprety = null;
5 public static void main(String[] args) throws Exception {
6 Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");
7 Object obj = clazz.newInstance();
8 // 可以直接对 private 的属性赋值
9 Field field = clazz.getDeclaredField("proprety");
10 field.setAccessible(true);
11 field.set(obj, "Java反射机制");
12 System.out.println(field.get(obj));
13 }
14 }
反射机制的动态代理
1 // 获取类加载器的方法
2 TestReflect testReflect = new TestReflect();
3 System.out.println("类加载器 " + testReflect.getClass().getClassLoader().getClass().getName());
4 package net.xsoftlab.baike;
5 import java.lang.reflect.InvocationHandler;
6 import java.lang.reflect.Method;
7 import java.lang.reflect.Proxy;
8 //定义项目接口
9 interface Subject {
10 public String say(String name, int age);
11 }
12 // 定义真实项目
13 class RealSubject implements Subject {
14 public String say(String name, int age) {
15 return name + " " + age;
16 }
17 }
18 class MyInvocationHandler implements InvocationHandler {
19 private Object obj = null;
20 public Object bind(Object obj) {
21 this.obj = obj;
22 return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
23 }
24 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
25 Object temp = method.invoke(this.obj, args);
26 return temp;
27 }
28 }
29 /**
30 * 在java中有三种类类加载器。
31 *
32 * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。
33 *
34 * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类
35 *
36 * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。
37 *
38 * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。
39 *
40 * @author xsoftlab.net
41 *
42 */
43 public class TestReflect {
44 public static void main(String[] args) throws Exception {
45 MyInvocationHandler demo = new MyInvocationHandler();
46 Subject sub = (Subject) demo.bind(new RealSubject());
47 String info = sub.say("Rollen", 20);
48 System.out.println(info);
49 }
50 }
二、反射机制的应用实例
在泛型为Integer的ArrayList中存放一个String类型的对象
1 package net.xsoftlab.baike;
2 import java.lang.reflect.Method;
3 import java.util.ArrayList;
4 public class TestReflect {
5 public static void main(String[] args) throws Exception {
6 ArrayList<Integer> list = new ArrayList<Integer>();
7 Method method = list.getClass().getMethod("add", Object.class);
8 method.invoke(list, "Java反射机制实例。");
9 System.out.println(list.get(0));
10 }
11 }
通过反射取得并修改数组的信息
1 package net.xsoftlab.baike;
2 import java.lang.reflect.Array;
3 public class TestReflect {
4 public static void main(String[] args) throws Exception {
5 int[] temp = { 1, 2, 3, 4, 5 };
6 Class<?> demo = temp.getClass().getComponentType();
7 System.out.println("数组类型: " + demo.getName());
8 System.out.println("数组长度 " + Array.getLength(temp));
9 System.out.println("数组的第一个元素: " + Array.get(temp, 0));
10 Array.set(temp, 0, 100);
11 System.out.println("修改之后数组第一个元素为: " + Array.get(temp, 0));
12 }
13 }
通过反射机制修改数组的大小
1 package net.xsoftlab.baike;
2 import java.lang.reflect.Array;
3 public class TestReflect {
4 public static void main(String[] args) throws Exception {
5 int[] temp = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
6 int[] newTemp = (int[]) arrayInc(temp, 15);
7 print(newTemp);
8 String[] atr = { "a", "b", "c" };
9 String[] str1 = (String[]) arrayInc(atr, 8);
10 print(str1);
11 }
12 // 修改数组大小
13 public static Object arrayInc(Object obj, int len) {
14 Class<?> arr = obj.getClass().getComponentType();
15 Object newArr = Array.newInstance(arr, len);
16 int co = Array.getLength(obj);
17 System.arraycopy(obj, 0, newArr, 0, co);
18 return newArr;
19 }
20 // 打印
21 public static void print(Object obj) {
22 Class<?> c = obj.getClass();
23 if (!c.isArray()) {
24 return;
25 }
26 System.out.println("数组长度为: " + Array.getLength(obj));
27 for (int i = 0; i < Array.getLength(obj); i++) {
28 System.out.print(Array.get(obj, i) + " ");
29 }
30 System.out.println();
31 }
32 }
将反射应用于工厂模式
1 package net.xsoftlab.baike;
2 interface fruit {
3 public abstract void eat();
4 }
5 class Apple implements fruit {
6 public void eat() {
7 System.out.println("Apple");
8 }
9 }
10 class Orange implements fruit {
11 public void eat() {
12 System.out.println("Orange");
13 }
14 }
15 class Factory {
16 public static fruit getInstance(String ClassName) {
17 fruit f = null;
18 try {
19 f = (fruit) Class.forName(ClassName).newInstance();
20 } catch (Exception e) {
21 e.printStackTrace();
22 }
23 return f;
24 }
25 }
26 /**
27 * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。
28 * Java 工厂模式可以参考
29 * http://baike.xsoftlab.net/view/java-factory-pattern
30 *
31 * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。
32 *
33 * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。
34 *
35 * java 读取 properties 配置文件 的方法可以参考
36 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file
37 *
38 * @author xsoftlab.net
39 */
40 public class TestReflect {
41 public static void main(String[] args) throws Exception {
42 fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");
43 if (f != null) {
44 f.eat();
45 }
46 }
47 }