news 2026/5/4 6:52:22

得物Java面试被问:反射机制的原理和应用场景

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
得物Java面试被问:反射机制的原理和应用场景

一、反射机制原理

1.核心原理

反射允许程序在运行时动态地:

  • 获取类的完整信息(类名、方法、字段、注解等)

  • 创建对象实例

  • 调用方法和访问字段

  • 修改字段值(包括私有字段)

2.实现机制

java

复制

下载

// Class对象的获取方式 // 1. 类名.class Class<?> clazz1 = String.class; // 2. 对象.getClass() String str = "hello"; Class<?> clazz2 = str.getClass(); // 3. Class.forName() - 最常用 Class<?> clazz3 = Class.forName("java.lang.String"); // 4. ClassLoader加载 ClassLoader loader = Thread.currentThread().getContextClassLoader(); Class<?> clazz4 = loader.loadClass("java.lang.String");

3.类加载与Class对象

java

复制

下载

// Class对象包含类的元数据 public final class Class<T> { // 类名 private final String name; // 方法信息 private Method[] methods; // 字段信息 private Field[] fields; // 构造方法 private Constructor<?>[] constructors; // 注解信息 private Annotation[] annotations; // 父类 private Class<? super T> superclass; }

4.内存模型

text

复制

下载

JVM方法区(元空间) 堆内存 ┌─────────────────┐ ┌─────────────┐ │ 类的元数据 │ │ Class对象 │ │ - 方法字节码 │◄───│ - 指向元数据 │ │ - 字段描述符 │ │ - 静态变量 │ │ - 常量池 │ └─────────────┘ └─────────────────┘ ▲ ▲ │ │ ┌───┴────┐ │ │ 实例对象 │ └──────────────────┤ - 字段值 │ └─────────┘

二、核心API详解

1.获取类信息

java

复制

下载

Class<?> clazz = User.class; // 获取类名 String className = clazz.getName(); // 全限定名: "com.example.User" String simpleName = clazz.getSimpleName(); // 简单名: "User" // 获取包信息 Package pkg = clazz.getPackage(); String packageName = pkg.getName(); // 获取修饰符 int modifiers = clazz.getModifiers(); Modifier.isPublic(modifiers); // 是否是public Modifier.isAbstract(modifiers); // 是否是abstract // 获取父类和接口 Class<?> superClass = clazz.getSuperclass(); Class<?>[] interfaces = clazz.getInterfaces(); // 获取注解 Annotation[] annotations = clazz.getAnnotations(); MyAnnotation myAnno = clazz.getAnnotation(MyAnnotation.class);

2.操作字段(Field)

java

复制

下载

class User { private String name; public int age; private static final String COUNTRY = "China"; } // 获取字段 Field[] fields = clazz.getDeclaredFields(); // 所有字段(包括private) Field publicField = clazz.getField("age"); // 仅public字段 // 获取/设置字段值 User user = new User(); Field nameField = clazz.getDeclaredField("name"); nameField.setAccessible(true); // 突破private限制 // 读取值 Object value = nameField.get(user); // 获取name值 // 设置值 nameField.set(user, "张三"); // 设置name为"张三" // 静态字段操作 Field countryField = clazz.getDeclaredField("COUNTRY"); countryField.setAccessible(true); Field modifiersField = Field.class.getDeclaredField("modifiers"); modifiersField.setAccessible(true); modifiersField.setInt(countryField, countryField.getModifiers() & ~Modifier.FINAL); countryField.set(null, "USA"); // 修改final静态字段(不推荐)

3.操作方法(Method)

java

复制

下载

class Calculator { public int add(int a, int b) { return a + b; } private void log(String message) { System.out.println(message); } } // 获取方法 Method[] methods = clazz.getDeclaredMethods(); Method addMethod = clazz.getDeclaredMethod("add", int.class, int.class); Method logMethod = clazz.getDeclaredMethod("log", String.class); // 调用方法 Calculator calc = new Calculator(); Object result = addMethod.invoke(calc, 10, 20); // 返回30 // 调用私有方法 logMethod.setAccessible(true); logMethod.invoke(calc, "test message"); // 静态方法调用 Method staticMethod = clazz.getDeclaredMethod("staticMethod"); staticMethod.invoke(null); // 静态方法传null

