为什么系统会自动将LinkedHashMap转换为HashMap,同时将其作为Serializable传递给Intent?

Sol*_*ace 1 java android classcastexception linkedhashmap android-intent

我正进入(状态

java.lang.ClassCastException: java.util.HashMap cannot be cast to java.util.LinkedHashMap
Run Code Online (Sandbox Code Playgroud)

LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");活动B的代码(相关部分)中.


  1. 在片段A中,我有以下检查:

    Log.i(TAG, "THE TYPE OF THE MAP RETURNED FROM populateSelectedEntryList(selectedResultEntry) IS " + 
    populateSelectedEntryList(selectedResultEntry).getClass().getSimpleName()
    + ".");//******PRINTS LinkedHashMap**********************
    
    Run Code Online (Sandbox Code Playgroud)

打印LinkedHashMap.

  1. 在活动B中,我有以下检查:

    LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>)intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");//**********ClassCastException*****************
    
    Run Code Online (Sandbox Code Playgroud)

    打印HashMap.


问题是为什么?为什么系统将LinkedHashMap转换为HashMap.当作为Serializable在intent中传递LinkedHashMap时,如何强制LinkedHashMap继续成为LinkedHashMap?

相关部分代码:

在片段A中,

public class A extends Fragment {
  ...

  public void onListItemClick(...) { 
    Intent intent = new Intent(getActivity(), B.class);
    ...
    intent.putExtra("tests.test.MyApp.A.EXTRA_KEY", populateSelectedEntryList(selectedResultEntry));
    Log.i(TAG, "THE TYPE OF THE MAP RETURNED FROM populateSelectedEntryList(selectedResultEntry) IS "
 + populateSelectedEntryList(selectedResultEntry).getClass().getSimpleName() + ".");//******PRINTS LinkedHashMap**********************
    startActivity(intent);
  };

  ...

  private LinkedHashMap<String, String> populateSelectedEntryList(MyParser.Entry selectedResultEntry) {
    LinkedHashMap<String, String> selectedEntryMap = new LinkedHashMap<>();
    ...
    return selectedEntryMap;
  }
}
Run Code Online (Sandbox Code Playgroud)

在活动B中,

public class B extends FragmentActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
        ...
        Intent intent = getIntent();
        LinkedHashMap<String, String> dataHashMap = (LinkedHashMap<String, String>) intent.getSerializableExtra("tests.test.MyApp.A.EXTRA_KEY");
  } //**********ClassCastException*****************
  ...
}
Run Code Online (Sandbox Code Playgroud)

Pau*_*ton 5

这里给出了对此的解释:在下一个活动中检索时,置于Intent extra中的LinkedList将重新转换为ArrayList

如果要恢复密钥LinkedListMap密钥顺序不重要的地方,可以使用@schtever的解决方案.如果你想恢复一个LinkedHashMap或一个TreeMap并且键的顺序重要,那就有点棘手了.

一种可能的解决方案是将其转换Map为一对Lists,如下所示:

活动1:

public class Activity1 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
        map.put(1, "ONE");
        map.put(2, "TWO");
        map.put(3, "THREE");

        ArrayList<Integer> keys = new ArrayList<Integer>();
        ArrayList<String> values = new ArrayList<String>();
        for (Map.Entry<Integer, String> entry : map.entrySet()) {
            keys.add(entry.getKey());
            values.add(entry.getValue());
        }

        Intent intent = new Intent(this, Activity2.class);
        intent.putExtra("KEYS", keys);
        intent.putExtra("VALUES", values);

        startActivity(intent);
    }
}
Run Code Online (Sandbox Code Playgroud)

活性2:

public class Activity2 extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Intent intent = getIntent();
        List<Integer> keys = (List<Integer>) intent.getSerializableExtra("KEYS");
        List<String> values = (List<String>) intent.getSerializableExtra("VALUES");

        Map<Integer, String> map = new LinkedHashMap<Integer, String>();
        for (int i = 0, n = keys.size(); i < n; i++)
            map.put(keys.get(i), values.get(i));

        Log.i("Activity2",  "" + map);
    }
}
Run Code Online (Sandbox Code Playgroud)

这有点像黑客,它非常冗长,但它确实有效.我很想知道是否有更好的解决方案.