温故而知新系列:Java反射机制详解
Java反射机制详解
| |目录
1反射机制是什么
反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
2反射机制能做什么
反射机制主要提供了以下功能:
- 
在运行时判断任意一个对象所属的类; 
- 
在运行时构造任意一个类的对象; 
- 
在运行时判断任意一个类所具有的成员变量和方法; 
- 
在运行时调用任意一个对象的方法; 
- 
生成动态代理。 
3反射机制的相关API
通过一个对象获得完整的包名和类名
| 
1 
2 
3 
4 
5 
6 
7 
8 | packagenet.xsoftlab.baike;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        TestReflect testReflect = newTestReflect();        System.out.println(testReflect.getClass().getName());        // 结果 net.xsoftlab.baike.TestReflect    }} | 
实例化Class类对象
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 | packagenet.xsoftlab.baike;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        Class<?> class1 = null;        Class<?> class2 = null;        Class<?> class3 = null;        // 一般采用这种形式        class1 = Class.forName("net.xsoftlab.baike.TestReflect");        class2 = newTestReflect().getClass();        class3 = TestReflect.class;        System.out.println("类名称   "+ class1.getName());        System.out.println("类名称   "+ class2.getName());        System.out.println("类名称   "+ class3.getName());    }} | 
获取一个对象的父类与实现的接口
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 | packagenet.xsoftlab.baike;importjava.io.Serializable;publicclassTestReflect implementsSerializable {    privatestaticfinallongserialVersionUID = -2862585049955236662L;    publicstaticvoidmain(String[] args) throwsException {        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");        // 取得父类        Class<?> parentClass = clazz.getSuperclass();        System.out.println("clazz的父类为:"+ parentClass.getName());        // clazz的父类为: java.lang.Object        // 获取所有的接口        Class<?> intes[] = clazz.getInterfaces();        System.out.println("clazz实现的接口有:");        for(inti = 0; i < intes.length; i++) {            System.out.println((i + 1) + ":"+ intes[i].getName());        }        // clazz实现的接口有:        // 1:java.io.Serializable    }} | 
获取某个类中的全部构造函数 - 详见下例
通过反射机制实例化一个类的对象
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
65 
66 
67 
68 
69 
70 | packagenet.xsoftlab.baike;importjava.lang.reflect.Constructor;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        Class<?> class1 = null;        class1 = Class.forName("net.xsoftlab.baike.User");        // 第一种方法,实例化默认构造方法,调用set赋值        User user = (User) class1.newInstance();        user.setAge(20);        user.setName("Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]        // 第二种方法 取得全部的构造函数 使用构造函数赋值        Constructor<?> cons[] = class1.getConstructors();        // 查看每个构造方法需要的参数        for(inti = 0; i < cons.length; i++) {            Class<?> clazzs[] = cons[i].getParameterTypes();            System.out.print("cons["+ i + "] (");            for(intj = 0; j < clazzs.length; j++) {                if(j == clazzs.length - 1)                    System.out.print(clazzs[j].getName());                else                    System.out.print(clazzs[j].getName() + ",");            }            System.out.println(")");        }        // 结果        // cons[0] (java.lang.String)        // cons[1] (int,java.lang.String)        // cons[2] ()        user = (User) cons[0].newInstance("Rollen");        System.out.println(user);        // 结果 User [age=0, name=Rollen]        user = (User) cons[1].newInstance(20, "Rollen");        System.out.println(user);        // 结果 User [age=20, name=Rollen]    }}classUser {    privateintage;    privateString name;    publicUser() {        super();    }    publicUser(String name) {        super();        this.name = name;    }    publicUser(intage, String name) {        super();        this.age = age;        this.name = name;    }    publicintgetAge() {        returnage;    }    publicvoidsetAge(intage) {        this.age = age;    }    publicString getName() {        returnname;    }    publicvoidsetName(String name) {        this.name = name;    }    @Override    publicString toString() {        return"User [age="+ age + ", name="+ name + "]";    }} | 
获取某个类的全部属性
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 | packagenet.xsoftlab.baike;importjava.io.Serializable;importjava.lang.reflect.Field;importjava.lang.reflect.Modifier;publicclassTestReflect implementsSerializable {    privatestaticfinallongserialVersionUID = -2862585049955236662L;    publicstaticvoidmain(String[] args) throwsException {        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");        System.out.println("===============本类属性===============");        // 取得本类的全部属性        Field[] field = clazz.getDeclaredFields();        for(inti = 0; i < field.length; i++) {            // 权限修饰符            intmo = field[i].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = field[i].getType();            System.out.println(priv + " "+ type.getName() + " "+ field[i].getName() + ";");        }                System.out.println("==========实现的接口或者父类的属性==========");        // 取得实现的接口或者父类的属性        Field[] filed1 = clazz.getFields();        for(intj = 0; j < filed1.length; j++) {            // 权限修饰符            intmo = filed1[j].getModifiers();            String priv = Modifier.toString(mo);            // 属性类型            Class<?> type = filed1[j].getType();            System.out.println(priv + " "+ type.getName() + " "+ filed1[j].getName() + ";");        }    }} | 
获取某个类的全部方法
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 | packagenet.xsoftlab.baike;importjava.io.Serializable;importjava.lang.reflect.Method;importjava.lang.reflect.Modifier;publicclassTestReflect implementsSerializable {    privatestaticfinallongserialVersionUID = -2862585049955236662L;    publicstaticvoidmain(String[] args) throwsException {        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");        Method method[] = clazz.getMethods();        for(inti = 0; i < method.length; ++i) {            Class<?> returnType = method[i].getReturnType();            Class<?> para[] = method[i].getParameterTypes();            inttemp = method[i].getModifiers();            System.out.print(Modifier.toString(temp) + " ");            System.out.print(returnType.getName() + "  ");            System.out.print(method[i].getName() + " ");            System.out.print("(");            for(intj = 0; j < para.length; ++j) {                System.out.print(para[j].getName() + " "+ "arg"+ j);                if(j < para.length - 1) {                    System.out.print(",");                }            }            Class<?> exce[] = method[i].getExceptionTypes();            if(exce.length > 0) {                System.out.print(") throws ");                for(intk = 0; k < exce.length; ++k) {                    System.out.print(exce[k].getName() + " ");                    if(k < exce.length - 1) {                        System.out.print(",");                    }                }            } else{                System.out.print(")");            }            System.out.println();        }    }} | 
通过反射机制调用某个类的方法
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 | packagenet.xsoftlab.baike;importjava.lang.reflect.Method;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");        // 调用TestReflect类中的reflect1方法        Method method = clazz.getMethod("reflect1");        method.invoke(clazz.newInstance());        // Java 反射机制 - 调用某个类的方法1.        // 调用TestReflect的reflect2方法        method = clazz.getMethod("reflect2", int.class, String.class);        method.invoke(clazz.newInstance(), 20, "张三");        // Java 反射机制 - 调用某个类的方法2.        // age -> 20. name -> 张三    }    publicvoidreflect1() {        System.out.println("Java 反射机制 - 调用某个类的方法1.");    }    publicvoidreflect2(intage, String name) {        System.out.println("Java 反射机制 - 调用某个类的方法2.");        System.out.println("age -> "+ age + ". name -> "+ name);    }} | 
通过反射机制操作某个类的属性
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 | packagenet.xsoftlab.baike;importjava.lang.reflect.Field;publicclassTestReflect {    privateString proprety = null;    publicstaticvoidmain(String[] args) throwsException {        Class<?> clazz = Class.forName("net.xsoftlab.baike.TestReflect");        Object obj = clazz.newInstance();        // 可以直接对 private 的属性赋值        Field field = clazz.getDeclaredField("proprety");        field.setAccessible(true);        field.set(obj, "Java反射机制");        System.out.println(field.get(obj));    }} | 
反射机制的动态代理
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 | // 获取类加载器的方法TestReflect testReflect = newTestReflect();        System.out.println("类加载器  "+ testReflect.getClass().getClassLoader().getClass().getName());packagenet.xsoftlab.baike;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.lang.reflect.Proxy;//定义项目接口interfaceSubject {    publicString say(String name, intage);}// 定义真实项目classRealSubject implementsSubject {    publicString say(String name, intage) {        returnname + "  "+ age;    }}classMyInvocationHandler implementsInvocationHandler {    privateObject obj = null;    publicObject bind(Object obj) {        this.obj = obj;        returnProxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);    }    publicObject invoke(Object proxy, Method method, Object[] args) throwsThrowable {        Object temp = method.invoke(this.obj, args);        returntemp;    }}/** * 在java中有三种类类加载器。 *  * 1)Bootstrap ClassLoader 此加载器采用c++编写,一般开发中很少见。 *  * 2)Extension ClassLoader 用来进行扩展类的加载,一般对应的是jrelibext目录中的类 *  * 3)AppClassLoader 加载classpath指定的类,是最常用的加载器。同时也是java中默认的加载器。 *  * 如果想要完成动态代理,首先需要定义一个InvocationHandler接口的子类,已完成代理的具体操作。 *  * @author xsoftlab.net *  */publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        MyInvocationHandler demo = newMyInvocationHandler();        Subject sub = (Subject) demo.bind(newRealSubject());        String info = sub.say("Rollen", 20);        System.out.println(info);    }} | 
4反射机制的应用实例
在泛型为Integer的ArrayList中存放一个String类型的对象。
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 | packagenet.xsoftlab.baike;importjava.lang.reflect.Method;importjava.util.ArrayList;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        ArrayList<Integer> list = newArrayList<Integer>();        Method method = list.getClass().getMethod("add", Object.class);        method.invoke(list, "Java反射机制实例。");        System.out.println(list.get(0));    }} | 
通过反射取得并修改数组的信息
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 | packagenet.xsoftlab.baike;importjava.lang.reflect.Array;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        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));    }} | 
通过反射机制修改数组的大小
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 | packagenet.xsoftlab.baike;importjava.lang.reflect.Array;publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        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);    }    // 修改数组大小    publicstaticObject arrayInc(Object obj, intlen) {        Class<?> arr = obj.getClass().getComponentType();        Object newArr = Array.newInstance(arr, len);        intco = Array.getLength(obj);        System.arraycopy(obj, 0, newArr, 0, co);        returnnewArr;    }    // 打印    publicstaticvoidprint(Object obj) {        Class<?> c = obj.getClass();        if(!c.isArray()) {            return;        }        System.out.println("数组长度为: "+ Array.getLength(obj));        for(inti = 0; i < Array.getLength(obj); i++) {            System.out.print(Array.get(obj, i) + " ");        }        System.out.println();    }} | 
将反射机制应用于工厂模式
| 
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 | packagenet.xsoftlab.baike;interfacefruit {    publicabstractvoideat();}classApple implementsfruit {    publicvoideat() {        System.out.println("Apple");    }}classOrange implementsfruit {    publicvoideat() {        System.out.println("Orange");    }}classFactory {    publicstaticfruit getInstance(String ClassName) {        fruit f = null;        try{            f = (fruit) Class.forName(ClassName).newInstance();        } catch(Exception e) {            e.printStackTrace();        }        returnf;    }}/** * 对于普通的工厂模式当我们在添加一个子类的时候,就需要对应的修改工厂类。 当我们添加很多的子类的时候,会很麻烦。 * Java 工厂模式可以参考 * http://baike.xsoftlab.net/view/java-factory-pattern *  * 现在我们利用反射机制实现工厂模式,可以在不修改工厂类的情况下添加任意多个子类。 *  * 但是有一点仍然很麻烦,就是需要知道完整的包名和类名,这里可以使用properties配置文件来完成。 *  * java 读取 properties 配置文件 的方法可以参考 * http://baike.xsoftlab.net/view/java-read-the-properties-configuration-file *  * @author xsoftlab.net */publicclassTestReflect {    publicstaticvoidmain(String[] args) throwsException {        fruit f = Factory.getInstance("net.xsoftlab.baike.Apple");        if(f != null) {            f.eat();        }    }} | 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号