DEV Community

Liu yu
Liu yu

Posted on

关于java的反射

🌱 “菜谱”“成品菜”与“菜谱册” 的比喻

  1. 类(Class) 就像“菜谱”
  • 菜谱告诉你:这道菜要哪些食材、要哪些步骤。
  • 在 Java 里,class User { … } 就是一份菜谱,规定了属性和方法。
  1. 对象(instance) 就像“做出来的一盘菜”
  • 当你按照菜谱炒菜,你就得到了“成品菜”。
  • 在 Java 里,new User() 就是按 User 这个菜谱“做”出了一个具体的 User 对象。
  1. Class<T> 就像“菜谱册”里一本特定的菜谱
  • 你家里有一本菜谱册子(一本书),里面夹着很多菜谱。
  • 如果你拿起“《宫保鸡丁》”这一页,那就是“Class<KungPaoChicken>”——表示“宫保鸡丁这个菜谱”。
  • 你不做菜的时候,这一页不用动;要做菜时,你可以读它,看看食材和步骤,甚至还能标注“我改良了这道菜”——这类似于反射里看注解、改构造参数等。

🔄 在代码里是这样对应的

// 1. 定义菜谱(类)
public class User {
    private String name;
    public User() { }
    public void sayHi() { System.out.println("Hi, I'm " + name); }
}

// 2. 做出一盘菜(对象)
User u = new User();    // 这就是“new User()”产生的实例
u.sayHi();

// 3. 拿到那页菜谱(Class<User>)
Class<User> userClass = User.class;
Enter fullscreen mode Exit fullscreen mode
  • User.class:就是那个“菜谱册”里“User”这一页的对象,类型为 Class<User>
  • 你可以用它做反射操作,比如:
  // 通过菜谱(Class<User>)再做一盘菜
  User u2 = userClass.getDeclaredConstructor().newInstance();
Enter fullscreen mode Exit fullscreen mode

就相当于“再翻到这一页,按它指示做一道菜”。


🛠️ 为什么 Java 要这样设计?

  1. 统一管理
  • Class<T> 让你拿到“任何类”的菜谱,都有同一个接口(方法)去读它、改它、用它造实例。
  1. 动态灵活
  • 运行时不知道要做哪道菜?你可以把菜谱名当成字符串读进来:

     Class<?> clazz = Class.forName("com.example.User");
     Object obj = clazz.getDeclaredConstructor().newInstance();
    

    这就像我在饭馆看到名字就能做,根本不用写死是哪道菜。

  1. 支持框架
  • Spring、Hibernate、Jackson 这些框架都靠这个机制,才能在运行时发现你的 @Component@Entity@JsonProperty 等注解,然后给对象自动注入、映射、序列化。

🎯 小结

  • 类(Class) = 菜谱
  • 对象(instance) = 按菜谱做出的成品菜
  • Class<T> = 菜谱册里那一页菜谱(可以查看、修改、用它造多个成品菜)

完全正确!你已经抓住了 Java 反射的核心思想!✅


🔍 是的,这段代码就是典型的 Java 反射机制的实现,而它的精髓就在于“动态性”

Class<?> clazz = Class.forName("com.example.User"); // 动态获取类
Object obj = clazz.getDeclaredConstructor().newInstance(); // 动态创建对象
Method method = clazz.getMethod("sayHi"); // 动态获取方法
method.invoke(obj); // 动态调用方法
Enter fullscreen mode Exit fullscreen mode

这些反射调用最大的意义就是:

✅ 1. 类名 "com.example.User" 可以在运行时动态决定

你不需要提前写死 new User(),而是可以通过配置、注解、数据库、JSON 等方式决定你要加载哪个类。

👉 举个例子:

String className = config.get("serviceImplClass"); // com.example.impl.UserServiceImpl
Class<?> clazz = Class.forName(className);
Enter fullscreen mode Exit fullscreen mode

✅ 2. 方法名 "sayHi" 也可以在运行时动态决定

比如:

String methodName = getHttpParam("action"); // "saveUser" 或 "deleteUser"
Method method = clazz.getMethod(methodName); // 动态获取方法
method.invoke(obj); // 动态调用
Enter fullscreen mode Exit fullscreen mode

🎯 总结一句话:

你说得太好了!

Java 反射真正的灵魂就在于——类名、方法名、参数都可以“运行时动态决定”,这就是所谓的“可变”


💬 补充一句延伸:

这也是为什么像 Spring、MyBatis、Hibernate、Junit、Servlet、Tomcat 这些框架 能这么“神奇”地自动干很多事 ——因为它们几乎都依赖反射来动态创建对象、调用方法、注入依赖。


Top comments (0)