JavaWeb_反射

反射之中包含了一个【反】字,所以想要解释反射就必须先从【正】开始解释。

一般情况下,我们使用某个类时必定知道它是什么类,是用来做什么的。于是我们直接对这个类进行实例化,之后使用这个类对象进行操作。

Person p1 = new Person();
p1.setName("zhangsan");

上面这个样子进行类对象的初始化,我们可以理解为【正】。

而反射则是一开始并不知道我们要初始化的类对象是什么,自然也无法使用new关键字来创建对象了。

这时候,我们使用JDK提供的反射API进行反射调用:

Class clz = Class.forName("com.study.reflect.Person");
Method method = clz.getMethod("setName",String.class);
Constructor constructor = clz.getConstructor();
Person p1 = (Person) constructor.newInstance();
method.invoke(p1,"zhangsan");
System.out.println(p1.getName());

上面两端代码的执行结果,其实是完全一样的。但是其思路完全不一样,第一段代码在未运行时就已经确定了要运行的类(Person),而第二段代码则是在运行时通过字符串值才得知要运行的类(com.study.reflect.Person)。

所以说什么是反射?

反射就是在运行时才知道要操作的类是什么,并且可以在运行时获取类的完整构造,并调用对应的方法。

一个类有多个组成部分,例如:成员变量,方法,构造方法等。反射就是加载类,并解剖出类的各个组成部分。

编程时什么情况下才需要加载类,并解剖出类的各个组成部分呢?

反射是用来做框架的。

从配置文件中解读类的方法等。

Java中有一个Class类用于代表某一个类的字节码。

Class类既然代表某个类的字节码,它当然就要提供加载某个类字节码的方法:forName().

forName方法用于加载某个类的字节码到内存中,并使用class对象进行封装。

另外两种得到class对象的方式

类名.class

对象.getClass()

因此类的加载方法公有三种:

1、Class.forName("com.xx.xx")

2、类名.class

3、对象.getClass()

下面看三种类的加载方法

 1 package cn.itcast.reflect;
 2 
 3 public class Demo1 {
 4 
 5     public static void main(String[] args) throws Exception {
 6         // TODO Auto-generated method stub
 7         //加载类的字节码1,常用
 8         Class clazz1 = Class.forName("cn.itcast.reflect.Person");
 9         
10         //加载类的字节码2
11         Class clazz2 = Person.class;
12         
13         //加载类的字节码3
14         Class clazz3 = new Person().getClass();
15 
16     }
17 
18 }

Class对象提供了如下常用方法:

1 public Constructor getConstructor(Class<?>... parameterTypes)
2 public Method getMethod(String name,Class<?>... parameterTypes)
3 public Field getField(String name)
4     
5 public Constructor getDeclaredConstructor(Class<?>... parameterTypes)
6 public Method getDeclaredMethod(String name,Class<?>... parameterTypes)
7 public Field getDeclaredField(String name) 

这些方法分别用于从类中解剖出构造函数、方法和成员变量(属性)。解剖出的成员分别使用Constructor,Method,Field对象表示。

思考:假设你是一个框架的设计者,出这些成员后你会干什么?

先看反射类的构造方法。

 1 //Demo1.java
 2 package cn.itcast.reflect;
 3 import java.lang.reflect.Constructor;
 4 import org.junit.Test;
 5 public class Demo1 {
 6 
 7     public static void main(String[] args) throws Exception {
 8         // TODO Auto-generated method stub
 9         //加载类的字节码1,常用
10         Class clazz = Class.forName("cn.itcast.reflect.Person");
11         Constructor c = clazz.getConstructor(null);
12         
13         Object obj = c.newInstance(null);
14         
15         System.out.println(obj);
16         
17 
18     }
19     
20     //反射无参的构造函数
21     @Test
22     public void test1() throws Exception{
23         Class clazz = Class.forName("cn.itcast.reflect.Person");
24         Constructor c = clazz.getConstructor(null);
25         
26         Object obj = c.newInstance(null);
27         
28         System.out.println(obj);
29     }
30     
31     
32     //反射有参的构造函数
33     @Test
34     public void test2() throws Exception{
35         Class clazz = Class.forName("cn.itcast.reflect.Person");
36         Constructor c = clazz.getConstructor(String.class);
37         
38         Person p = (Person) c.newInstance("fix");
39         System.out.println(p);
40     }
41     
42     //反射私有的,有参的构造函数
43     @Test
44     public void test3() throws Exception{
45         Class clazz = Class.forName("cn.itcast.reflect.Person");
46         Constructor c = clazz.getDeclaredConstructor(int.class);
47         c.setAccessible(true);//暴力反射
48         Person p = (Person) c.newInstance(1);
49         System.out.println(p);
50     }
51 }

