1.什么是反射
1.1 反射概念
- 反射是一种机制,利用该机制可以在程序运行过程中对类进行解剖,并得到并操作类中的方法,属性,构造方法等成员。
- 简单理解为:
- 通过反射可以获取类里的所有成员:获取类的信息、所有构造方法、所有普通方法、所有成员变量等等
- 通过反射可以操作类里的所有成员:反射方式调用类的构造方法、普通方法、成员方法
1.2 什么时候需要使用反射?
- 当使用普通方式不能调用的时候,可以考虑使用反射调用。
- 例如想要强制调用私有方法,普通调用方式调不了,使用反射就可以了(原则上不建议强制调用private方法)。
2. 反射的使用
2.1 获取Class对象★
API说明:java.lang.Class:是类的信息对象。Java中一切皆对象,那么一个类的信息也被封装成了对象--Class对象。一切反射操作的前提,必须先获取类的Class对象。
2.1.1 获取Class的方式
- 通过class指令获取:
Class clazz = 类名.class - 通过getClass()获取:
Class clazz = 对象.getClass()Object类提供了getClass方法,用于获取类的Class - 通过Class.forName获取:
Class clazz = Class.forName("全限定类名")
全限定类名:即包名+类名。例如:
java.lang.Object是全限定类名,Object是简单类名
2.1.2 Class的常用方法
| 方法 | 说明 |
|---|---|
String getName() | 获取类的全限定类名 |
String getSimpleName() | 获取简单类名 |
Constructor[] getConstructors() | 获取所有public构造方法 |
Constructor[] getDeclaredConstructors() | 获取所有构造方法 |
Constructor getConstructor(Class... argTypes) | 获取指定类型形参的public构造方法 |
Constructor getDeclaredConstructor(Class... argTypes) | 获取指定类型形参的构造方法 |
Method[] getMethods() | 获取所有public的成员方法 |
Method[] getDeclaredMethods() | 获取所有成员方法 |
Method getMethod(String name,Class...argTypes) | 获取指定名称和形参类型的public方法 |
Method getDeclaredMethod(String name,Class...argTypes) | 获取指定名称和形参类型的方法 |
Field[] getFields() | 获取所有public成员变量 |
Field[] getDeclaredFields() | 获取所有成员变量 |
Field getField(String name) | 获取指定名称的public成员变量 |
Field getDeclaredField(String name) | 获取指定名称的成员变量 |
2.2 使用示例
2.2.1 准备一个User类
public class User {
private String name;
public int age;
public User() {
}
public User(String name) {
this.name = name;
}
private User(String name, int age) {
this.name = name;
this.age = age;
}
public void eat(String food){
System.out.println("吃" + food);
}
private String sleep(){
System.out.println("睡");
return "睡爽了";
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
2.2.2 操作Class示例
/**
* 获取User的Class对象
*/
public class Demo01Class {
@Test
public void testClass1() throws ClassNotFoundException {
//1. 类名.class
Class<User> clazz = User.class;
System.out.println(clazz);
}
@Test
public void testClass2() throws ClassNotFoundException {
//2. 对象.getClass()
User user = new User();
Class clazz = user.getClass();
System.out.println(clazz);
}
@Test
public void testClass3() throws ClassNotFoundException {
//3. Class.forName("")
Class clazz = Class.forName("demo02_reflect.User");
System.out.println(clazz);
}
}
3. 反射操作构造方法
3.1 API说明
3.1.1 Constructor类
java.lang.reflect.Constructor:构造方法信息封装成的对象。它提供了以下常用方法:
| 方法 | 说明 |
|---|---|
newInstance(Object... args) | 反射调用构造方法并传入实参,得到创建的实例对象 |
setAccessible(boolean flag) | 如果传参true,表示强制允许反射调用。即使是private也允许访问 |
- 从Class里获取Constructor对象的API:
| 方法 | 说明 |
|---|---|
Constructor[] getConstructors() | 获取所有public构造方法 |
Constructor[] getDeclaredConstructors() | 获取所有构造方法 |
Constructor getConstructor(Class... argTypes) | 获取指定类型形参的public构造方法 |
Constructor getDeclaredConstructor(Class... argTypes) | 获取指定类型形参的构造方法 |
3.1.2 反射调用构造方法的步骤
-
一切反射的前提,是获取类的Class字节码对象
-
反射调用构造方法的步骤
- 获取类的Class对象:前边有API
- 从Class对象中获取构造方法的Constructor对象:前边有API
- 反射调用Constructor,得到类实例对象
3.2 使用示例
public class Demo02Constructor {
/**
* 通过User的无参构造,得到一个User实例对象
*/
@Test
public void testConstructor() throws Exception {
//1. 获取类的Class对象
Class clazz = User.class;
//2. 获取构造方法对象
Constructor constructor = clazz.getConstructor();
//3. 反射调用构造方法,生成类实例对象
Object user = constructor.newInstance();
System.out.println(user);
}
/**
* 通过User的有参构造,得到一个User实例对象
* 参数:String, Integer,并且方法是private
*
*/
@Test
public void testConstructor2() throws Exception {
//1. 获取类的Class对象
Class clazz = User.class;
//2. 获取类的有参构造方法对象
Constructor constructor = clazz.getDeclaredConstructor(String.class, Integer.class);
constructor.setAccessible(true);
//3. 反射调用构造方法
Object user = constructor.newInstance("tom", 45);
System.out.println(user);
}
}
4. 反射操作成员方法
4.1 API说明
4.1.1 Method类
java.lang.reflect.Method:普通方法信息封装成的对象。它提供了以下常用方法:
| 方法 | 说明 |
|---|---|
invoke(Object instance, Object... args) | 反射调用方法并传入实参,得到方法的返回值 |
setAccessible(boolean flag) | 如果传参true,表示强制允许反射调用。 即使是private也允许访问 |
- 从Class里获取Method对象的API:
| 方法 | 说明 |
|---|---|
Method[] getMethods() | 获取所有public的成员方法 |
Method[] getDeclaredMethods() | 获取所有成员方法 |
Method getMethod(String name,Class...argTypes) | 获取指定名称和形参类型的public方法 |
Method getDeclaredMethod(String name,Class...argTypes) | 获取指定名称和形参类型的方法 |
4.1.2 反射调用普通方法的步骤
-
一切反射的前提,是获取类的Class字节码对象
-
反射调用普通方法的步骤
- 获取类的Class对象
- 从Class中获取普通方法的Method对象
- 反射调用Method,得到方法的返回值
4.2 使用示例
public class Demo03Method {
/**
* 调用User对象(user1)的eat方法:参数 String
*/
@Test
public void testMethod() throws Exception {
//普通方式调用:
User user1 = new User();
User user2 = new User();
User user3 = new User();
User user4 = new User();
//user1.eat("泡面");
//反射方式调用
//1. 获取类的Class
Class clazz = User.class;
//2. 获取方法的Method对象
Method method = clazz.getMethod("eat", String.class);
//3. 反射调用method(执行方法)
Object result = method.invoke(user1, "泡面");
System.out.println(result);
}
/**
* 调用User的sleep方法:参数String
*/
@Test
public void testMethod2() throws Exception {
User user = new User();
//user.sleep("");
//1.获取类的字节码对象Class
Class clazz = User.class;
//2. 获取方法的Method对象
Method method = clazz.getDeclaredMethod("sleep", String.class);
method.setAccessible(true);
//3. 反射调用方法
Object result = method.invoke(user, "tom");
System.out.println(result);
}
}
5. 反射操作成员变量
5.1 API说明
5.1.1 Field类
java.lang.reflect.Field:类成员变量信息封装成的对象。它提供了以下常用方法:
| 方法 | 说明 |
|---|---|
get(Object instance) | 获取实例对象的成员变量值 |
set(Object instance, Object value) | 设置实例对象的成员变量值 |
setAccessible(boolean flag) | 如果传参true,表示强制允许反射调用。即使是private也允许访问 |
- 从Class里获取Field对象的API:
| 方法 | 说明 |
|---|---|
Field[] getFields() | 获取所有public成员变量 |
Field[] getDeclaredFields() | 获取所有成员变量 |
Field getField(String name) | 获取指定名称的public成员变量 |
Field getDeclaredField(String name) | 获取指定名称的成员变量 |
5.1.2 反射操作成员变量的步骤
-
一切反射的前提,是获取类的Class字节码对象
-
反射操作属性的步骤
- 获取类的Class对象
- 从Class中获取属性成员变量的Field对象
- 反射调用Field,设置属性字段值,或者获取属性成员变量值
5.2 使用示例
public class Demo04Field {
/**
* 操作User的age属性值
*/
@Test
public void testField1() throws Exception {
//普通方式
User user = new User();
User user1 = new User();
//user.age = 45;
//System.out.println(user.age);
//反射方式
//1. 获取类的Class
Class clazz = User.class;
//2. 获取Field对象
Field field = clazz.getField("age");
//3. 设置属性值
field.set(user, 50);
//4. 获取属性值
Object value = field.get(user);
System.out.println(value);
}
/**
* 操作User的name属性 private
*/
@Test
public void testField2() throws Exception {
User user = new User();
//1. 获取类的Class
Class clazz = User.class;
//2. 获取Field
Field field = clazz.getDeclaredField("name");
field.setAccessible(true);
//3. 设置属性值
field.set(user, "jerry");
//4. 获取属性值
Object value = field.get(user);
System.out.println(value);
}
}