news 2026/6/14 18:48:08

第十七章 反射与设计模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
第十七章 反射与设计模式

一、反射机制

1. 核心概念拆解

• 实例对象:通过new关键字创建的类实体,直接对应类的业务实例,包含成员变量、方法的具体数据。

• Class类对象:JVM在类加载时自动生成的“类元数据容器”,封装了类的全限定名、父类、接口、构造器、方法、字段等所有结构信息,是反射操作的核心入口。

• 反射:一种动态获取类信息、调用类成员的技术,打破了编译期的封装限制,允许程序在运行时操作类的结构,是框架实现灵活性的核心基础。
2. 获取Class对象的三种方式

1. 实例对象调用getClass():适用于已有实例对象的场景
Student stu = new Student();
Class<?> clazz1 = stu.getClass(); // 获取Student类的Class对象
2. 类名直接调用.class属性:编译期即可确定类型,无需实例化
Class<?> clazz2 = Student.class; // 直接通过类名获取Class对象
3. Class类静态方法forName():通过全限定类名字符串动态加载类,框架中最常用
Class<?> clazz3 = Class.forName("com.example.Student");
// 必须传入"包名.类名"格式的全限定名,否则抛出ClassNotFoundException
3. 类加载触发时机

• 首次创建类的实例(new关键字)

• 首次调用类的静态成员(静态变量、静态方法)

• 子类加载时,会优先触发父类的加载

• 调用Class.forName()获取Class对象时,直接触发类加载
4. 反射常用API详解

(1)获取类的基本信息
Class<?> clazz = Class.forName("com.example.Student");
String className = clazz.getName(); // 获取全限定类名:com.example.Student
String simpleName = clazz.getSimpleName(); // 获取简单类名:Student
Class<?> superClass = clazz.getSuperclass(); // 获取父类的Class对象
Class<?>[] interfaces = clazz.getInterfaces(); // 获取类实现的所有接口
(2)获取类的成员方法

• getMethods():获取本类及父类中所有public修饰的方法

• getDeclaredMethods():获取本类中所有方法(包括private、protected、default修饰的方法)
Method[] publicMethods = clazz.getMethods();
Method[] allMethods = clazz.getDeclaredMethods();
(3)通过反射创建实例对象

• 调用无参构造器创建实例(默认方式)
Class<?> clazz = Class.forName("com.example.Student");
Student student = (Student) clazz.newInstance(); // 底层调用无参构造器
注意:如果类没有无参构造器,会抛出InstantiationException。

• 调用有参构造器创建实例
// 1. 获取指定参数类型的构造器
Constructor<?> constructor = clazz.getConstructor(String.class, int.class);
// 2. 传入参数创建实例
Student student = (Student) constructor.newInstance("张三", 18);
(4)通过反射调用方法
// 1. 获取方法对象(方法名+参数类型)
Method studyMethod = clazz.getDeclaredMethod("study", String.class);
// 2. 解除私有方法的访问权限限制
studyMethod.setAccessible(true);
// 3. 调用方法(实例对象 + 方法参数)
studyMethod.invoke(student, "Java反射");
5. 反射的优缺点

• 优点:实现代码的动态性与通用性,是Spring、MyBatis等框架实现底层逻辑的核心技术,大幅提升程序的灵活性。

• 缺点:破坏类的封装性,可读性差;绕过编译期语法检查,错误只能在运行时暴露;性能低于直接调用,频繁反射会影响程序效率。
二、设计模式基础

1. 设计模式概述

设计模式是软件开发中反复出现问题的通用解决方案,是前人经验的总结,能提升代码的可复用性、可维护性和扩展性。Java中共有23种经典设计模式,本次重点学习单例模式与工厂模式。
2. 单例模式(Singleton Pattern)

单例模式确保一个类在JVM中只有一个实例对象,并提供全局访问入口,常用于配置类、连接池等场景。

(1)饿汉式单例
public class HungrySingleton {
// 类加载时直接创建实例
private static final HungrySingleton instance = new HungrySingleton();

// 私有构造器,禁止外部实例化
private HungrySingleton() {}

// 全局访问入口
public static HungrySingleton getInstance() {
return instance;
}
}
• 优点:实现简单,线程安全

• 缺点:类加载时就创建实例,占用内存,可能造成资源浪费

(2)懒汉式单例(线程安全版)
public class LazySingleton {
// 延迟初始化实例
private static LazySingleton instance;

private LazySingleton() {}

// 加锁保证线程安全
public static synchronized LazySingleton getInstance() {
if (instance == null) {
instance = new LazySingleton();
}
return instance;
}
}
• 优点:延迟加载,节省内存

• 缺点:加锁导致多线程环境下效率较低

(3)静态内部类单例(推荐写法)
public class InnerClassSingleton {
private InnerClassSingleton() {}

// 静态内部类,JVM加载时不会初始化
private static class SingletonHolder {
private static final InnerClassSingleton INSTANCE = new InnerClassSingleton();
}

public static InnerClassSingleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
• 优点:结合饿汉式与懒汉式的优点,线程安全且延迟加载,无性能损耗
3. 工厂模式(Factory Pattern)

工厂模式专门处理对象的创建逻辑,将对象创建与业务逻辑分离,提升代码的可维护性,结合反射可实现通用工厂。

(1)核心作用

将对象的创建逻辑封装在工厂类中,业务代码无需直接使用new创建对象,降低耦合度。

(2)结合反射的通用工厂实现
public class ObjectFactory {
// 根据全限定类名创建对象
public static Object createObject(String className) throws Exception {
Class<?> clazz = Class.forName(className);
return clazz.newInstance();
}
}
通过传入不同的全限定类名,即可创建不同类的实例,实现工厂的通用性。
4. Properties配置文件结合工厂模式

利用Properties读取配置文件,实现对象创建的解耦,是框架中常见的实现方式:
// 1. 创建Properties对象
Properties props = new Properties();
// 2. 加载配置文件
props.load(new FileInputStream("config.properties"));
// 3. 获取配置文件中的类全限定名
String className = props.getProperty("student.class");
// 4. 通过工厂创建对象
Student student = (Student) ObjectFactory.createObject(className);
• Properties是Hashtable的子类,默认键值对均为String类型

• load()方法可自动解析配置文件,按=或:分割键值对
💡 补充:反射破坏单例模式的问题

反射可以通过getConstructor()调用私有构造器,创建多个单例对象,破坏单例的唯一性。解决方案:在构造器中判断实例是否已存在,若存在则抛出异常:
private InnerClassSingleton() {
if (SingletonHolder.INSTANCE != null) {
throw new RuntimeException("单例模式不允许重复创建实例!");
}
}

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/14 18:46:23

突破性移动网络方案:如何为智能硬件实现稳定4G连接

突破性移动网络方案&#xff1a;如何为智能硬件实现稳定4G连接 【免费下载链接】xiaozhi-esp32 An MCP-based chatbot | 一个基于MCP的聊天机器人 项目地址: https://gitcode.com/GitHub_Trending/xia/xiaozhi-esp32 还在为物联网设备的网络连接问题而烦恼吗&#xff1f…

作者头像 李华
网站建设 2026/6/14 18:46:14

终极指南:如何用TIDAL下载器轻松获取24-bit无损音乐

终极指南&#xff1a;如何用TIDAL下载器轻松获取24-bit无损音乐 【免费下载链接】tidal-dl-ng TIDAL Media Downloader Next Generation! Up to HiRes / TIDAL MAX 24-bit, 192 kHz. 项目地址: https://gitcode.com/gh_mirrors/ti/tidal-dl-ng 你是否曾为TIDAL平台上那些…

作者头像 李华
网站建设 2026/6/14 18:44:41

如何免费解锁Cursor Pro完整功能:高效实用的完整解决方案指南

如何免费解锁Cursor Pro完整功能&#xff1a;高效实用的完整解决方案指南 【免费下载链接】cursor-free-vip [Support 0.45]&#xff08;Multi Language 多语言&#xff09;自动注册 Cursor Ai &#xff0c;自动重置机器ID &#xff0c; 免费升级使用Pro 功能: Youve reached y…

作者头像 李华
网站建设 2026/6/14 18:40:52

Qwerty Learner:用打字重塑你的英语学习体验

Qwerty Learner&#xff1a;用打字重塑你的英语学习体验 【免费下载链接】qwerty-learner 为键盘工作者设计的单词记忆与英语肌肉记忆锻炼软件 / Words learning and English muscle memory training software designed for keyboard workers 项目地址: https://gitcode.com/…

作者头像 李华