最近版本組織清理編譯告警,其中有這麼一條比較有意思,以前沒見過,拿出來講一說java
「serializable class anonymous com.demo.Main$1 has no definition of serialVersionUID」segmentfault
編譯告警指向了這段代碼:dom
private static List<String> defaultAttrList = new ArrayList<String>() { { add(ResourceConsts.RES_NAME); add(ResourceConsts.RES_TYPE); add(ResourceConsts.RES_IP); add(ResourceConsts.RES_VERSION); } };
乍一看好像沒什麼問題,我用雙大括號的方式定義並初始化了一個ArrayList
,往裏面塞了幾個值,代碼簡潔易懂。this
但問題並無看起來那麼簡單,緣由就在雙大括號。code
雙大括號的寫法實際上建立了一個匿名類,咱們將源文件編譯後也會發現,生成了一個Main$1.class
的文件,它就對應這個匿名類。反編譯後的代碼以下:繼承
class Main$1 extends ArrayList<String> { Main$1() { this.add("1");// 10 }// 11 }
能夠看到,咱們建立了一個名爲Main$1
的匿名類,繼承自ArrayList
,而ArrayList
的類定義以下:接口
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable { // ...... }
正是由於ArrayList
實現了Serializable
接口,因此Main$1
也須要定義serialVersionUID
。get
既然是因爲匿名類引發的編譯告警,咱們能夠幹掉匿名類,用靜態域來初始化List
,像下面這樣便可消除告警:it
private static List<String> defaultAttrList = new ArrayList<>(); static { defaultAttrList.add(ResourceConsts.RES_NAME); defaultAttrList.add(ResourceConsts.RES_TYPE); defaultAttrList.add(ResourceConsts.RES_IP); defaultAttrList.add(ResourceConsts.RES_VERSION); }