實戰案例丨代碼優化:如何去除context中的warning?

在一個java語言羣裏面,有人拋了這麼一段代碼出來,問題是出現了下下圖中的warning,問有什麼好的方法消除java

這種強轉都是由於類型鏈條斷掉了,寫入的時候擦除了類型,讀出來的時候也就只能強轉了,那個instanceof 其實並無幫到什麼忙,無外乎把A異常變成了B異常。編程

最簡單的解決方法也很是直觀,就是加上 @SuppressWarnings("unchecked")。segmentfault

這裏先不談用其餘的方法相對優雅的除掉這個warning,而是看看這段代碼自己的問題。編碼

這是一個context,這種模式就是一個數據容器,啥都能裝,經過編碼的人來保證類型匹配,進去擦除類型,出來補上類型,能不能弄對,全看人。spa

這種模式相似於在其餘的語言裏面就拿個容器類型就開始編程,忽略一切的type信息。設計

咱們應當可以看到幾個問題

1. context裝進去的是有類型化的對象,出來就沒有了,設計上講究封裝性,封裝基本的就要保證對稱,那麼context抹除掉的東西,就應該由他來補上。3d

2. 因爲他沒有補上,因此全部使用的地方本身來補充,代碼其實會產生不少冗餘,考慮到他是一個context,那麼實際上其餘地方必定還有不少處有相似的代碼日誌

3. 這裏模擬的實際上是一個computeIfAbsent的邏輯,若是沒有對象就補一個默認值,而後set進去,借用了isEmpty來婉轉的表達容器裏面沒有這個元素。這裏做者應當對java容器上的computeIfAbsent一類的方法不熟悉,由於兜兜轉轉作的就是這個事情。code

4. 因爲沒有用computeIfAbsent,本身的實現中,不管對象是否存在於context中,都會new一個HashMap出來,這在多數狀況下,都是一個浪費。對象

5. 更不要說,當他發現類型不匹配的時候,僅僅打了一行日誌。 元素沒有推動去,程序也不知道,只有日誌知道了。

下面是一個建議的解決方案

1. context作對稱設計,出來的時候就把類型轉換好,不要讓調用者本身來作。 這樣抑制告警就在一處便可。

2. 實現computeIfAbsent的邏輯封裝,有就返回,沒有就插入一個對象,而後返回對象。 對象的建立是按需的。

context的包裝類樣子以下

public static class SomeClass {
    Map<String, Object> context = new HashMap<>();

    @SuppressWarnings("unchecked")
    public <T> T computeIfAbsent(String key, Supplier<T> defaultGen) {
        return (T) context.computeIfAbsent(key, k -> defaultGen.get());
    }
}

使用者樣子以下

public static class Usage {
    public void test() {
        SomeClass workingClass = new SomeClass();
        Supplier<Integer> wantToAppendItem = () -> 2;

        Map<String, Supplier<Integer>> element = workingClass.computeIfAbsent("my-key", HashMap::new);
        element.put("level2-key", wantToAppendItem);

        Supplier<String> wantToAppendStringItem = () -> "good";
        workingClass.computeIfAbsent("my-str-key", HashMap::new).put("level2-str-key", wantToAppendStringItem);
    }
}

是否是會好一點,業務也更聚焦一點,從雞毛蒜皮的重複中解脫出來了?

點擊關注,第一時間瞭解華爲雲新鮮技術~

相關文章
相關標籤/搜索