反射:
1. 反射(发生在运行时期)作用:
a) 判断任意一个对象所属的类
b) 构造任意一个对象
c) 判断任意一个类所具有的成员变量和方法
d) 在运行时调用一个对象的方法
2.在JDK中,主要由以下类来实现Java反射机制,这些类都位于java.lang.reflect包中
1) Class类:代表一个类。
2) Field 类:代表类的成员变量(成员变量也称为类的属性)。
3) Method类:代表类的方法。
4) Constructor 类:代表类的构造方法。
5) Array类:提供了动态创建数组,以及访问数组的元素的静态方法
3. 要想使用反射,首先需要获得待处理类或对象所对应的 Class 对象。
4. 获取某个类或某个对象所对应的Class 对象的常用的 3 种方式:
a) 使用 Class 类的静态方法 forName :Class.forName(“java.lang.String”);
b) 使用类的.class 语法:String.class;
c) 使用对象的 getClass() 方法:String s = “aa”; Class<?> clazz = s.getClass();
5. 若想通过类的不带参数的构造方法来生成对象,我们有两种方式:
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(newObject[]{});
6. 若想通过类的带参数的构造方法生成对象,只能使用下面这一种方式:
Class<?> classType =Customer.class;
Constructor cons =classType.getConstructor(new Class[]{String.class, int.class});
Object obj = cons.newInstance(newObject[]{“hello”, 3});
public class ReflectTester
{
// 该方法实现对Customer对象的拷贝操作
public Object copy(Object object) throws Exception
{
Class<?> classType = object.getClass();
Object objectCopy = classType.getConstructor(new Class[] {})
.newInstance(new Object[] {});
// 获得对象的所有成员变量
Field[] fields = classType.getDeclaredFields();
for (Field field : fields)
{
String name = field.getName();
String firstLetter = name.substring(0, 1).toUpperCase();// 将属性的首字母转换为大写
String getMethodName = "get" + firstLetter + name.substring(1);
String setMethodName = "set" + firstLetter + name.substring(1);
Method getMethod = classType.getMethod(getMethodName,
new Class[] {});
Method setMethod = classType.getMethod(setMethodName,
new Class[] { field.getType() });
Object value = getMethod.invoke(object, new Object[] {});
setMethod.invoke(objectCopy, new Object[] { value });
}
// 以上两行代码等价于下面一行
// Object obj2 = classType.newInstance();
// System.out.println(obj);
return objectCopy;
}
public static void main(String[] args) throws Exception
{
Customer customer = new Customer("Tom", 20);
customer.setId(1L);
ReflectTester test = new ReflectTester();
Customer customer2 = (Customer) test.copy(customer);
System.out.println(customer2.getId() + "," + customer2.getName() + ","
+ customer2.getAge());
}
}
class Customer
{
private Long id;
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;
}
}
例题详解:
• ReflectTester类有一个copy(Object object)方法,这个方法能够创建一个和参数object 同样类型的对象,然后把object对象中的所有属性拷贝到新建的对象中,并将它返回
• 这个例子只能复制简单的JavaBean,假定JavaBean 的每个属性都有public 类型的getXXX()和setXXX()方法。
• ReflectTester 类的copy(Object object)方法
依次执行以下步骤
• (1)获得对象的类型:
Class classType=object.getClass();
System.out.println("Class:"+classType.getName());
• 在java.lang.Object 类中定义了getClass()方法,因此对于任意一个Java对象,都可以通过此方法获得对象的类型。Class类是Reflection API中的核心类,它有以下方法
getName():获得类的完整名字。
getFields():获得类的public类型的属性。
getDeclaredFields():获得类的所有属性。
getMethods():获得类的public类型的方法。
getDeclaredMethods():获得类的所有方法。
getMethod(String name, Class[]parameterTypes):获得类的特定方法,name参数指定方法的名字,parameterTypes 参数指定方法的参数类型。
• getConstructors():获得类的public类型的构造方法。
• getConstructor(Class[] parameterTypes):获得类的特定构造方法,parameterTypes 参数指定构造方法的参数类型。
• newInstance():通过类的 不带参数的构造方法创建这个类的一个对象。
• (2)通过默认构造方法创建一个新对象:
• Object objectCopy=classType.getConstructor(new Class[]{}).newInstance(new Object[]{});
• 以上代码先调用Class类的getConstructor()方法获得一个Constructor 对象,它代表默认的构造方法,然后调用Constructor对象的newInstance()方法构造一个实例。
• (3)获得对象的所有属性:
• Field fields[]=classType.getDeclaredFields();
• Class 类的getDeclaredFields()方法返回类的所有属性,包括public、protected、默认和private访问级别的属性
• (4)获得每个属性相应的getXXX()和setXXX()方法,然后执行这些方法,把原来对象的属性拷贝到新的对象中
• 在例程InvokeTester类的main()方法中,运用反射机制调用一个InvokeTester对象的add()和echo()方法
• add()方法的两个参数为int 类型,获得表示add()方法的Method对象的代码如下:
• Method addMethod=classType.getMethod("add",new Class[]{int.class,int.class});
• Method类的invoke(Object obj,Object args[])方法接收的参数必须为对象,如果参数为基本类型数据,必须转换为相应的包装类型的对象。invoke()方法的返回值总是对象,如 果实际被调用的方法的返回类型是基本类型数据,那么invoke()方法会把它转换为相应的包装类型的对象,再将其返回
• 在本例中,尽管InvokeTester 类的add()方法的两个参数以及返回值都是int类型,调用add Method 对象的invoke()方法时,只能传递Integer 类型的参数,并且
invoke()方法的返回类型也是Integer 类型,Integer类是int 基本类型的包装类:
• Object result=addMethod.invoke(invokeTester,new Object[]{new Integer(100),newInteger(200)});
• System.out.println((Integer)result); //result 为Integer类型