日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

扩展枚举功能的两种方法

發布時間:2023/12/3 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 扩展枚举功能的两种方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在上一篇文章中,我解釋了如何以及為什么在Java代碼中使用enums而不是switch/case控制結構。 在這里,我將展示如何擴展現有enums功能。

介紹

Java enum是一種編譯器魔術。 在字節碼中,任何enum都表示為擴展抽象類java.lang.Enum并具有幾個靜態成員的類。 因此,枚舉不能擴展任何其他類或枚舉:沒有多重繼承。

類也不能擴展枚舉。 此限制由編譯器強制執行。

這是一個簡單的enum :

enum Color {red, green, blue}

此類嘗試擴展它:

SubColor class extends Color {}

這是嘗試編譯類SubColor的結果:

$ javac SubColor.java SubColor.java: 1 : error: cannot inherit from final Color SubColor class extends Color {} ^ SubColor.java: 1 : error: enum types are not extensible SubColor class extends Color {} ^ 2 errors

Enum既不能擴展也不能擴展。 那么,如何擴展其功能呢? 關鍵字是“功能”。 Enum可以實現方法。 例如,枚舉Color可以聲明抽象方法draw() ,每個成員都可以重寫它:

enum Color {red { @Override public void draw() { } },green { @Override public void draw() { } },blue { @Override public void draw() { } },;public abstract void draw(); } 在此說明該技術的流行用法。 不幸的是,不可能總是在枚舉本身中實現方法,因為:
  • 枚舉可能屬于第三方庫或公司中的其他團隊
  • 枚舉可能被過多的其他數據和函數重載,因此變得不可讀
  • 枚舉屬于模塊,該模塊不具有實現方法draw()所需的依賴項。
  • 本文針對此問題提出了以下解決方案。

    鏡像枚舉

    我們不能修改枚舉顏色嗎? 沒問題! 讓我們創建具有與Color完全相同的元素的枚舉DrawableColor。 這個新的枚舉將實現我們的方法draw(): enum DrawableColor {red { @Override public void draw() { } },green { @Override public void draw() { } },blue { @Override public void draw() { } },;public abstract void draw(); }

    這個枚舉是源枚舉Color的一種反映,即Color是它的鏡像 。但是如何使用新的枚舉? 我們所有的代碼都使用Color而不是DrawableColor 。 實現此過渡的最簡單方法是使用內置的枚舉方法name()和valueOf(),如下所示:

    Color color = ... DrawableColor.valueOf(color.name()).draw();

    由于name()方法是最終方法,不能被覆蓋,并且valueOf()由編譯器生成,因此這些方法始終相互配合,因此在此不會出現功能問題。 這種過渡的性能也很好:方法name()甚至不創建新的String而是返回預初始化的String(請參見java.lang.Enum源代碼)。 方法valueOf()是使用Map實現的,因此其復雜度為O(1)。

    上面的代碼包含明顯的問題。 如果更改了源枚舉Color,則輔助枚舉DrawableColor將不知道這一事實,因此具有name()和valueOf()的技巧將在運行時失敗。 我們不希望這種情況發生。 但是如何防止可能的故障?

    我們必須讓DrawableColor知道其鏡像是Color,并且最好在編譯時或至少在單元測試階段強制執行此操作。 在這里,我們建議在單元測試執行期間進行驗證。 Enum可以實現時所執行的靜態初始化enum中的任何代碼被提及。 這實際上意味著,如果靜態初始化程序驗證枚舉DrawableColor是否適合Color,則足以執行以下測試,以確保代碼不會在生產環境中被破壞:

    @Test public void drawableColorFitsMirror {DrawableColor.values(); }

    靜態初始化器只需要比較DrawableColor和Color元素,如果不匹配則拋出異常。 該代碼很簡單,可以針對每種特定情況編寫。 幸運的是,名為enumus的簡單開放源代碼庫已經實現了此功能,因此任務變得微不足道:

    enum DrawableColor {....static {Mirror.of(Color.class);} }

    而已。 如果源枚舉和DrawableColor不再適合,則測試將失敗。 實用程序類Mirror其他方法有2個參數:必須包含2個枚舉的類。 可以從代碼中的任何位置調用此版本,而不僅僅是從必須經過驗證的枚舉中調用。

    枚舉地圖

    我們是否真的必須定義僅包含一種方法的實現的另一個枚舉? 實際上,我們不必這樣做。 這是一個替代解決方案。 讓我們定義接口抽屜如下:

    public interface Drawer {void draw(); }

    現在讓我們在枚舉元素和接口Drawer的實現之間創建映射:

    Map<Color, Drawer> drawers = new EnumMap<>(Color.class) {{put(red, new Drawer() { @Override public void draw();});put(green, new Drawer() { @Override public void draw();})put(blue, new Drawer() { @Override public void draw();}) }}

    用法很簡單:

    drawers.get(color).draw();

    這里選擇EnumMap作為Map實現,以獲得更好的性能。 Map保證每個枚舉元素僅出現一次。 但是,它不能保證每個enum元素都有相應的條目。 但是檢查映射的大小等于enum元素的數量就足夠了:

    drawers.size() == Color.values().length


    枚舉還建議在這種情況下方便實用。 如果地圖不適合Color,則以下代碼將引發IllegalStateException及其描述性消息:

    EnumMapValidator.validateValues(Color. class , map, "Colors map" );

    從單元測試執行的代碼中調用驗證器很重要。 在這種情況下,基于地圖的解決方案對于將來對源枚舉的修改是安全的。

    EnumMap和Java 8功能接口

    實際上,我們不必定義特殊的接口來擴展
    枚舉功能。 從版本8開始,我們可以使用JDK提供的功能接口之一( Function,BiFunction,Consumer,BiConsumer,
    Supplieretc Function,BiFunction,Consumer,BiConsumer,
    Supplieretc Function,BiFunction,Consumer,BiConsumer,
    Supplieretc 。)選擇取決于必須發送給功能的參數。 例如,可以使用Supplier代替上一個示例中定義的Drawable :

    Map<Color, Supplier<Void>> drawers = new EnumMap<>(Color. class ) {{ put(red, new Supplier<Void>() { @Override public void get();}); put(green, new Supplier<Void>() { @Override public void get();}) put(blue, new Supplier<Void>() { @Override public void get();}) }}


    該映射的用法與上一個示例非常相似:

    drawers.get(color).get();

    該地圖可以與存儲以下實例的地圖完全一樣地進行驗證:
    可繪制。

    結論

    本文顯示了如果我們在其中添加一些邏輯,那么Java enums有多么強大。 它還演示了兩種擴展語言enums功能的方法,盡管存在語言限制。 本文向用戶介紹了名為enumus的開放源代碼庫,該庫提供了一些有用的實用程序,可幫助更輕松地操作enums 。

    翻譯自: https://www.javacodegeeks.com/2019/03/two-ways-extend-enum-functionality.html

    總結

    以上是生活随笔為你收集整理的扩展枚举功能的两种方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。