1. 程式人生 > >【面試】列舉相關-這一篇全瞭解

【面試】列舉相關-這一篇全瞭解

什麼是列舉?

解:

連結:Java的列舉型別用法介紹-HollisChuang's Blog

列舉是如何實現的?

解:

參考連結:深度分析Java的列舉型別—-列舉的執行緒安全性及序列化問題-HollisChuang's Blog

Java 列舉類比較用 == 還是 equals,有哪些區別?

解:

java 列舉值比較用 == 和 equals 方法沒啥區別,兩個隨便用都是一樣的效果。因為列舉 Enum 類的 equals 方法預設實現就是通過 == 來比較的;類似的 Enum 的 compareTo 方法比較的是 Enum 的 ordinal 順序大小;類似的還有 Enum 的 name 方法和 toString 方法一樣都返回的是 Enum 的 name 值。

Java 列舉類可以繼承其他類(或實現其他介面)或者被其他類繼承嗎,為什麼?

 解:

列舉類可以實現其他介面但不能繼承其他類,因為所有列舉類在編譯後的位元組碼中都繼承自 java.lang.Enum,而 Java 不支援多繼承,所以列舉類不可以繼承其他類。 列舉類不可以被繼承,因為所有列舉類在編譯後的位元組碼中都是繼承自 java.lang.Enum)的 final class 類,final 的類是不允許被派生繼承的。

Java中的switch是如何對列舉進行支援的?

解:

Java 1.7 之前 switch 引數可用型別為 short、byte、int、char,列舉型別之所以能使用其實是編譯器層面實現的,編譯器會將列舉 switch 轉換為類似 switch(s.ordinal()) { case Status.START.ordinal() } 形式,所以實質還是 int 引數型別,感興趣的可以自己寫個使用列舉的 switch 程式碼然後通過 javap -v 去看下位元組碼就明白了。

請使用列舉實現一個單例。

解:

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

為什麼列舉實現的單例比較受推崇?有哪些好處?

解:

參考:連結:為什麼我牆裂建議大家使用列舉來實現單例。-HollisChuang's Blog

列舉的序列化是如何實現的?為什麼列舉實現的單例不存在可能序列化破壞的問題。

解:

答案可以在Java Object Serialization Specification 中找到答案。其中專門對列舉的序列化做了規定。

大概意思就是:在序列化的時候Java僅僅是將列舉物件的name屬性輸出到結果中,反序列化的時候則是通過java.lang.Enum的valueOf方法來根據名字查詢列舉物件。同時,編譯器是不允許任何對這種序列化機制的定製的,因此禁用了writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。

普通的Java類的反序列化過程中,會通過反射呼叫類的預設建構函式來初始化物件。所以,即使單例中建構函式是私有的,也會被反射給破壞掉。由於反序列化後的物件是重新new出來的,所以這就破壞了單例。

但是,列舉的反序列化並不是通過反射實現的。所以,也就不會發生由於反序列化導致的單例破壞問題。

Java 列舉是如何保證執行緒安全的?

解:

enum反編譯之後 是一個繼承Enum類的public final class類(final保證不能被繼承),類中的屬性和方法都是static的 ,根據類的載入機制可知靜態資源的初始化是執行緒安全的,所以java列舉是執行緒安全的