一、反射的定义
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制
注:反射式框架的基石,大部分主流的框架都用到了反射技术
二、Class类
- Class类位于java.lang包下
- Class类代表着Java中所有的类,是类的再往上抽象
(一)获取Class类的三种方法
- 方法一:通过Class.forName(“类的全路径”)
- 方法二:通过类的名字打点class,如:Person.class
- 方法三:通过调用该类的对象调用getClass()方法
示例:
public class Test
{
public static void main(String[] args) throws ClassNotFoundException
{
// 【方法一】通过Class.forName("类的全路径")
Class<?> clazz1 = Class.forName("java.lang.String");
// 【方法二】通过类的名字打点class,如:String.class
Class<?> clazz3 = String.class;
// 【方法三】通过调用该类的对象调用getClass()方法
String str = new String();
Class<?> clazz2 = str.getClass();
prints(clazz1);
prints(clazz2);
prints(clazz3);
}
/**
* 打印类的所有方法
* @param clazz
*/
public static void prints(Class<?> clazz)
{
Method[] declaredMethods = clazz.getDeclaredMethods();
for (Method m : declaredMethods)
{
System.out.println(m);
}
}
}
(二)Class类的常用方法
返回值 | 方法声明 | 用法说明 |
---|---|---|
Constructor<T> | getDeclaredConstructor(Class<?>… parameterTypes) | 获得构造器 |
Field | getDeclaredField(String name) | 获得指定字段 |
Field[] | getDeclaredFields() | 获得所有字段 |
Method | getDeclaredMethod(String name, Class<?>… parameterTypes) | 获得指定方法 |
Method[] | getDeclaredMethods() | 获得所有方法 |
示例:
package pl_reflect;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Test
{
public static void main(String[] args) throws Exception
{
Class<?> clazz = Class.forName("pl_reflect.Person");
// 获得对象的一个属性
Field field = clazz.getDeclaredField("address");
System.out.println(field);
// 获得一个具体的方法
Method method = clazz.getDeclaredMethod("getName", new Class[] {});
Method method1 = clazz.getDeclaredMethod("setName", new Class[] { String.class });
System.out.println(method);
System.out.println(method1);
// 获得构造器
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[] {});
System.out.println(constructor);
Constructor<?> constructor2 = clazz
.getDeclaredConstructor(new Class[] { Integer.class, String.class, String.class });
System.out.println(constructor2);
}
}
class Person
{
private Integer id;
private String name;
private String address;
public Person()
{
}
public Person(Integer id, String name, String address)
{
super();
this.id = id;
this.name = name;
this.address = address;
}
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public String getAddress()
{
return address;
}
public void setAddress(String address)
{
this.address = address;
}
}
三、通过反射进行方法的调用
public class Test
{
public static void main(String[] args) throws Exception
{
Class<?> class1 = Class.forName("pl_reflect.Person");
//获得构造器
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
//根据类的默认构造器来获得一个对象
Object instance=constructor.newInstance(new Object[]{});
//获得方法
Method method = class1.getDeclaredMethod("setName", new Class[]{String.class});
//调用方法赋值
Object invoke = method.invoke(instance, new Object[]{"张三"});
}
}
- 如果底层方法是实例方法,第一个参数就是该对象的实例,第二个参数是方法的参数列表,invoke的返回值就是实例方法的返回值
- 如果底层方法是静态的,那么可以忽略指定的obj参数,该参数可以为null
- 如果底层方法所需的形参数为0,则所提供的args数组长度可以为0或null
四、通过反射进行属性的设值
public class Test
{
public static void main(String[] args) throws Exception
{
Class<?> class1 = Class.forName("pl_reflect.Person");
//获得构造器
Constructor<?> constructor = class1.getDeclaredConstructor(new Class[]{});
//根据类的默认构造器来获得一个对象
Object instance=constructor.newInstance(new Object[]{});
//根据属性名字来获得属性对象
Field field = class1.getDeclaredField("name");
//破坏掉私有属性
field.setAccessible(true);
//设置属性的值
field.set(instance, "张三");
}
}