我遇到了崩潰,僅在我的應用程式中發生過一次,這是由于我嘗試向地圖添加專案時出現 UnsupportedOperationException。對于堆疊跟蹤,似乎實體化了 AbstractMap 而不是 MutableMap。代碼在 kotlin 中:
val productMap: MutableMap<ProductModel, Int> =
binding.myView.getProductMap() as? MutableMap<ProductModel, Int>
?: mutableMapOf()
presenter.getProduct()?.let {
productMap.put(it, 0)
}
可能是 kotlin/java 在幕后做了什么奇怪的事情還是我遺漏了什么?
堆疊跟蹤:
Fatal Exception: java.lang.UnsupportedOperationException
at java.util.AbstractMap.put(AbstractMap.java:218)
at com.package.MyView.method2(MyView.java:108)
at com.package.MyParentView.method1(MyParentView.java:1278)
uj5u.com熱心網友回復:
我不知道這是否是這里發生的情況,但我們不應該像這樣將只讀型別轉換為可變型別。如果回傳型別getProductMap()是Map, notMutableMap那么這可能是有原因的,我們不應該嘗試使用它,因為它是可變的。
例如,buildList(): List實用程式實際上回傳一個實作 的串列MutableList,但實際上是只讀的,并在我們嘗試修改它時拋出例外。類似地,從諸如Collections.unmodifiableMap() 之類的實用程式回傳的集合可以轉換為可變的。
我認為您在這里真正需要做的是在地圖中創建資料的可變副本:
binding.myView.getProductMap().toMutableMap()
或者,如果getProductMap()回傳可為空:
binding.myView.getProductMap()?.toMutableMap() ?: mutableMapOf()
作為旁注,您的代碼對我來說似乎很奇怪。如果源映射是可變的,則它使用源映射的內容,但如果不是,則忽略其內容。
uj5u.com熱心網友回復:
我覺得這里的問題是,MutableMap是一個映射型別:在科特林編譯器知道之間的區別Map和MutableMap,但他們都編譯到java.util.Map在Java *位元組碼。那是因為底層 Java 類不區分可變集合和不可變集合;它們對兩者使用相同的介面,并且不可變的實作只是 throw UnsupportedOperationException。
所以在這種情況下,將as?安全鑄不會做你想要的:它的有效檢查物件只是否是一個Map,不是它是否是可變的。(我不知道 Android,但如果getProductMap()定義為回傳 a Map,那么這歸結為一個簡單的空檢查。)
根據您的需要,有幾種方法可以解決此問題,例如:
如果您碰巧知道您期望的具體的可變型別(例如
ArrayList),那么您可以轉換為該型別。由于ArrayLists 總是可變的,所以 sput()應該是安全的;但它不會提供任何其他型別的地圖。你可以把 困
UnsupportedOperationException在一個try…catch塊中。這將避免錯誤,但如果提供了不可變的映射,則什么也不做。您可以使用
toMutableMap(). 這將始終更新地圖 - 但它可能是視圖未使用的私有地圖。
(* 堆疊跟蹤顯示此問題是關于 Kotlin/JVM。您在其他平臺上可能會得到不同的結果。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/350358.html
