反射

1.反射

1.1.反射概述

一种计算机处理方式。是程序可以访问、检测和修改它本身状态或行为的一种能力。 JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法; 对于任意一个对象,都能够调用它的任意方法和属性; 这种动态获取信息以及动态调用对象方法的功能称为java语言的反射机制。

1.2.优缺点

1.2.1优点

a.反射提高了程序的灵活性和扩展性。
b.降低耦合性,提高自适应能力。
c.它允许程序创建和控制任何类的对象,无需提前硬编码目标类。

1.2.2缺点

a.性能问题:使用反射基本上是一种解释操作,用于字段和方法接入时要远慢于直接代码。因此反射机制主要应用在对灵活性和拓展性要求很高的系统框架上,普通程序不建议使用。
b.使用反射会模糊程序内部逻辑;程序员希望在源代码中看到程序的逻辑,反射却绕过了源代码的技术因而会带来维护的问题,反射代码比相应的直接代码更复杂。

2.Class介绍

2.1.获取Class的方式

(1)如果持有一个对象,可以直接通过Object类中继承的getClass方法获取。

Student s = new Student();
Class clazz = s.getClass();

(2)可以直接通过类包(接口)直接调用其属性.class获取

Class clazz = Student.class

(3)可以通过Class类中提供的forName方法获取

Class clazz = Class.forName("全类名");

2.2.通过Class对象获取Constructor、Field、Method

2.2.1通过Class对象获取Constructor

getConstructor(Class<?>...parameterType)    //它获取的是类的public构造
getConstructors	//它获取的是类的所有的public构造
			
getDeclaredConstructor(Class<?>...parameterType)  //获取的一个类的任意构造方法(私有和非私有的都可以)
getDeclaredConstructors	//获取的是类的所有的构造(包括私有的)例如:  

(1)获取非私有的实例化对象的代码

//获取Student的Class对象
Class clazz = Class.forName("com.ccsoft.Student");
//获取构造方法对象
Constructor ct = clazz.getConstructor();
//获取Student的实例化对象
Object obj = ct.newInstance();
//也可以强转 Student stu = (Student)ct.newInstance();
			 

(2)获取包括私有的实例化对象的代码

/获取Student的Class对象
Class clazz = Class.forName("com.ccsoft.Student");
//获取构造方法对象
Constructor ct = clazz.getDeclaredConstructor();
//取消检查
ct.setAccessible(true);		
//获取Student的实例化对象																					 
Object obj = ct.newInstance();
//也可以强转 
Student stu = (Student)ct.newInstance();

2.3 Field介绍

getField(String name)  //获取一个Field对象(非私有的),
getFields()	  //获取包含所有的Field对象的数组(非私有的),	
getDeclaredField(String name) //获取任意一个Field对象(包含私有的和非私有的),
getDeclaredFields()  	//获取包含所有的Field对象的数组(包含私有的和非私有的), 

举例:给Student类的私有age赋值

//获取Student的Class对象
Class clazz = Class.forName("com.itheima01.Student");
//获取属性对象
Field field_age = clazz.getDeclaredField("age");
//取消检查
field_age.setAccessible(true);
//赋值操作
field_age.set(Student,18);

2.4 Method介绍

getMethod(String name,Class<?>...parameterType)	//获取本类中非私有方法的对象
getMethods()	//获取本类和父类以及超类的非私有方法的对象的数组
getDeclaredMethod(String name,Class<?>...parameterType)	//获取本类中任意方法的对象
getDeclaredMethods()	//获取本类包含私有的方法对象的数组

invoke方法:Method对象.invoke(类的实例化对象,方法参数)

User user  = new User();

// 1.获取sayHello方法

// 1.获取sayHello方法的Method对象
Class clazz = user.getClass();

// 2.获取Method对象	|->此处传递的class是方法中的参数.class
Method method = clazz.getMethod("sayHello", String.class);

// 3.让方法执行
Object invoke = method.invoke(user, "fox");

System.out.println(invoke);

2.5.Method的invoke使用时注意事项

2.5.1如果方法是static,我们怎样调用?

如果方法是静态的,在通过invoke调用时不需要传递对象

Method method = clazz.getMethod("sum");
method.invoke(null);

2.5.1 如果方法的参数是一个数组类型,怎样处理?

(1)将args直接强制转换成Object再传递。

Integer[] args = {1,2,3,4};

method.invoke(user,(object)args);

(2)在数组参数的外面再包装一层数组

Object[] obj={args};

mothod.invoke(user,obj); 

3.反射案例

将Map集合中的数据匹配javaben 中的属性,并将值赋给javabean中的属性。

 

 1 @Test
 2                 public void test() {
 3 
 4                     Map<String, Object> map = new HashMap<String, Object>();
 5                     map.put("username", "tom");
 6                     map.put("age", 20);
 7                     map.put("sex", "男");
 8                     map.put("address", "北京");
 9 
10                 }
11 
12                 // 通过属性对应setXxx方法来完成操作
13                 @Test
14                 public void test2() throws Exception{
15                     Map<String, Object> map = new HashMap<String, Object>();
16                     map.put("username", "tom");
17                     map.put("age", 20);
18                     map.put("sex", "男");
19                     map.put("address", "北京");
20                     // 1.得到Person类的Class
21                     Class clazz = Class.forName("com.itheima.reflect.Person");
22                     Object obj = clazz.newInstance();
23                     //2.得到Person类中的方法
24                     Method[] methods = clazz.getDeclaredMethods();
25                     //3.遍历map
26                     for(String key:map.keySet()){
27                         //将所有的key前面添加上set,与方法的名称不区分大小写来对比。
28                         String methodName="set"+key; //操作的方法
29                         for(Method method:methods){
30                             String mname=method.getName();
31                             if(methodName.equalsIgnoreCase(mname)){
32                                 method.invoke(obj, map.get(key));
33                             }
34                         }
35                     }
36                     System.out.println(obj);
37                 }
38                 // 通过属性来完成操作
39                 @Test
40                 public void test1() throws Exception {
41                     Map<String, Object> map = new HashMap<String, Object>();
42                     map.put("username", "tom");
43                     map.put("age", 20);
44                     map.put("sex", "男");
45                     map.put("address", "北京");
46                     // 1.得到Person类的Class
47                     Class clazz = Class.forName("com.itheima.reflect.Person");
48                     Object obj = clazz.newInstance();
49                     // 2.得到Person类的所有属性
50                     Field[] fds = clazz.getDeclaredFields();
51                     // 3.得到map中所有的key
52                     Set<String> keys = map.keySet();
53                     for (Field f : fds) {
54                         String field_name = (f.getName()); // 得到属性名称
55 
56                         if (keys.contains(field_name)) { // map的key中包含了Person类的属性
57                             // 4.将key对应的value赋值给属性
58                             f.setAccessible(true);
59                             f.set(obj, map.get(field_name));
60                         }
61                     }
62                     System.out.println(obj);
63                 }

 

  

原文地址:https://www.cnblogs.com/battlecry/p/9911286.html