一、获取 Class 对象的 3 种方式(重点)
1. 方式 1:Class.forName("全类名")(最常用)
**(1) 作用:**通过类的 "全类名"(包名 + 类名)动态加载类,生成 Class 对象。
(2) 代码示例
java
// 示例:加载 java.lang.String 类
Class<?> clazz1 = Class.forName("java.lang.String");
2. 方式 2:类名.class
**(1) 作用:**通过类名直接获取 Class 对象。
(2) 代码示例:
java
// 示例:获取 String 类的 Class 对象
Class<?> clazz2 = String.class;
3. 方式 3:对象.getClass()
(1) 作用: 通过已有对象的 getClass() 方法获取 Class 对象。
(2) 代码示例:
java
// 示例:通过 String 对象获取 Class 对象
String str = "hello";
Class<?> clazz3 = str.getClass();
二、反射核心操作
以自定义 User 类为示例,演示反射的核心操作:
java
// 目标类:包含公有/私有属性、构造器、方法
public class User {
// 公有属性
public String username;
// 私有属性
private int age;
// 无参构造器(公有)
public User() {}
// 有参构造器(私有)
private User(String username, int age) {
this.username = username;
this.age = age;
}
// 公有方法
public void show() {
System.out.println("username: " + username + ", age: " + age);
}
// 私有方法
private String getInfo(String prefix) {
return prefix + ": " + username + "-" + age;
}
// getter/setter(省略)
}
1. 操作构造器(创建对象)
通过 Class 对象的方法获取构造器,再通过构造器创建对象。
| 方法名 | 作用 |
|---|---|
getConstructor(Class<?>... parameterTypes) |
获取公有的指定参数类型的构造器 |
getConstructors() |
获取所有公有构造器 |
getDeclaredConstructor(Class<?>... parameterTypes) |
获取任意访问权限的指定参数类型的构造器(包括私有) |
getDeclaredConstructors() |
获取所有构造器(包括私有) |
示例1:通过公有无参构造器创建对象
java
// 1. 获取 User 类的 Class 对象
Class<?> userClass = Class.forName("com.itheima.reflect.User");
// 2. 获取公有无参构造器(参数类型为 null,可省略)
Constructor<?> constructor = userClass.getConstructor();
// 3. 创建对象(newInstance() 方法)
User user = (User) constructor.newInstance();
// 4. 操作对象
user.username = "张三";
user.show(); // 输出:username: 张三, age: 0
示例2:通过私有有参构造器创建对象
私有构造器需要先通过 setAccessible(true) 打破封装(忽略访问权限检查):
java
// 1. 获取私有有参构造器(参数类型:String.class, int.class)
Constructor<?> privateConstructor = userClass.getDeclaredConstructor(String.class, int.class);
// 2. 打破封装(关键:否则无法访问私有构造器)
privateConstructor.setAccessible(true);
// 3. 创建对象(传入构造器参数)
User user2 = (User) privateConstructor.newInstance("李四", 20);
// 4. 调用方法
user2.show(); // 输出:username: 李四, age: 20
2. 操作成员变量(获取 / 修改属性值)
通过 Class 对象的方法获取成员变量,再通过 get()/set() 方法操作属性值。
| 方法名 | 作用 |
|---|---|
getField(String name) |
获取公有的指定名称的成员变量 |
getFields() |
获取所有公有成员变量 |
getDeclaredField(String name) |
获取任意访问权限的指定名称的成员变量(包括私有) |
getDeclaredFields() |
获取所有成员变量(包括私有) |
示例:调用私有方法 getInfo(String prefix)
java
// 1. 获取 User 类的 Class 对象
Class<?> userClass = Class.forName("com.itheima.reflect.User");
// 2. 创建对象(通过无参构造器)
User user = (User) userClass.getConstructor().newInstance();
// 3. 获取私有属性 age
Field ageField = userClass.getDeclaredField("age");
// 4. 打破封装
ageField.setAccessible(true);
// 5. 修改属性值(set(对象, 新值))
ageField.set(user, 25);
// 6. 获取属性值(get(对象))
int age = (int) ageField.get(user);
System.out.println("修改后的 age: " + age); // 输出:25
// 7. 操作公有属性 username(无需打破封装)
Field usernameField = userClass.getField("username");
usernameField.set(user, "王五");
System.out.println("username: " + usernameField.get(user)); // 输出:王五
3. 操作成员方法(调用方法)
通过 Class 对象的方法获取成员方法,再通过 invoke() 方法调用。
| 方法名 | 作用 |
|---|---|
getMethod(String name, Class<?>... parameterTypes) |
获取公有的指定名称和参数类型的方法 |
getMethods() |
获取所有公有方法(包括父类继承的) |
getDeclaredMethod(String name, Class<?>... parameterTypes) |
获取任意访问权限的指定名称和参数类型的方法(包括私有) |
getDeclaredMethods() |
获取所有方法(不包括父类继承的,只含当前类定义的) |
示例:调用私有方法 getInfo(String prefix)
java
// 1. 获取 User 类的 Class 对象
Class<?> userClass = Class.forName("com.itheima.reflect.User");
// 2. 创建对象
User user = (User) userClass.getConstructor().newInstance();
user.username = "赵六";
// 3. 获取私有方法 getInfo(方法名:"getInfo",参数类型:String.class)
Method getInfoMethod = userClass.getDeclaredMethod("getInfo", String.class);
// 4. 打破封装
getInfoMethod.setAccessible(true);
// 5. 调用方法(invoke(对象, 方法参数))
String result = (String) getInfoMethod.invoke(user, "用户信息");
System.out.println(result); // 输出:用户信息: 赵六-0(age 未赋值,默认 0)
三、动态代理
1. 核心概念
① 动态代理指运行时动态生成目标类的代理对象,在不修改目标类源码的前提下,对目标方法进行增强(如日志、权限校验)。
② 核心要求: 目标类必须实现至少一个接口(JavaSE 原生限制)。
③ 核心类:
java.lang.reflect.Proxy:生成代理对象的工具类;java.lang.reflect.InvocationHandler:定义增强逻辑的接口。
2. 代码示例
ProxyUtil.java
java
package demo1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
public static Star createProxy(BigStar bigStar) {
Star star = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("sing".equals(method.getName())){
System.out.println("准备话筒,收钱");
}else if("dance".equals(method.getName())){
System.out.println("准备场地,收钱");
}
method.invoke(bigStar,args);
return null;
}
});
return star;
}
}
Star.java
java
package demo1;
public interface Star {
public abstract String sing(String name);
public abstract void dance();
}
test.java
java
package demo1;
public class test {
public static void main(String[] args) {
BigStar bigStar = new BigStar("鸡哥");
Star proxy = ProxyUtil.createProxy(bigStar);
String result = proxy.sing("只因你太美");
System.out.println(result);
}
}
BigStar.java
java
package demo1;
public class BigStar implements Star {
private String name;
public BigStar() {
}
public BigStar(String name) {
this.name = name;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
@Override
public String sing(String name) {
System.out.println(this.name + "正在唱" + name);
return "谢谢";
}
@Override
public void dance() {
System.out.println(this.name + "跳舞");
}
public String toString() {
return "BigStar{name = " + name + "}";
}
}