4.操作构造器(Constructor)

java

复制

下载

class Person { private String name; private int age; public Person() {} private Person(String name) { this.name = name; } public Person(String name, int age) { this.name = name; this.age = age; } } // 获取构造器 Constructor<?>[] constructors = clazz.getDeclaredConstructors(); Constructor<?> defaultConstructor = clazz.getDeclaredConstructor(); // 无参 Constructor<?> paramConstructor = clazz.getDeclaredConstructor(String.class, int.class); // 创建实例 Person p1 = (Person) defaultConstructor.newInstance(); Person p2 = (Person) paramConstructor.newInstance("张三", 25); // 创建私有构造器的实例 Constructor<?> privateConstructor = clazz.getDeclaredConstructor(String.class); privateConstructor.setAccessible(true); Person p3 = (Person) privateConstructor.newInstance("李四");

三、应用场景

1.框架开发(最常用)

java

复制

下载

// Spring IOC容器实现原理示例 public class SimpleContainer { private Map<String, Object> beans = new HashMap<>(); public void register(Class<?> clazz) throws Exception { // 通过注解获取Bean名称 Component anno = clazz.getAnnotation(Component.class); String beanName = anno != null ? anno.value() : clazz.getSimpleName().toLowerCase(); // 创建实例(支持依赖注入) Object bean = createInstance(clazz); beans.put(beanName, bean); } private Object createInstance(Class<?> clazz) throws Exception { // 1. 获取所有构造方法 Constructor<?>[] constructors = clazz.getConstructors(); // 2. 选择@Autowired标注的构造方法 for (Constructor<?> constructor : constructors) { if (constructor.isAnnotationPresent(Autowired.class)) { // 3. 获取参数类型 Class<?>[] paramTypes = constructor.getParameterTypes(); Object[] params = new Object[paramTypes.length]; // 4. 递归创建参数实例 for (int i = 0; i < paramTypes.length; i++) { params[i] = getBean(paramTypes[i]); } // 5. 创建实例 return constructor.newInstance(params); } } // 6. 使用默认构造方法 return clazz.newInstance(); } } // 使用注解定义Bean @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) @interface Component { String value() default ""; } @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.CONSTRUCTOR) @interface Autowired {}

2.动态代理

java

复制

下载

// JDK动态代理(基于接口) public class DynamicProxyHandler implements InvocationHandler { private Object target; public DynamicProxyHandler(Object target) { this.target = target; } public Object createProxy() { return Proxy.newProxyInstance( target.getClass().getClassLoader(), target.getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 前置处理 System.out.println("Before method: " + method.getName()); // 调用目标方法 Object result = method.invoke(target, args); // 后置处理 System.out.println("After method: " + method.getName()); return result; } } // 使用示例 interface UserService { void save(User user); } class UserServiceImpl implements UserService { public void save(User user) { // 业务逻辑 } } // 创建代理 UserService proxy = (UserService) new DynamicProxyHandler(new UserServiceImpl()).createProxy(); proxy.save(user);

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

3.注解处理器

java

复制

下载

// 自定义注解 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @interface LogExecutionTime { } // 注解处理器 public class LogExecutionTimeProcessor { public static void process(Object obj) throws Exception { Class<?> clazz = obj.getClass(); for (Method method : clazz.getDeclaredMethods()) { if (method.isAnnotationPresent(LogExecutionTime.class)) { // 创建代理方法 Method originalMethod = method; // 动态生成代理类(简化示例) System.out.println("Logging execution time for: " + method.getName()); long startTime = System.currentTimeMillis(); originalMethod.invoke(obj); long endTime = System.currentTimeMillis(); System.out.println("Execution time: " + (endTime - startTime) + "ms"); } } } } // 使用 class Service { @LogExecutionTime public void processData() { // 耗时操作 } }

4.配置文件映射

java

复制

下载

