首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android Activity 間傳遞 LinkedHashMap:ClassCastException 根因與三種解決方案

     編輯:程式設計綜合問答

問題重現

// Activity A
LinkedHashMap map = new LinkedHashMap<>();
map.put("key", "value");
Bundle bundle = new Bundle();
bundle.putSerializable("map", map); // LinkedHashMap 實作了 Serializable
Intent intent = new Intent(this, ActivityB.class);
intent.putExtras(bundle);
startActivity(intent);

// Activity B
Bundle bundle = getIntent().getExtras();
// ❌ 拋出 ClassCastException: java.util.HashMap cannot be cast to LinkedHashMap
LinkedHashMap map = (LinkedHashMap) bundle.getSerializable("map");

根因分析

Bundle.putSerializable() 序列化時保留型別,但 getSerializable() 反序列化時,Android 內部預設實例化為 java.util.HashMap(而非 LinkedHashMap),導致強制轉型失敗。這是 Android 框架的已知行為,非 Bug。

方案一:接受 HashMap 再轉換(最簡單)

// Activity B
Map rawMap = (Map) bundle.getSerializable("map");
LinkedHashMap orderedMap = new LinkedHashMap<>(rawMap); // 保留插入順序
// 後續使用 orderedMap

方案二:Parcelable 替代 Serializable(高效能)

自定義 ParcelableMap 封裝 LinkedHashMap,完全掌控反序列化型別:

public class ParcelableMap implements Parcelable {
    private final LinkedHashMap map;
    
    public ParcelableMap(LinkedHashMap map) { this.map = map; }
    
    protected ParcelableMap(Parcel in) {
        int size = in.readInt();
        map = new LinkedHashMap<>(size);
        for (int i = 0; i < size; i++) {
            String key = in.readString();
            Object value = in.readValue(Object.class.getClassLoader());
            map.put(key, value);
        }
    }
    
    public LinkedHashMap getMap() { return map; }
    
    @Override public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(map.size());
        for (Map.Entry e : map.entrySet()) {
            dest.writeString(e.getKey());
            dest.writeValue(e.getValue());
        }
    }
    // CREATOR 略...
}

// 使用
intent.putExtra("map", new ParcelableMap(myLinkedHashMap));
// 取出
LinkedHashMap map = getIntent().getParcelableExtra("map").getMap();

方案三:單例/靜態持有者(大數據、跨進程慎用)

public class DataHolder {
    private static final Map sStore = new LinkedHashMap<>();
    public static void put(String key, Object value) { sStore.put(key, value); }
    public static Object get(String key) { return sStore.remove(key); } // 取完即刪,防洩漏
}

// Activity A
DataHolder.put("my_map_key", myLinkedHashMap);
startActivity(new Intent(this, ActivityB.class));

// Activity B
LinkedHashMap map = (LinkedHashMap) DataHolder.get("my_map_key");

方案選擇建議

場景推薦方案
資料量小(< 50KB)、不追求極致效能方案一:HashMap 轉 LinkedHashMap
高頻跳轉、大資料、追求效能方案二:Parcelable
同一進程、單一流程、資料極大方案三:靜態持有者(注意記憶體洩漏)

補充:Kotlin 簡化寫法

// Activity B (Kotlin)
val rawMap = intent.getSerializableExtra("map") as? Map ?: emptyMap()
val orderedMap = LinkedHashMap(rawMap)
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved