Java笔记1–类反射

2016年1月20日

13:32

什么是类反射?为什么要有类反射?类反射能做什么?

        首先java是一种静态的语言,即它在编译后便不会再作出改变,这让它有了很高的安全性,但这也会降低它的灵活性。

        类反射机制是让一个java类在运行时还能对它的状态进行调整的机制,这在一定程度上弥补了它灵活性不足的缺点。

        类反射能对类进行各种操作:

        1.获取一个对象的类型:

 

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
package com.firefly.classreflect.pojo;
 
public class Student {
    private int id;
    public String name;
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Student(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
    public Student(String name) {
        super();
        this.name = name;
    }
    public Student() {
        super();
    }
 
}

以上的Student.java是一个普通的java类

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.firefly.classreflect.test;
 
public class Main {
    public static void main(String[] args) {
        try {
            Class c = Class.forName(“com.firefly.classreflect.pojo.Student”);
            System.out.println(c);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
        String s = “abc”;
        Class c1 = s.getClass();
        System.out.println(c1);
 
        Class c2 = String.class;
        System.out.println(c2);
 
 
    }
}

以上为三种常见获取对象类型的方法

Class类是整个Java反射机制的源头,Class类本身表示Java对象的类型,我们可通过一个Object对象的getClass()方法取得一个对象的类型,此函数返回的就是一个Class类。

注意Class是一个类,而class是一种类型,如同String,int

 

如何获得一个类的构造方法,并用来创建一个对象:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.firefly.classreflect.test;
 
import java.lang.reflect.Constructor;
 
import com.firefly.classreflect.pojo.Student;
 
public class AccessConstructor {
    public static void main(String[] args) {
        try {
            Class c = Class.forName(“com.firefly.classreflect.pojo.Student”);
            //返回一个装有该类所有构造方法的数组
            Constructor[] con1 = c.getDeclaredConstructors();
            //通过参数获得特定的构造方法,并创建对象
            Constructor con = c.getConstructor(String.class);
            Student s = (Student)con.newInstance(“test”);
            System.out.println(s.getName());
 
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

以下演示如何获得成员变量,并改变它的值:

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
package com.firefly.classreflect.test;
 
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
 
import com.firefly.classreflect.pojo.Student;
 
public class AccessField {
    public static void main(String[] args) {
        try {
            Class c = Class.forName(“com.firefly.classreflect.pojo.Student”);
            //获得指定的构造方法,创建对象
            Constructor con = c.getConstructor(int.class,String.class);
            Student s = (Student)con.newInstance(1,”test”);
            //重新得到Class类对象,为了以下演示获得成员变量需要,该方法无法使用Student类型
            Class c1 = s.getClass();
            //获得了所有的成员变量
            Field[] f = c1.getDeclaredFields();
            for(Field field : f){
                System.out.println(“名为:”+field.getName());
                System.out.println(“类型:”+field.getType());
                //如果该变量无访问权限,则给予权限
                if(!field.isAccessible()){
                    field.setAccessible(true);
                }
                //改变该变量的值
                if(field.getType().equals(int.class)){
                    System.out.println(“原来值为:”+field.get(s));
                    field.setInt(s, 2);
                    System.out.println(“修改后的值为:”+field.get(s));
                }
                if(field.getType().equals(String.class)){
                    System.out.println(“原来值为:”+field.get(s));
                    field.set(s, “旭哥”);
                    System.out.println(“修改后的值为:”+field.get(s));
                }
            }
 
 
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

如何获得类的方法并调用:

 

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
package com.firefly.classreflect.test;
 
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
 
import com.firefly.classreflect.pojo.Student;
 
public class AccessMethod {
    public static void main(String[] args) {
        Student s = new Student(“firefly”);
        Class c = s.getClass();
        //获得所有的方法
        Method[] method = c.getDeclaredMethods();
        for(Method m : method){
            System.out.println(“方法名为:”+m.getName());
            //获得所有的参数
            Class[] parameterType = m.getParameterTypes();
            for(Class p : parameterType){
                System.out.println(“方法的参数为:”+p);
            }
            System.out.println(“返回值类型为:”+m.getReturnType());
            if(!m.isAccessible()){
                m.setAccessible(true);
            }
            //获得指定方法并调用
            if(“show”.equals(m.getName())){
                try {
                    m.invoke(s);
                } catch (Exception e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
 
        }
    }
}

已使用 Microsoft OneNote 2016 创建。