Java的反射机制

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性
Java本身是一种静态语言 , 不能够在运行期改变程序结构和变量类型
但是反射机制是一种十分重要的动态特性

实现示例
首先定义一个类

 1 class Demo {
 2     private String name;
 3     private int age ;
 4     private Date birth;
 5     private boolean sex ;
 6     //注意 :对于boolean类型属性,IDE自动生成的是名为isXXX的getter方法
 7     public Demo(){}
 8     public Demo(String name, int age, Date birth){
 9         this.name = name;
10         this.age = age;
11         this.birth = birth;
12     }
13    //getter与setter方法...
14 
15 }

获取该类中的属性和值

 1 public static void getObjectValue(Object object) throws Exception {
 2     if (object == null) {
 3         //验证是否为null,防止NullPointerException
 4         return;
 5     }
 6     Class<?> clz = object.getClass();
 7     // 获取实体类的所有字段(但不包括继承自父类的)
 8     Field[] fields = clz.getDeclaredFields();
 9     // 执行遍历
10     for (Field field : fields) {
11         //拿到该属性的getter方法
12         Method method = clz.getMethod("get"+ getMethodName(field.getName()));
13         // 调用getter方法获取属性值
14         Object val = method.invoke(object);
15         System.out.println(field.getName()+":" + val);
16         }
17     }
18 
19     // 把一个字符串的第一个字母大写
20 private static String getMethodName(String fieldName) {
21     StringBuilder sb = new StringBuilder(fieldName);
22     char ch = Character. toUpperCase(fieldName.charAt(0));
23     sb.setCharAt(0, ch);
24     return sb.toString();
25 }
调用方式
1 public static void main(String[] args){
2     Demo demo = new Demo("Loli" ,18,new Date());
3     try {
4         getObjectValue(demo);
5     } catch (Exception e) {
6         e.printStackTrace();
7     }
8 }

基于这种反射机制的实现 , 我们可以动态获取到任意一个类中所有的属性和方法
从而可以去开发一些复用性很强的功能函数
比如把任意一个对象的属性和对应的值放入到一个Map集合当中
从而方便进行遍历或者数据的传输


使用反射机制在外部给对象私有属性赋值

1 public class Cat {
2     private String name;
3     public String getName(){
4         return this.name;
5     }
6 }

这个类没有提供name属性的set方法

 1 try {
 2     Class<Cat> catClass = Cat.class;
 3     Field name = catClass.getDeclaredField("name");
 4     name.setAccessible(true);//取消Java语言访问检查
 5     Cat cat = (Cat) catClass.newInstance();
 6     name.set(cat, "abc");
 7     System.out.println(cat.getName());
 8 } catch (IllegalAccessException e) {
 9     e.printStackTrace();
10 } catch (InstantiationException e) {
11     e.printStackTrace();
12 } catch (NoSuchFieldException e) {
13     e.printStackTrace();
14 }

在Field对象上调用set方法可以修改一个对象的属性
需要注意的是 , 必须调用setAccessible取消Java语言的访问检查 , 否则是无法给私有属性赋值的

同理 , 在Field对象上调用get方法可以获取指定对象的这个属性的值

可以想到Spring框架当中的 @Autowired 自动注入 , 即使是私有属性 , 没有提供set方法也可以注入
应该就是基于这种机制去实现的 

posted @ 2017-02-03 17:20  日月追影俯河山  阅读(150)  评论(0编辑  收藏  举报
TOP