自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Coder,我懷疑你并不會(huì)枚舉

開發(fā) 后端
關(guān)于枚舉,阿里巴巴開發(fā)手冊(cè)有這樣兩條建議:枚舉類名帶上 Enum 后綴,枚舉成員名稱需要全大寫,單詞間用下劃線隔開。

[[337601]]

枚舉是JDK1.5引入的新特性。被enum關(guān)鍵字修飾的類就是一個(gè)枚舉類。

關(guān)于枚舉,阿里巴巴開發(fā)手冊(cè)有這樣兩條建議:

枚舉類名帶上 Enum 后綴,枚舉成員名稱需要全大寫,單詞間用下劃線隔開。

如果變量值僅在一個(gè)固定范圍內(nèi)變化用 enum 類型來(lái)定義。

一 枚舉類有哪些特點(diǎn)

創(chuàng)建一個(gè)ColorEnum的枚舉類,通過(guò)編譯,再反編譯看看它發(fā)生了哪些變化。

  1. public enum ColorEnum { 
  2.     RED,GREEN,BULE; 

使用命令javac ColorEnum.java進(jìn)行編譯生成class文件,然后再用命令javap -p ColorEnum.class進(jìn)行反編譯。

 

去掉包名,反編譯后的內(nèi)容如下:

  1. public final class ColorEnum extends Enum{ 
  2.     public static final ColorEnum GREEN; 
  3.     public static final ColorEnum BULE; 
  4.     private static final ColorEnum[] $VALUES
  5.     public static ColorEnum[] values(); 
  6.     public static ColorEnum valueOf(java.lang.String); 
  7.     private ColorEnum(); 
  8.     static {}; 
  1. 枚舉類被final修飾,因此枚舉類不能被繼承;
  2. 枚舉類默認(rèn)繼承了Enum類,java不支持多繼承,因此枚舉類不能繼承其他類;
  3. 枚舉類的構(gòu)造器是private修飾的,因此其他類不能通過(guò)構(gòu)造器來(lái)獲取對(duì)象;
  4. 枚舉類的成員變量是static修飾的,可以用類名.變量來(lái)獲取對(duì)象;
  5. values()方法是獲取所有的枚舉實(shí)例;
  6. valueOf(java.lang.String)是根據(jù)名稱獲取對(duì)應(yīng)的實(shí)例;

二 枚舉創(chuàng)建線程安全的單例模式

  1. public enum  SingletonEnum { 
  2.  
  3.     INSTANCE; 
  4.  
  5.     public void doSomething(){ 
  6.         // dosomething... 
  7.     } 

這樣一個(gè)單例模式就創(chuàng)建好了,通過(guò)SingletonEnum.INSTANCE來(lái)獲取對(duì)象就可以了。

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

一個(gè)類如果如果實(shí)現(xiàn)了序列化接口,則可能破壞單例。每次反序列化一個(gè)序列化的一個(gè)實(shí)例對(duì)象都會(huì)創(chuàng)建一個(gè)新的實(shí)例。

枚舉序列化是由JVM保證的,每一個(gè)枚舉類型和定義的枚舉變量在JVM中都是唯一的,在枚舉類型的序列化和反序列化上,Java做了特殊的規(guī)定:在序列化時(shí)Java僅僅是將枚舉對(duì)象的name屬性輸出到結(jié)果中,反序列化的時(shí)候則是通過(guò)java.lang.Enum的valueOf方法來(lái)根據(jù)名字查找枚舉對(duì)象。同時(shí),編譯器是不允許任何對(duì)這種序列化機(jī)制的定制的并禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法,從而保證了枚舉實(shí)例的唯一性。

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

通過(guò)反射強(qiáng)行調(diào)用私有構(gòu)造器來(lái)生成實(shí)例對(duì)象,造成單例模式不安全。

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

但是使用枚舉創(chuàng)建的單例完全不用考慮這個(gè)問題,來(lái)看看newInstance的源碼!

  1. public T newInstance(Object ... initargs) 
  2.     throws InstantiationException, IllegalAccessException, 
  3. IllegalArgumentException, InvocationTargetException 
  4.     if (!override) { 
  5.         if (!Reflection.quickCheckMemberAccess(clazz, modifiers)) { 
  6.             Class<?> caller = Reflection.getCallerClass(); 
  7.             checkAccess(caller, clazz, null, modifiers); 
  8.         } 
  9.     } 
  10.     // 如果是枚舉類型,直接拋出異常,不讓創(chuàng)建實(shí)例對(duì)象! 
  11.     if ((clazz.getModifiers() & Modifier.ENUM) != 0) 
  12.         throw new IllegalArgumentException("Cannot reflectively create enum objects"); 
  13.     ConstructorAccessor ca = constructorAccessor;   // read volatile 
  14.     if (ca == null) { 
  15.         ca = acquireConstructorAccessor(); 
  16.     } 
  17.     @SuppressWarnings("unchecked"
  18.     T inst = (T) ca.newInstance(initargs); 
  19.     return inst; 

如果是enum類型,則直接拋出異常Cannot reflectively create enum objects,無(wú)法通過(guò)反射創(chuàng)建實(shí)例對(duì)象!

三 通過(guò)枚舉消除if/else

假如要寫一套加密接口,分別給小程序、app和web端來(lái)使用,但是這三種客戶端的加密方式不一樣。一般情況下我們會(huì)傳一個(gè)類型type來(lái)判斷來(lái)源,然后調(diào)用對(duì)應(yīng)的解密方法即可。代碼如下:

  1. if("WEIXIN".equals(type)){ 
  2.     // dosomething 
  3. }else if("APP".equals(type)){ 
  4.     // dosomething 
  5. }else if("WEB".equals(type)){ 
  6.     // dosomething 

現(xiàn)在使用枚舉來(lái)消除這些if/else。

寫一個(gè)加密用的接口,有加密和解密兩個(gè)方法。然后用不同的算法去實(shí)現(xiàn)這個(gè)接口完成加解密。

  1. public interface Util { 
  2.  
  3.     // 解密 
  4.     String decrypt(); 
  5.  
  6.     // 加密 
  7.     String encrypt(); 

創(chuàng)建一個(gè)枚舉類來(lái)實(shí)現(xiàn)這個(gè)接口

  1. public enum UtilEnum implements Util { 
  2.  
  3.     WEIXIN { 
  4.         @Override 
  5.         public String decrypt() { 
  6.             return "微信解密"
  7.         } 
  8.  
  9.         @Override 
  10.         public String encrypt() { 
  11.             return "微信加密"
  12.         } 
  13.     }, 
  14.     APP { 
  15.         @Override 
  16.         public String decrypt() { 
  17.             return "app解密"
  18.         } 
  19.  
  20.         @Override 
  21.         public String encrypt() { 
  22.             return "app加密"
  23.         } 
  24.     }, 
  25.     WEB { 
  26.         @Override 
  27.         public String decrypt() { 
  28.             return "web解密"
  29.         } 
  30.  
  31.         @Override 
  32.         public String encrypt() { 
  33.             return "web加密"
  34.         } 
  35.     }; 

最后,獲取到type后,直接調(diào)用解密方法就行了。

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

以后,如果新增了一個(gè)其他加密方式,只需要修改上面的枚舉類就完成了,業(yè)務(wù)代碼都不需要改動(dòng)。

 

這就是枚舉類比較高級(jí)的兩個(gè)用法。

本文轉(zhuǎn)載自微信公眾號(hào)「Java旅途」,可以通過(guò)以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系Java旅途公眾號(hào)。

 

責(zé)任編輯:武曉燕 來(lái)源: Java旅途
相關(guān)推薦

2018-03-09 12:40:41

內(nèi)存降價(jià)國(guó)產(chǎn)

2019-03-29 15:13:59

數(shù)據(jù)中心Spiceworks服務(wù)器

2016-05-24 11:33:50

網(wǎng)絡(luò)基礎(chǔ)設(shè)施公有云軟件即服務(wù)

2013-05-10 09:17:23

2015-08-13 10:28:29

網(wǎng)絡(luò)詐騙手機(jī)實(shí)名制

2019-01-16 10:40:08

2016-03-03 15:00:50

智能記錄數(shù)據(jù)

2020-05-14 08:59:28

API網(wǎng)關(guān)性能

2020-06-24 09:00:43

分庫(kù)分表MySQL

2021-09-14 09:19:49

一號(hào)多卡手機(jī)卡號(hào)碼

2021-12-31 18:24:45

ThreadLocal數(shù)據(jù)庫(kù)對(duì)象

2017-10-31 10:12:12

無(wú)人駕駛安全性乘客信任

2020-11-01 17:00:04

重載重寫java

2016-04-28 09:36:44

人才教育/華三

2025-04-08 11:30:00

DIM數(shù)據(jù)倉(cāng)庫(kù)架構(gòu)

2019-01-23 11:17:22

電腦程序員工作

2020-06-23 14:09:49

枚舉JDK場(chǎng)景

2024-01-18 00:16:07

2022-08-01 08:17:46

mysqlwindows系統(tǒng)

2019-07-01 14:44:23

Java互聯(lián)網(wǎng)代碼
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)