1. 在上一讲中,我们知道Java中,无论生成某个类的多少对象,这些对象都会对应于同一个Class对象。
这边的Class对象是非常重要的概念,这个Class对象描述了类的本身结构,这个对象是由JVM生成的,是在类转载的时候生成的,并不是在new出一个对象的时候生成的。在以后学习JVM的时候会详细剖析。
2.要想使用反射,首先需要获得待处理类或对象所对应的 Class 对象。有两种获得方式,详细查看上一讲内容。
3.练习以下一个程序,掌握反射。
定义一个方法,这个方法的功能是:接受一个Customer类型的对象,讲对象的属性拷贝出来,生成一个新的对象,然后将新的对象返回回来,相当于一个对象的拷贝。
如果使用传统的方式比较容易:比如先有一个Customer对象,再去生成一个Customer对象,调用新生成对象的set方法和已有对象的get方法,将get的值set到新对象里面,就返回到新的对象。
如果使用反射的话,这个功能就会想比较难
package com.ahuier.reflect; import java.lang.reflect.Field; import java.lang.reflect.Method; public class ReflectTest { /* * 定义一个方法实现对象的拷贝,使用反射.该方法实现对Customer对象的拷贝操作 * 所谓的拷贝,就是将原有对象属性属性拷贝出来放到新的对象,将对象返回回来 */ public Object copy(Object object) throws Exception{ //获取class对象的第三种方式 Class<?> classType = object.getClass(); /* System.out.println(classType); //直接打印输出class对象的全称:class com.ahuier.reflect.Customer System.out.println(classType.getName()); //打印出class对象它所关联的类的全称:com.ahuier.reflect.Customer */ //这边要新生成一个对象,以便将这个对象接受到的属性值返回给调用端。 //查看JDK Doc文档 java.lang.Class.newInstance()方法 和 java.lang.reflect下的Constructor<T>类的newInstance()方法 /* Constructor cons = classType.getConstructor(new Class[]{}); //这边调用不带参数的构造方法 Object obj = cons.newInstance(new Object[]{}); 对于调用不接受参数的构造方法,以上两行代码等价于 Object obj2 = classType.newInstance();*/ /* Constructor cons = classType.getConstructor(new Class[]{String.class, int.class}); //这边调用带参数的构造方法 Object obj = cons.newInstance(new Object[]{"Hello", 3});*/ // System.out.println(obj); //输出:com.ahuier.reflect.Customer@497934 说明生成的对象是Constructor对象 Object objectCopy = classType.getConstructor(new Class[]{}) .newInstance(new Object[]{}); //获得对象的所有成员变量,查看JDK Doc文档,class里的getDeclaredFields() Field[] fields = classType.getDeclaredFields(); for(Field field : fields){ // System.out.println(field); 可以查看这边的field输出内容呢 String name = field.getName(); //获取到属性的名字 //这边观察set()方法get()方法他们与属性的规律 "set" + 属性首字母大写 + 属性其他字母小写 //这边查看String的方法,substring(0, 1)获取字符串的子字符串0与1之间的字符串内容 //toUpperCase()字符转换大写 String firstLetter = name.substring(0,1).toUpperCase();//将属性的首字母转换为大写 //获取get和set方法的名字 String getMethodName = "get" + firstLetter + name.substring(1); String setMethodName = "set" + firstLetter + name.substring(1); // System.out.println(getMethodName + "," + setMethodName); //获得Method对象 Method getMethod = classType.getMethod(getMethodName, new Class[]{}); Method setMethod = classType.getMethod(setMethodName, new Class[]{field.getType()}); //获取属性本身的类型:field.getType() Object value = getMethod.invoke(object, new Object[]{});//这边第一个参数object表示调用方法的目标对象,这里的对象是传递进去的参数 setMethod.invoke(objectCopy, new Object[]{value}); } return objectCopy; } public static void main(String[] args) throws Exception{ Customer customer = new Customer("Tom", 20); customer.setId(1L); ReflectTest test = new ReflectTest(); Customer customer2 = (Customer)test.copy(customer); System.out.println(customer2.getId() + "," + customer2.getName() + "," + customer2.getAge()); } } class Customer{ private Long id; //注意这边是包装类型的Lang private String name; private int age; public Customer(){ } public Customer(String name, int age){ this.name = name; this.age = age; } public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
编译执行结果:1,Tom,20
1. 获取某个类或某个对象所对应的 Class 对象的常用的 3 种方式:
a) 使用 Class 类的静态方法 forName:Class.forName(“java.lang.String”);
b) 使用类的.class 语法:String.class;
c) 使用对象的 getClass()方法:String s = “aa”; Class<?> clazz = s.getClass();
查看JDK Doc文档Object类中的getClass对象:
getClass
public final Class<?> getClass()
Returns the runtime class of this Object. The returned Class object is the object that is locked by static synchronized methods of the represented class.
[返回这个对象的运行期的类的实例,也就是说对于任何的Object对象,只要我调用getClass()方法,就会获得与之相关联的class对象,而且这个方法还定义为final,子类没法去重写这个方法,所以对于他的任何子类调用这个方法返回的都是与这个子类对应的class对象,这也就更加的表面这是一种运行期的行为]
2.若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
a) 先获得 Class 对象,然后通过该 Class 对象的 newInstance()方法直接生成即可:
Class<?> classType = String.class; Object obj = classType.newInstance();
b) 先获得 Class 对象,然后通过该对象获得对应的 Constructor 对象,再通过该 Constructor 对的 newInstance()方法生成:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[]{});
Object obj = cons.newInstance(new Object[]{});
4. 若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType = Customer.class;
Constructor cons = classType.getConstructor(new Class[{String.class, int.class});
Object obj = cons.newInstance(new Object[]{“hello”, 3});