当前位置: 首页 > news >正文

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 等。

相关文章:

  • Text-to-SQL技术深度解析:从理论突破到工程实践
  • Jmeter+Jenkins+Ant自动化持续集成环境搭建
  • [ctfshow web入门] web7
  • PyQt6实例_A股日数据维护工具_完整项目代码_终结章
  • Gis相关记录备忘录
  • 软件工程第五章习题
  • 15-产品经理-维护需求
  • redis 和 MongoDB都可以存储键值对,并且值可以是复杂json,用完整例子分别展示说明两者在存储json键值对上的使用对比
  • 贪心算法(16)(java)俄罗斯套娃信封问题
  • 从零到一:用Java和Spring Security构建OAuth2授权服务器
  • 【Vue-vue基础知识】学习笔记
  • 强化学习Q-Learning:DQN
  • 17-产品经理-创建发布
  • Golang 项目平滑重启
  • Python小练习系列 Vol.13:用装饰器记录函数执行时间
  • 蓝桥杯2024年第十五届省赛真题-爬山
  • 刺杀大使--bfs还是比dfs快+二分
  • 专题|MATLAB-R语言Logistic逻辑回归增长模型在互联网金融共生及移动通信客户流失分析实例合集
  • 基于Python Flask快速构建网络安全工具资源库的Web应用实践
  • 【简历全景认知2】电子化时代对简历形式的降维打击:从A4纸到ATS的生存游戏
  • 怎样重新安装wordpress/什么是seo什么是sem
  • 铜梁网站建设/网络运营工作内容
  • 服饰怎么做网站推广/网站流量分析
  • 兰州做网站维护的公司/成都sem优化
  • wordpress外贸建站/济南网络营销外包
  • 做网站免费送域名/济南优化哪家好