docs/bugpattern/android/BundleDeserializationCast.md
When a Serializable object is placed in an android.os.Bundle, certain types
whose serialization is handled with custom logic are 'flattened' to their base
types. Casting items retrieved from a bundle with bundle.getSerializable(...)
back to their original types may therefore cause a ClassCastException.
See discussion here.
Casting the result of bundle.getSerializable(...) to any subtype of any of the
following classes is forbidden1:
Map (except HashMap)List (except ArrayList or any Parcelable)SparseArray (except Parcelables)CharSequence (except String or any Parcelable)CharSequence[] (except String[])Note that getSerializable happens to return HashMaps for any Map
implementation or ArrayLists for any List implementation, however, this is
not guaranteed by the API. Therefore, casting to ArrayList or HashMap is
allowed, but it is safer to cast to the base List or Map.
An exception is made for most types if they also implement Parcelable, as they
are handled such that their type is preserved.
In many cases, you may be able to cast your object to its base type without any ill effects if you don't require any features of a specific implementation.
In other cases, there may be an constructor that will create an instance of your type from an instance of the base type (but beware of null results causing IllegalArgumentExceptions!) For example:
TreeMap<K, V> myMap;
Map<K, V> deserialized = (Map<K, V>) myBundle.getSerializable("KEY");
myMap = deserialized == null ? null : new TreeMap<K, V>(deserialized);
If you really need a different workaround, wrapping your object (e.g. of type
MyList) in an arbitrary wrapper class (e.g. MyListHolder) that implements
just Serializable will serialize and deserialize it through the standard
Serializable path and preserve your original type.
Here is a full list of types that are handled specially in the
bundling/parceling serialization/deserialization process, in order of
precedence. If a serialized object inherits from multiple types on this
list, it will be bundled as the first of those types to appear. e.g. if an
object implements both Parcelable and List, it will be serialized as a
Parcelable rather than a List, and its type will be preserved. Note also
that it is okay to cast to String even though it inherits from
CharSequence since String is handled first.
StringIntegerMapBundlePersistableBundleParcelable - Parcelables are handled such that their type is
preserved.ShortLongFloatDoubleBooleanCharSequenceListSparseArrayboolean[]byte[]String[]CharSequence[]IBinderParcelable[]int[]long[]ByteSizeSizeFdouble[]Object[] - Only handles pure Object[], not subtypes.Serializable objects go through the normal serialization
path, types are preserved.