Java学习——day23(反射的对象创建与方法调用)
文章目录
- 1. 使用反射实例化对象
- 1.1 利用无参构造函数创建对象
- 1.2利用带参构造函数创建对象
- 2.通过反射调用对象方法
- 2.1 调用公共方法
- 2.2 调用私有方法(需设置访问权限)
- 3. 访问和修改对象的属性
- 3.1 公共属性
- 3.2 私有属性
- 4. 实践任务
- 4.1工厂类 SimpleFactory
- 4.2 测试工厂类 TestFactory
- 5. 总结与思考
1. 使用反射实例化对象
1.1 利用无参构造函数创建对象
代码示例:
package com.example;
import java.lang.reflect.Method;
public class ReflectionTest {
public static void main(String[] args) {
try {
// 1. 获取 Person 类的 Class 对象
Class<?> clazz = Class.forName("com.example.Person");
// 2. 获取无参构造函数并创建实例
Object person1 = clazz.getConstructor().newInstance();
// 验证:获取公共方法 sayHello 并调用
Method sayHelloMethod = clazz.getMethod("sayHello");
sayHelloMethod.invoke(person1);
} catch (Exception e) {
e.printStackTrace();
}
}
}
1.2利用带参构造函数创建对象
package com.example;
import java.lang.reflect.Method;
public class ReflectionTest {
public static void main(String[] args) {
try {
Class<?> clazz = Class.forName("com.example.Person");
// 1. 获取带参构造函数(参数类型要匹配)
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
// 2. 创建实例
Object person2 = constructor.newInstance("张三", 25);
// 验证
Method sayHelloMethod = clazz.getMethod("sayHello");
sayHelloMethod.invoke(person2);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.通过反射调用对象方法
2.1 调用公共方法
try {
Class<?> clazz = Class.forName("com.example.Person");
Object person = clazz.getConstructor(String.class, int.class).newInstance("李四", 30);
// 1. 获取公共方法 sayHello
Method sayHelloMethod = clazz.getMethod("sayHello");
// 2. 调用方法
sayHelloMethod.invoke(person);
} catch (Exception e) {
e.printStackTrace();
}
2.2 调用私有方法(需设置访问权限)
假设 Person 类中有一个私有方法 secretMethod:
private void secretMethod() {
System.out.println("这是一个私有方法。");
}
可以通过以下方式调用:
try {
Class<?> clazz = Class.forName("com.example.Person");
Object person = clazz.getConstructor().newInstance();
// 1. 获取私有方法
Method secretMethod = clazz.getDeclaredMethod("secretMethod");
// 2. 设置可访问
secretMethod.setAccessible(true);
// 3. 调用
secretMethod.invoke(person);
} catch (Exception e) {
e.printStackTrace();
}
3. 访问和修改对象的属性
3.1 公共属性
若 Person 中有公共属性 public String address;,可直接使用 getField 和 set/get 来操作。
3.2 私有属性
假设要访问或修改私有属性 name:
try {
Class<?> clazz = Class.forName("com.example.Person");
Object person = clazz.getConstructor().newInstance();
// 获取私有字段 name
Field nameField = clazz.getDeclaredField("name");
// 允许访问私有字段
nameField.setAccessible(true);
// 修改 person 的 name 值
nameField.set(person, "王五");
// 调用 sayHello() 验证
Method sayHelloMethod = clazz.getMethod("sayHello");
sayHelloMethod.invoke(person);
} catch (Exception e) {
e.printStackTrace();
}
4. 实践任务
实现一个简单的工厂模式
利用反射根据传入的类名生成对象,并调用其方法。
4.1工厂类 SimpleFactory
public class SimpleFactory {
/**
* 根据传入的类名动态创建对象
*
* @param className 类的全限定名
* @return 创建的对象实例,若出错则返回 null
*/
public static Object createInstance(String className) {
try {
// 1. 加载类
Class<?> clazz = Class.forName(className);
// 2. 使用无参构造函数实例化
return clazz.getConstructor().newInstance();
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
4.2 测试工厂类 TestFactory
public class TestFactory {
public static void main(String[] args) {
// 1. 使用简单工厂创建对象
Object obj = SimpleFactory.createInstance("com.example.Person");
if (obj != null) {
try {
// 2. 获取并调用 sayHello 方法
Method sayHelloMethod = obj.getClass().getMethod("sayHello");
sayHelloMethod.invoke(obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
运行结果
Hello,我是 默认姓名,年龄 0
5. 总结与思考
1.反射的作用:
- 让代码具备了动态性,能在运行时操作类、方法和属性。
- 适合做框架开发和插件机制等对扩展性要求高的场景。
2.常见应用场景:
- 依赖注入:如 Spring 中的 @Autowired。
- 动态代理:如 AOP(面向切面编程)。
- 通用工具类:如 Bean 拷贝、ORM 映射(MyBatis、Hibernate 等)。
3.注意事项:
- 反射往往会带来一定的性能开销,频繁调用需谨慎。
- 对私有成员的访问需设置 setAccessible(true),可能存在安全风险。
- 异常处理要充分,包括 ClassNotFoundException、NoSuchMethodException、IllegalAccessException 等。