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方法也可以注入
应该就是基于这种机制去实现的