// properties文件:config.properties // database.url=jdbc:mysql://localhost:3306/test // database.username=root // database.password=123456 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) @interface ConfigValue { String key(); } class DatabaseConfig { @ConfigValue(key = "database.url") private String url; @ConfigValue(key = "database.username") private String username; @ConfigValue(key = "database.password") private String password; // getters and setters } public class ConfigLoader { public static <T> T load(Class<T> clazz, Properties props) throws Exception { T instance = clazz.newInstance(); for (Field field : clazz.getDeclaredFields()) { ConfigValue annotation = field.getAnnotation(ConfigValue.class); if (annotation != null) { String value = props.getProperty(annotation.key()); if (value != null) { field.setAccessible(true); // 类型转换 Object convertedValue = convertValue(value, field.getType()); field.set(instance, convertedValue); } } } return instance; } private static Object convertValue(String value, Class<?> targetType) { if (targetType == String.class) return value; if (targetType == int.class || targetType == Integer.class) return Integer.parseInt(value); if (targetType == boolean.class || targetType == Boolean.class) return Boolean.parseBoolean(value); // 其他类型转换... return value; } }

5.ORM框架

java

复制

下载

// 简易ORM实现 public class SimpleORM { public static <T> T queryOne(Class<T> clazz, String sql, Object... params) throws Exception { // 执行SQL获取ResultSet ResultSet rs = executeQuery(sql, params); if (rs.next()) { T instance = clazz.newInstance(); // 获取ResultSetMetaData ResultSetMetaData metaData = rs.getMetaData(); int columnCount = metaData.getColumnCount(); for (int i = 1; i <= columnCount; i++) { String columnName = metaData.getColumnLabel(i); Object columnValue = rs.getObject(i); // 使用反射设置字段值 Field field = findField(clazz, columnName); if (field != null) { field.setAccessible(true); field.set(instance, columnValue); } } return instance; } return null; } private static Field findField(Class<?> clazz, String columnName) { // 支持驼峰转换:user_name -> userName String fieldName = toCamelCase(columnName); try { return clazz.getDeclaredField(fieldName); } catch (NoSuchFieldException e) { // 查找父类字段 if (clazz.getSuperclass() != null) { return findField(clazz.getSuperclass(), columnName); } return null; } } }

6.插件化系统

java

复制

下载

// 插件接口 interface Plugin { void execute(); String getName(); } // 插件管理器 public class PluginManager { private List<Plugin> plugins = new ArrayList<>(); public void loadPlugins(String pluginDir) throws Exception { File dir = new File(pluginDir); for (File jarFile : dir.listFiles((d, name) -> name.endsWith(".jar"))) { // 创建自定义ClassLoader URLClassLoader loader = new URLClassLoader( new URL[]{jarFile.toURI().toURL()}, getClass().getClassLoader() ); // 读取插件配置 Properties props = new Properties(); try (InputStream is = loader.getResourceAsStream("plugin.properties")) { props.load(is); } String className = props.getProperty("main.class"); if (className != null) { // 加载插件类 Class<?> pluginClass = loader.loadClass(className); // 检查是否实现了Plugin接口 if (Plugin.class.isAssignableFrom(pluginClass)) { Plugin plugin = (Plugin) pluginClass.newInstance(); plugins.add(plugin); } } } } public void executeAll() { for (Plugin plugin : plugins) { plugin.execute(); } } }

7.序列化/反序列化

java

复制

下载

