首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java从入门到“放弃”(精通)之旅——反射、枚举与Lambda

Java从入门到“放弃”(精通)之旅——反射、枚举与Lambda

作者头像
想不明白的过度思考者
发布2025-10-29 16:12:48
发布2025-10-29 16:12:48
990
举报
文章被收录于专栏:OverThinker的专栏OverThinker的专栏

一、反射:Java的“照妖镜”🔍

1.1 什么是反射?

想象一下,你正在参加一个化妆舞会,每个人都戴着面具。突然,你掏出一面“照妖镜”(反射),不仅能看穿对方的面具(私有属性),还能让对方即兴跳支舞(调用私有方法)。这就是Java反射——在运行时窥探和操作类的私密信息

1.2 反射的“武器库”

反射四大金刚:

类名

用途

Class

代表类的实体(一切起点)

Field

操作属性(甚至私有)

Method

调用方法(包括私有的)

Constructor

调用构造方法(偷偷new对象)

1.3 获取Class对象的三种姿势
代码语言:javascript
复制
// 1. 通过对象getClass()(最直白)
Student s1 = new Student();
Class c1 = s1.getClass();

// 2. 通过类名.class(最安全)
Class c2 = Student.class;

// 3. 通过Class.forName()(最常用,但容易翻车)
Class c3 = Class.forName("com.example.Student"); // 注意全限定名!

💡冷知识:一个类在JVM中只有一个Class实例,所以c1==c2==c3都是true

