注意由雙大括號匿名類引發的serialVersionUID編譯告警

問題描述

最近版本組織清理編譯告警,其中有這麼一條比較有意思,以前沒見過,拿出來講一說java

serializable class anonymous com.demo.Main$1 has no definition of serialVersionUIDsegmentfault

編譯告警指向了這段代碼: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也須要定義serialVersionUIDget

解決方法

既然是因爲匿名類引發的編譯告警,咱們能夠幹掉匿名類,用靜態域來初始化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);
}

參考資料

  1. 永遠不要使用雙花括號初始化實例,不然就會OOM!
相關文章
相關標籤/搜索