“反射?我会啊!” 真的吗?那你知道Spring为什么能"无中生有"创建对象?为什么JSON能把字符串变成实体类?为什么一个注解就能完成依赖注入?如果这些问题让你哑口无言,那恭喜你——你正在错过编程世界最强大的"魔法"!
今天,我要用最直白的话告诉你反射的真相。不是那种让人昏昏欲睡的八股文,而是能让你立刻上手、面试无敌、同事刮目相看的干货!
反射到底是个什么鬼?
想象一下,你有一个神奇的万能钥匙,能打开任何房门、翻看任何抽屉、甚至能让房间里的东西按你的意愿行动。反射就是程序世界的这把万能钥匙!
反射(Reflection)的本质就是:在程序运行时,动态获取类的信息,并能够操作类的属性、方法,甚至创建对象。
普通情况下,我们写代码是这样的:
// 传统方式:编译时就确定了一切
User user = new User();
user.setName("张三");
String name = user.getName();
但有了反射,我们可以这样:
// 反射方式:运行时动态决定一切
Class<?> clazz = Class.forName("com.example.User");
Object user = clazz.newInstance();
Method setName = clazz.getMethod("setName", String.class);
setName.invoke(user, "张三");
看到区别了吗?传统方式像是按菜谱做菜,每一步都写死了。反射则像是一个万能厨师,能根据食材动态决定做什么菜!
反射的威力有多大?看看这些场景你就懂了
Spring的"黑魔法"
还记得你第一次用Spring时的震撼吗?一个@Autowired
注解,对象就自动注入了。这背后就是反射在发力!
@Service
public class UserService {
@Autowired
private UserRepository userRepository; // 这里怎么自动有值的?
}
Spring容器启动时,通过反射扫描所有类,找到带@Service
、@Component
等注解的类,然后用反射创建实例,再通过反射找到需要注入的字段,最后完成依赖注入。整个过程就像一个高效的工厂流水线,全自动!
JSON序列化的秘密
你有没有好奇过,Jackson、Gson是怎么把一个JSON字符串变成Java对象的?
String json = "{\"name\":\"张三\",\"age\":25}";
User user = objectMapper.readValue(json, User.class);
答案还是反射!JSON库通过反射获取User类的所有字段信息,然后根据JSON中的key-value对,动态调用setter方法或直接设置字段值。就像一个智能翻译官,能把任何"外语"翻译成Java对象!
动态代理的核心
还有我们经常用到的动态代理,比如MyBatis的Mapper接口:
@Mapper
public interface UserMapper {
User findById(Long id);
}
明明只是一个接口,没有实现类,怎么就能执行SQL查询?MyBatis通过反射和动态代理,在运行时生成了实现类!
手把手教你玩转反射
说了这么多理论,来点实战的!我用最简单的例子,让你10分钟就能上手反射。
Java反射完整攻略
先来个简单的用户类:
public class User {
private String name;
private int age;
private String email;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
private void secretMethod() {
System.out.println("这是个私有方法,你居然能调用我!");
}
// getter和setter方法省略...
}
现在,让我们用反射把这个类玩出花来:
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
// 1. 获取Class对象的三种方式
Class<?> clazz1 = User.class; // 方式一
Class<?> clazz2 = new User().getClass(); // 方式二
Class<?> clazz3 = Class.forName("com.example.User"); // 方式三
// 2. 创建对象实例
User user1 = (User) clazz1.newInstance(); // 无参构造器
Constru