下面看反射类的方法

 1 package cn.itcast.reflect;
 2 
 3 import java.lang.reflect.Method;
 4 
 5 import org.junit.Test;
 6 
 7 public class Demo2 {
 8     //反射方法
 9     
10     //反射不带参数的方法
11     @Test
12     public void test1() throws Exception{
13         Class clazz = Class.forName("cn.itcast.reflect.Person");
14         
15         Method method = clazz.getMethod("eat", null);
16         
17         method.invoke(clazz.newInstance(), null);
18     }
19     
20     //反射带参数的方法
21     @Test
22     public void test2() throws Exception{
23         Class clazz = Class.forName("cn.itcast.reflect.Person");
24         
25         Method method = clazz.getMethod("run", String.class);
26         
27         method.invoke(clazz.newInstance(), "上海");
28     }
29     
30     //反射带多个参数的方法
31     @Test
32     public void test3() throws Exception{
33         Class clazz = Class.forName("cn.itcast.reflect.Person");
34         
35         Method method = clazz.getMethod("run", String.class,int[].class,String[].class);
36         
37         method.invoke(clazz.newInstance(), "上海",new int[]{1,2,3},new String[]{"a","b","c"});
38     }
39     
40     
41     //反射带返回值的方法
42     @Test
43     public void test4() throws Exception{
44         Class clazz = Class.forName("cn.itcast.reflect.Person");
45         
46         Method method = clazz.getMethod("test", String.class);
47         
48         String result = (String) method.invoke(clazz.newInstance(), "上海");
49         System.out.println(result);
50     }
51     
52     
53     //反射私有方法
54     @Test
55     public void test5() throws Exception{
56         Class clazz = Class.forName("cn.itcast.reflect.Person");
57         
58         Method method = clazz.getDeclaredMethod("test2", String.class);
59         method.setAccessible(true);//暴力反射
60         String result = (String) method.invoke(clazz.newInstance(), "上海");
61         System.out.println(result);
62     }
63     
64     
65     //反射静态方法
66     @Test
67     public void test6() throws Exception{
68         Class clazz = Class.forName("cn.itcast.reflect.Person");
69         
70         Method method = clazz.getMethod("test3", String.class);
71         String result = (String) method.invoke(null, "上海");
72         System.out.println(result);
73     }
74         
75     //反射main方法
76     //通过反射调用带数组的方法,要注意处理
77     @Test
78     public void test7() throws Exception{
79         Class clazz = Class.forName("cn.itcast.reflect.Person");
80         
81         Method method = clazz.getMethod("main", String[].class);
82         //method.invoke(null, (Object)new String[]{"1","2"});
83         method.invoke(null, new Object[]{new String[]{"1","2"}});
84     }
85 }

利用Field访问属性

Field对象提供了如下方法,用于设置、获取对象属性的值:

public void set(Object obj,Object value)

public Object get(Object obj)

 1 package cn.itcast.reflect;
 2 
 3 import java.lang.reflect.Field;
 4 
 5 import org.junit.Test;
 6 
 7 public class Demo3 {
 8 
 9     /**
10      * 反射类的字段
11      * @throws Exception 
12      */
13     //反射公有成员变量
14     @Test
15     public void test1() throws Exception{
16         
17         Person p = new Person();
18         Class clazz = Class.forName("cn.itcast.reflect.Person");
19         
20         Field f = clazz.getField("name");
21         
22         f.set(p, "flx");
23         System.out.println(p.getName());
24         
25     }
26     
27     
28     //反射公有成员变量
29     @Test
30     public void test2() throws Exception{
31         
32         Person p = new Person();
33         p.setName("xxx");
34         Class clazz = Class.forName("cn.itcast.reflect.Person");
35         Field f = clazz.getField("name");
36         String result = (String)f.get(p);
37         System.out.println(result);
38         
39     }
40     
41     //反射final成员变量
42     @Test
43     public void test3() throws Exception{
44         
45         Person p = new Person();
46         Class clazz = Class.forName("cn.itcast.reflect.Person");
47         Field f = clazz.getField("password");
48         String result = (String)f.get(p);
49         System.out.println(result);
50         
51     }
52     
53     //反射私有成员变量
54     @Test
55     public void test4() throws Exception{
56         Person p = new Person();
57         Class clazz = Class.forName("cn.itcast.reflect.Person");
58         Field f = clazz.getDeclaredField("age");
59         f.setAccessible(true);
60         f.set(p, 123);
61         int result = (Integer)f.getInt(p);
62         System.out.println(result);
63     }
64 }

Person类如下:

 1 package cn.itcast.reflect;
 2 
 3 public class Person {
 4     
 5     public String name;//字段或成员变量
 6     private int age;
 7     
 8     public final String password="123";
 9     
10     
11     public String getName() {
12         return name;
13     }
14 
15     public void setName(String name) {
16         this.name = name;
17     }
18 
19     public int getAge() {
20         return age;
21     }
22 
23     public void setAge(int age) {
24         this.age = age;
25     }
26 
27     public Person(){
28         System.out.println("person");
29     }
30     
31     public Person(String name){
32         System.out.println(name);
33     }
34     
35     private Person(int name){
36         System.out.println(name);
37     }
38     
39     public void eat(){
40         System.out.println("eat!!!");
41     }
42     
43     public void run(String address){
44         System.out.println("跑到"+address);
45     }
46     
47     public void run(String address,int num[],String ss[]){
48         System.out.println("跑到"+address+"," +num);
49     }
50     
51     public String test(String str){
52         return str+"aaaaaa";
53     }
54     
55     private String test2(String str){
56         return str+"aaaaaa";
57     }
58     
59     public static String test3(String str){
60         return str+"aaaa";
61     }
62     
63     
64     public static void main(String[] args) {
65         System.out.println(args[0]);
66     }
67 
68 }

如上就是反射所有常用的一些方法。

心再坚强也不要独自飞翔
原文地址:https://www.cnblogs.com/LoganChen/p/6362820.html