< 返回技术文档列表

Java枚举类的使用方法是什么

发布时间:2021-11-07 02:24:36⊙投诉举报

本篇内容介绍了“Java枚举类的使用方法是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

一 枚举类有哪些特点

创建一个ColorEnum的枚举类,通过编译,再反编译看看它发生了哪些变化。

public enum ColorEnum {     RED,GREEN,BULE; }

使用命令javac ColorEnum.java进行编译生成class文件,然后再用命令javap -p  ColorEnum.class进行反编译。

Java枚举类的使用方法是什么

去掉包名,反编译后的内容如下:

public final class ColorEnum extends Enum{     public static final ColorEnum GREEN;     public static final ColorEnum BULE;     private static final ColorEnum[] $VALUES;     public static ColorEnum[] values();     public static ColorEnum valueOf(java.lang.String);     private ColorEnum();     static {}; }
  1. 枚举类被final修饰,因此枚举类不能被继承;

  2. 枚举类默认继承了Enum类,java不支持多继承,因此枚举类不能继承其他类;

  3. 枚举类的构造器是private修饰的,因此其他类不能通过构造器来获取对象;

  4. 枚举类的成员变量是static修饰的,可以用类名.变量来获取对象;

  5. values()方法是获取所有的枚举实例;

  6. valueOf(java.lang.String)是根据名称获取对应的实例;

二 枚举创建线程安全的单例模式

public enum  SingletonEnum {      INSTANCE;      public void doSomething(){         // dosomething...     } }

这样一个单例模式就创建好了,通过SingletonEnum.INSTANCE来获取对象就可以了。

2.1 序列化造成单例模式不安全

一个类如果如果实现了序列化接口,则可能破坏单例。每次反序列化一个序列化的一个实例对象都会创建一个新的实例。

枚举序列化是由JVM保证的,每一个枚举类型和定义的枚举变量在JVM中都是唯一的,在枚举类型的序列化和反序列化上,Java做了特殊的规定:在序列化时Java仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。同时,编译器是不允许任何对这种序列化机制的定制的并禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,从而保证了枚举实例的唯一性。

2.2 反射造成单例模式不安全

通过反射强行调用私有构造器来生成实例对象,造成单例模式不安全。

Class<?> aClass = Class.forName("xx.xx.xx"); Constructor<?> constructor = aClass.getDeclaredConstructor(String.class); SingletonEnum singleton = (SingletonEnum) constructor.newInstance("Java旅途");

但是使用枚举创建的单例完全不用考虑这个问题,来看看newInstance的源码!

public T newInstance(Object ... initargs)     throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {     if (!override) {         if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) {             Class<?> caller = Reflection.getCallerClass();             checkAccess(caller, clazz, null, modifiers);         }     }     // 如果是枚举类型,直接抛出异常,不让创建实例对象!     if ((clazz.getModifiers() & Modifier.ENUM) != 0)         throw new IllegalArgumentException("Cannot reflectively create enum objects");     ConstructorAccessor ca = constructorAccessor;   // read volatile     if (ca == null) {         ca = acquireConstructorAccessor();     }     @SuppressWarnings("unchecked")     T inst = (T) ca.newInstance(initargs);     return inst; }

如果是enum类型,则直接抛出异常Cannot reflectively create enum objects,无法通过反射创建实例对象!

三 通过枚举消除if/else

假如要写一套加密接口,分别给小程序、app和web端来使用,但是这三种客户端的加密方式不一样。一般情况下我们会传一个类型type来判断来源,然后调用对应的解密方法即可。代码如下:

if("WEIXIN".equals(type)){     // dosomething }else if("APP".equals(type)){     // dosomething }else if("WEB".equals(type)){     // dosomething }

现在使用枚举来消除这些if/else。

写一个加密用的接口,有加密和解密两个方法。然后用不同的算法去实现这个接口完成加解密。

public interface Util {      // 解密     String decrypt();      // 加密     String encrypt(); }

创建一个枚举类来实现这个接口

public enum UtilEnum implements Util {      WEIXIN {         @Override         public String decrypt() {             return "微信解密";         }          @Override         public String encrypt() {             return "微信加密";         }     },     APP {         @Override         public String decrypt() {             return "app解密";         }          @Override         public String encrypt() {             return "app加密";         }     },     WEB {         @Override         public String decrypt() {             return "web解密";         }          @Override         public String encrypt() {             return "web加密";         }     }; }

最后,获取到type后,直接调用解密方法就行了。

String decryptMessage = UtilEnum.valueOf(type).decrypt();

以后,如果新增了一个其他加密方式,只需要修改上面的枚举类就完成了,业务代码都不需要改动。

这就是枚举类比较高级的两个用法。

“Java枚举类的使用方法是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注血鸟云网站,小编将为大家输出更多高质量的实用文章!


/template/Home/Zkeys/PC/Static