跳转至

反射的原理?反射创建类实例的三种方式是什么?

一、反射是什么

Java 反射允许程序在运行时获取类信息、调用方法、访问字段,即使编译期不知道类型。

核心类:

  • Class:类的字节码对象。
  • Method:方法。
  • Field:字段。
  • Constructor:构造器。

二、原理

类加载后,JVM 在方法区保存类的元数据(方法表、字段表)。反射通过这些元数据直接操作,绕过编译期的类型检查。

Class<?> cls = Class.forName("com.example.User");
Method m = cls.getMethod("sayHello");
Object obj = cls.newInstance();
m.invoke(obj);

三、创建实例的三种方式

1. Class.newInstance()(已废弃)

Class<?> cls = Class.forName("com.example.User");
Object obj = cls.newInstance();   // 调用无参构造

JDK9 废弃,因为只能调无参构造,异常不友好。

2. Constructor.newInstance()(推荐)

Constructor<?> ctor = Class.forName("com.example.User")
    .getConstructor(String.class, int.class);
Object obj = ctor.newInstance("张三", 18);

可以调任意参数的构造器。

3. Class.forName + newInstance

Object obj = Class.forName("com.example.User").newInstance();

本质和方式 1 一样。

4. (补充)clazz.getDeclaredConstructor().newInstance()

JDK9+ 推荐:

User u = User.class.getDeclaredConstructor().newInstance();

四、反射的优缺点

优点

  • 灵活,框架(Spring、JDBC)必备。
  • 运行时才知道类名。

缺点

  • 性能比直接调用慢(要做安全检查、方法表查找)。
  • 破坏封装(可以访问 private)。
  • 编译期类型检查失效。

五、Spring 怎么优化反射

  • 缓存 Method/Field。
  • setAccessible(true) 关闭安全检查。
  • JIT 会内联反射调用。

高频追问

  • 反射破坏单例:可以 new 私有构造器。
  • 反射和泛型:编译期擦除,运行时拿不到泛型类型。