public class JsonSerializer { public static String toJson(Object obj) throws IllegalAccessException { if (obj == null) return "null"; Class<?> clazz = obj.getClass(); // 处理基本类型 if (clazz.isPrimitive() || isWrapperType(clazz)) { return obj.toString(); } // 处理String if (clazz == String.class) { return "\"" + obj + "\""; } // 处理数组 if (clazz.isArray()) { return arrayToJson(obj); } // 处理集合 if (Collection.class.isAssignableFrom(clazz)) { return collectionToJson((Collection<?>) obj); } // 处理Map if (Map.class.isAssignableFrom(clazz)) { return mapToJson((Map<?, ?>) obj); } // 处理普通对象 return objectToJson(obj); } private static String objectToJson(Object obj) throws IllegalAccessException { StringBuilder json = new StringBuilder("{"); Class<?> clazz = obj.getClass(); Field[] fields = clazz.getDeclaredFields(); boolean first = true; for (Field field : fields) { field.setAccessible(true); Object value = field.get(obj); if (value != null) { if (!first) json.append(","); json.append("\"").append(field.getName()).append("\":") .append(toJson(value)); first = false; } } json.append("}"); return json.toString(); } }

四、性能考虑

1.性能对比

java

复制

下载

// 直接调用 vs 反射调用 public class PerformanceTest { private static final int LOOP_COUNT = 1000000; public void directCall() { User user = new User(); for (int i = 0; i < LOOP_COUNT; i++) { user.getName(); // 直接调用 } } public void reflectionCall() throws Exception { User user = new User(); Class<?> clazz = user.getClass(); Method method = clazz.getMethod("getName"); for (int i = 0; i < LOOP_COUNT; i++) { method.invoke(user); // 反射调用 } } public void optimizedReflection() throws Exception { User user = new User(); Class<?> clazz = user.getClass(); Method method = clazz.getMethod("getName"); method.setAccessible(true); // 关闭访问检查 for (int i = 0; i < LOOP_COUNT; i++) { method.invoke(user); } } }

篇幅限制下面就只能给大家展示小册部分内容了。整理了一份核心面试笔记包括了:Java面试、Spring、JVM、MyBatis、Redis、MySQL、并发编程、微服务、Linux、Springboot、SpringCloud、MQ、Kafc

需要全套面试笔记及答案
【点击此处即可/免费获取】​​​

2.性能优化方案

java

复制

下载

// 1. 缓存Class对象和Method对象 class MethodCache { private static final Map<String, Method> METHOD_CACHE = new ConcurrentHashMap<>(); public static Method getMethod(Class<?> clazz, String methodName, Class<?>... paramTypes) throws NoSuchMethodException { String key = clazz.getName() + "#" + methodName; return METHOD_CACHE.computeIfAbsent(key, k -> { try { Method method = clazz.getMethod(methodName, paramTypes); method.setAccessible(true); return method; } catch (Exception e) { throw new RuntimeException(e); } }); } } // 2. 使用MethodHandle(Java 7+) public class MethodHandleExample { public static void main(String[] args) throws Throwable { MethodHandles.Lookup lookup = MethodHandles.lookup(); MethodHandle mh = lookup.findVirtual(String.class, "length", MethodType.methodType(int.class)); String str = "hello"; int length = (int) mh.invokeExact(str); // 性能接近直接调用 } } // 3. 使用Unsafe(不推荐,绕过安全检查) public class UnsafeExample { private static final Unsafe unsafe; private static final long nameOffset; static { try { Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); unsafe = (Unsafe) theUnsafe.get(null); nameOffset = unsafe.objectFieldOffset(User.class.getDeclaredField("name")); } catch (Exception e) { throw new Error(e); } } public static void setUserName(User user, String name) { unsafe.putObject(user, nameOffset, name); } }

五、安全考虑

1.安全管理器

java

复制

下载

// 启用安全管理器限制反射 System.setSecurityManager(new SecurityManager() { @Override public void checkMemberAccess(Class<?> clazz, int which) { // 禁止访问私有成员 if (which == Member.PRIVATE) { throw new SecurityException("Access to private members is not allowed"); } } @Override public void checkPackageAccess(String pkg) { // 禁止访问某些包 if (pkg.startsWith("sun.") || pkg.startsWith("com.sun.")) { throw new SecurityException("Access to " + pkg + " is not allowed"); } } });

2.安全使用建议

java

复制

下载

// 1. 避免过度使用setAccessible(true) Field field = clazz.getDeclaredField("secret"); // field.setAccessible(true); // 谨慎使用 // 2. 限制可反射的类 public class SafeReflection { private static final Set<String> ALLOWED_CLASSES = new HashSet<>( Arrays.asList("com.example.User", "com.example.Product") ); public static Class<?> safeForName(String className) throws ClassNotFoundException { if (!ALLOWED_CLASSES.contains(className)) { throw new SecurityException("Class not allowed: " + className); } return Class.forName(className); } } // 3. 使用MethodHandles.Lookup限制访问 MethodHandles.Lookup lookup = MethodHandles.privateLookupIn( TargetClass.class, MethodHandles.lookup() ); // 只能访问TargetClass的私有成员

六、总结

适用场景:

  1. 框架开发:Spring、MyBatis等

  2. 动态代理:AOP、RPC、事务管理

  3. 注解处理:自定义注解处理器

