浅析Java反射机制
目前,在项目中使用Java反射机制(除Spring框架)的地方不多,但为后续准备,简单将最近的反射体会总结如下:
1. 按光学中的反射,可以将java中的反射理解为“镜像”。有以下用途:
Java反射机制主要提供下面几种用途:
- 在运行时判断任意一个对象所属的类
- 在运行时构造任意一个类的对象
- 在运行时判断任意一个类所具有的成员变量和方法
- 在运行时调用任意一个对象的方法
2. 使用java的反射机制,一般需要遵循三步:
- 获得类的Class对象
- 取得操作类的方法或属性名
- 操作第二步取得的方法或属性
3. 获得类的Class对象,有3种方法:
1. 调用Class的静态方法forName
2. 使用类的.class语法,如:Class<?> cls = String.class
3. 调用对象的getClass方法
4. 在Java的反射机制中,类与Class对象对应;类方法与Method对应;类属性与Field对应。
5. 在获得类的方法、属性、构造函数时,会有getXXX和getDeclaredXXX两种对应的方法。区别在于前者返回的是访问权限为public的方法和属性,包括父类中的;后者返回的是所有访问权限的方法和属性,但不包括父类的。
6. 实例:用反射机制完成对象的copy (浅复制)
public static void main(String[] args) { Student student = new Student(); student.setStuAge(29); student.setStuName("Chris"); Persons persons = new Persons(); persons.setFriend("Chen"); persons.setTeacher("All people"); student.setPersons(persons); Student copyStu = copyObject(student); System.out.println("-------- " + copyStu.getStuName() + " : " + copyStu.getStuAge() + " - " +copyStu.getPersons().getFriend() + " - " + copyStu.getPersons().getTeacher()); student.getPersons().setTeacher("hehe"); System.out.println("-------- " + copyStu.getStuName() + " : " + copyStu.getStuAge() + " - " +copyStu.getPersons().getFriend() + " - " + copyStu.getPersons().getTeacher()); }
Persons类:
public class Persons { private String friend; private String teacher; public String getFriend() { return friend; } public void setFriend(String friend) { this.friend = friend; } public String getTeacher() { return teacher; } public void setTeacher(String teacher) { this.teacher = teacher; } }
Student类:
public class Student { /** 姓名 */ private String stuName; /** 年龄 */ private int stuAge; /** Persons */ private Persons persons; public Persons getPersons() { return persons; } public void setPersons(Persons persons) { this.persons = persons; } public String getStuName() { return stuName; } public void setStuName(String stuName) { this.stuName = stuName; } public int getStuAge() { return stuAge; } public void setStuAge(int stuAge) { this.stuAge = stuAge; } }
copyObject方法:
private static <T> T copyObject(T t) { Class<?> cls = t.getClass(); Field[] fields = cls.getDeclaredFields(); T o = null; try { o = (T)cls.newInstance(); for (Field field : fields){ field.setAccessible(true); Object o1 = field.get(t); field.set(o,o1); } } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return o; }
在写copyObject方法时,尝试了下泛型方法。原来泛型方法中的标志<T>是必须的。
由以上例子可知,即使用反射机制来实现copy对象的功能,也只能是浅复制。
由这个例子延伸到copy对象的实现上,如下:
http://blog.sina.com.cn/s/blog_70e6618b0100om09.html
(1) 对象复制分浅复制和深复制。二者的区别在于对非基本数据类型的复制上。前者复制引用,后者复制子对象。
(2) 浅复制对象:
1. 实现方式:
第一步:实现java.lang.Cloneable接口;
第二步:重写java.lang.Object.clone()方法,设置方法为public
2. Object类中的clone()方法是native的,执行效率更高。但执行的仍是浅复制!!!所以,重写的clone()方法执行浅复制。
(3) 深复制对象:
实现方式有多种:
1. new对象以及子对象,全部重新设置属性;
2. 所有非基本数据类型的属性,对应的类实现Cloneable接口并重写clone()方法;
3. 使用对象序列化与反序列化。