天天看點

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

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

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

這種強轉都是因為類型鍊條斷掉了,寫入的時候擦除了類型,讀出來的時候也就隻能強轉了,那個instanceof 其實并沒有幫到什麼忙,無外乎把A異常變成了B異常。

最簡單的解決方法也非常直覺,就是加上 @SuppressWarnings("unchecked")。

這裡先不談用其他的方法相對優雅的除掉這個warning,而是看看這段代碼本身的問題。

這是一個context,這種模式就是一個資料容器,啥都能裝,通過編碼的人來保證類型比對,進去擦除類型,出來補上類型,能不能弄對,全看人。

這種模式類似于在其他的語言裡面就拿個容器類型就開始程式設計,忽略一切的type資訊。

我們應當能夠看到幾個問題

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

2. 由于他沒有補上,是以所有使用的地方自己來補充,代碼其實會産生很多備援,考慮到他是一個context,那麼實際上其他地方一定還有很多處有類似的代碼

3. 這裡模拟的其實是一個computeIfAbsent的邏輯,如果沒有對象就補一個預設值,然後set進去,借用了isEmpty來婉轉的表達容器裡面沒有這個元素。這裡作者應當對java容器上的computeIfAbsent一類的方法不熟悉,因為兜兜轉轉做的就是這個事情。

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);
    }
}      

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

點選關注,第一時間了解華為雲新鮮技術~

繼續閱讀