在一個java語言群裡面,有人抛了這麼一段代碼出來,問題是出現了下下圖中的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);
}
}
是不是會好一點,業務也更聚焦一點,從雞毛蒜皮的重複中解脫出來了?
點選關注,第一時間了解華為雲新鮮技術~