1.4 反射实战:偷看私有日记📖
代码语言:javascript
复制
public class ReflectClassDemo {
    // 1. 反射创建对象(无参构造)
    public static void reflectNewInstance() {
        try {
            Class<?> clazz = Class.forName("Student");
            Student student = (Student) clazz.newInstance(); // 相当于new Student()
            System.out.println("反射创建对象: " + student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 2. 反射私有构造方法(带参数)
    public static void reflectPrivateConstructor() {
        try {
            Class<?> clazz = Class.forName("Student");
            Constructor<?> constructor = clazz.getDeclaredConstructor(String.class, int.class);
            constructor.setAccessible(true); // 关键!突破私有限制
            Student student = (Student) constructor.newInstance("高博", 15);
            System.out.println("反射私有构造: " + student);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 3. 反射私有属性(修改name)
    public static void reflectPrivateField() {
        try {
            Class<?> clazz = Class.forName("Student");
            Field field = clazz.getDeclaredField("name");
            field.setAccessible(true); // 再次突破限制
            Student student = (Student) clazz.newInstance();
            field.set(student, "小明"); // 偷偷改名字
            System.out.println("修改后的name: " + field.get(student));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // 4. 反射私有方法(调用function)
    public static void reflectPrivateMethod() {
        try {
            Class<?> clazz = Class.forName("Student");
            Method method = clazz.getDeclaredMethod("function", String.class);
            method.setAccessible(true); // 继续突破
            Student student = (Student) clazz.newInstance();
            method.invoke(student, "我是参数"); // 偷偷调用方法
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

⚠️警告:反射虽好,可不要滥用哦!否则你的代码会变成“蜘蛛网”,维护起来想哭。


二、枚举:Java的“选择题”🔘

2.1 为什么需要枚举?

以前定义常量:

代码语言:javascript
复制
public static final int RED = 1;
public static final int GREEN = 2;
public static final int BLACK = 3;

问题:

  • 容易混淆(1是RED还是ERROR?)
  • 没有类型安全(你可以把1赋值给任何int)

枚举来了!

代码语言:javascript
复制
public enum Color {
    RED, GREEN, BLACK, WHITE;
}

现在Color.RED是一个类型安全的常量,再也不会和1搞混了!

2.2 枚举的高级玩法(带参数的枚举)
代码语言:javascript
复制
public enum Color {
    RED("红色", 1), GREEN("绿色", 2), BLACK("黑色", 3), WHITE("白色", 4);

    private String name;
    private int key;

    // 枚举构造默认是私有的!
    private Color(String name, int key) {
        this.name = name;
        this.key = key;
    }

    public static Color getByKey(int key) {
        for (Color color : values()) {
            if (color.key == key) {
                return color;
            }
        }
        return null;
    }
}
2.3 枚举与反射的“爱恨情仇”

尝试用反射创建枚举实例:

代码语言:javascript
复制
public static void reflectPrivateConstructor() {
    try {
        Class<?> clazz = Class.forName("Color");
        Constructor<?> constructor = 
            clazz.getDeclaredConstructor(String.class, int.class, String.class, int.class);
        constructor.setAccessible(true);
        Object object = constructor.newInstance("父类参数", 666, "子类参数", 888);
        Color color = (Color) object;
        System.out.println("反射创建枚举: " + color);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出:

代码语言:javascript
复制
java.lang.IllegalArgumentException: Cannot reflectively create enum objects

结论:枚举防反射!这是Java专门设计的安全机制。所以枚举实现单例模式是安全的(阿里面试题哦!)。


三、Lambda表达式:Java的“瘦身教练”💃

3.1 什么是Lambda?

以前写匿名内部类:

代码语言:javascript
复制
Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello");
    }
};

现在:

代码语言:javascript
复制
Runnable r = () -> System.out.println("Hello");

从“臃肿大叔”变身“精神小伙”!

3.2 函数式接口(Lambda的前提)

只有一个抽象方法的接口就是函数式接口。可以用@FunctionalInterface注解标记。

代码语言:javascript
复制
@FunctionalInterface
interface NoParameterNoReturn {
    void test();
    // 可以有默认方法
    default void test2() {
        System.out.println("我是默认方法");
    }
}
3.3 Lambda语法精简规则
  1. 参数类型可省略
  2. 只有一个参数时,()可省略
  3. 方法体只有一句时,{}可省略
  4. 有返回值且只有一句时,return可省略

示例:

代码语言:javascript
复制
// 1. 无参无返回值
NoParameterNoReturn () -> System.out.println("Hello");

// 2. 有参无返回值
OneParameterNoReturn a -> System.out.println(a);

// 3. 有参有返回值
MoreParameterReturn (a, b) -> a + b; // 自动return
3.4 Lambda在集合中的应用
forEach遍历:
代码语言:javascript
复制
List<String> list = Arrays.asList("Hello", "bit", "Lambda");
list.forEach(s -> System.out.println(s));
sort排序:
代码语言:javascript
复制
list.sort((s1, s2) -> s1.length() - s2.length());
Map遍历:
代码语言:javascript
复制
Map<Integer, String> map = new HashMap<>();
map.put(1, "Hello");
map.put(2, "Lambda");
map.forEach((k, v) -> System.out.println(k + "=" + v));
3.5 变量捕获(Lambda的“闭包”)

Lambda只能捕获final或等效final的局部变量。

代码语言:javascript
复制
int a = 10;
NoParameterNoReturn r = () -> {
    // a = 20; // 错误!不能修改捕获的变量
    System.out.println(a); // 可以读取
};

四、总结:三剑客的优缺点

技术

优点

缺点

反射

动态、灵活、框架基石

性能低、代码复杂、不安全

枚举

安全、清晰、防反射

不可继承、扩展性差

Lambda

代码简洁、函数式编程、并行友好

可读性差、调试困难


五、彩蛋:单例模式大PK

5.1 静态内部类实现
代码语言:javascript
复制
class Singleton {
    private Singleton() {}
    private static class Holder {
        private static final Singleton INSTANCE = new Singleton();
    }
    public static Singleton getInstance() {
        return Holder.INSTANCE;
    }
}
5.2 枚举实现(最安全!)
代码语言:javascript
复制
public enum Singleton {
    INSTANCE;
    public void doSomething() {
        System.out.println("我是单例!");
    }
}
// 使用:Singleton.INSTANCE.doSomething();

最后提醒:

  • 反射要用在正道(框架、工具),别偷看别人隐私!
  • 枚举是单例的最佳选择,安全又省心。
  • Lambda能让代码变帅,但别写得太抽象,否则同事会打你。

致谢:感谢Java设计者给了我们这么多好玩的东西,也感谢各位佬们的关注和支持,点个赞再走吧😊。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-09-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、反射:Java的“照妖镜”🔍
    • 1.1 什么是反射?
    • 1.2 反射的“武器库”
    • 1.3 获取Class对象的三种姿势
    • 1.4 反射实战:偷看私有日记📖
  • 二、枚举:Java的“选择题”🔘
    • 2.1 为什么需要枚举?
    • 2.2 枚举的高级玩法(带参数的枚举)
    • 2.3 枚举与反射的“爱恨情仇”
  • 三、Lambda表达式:Java的“瘦身教练”💃
    • 3.1 什么是Lambda?
    • 3.2 函数式接口(Lambda的前提)
    • 3.3 Lambda语法精简规则
    • 3.4 Lambda在集合中的应用
      • forEach遍历:
      • sort排序:
      • Map遍历:
    • 3.5 变量捕获(Lambda的“闭包”)
  • 四、总结:三剑客的优缺点
  • 五、彩蛋:单例模式大PK
    • 5.1 静态内部类实现
    • 5.2 枚举实现(最安全!)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档