  4. 配置文件映射:属性文件到对象的映射

  5. ORM框架:数据库结果集到对象的映射

  6. 插件系统:动态加载和执行插件

  7. 序列化:JSON/XML序列化

  8. 测试框架:JUnit的@Test注解处理

  9. 代码生成:动态生成类和方法

不适用场景:

  1. 性能敏感:高频调用的核心业务逻辑

  2. 简单场景:可以直接调用的简单方法

  3. 安全敏感:需要严格控制访问权限的场景

  4. 类型安全要求高:编译时类型检查重要的场景

最佳实践:

  1. 缓存反射对象:Class、Method、Field、Constructor

  2. 最小化setAccessible(true):只在必要时使用

  3. 考虑性能开销:避免在循环中使用反射

  4. 提供安全边界:限制可反射的类和成员

  5. 使用替代方案:考虑MethodHandle、LambdaMetafactory等

  6. 错误处理:妥善处理NoSuchMethodException等异常

反射是Java强大的特性,但也是一把双刃剑。合理使用可以极大提高代码的灵活性和可扩展性,滥用则会导致性能问题和安全隐患。

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

收藏!11种大模型微调方法详解,从LORA到QLORA一篇掌握

这篇文章系统介绍了11种大型语言模型的微调方法&#xff0c;包括前缀调优、提示调优、P-Tuning v2、LORA及其变种(DyLORA、AdaLORA)、QLORA、OA-LOR、LongLORA、VeRA和S-LORA等。这些方法各有特点&#xff0c;旨在提高微调效率、减少参数量和计算资源消耗&#xff0c;同时保持或…

作者头像 李华
网站建设 2026/5/1 17:38:45

算法定义未来:Deepoc-M重构通信技术新生态

当顶尖数学理论与产业应用深度融合&#xff0c;通信行业正在经历一场静默的技术革命在通信技术快速迭代的今天&#xff0c;中小企业往往面临核心技术研发门槛高、创新资源有限的困境。Deepoc-M模型通过将前沿数学理论转化为实用工具&#xff0c;为通信行业特别是中小企业提供了…

作者头像 李华
网站建设 2026/5/1 3:13:05

通过SSH安全连接TensorFlow 2.9容器执行远程训练任务

通过SSH安全连接TensorFlow 2.9容器执行远程训练任务 在深度学习项目日益复杂的今天&#xff0c;开发者常常面临一个现实困境&#xff1a;本地笔记本跑不动大模型&#xff0c;而远程服务器又“环境难配、操作不便、断了就崩”。尤其是在高校实验室或初创团队中&#xff0c;多人…

作者头像 李华
网站建设 2026/5/2 0:02:37

液压冲镦机电气原理图

镦台上料部分 输入 回原点 伺服电机前进 后退 X0 阀门油缸 上升 下降 X1 X2 夹紧松开 气缸 X3 X4 上下限位 X5 X6 高度检测 AD0 急停开关 X10 输出 伺服电机 前进 后退 脉冲 Y0 Y3 阀门 脉冲 Y1 Y4 旋转 脉冲 Y2 Y5 减速电机 Y6 Y7 膨胀轴 Y10 压力速度 DA0 DA1 机械手取料部分…

作者头像 李华
网站建设 2026/4/29 17:20:30

GitHub标签系统整理TensorFlow项目里程碑

GitHub标签系统整理TensorFlow项目里程碑 在AI工程化落地日益深入的今天&#xff0c;一个常见的开发困境始终困扰着团队&#xff1a;为什么同一段代码&#xff0c;在A的机器上能跑通&#xff0c;到了B的环境却报错&#xff1f;问题往往不在于算法本身&#xff0c;而在于“环境差…

作者头像 李华
网站建设 2026/4/22 21:38:48

TensorFlow-v2.9镜像内置了哪些优化过的CUDA驱动?

TensorFlow-v2.9 镜像中的 CUDA 加速体系解析 在现代深度学习工程实践中&#xff0c;一个常见的痛点是&#xff1a;明明买了高性能 GPU&#xff0c;却因为环境配置问题迟迟跑不起训练任务。ImportError: libcudart.so.11.0 not found、UnknownError: Failed to get convolution…

作者头像 李华