仿写Spring——能够防御反射和序列化的IOC单例模式容器载体

饿汉式枚举封装的单例模式

!!!反射和序列化攻击无法穿透枚举内部,因为枚举的构造函数在类加载时就创建好了。即EnumStarvingSingleton只有一份。

public class EnumStarvingSingleton {
    private EnumStarvingSingleton(){}

    public static EnumStarvingSingleton getInstance(){
        return ContainerHolder.HOLDER.instance;
    }

    private enum ContainerHolder{
        HOLDER;
        private EnumStarvingSingleton instance;
        ContainerHolder(){
            instance = new EnumStarvingSingleton();
        }
    }
}

解释:

这段代码实现了单例模式的一种变体,称为枚举式单例模式(Enum Singleton)。让我详细解释一下代码的每个部分:

EnumStarvingSingleton 类:

这是一个普通的 Java 类,它私有化了构造函数,这意味着其他类无法直接实例化该类的对象。
它提供了一个静态的 getInstance() 方法,用于获取单例对象的实例。
ContainerHolder 枚举类型:

这是一个内部枚举类型,它定义了一个枚举常量 HOLDER。
在枚举类型中,HOLDER 被实例化为 EnumStarvingSingleton 类的一个实例。
枚举类型的特性确保了在类加载的时候就会初始化 HOLDER 常量。
实现原理:

在 Java 中,枚举类型的实例是在类加载阶段被创建的,并且是线程安全的。
当 EnumStarvingSingleton 类被加载时,ContainerHolder.HOLDER 实例会被创建,从而实例化了 EnumStarvingSingleton 类的单例对象。
由于枚举类型的特性,枚举实例的初始化在类加载时就会完成,保证了实例的唯一性和线程安全性。
getInstance() 方法直接返回 ContainerHolder.HOLDER.instance,获取的是单例对象的唯一实例。
总体来说,这种枚举式单例模式简洁、高效且线程安全,是实现单例模式的推荐方式之一。

ContainerHolder() 是枚举类型 ContainerHolder 的构造函数。在枚举中,每个枚举常量都可以有自己的构造函数。在这种情况下,枚举常量 HOLDER 的构造函数被调用时会创建单例对象 EnumStarvingSingleton 的实例,并将其赋值给 instance 属性。这样,在枚举类被加载的时候,就会创建单例对象的实例,实现了线程安全的单例模式。

枚举复习

枚举(Enum)是一种特殊的数据类型,用于定义一组命名的常量。在许多编程语言中,枚举类型是一种基本数据类型,用于表示一组固定的常量值。

在Java中,枚举是一种类,定义了一组预定义的常量对象。它可以帮助提高代码的可读性,使代码更加清晰和易于理解。以下是枚举的一些重要特性和用法:

定义枚举类型: 在Java中,可以使用 enum 关键字来定义枚举类型。例如:

enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

枚举常量: 枚举类型中的每个值都是一个枚举常量,它们是在枚举类型的内部定义的,以逗号分隔。

枚举构造函数: 枚举类型可以有构造函数、方法和字段。每个枚举常量都会调用构造函数,并且可以使用构造函数初始化常量的属性。

访问枚举常量: 可以通过枚举常量的名称来访问它们。

Day today = Day.MONDAY;

枚举方法: 可以向枚举类型添加方法,以便在枚举常量上执行操作。

enum Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY;

    public boolean isWeekend() {
        return this == SATURDAY || this == SUNDAY;
    }
}

switch语句中的枚举: 枚举类型非常适合在 switch 语句中使用,因为它们提供了对常量的类型安全性检查。

Day today = Day.MONDAY;
switch (today) {
    case MONDAY:
        System.out.println("It's Monday");
        break;
    case TUESDAY:
        System.out.println("It's Tuesday");
        break;
    // 其他枚举常量的情况...
}

总的来说,枚举提供了一种在代码中定义和使用一组常量的简洁、类型安全和易读的方式。

  • 25
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值