Java枚举的一些易忽视点

1、==和equals方法

枚举相等比较中,==和equals方法没有任何区别,查看源码你会发现,equals方法的实现就是通过==判断的。

2、compareTo方法

Enum类的compareTo方法比较的其实是枚举的顺序大小,所以先定义的枚举项要“小于”后定义的枚举项。

3、枚举是实现单例的最好的方式

采用双重校验锁实现单例模式

public class Singleton {
    private volatile static Singleton singleton;
    private Singleton(){}
    public static Singleton getSingleton() {
        if (singleton == null) {
            synchronized (Singleton.class) {
                if (singleton == null) {
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

“双重锁校验”方式虽然保证了线程安全,但是无法解决反序列化会破坏单例模式的问题。

采用枚举实现单例

public enum Singleton {
    INSTANCE;
    public void whateverMethon() {}
}

枚举可以解决线程安全问题,因此和上面的双重校验锁方式比代码简洁明了。这是因为枚举在反编译后,属性都带有static。static类型的属性会在类加载之后被初始化,当第一个Java类第一次被真正使用时静态资源被初始化,Java类的加载和初始化过程都是线程安全的,因为虚拟机在加载枚举的类时,会使用ClassLoader的loadClass方法,而这个方法使用同步代码保证了线程安全。所以创建一个enum类型时线程安全的。

那为什么说枚举可以解决反序列化会破坏单例模式问题呢?

普通的Java类的反序列化过程中,会通过反射调用类的默认构造函数来初始化对象。所以,即使单例中的构造函数是私有的,也会被反射破坏。由于反序列化后的对象是重新new出来的,所以就破坏了单例模式。而枚举的反序列化并不是通过反射实现的,是通过enmu类中的valueOf方法来根据名字查找对象,所以也就不会发生由于反序列化导致的单例破坏问题了。(每一个枚举项在JVM中都是单例的,因为序列化+反序列化可以破坏单例,所以Java就针对枚举的序列化作出了特殊规定)。

4、接口的返回值中不能使用枚举类型

有A和B两个服务,A提供一个接口给B服务,接口的方法中返回有有个枚举Atype,刚开始这个枚举汇总有2个值enum1和enum2。但是某一天A升级了,返回的枚举中多了enum3,B未升级,在反序列化的过程中使用valueOf方法在枚举类中找enum3,找不到就会抛出IllegalArgumentException异常。

值得注意的是,在代码开发中,可以使用javadoc的@see注解表明这个字符串的取值从哪个枚举中获取。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值