I understand Enum
is Serializable. Hence, it is safe to do so. (selectedCountry is enum Country
)
public enum Country { Australia, Austria, UnitedState; }
@Override public void onActivityCreated (Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (savedInstanceState != null) { selectedCountry = (Country)savedInstanceState.getSerializable(SELECTED_COUNTRY_KEY); } } @Override public void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putSerializable(SELECTED_COUNTRY_KEY, selectedCountry); }
However, what if I have non-serializable members in custom enum class? For instance,
package org.yccheok; import org.yccheok.R; /** * * @author yccheok */ public enum Country { Australia(R.drawable.flag_au), Austria(R.drawable.flag_at), UnitedState(R.drawable.flag_us); Country(int icon) { this.icon = icon; nonSerializableClass = new NonSerializableClass(this.toString()); } public int getIcon() { return icon; } public static class NonSerializableClass { public NonSerializableClass(String dummy) { this.dummy = dummy; } public String dummy; } private final int icon; public NonSerializableClass nonSerializableClass; }
I tested. It works. (I tested by printing out all the value of member variables before and after serialization. They are same before and after)
However, I do not understand why it works? As I do not provide proper readObject
and writeObject
, as required by Serializable
interface.
As pointed in Effective Java Item 75: Consider using a custom serialized form, do I need to provide my own readObject
and writeObject
, if I have custom member variables in my enum?
Because enums are automatically Serializable (see Javadoc API documentation for Enum), there is no need to explicitly add the "implements Serializable" clause following the enum declaration. Once this is removed, the import statement for the java. io.
In C#, JSON serialization very often needs to deal with enum objects. By default, enums are serialized in their integer form. This often causes a lack of interoperability with consumer applications because they need prior knowledge of what those numbers actually mean.
There are two ways for making comparison of enum members : equals method uses == operator internally to check if two enum are equal. This means, You can compare Enum using both == and equals method.
equals() method. equals() method returns true if the specified object is equal to this enum constant. Using == operator. The == operator checks the type and makes a null-safe comparison of the same type of enum constants.
The reason it works is that serialization process for Enum
's is different from serialization process for other classes. From the official documentation:
1.12 Serialization of Enum Constants
Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream.
That means, all your custom fields won't be serialized. In your case everything works well because your application process is still running and you are getting the same Enum
instance that you passed to savedInstanceState.putSerializable
.
But imagine a situation where your app get killed because Android
has not enough memory. The next time user opens the app you will get a new Enum
instance and all custom fields will have been lost and reinitialized by the constructor. Thus, mutable fields in an enum are always effectively transient
.
As per Serializable documentation, readObject
and writeObject
are not needed at all, so your question might be not fully correct.
Serializable
is a marker interface and doesn't have any methods.
I refer you to this answer which provides additional details about the Serialization implementation (which explains why you don't necessary need write and read functions).
And, as mentioned here by Dianne Hackborn, Parcelable is much more efficient for Android.
If you're particularly interested in Enum, refer to below paragraph:
1.12 Serialization of Enum Constants
Enum constants are serialized differently than ordinary serializable or externalizable objects. The serialized form of an enum constant consists solely of its name; field values of the constant are not present in the form. To serialize an enum constant, ObjectOutputStream writes the value returned by the enum constant's name method. To deserialize an enum constant, ObjectInputStream reads the constant name from the stream; the deserialized constant is then obtained by calling the java.lang.Enum.valueOf method, passing the constant's enum type along with the received constant name as arguments. Like other serializable or externalizable objects, enum constants can function as the targets of back references appearing subsequently in the serialization stream.
The process by which enum constants are serialized cannot be customized: any class-specific writeObject, readObject, readObjectNoData, writeReplace, and readResolve methods defined by enum types are ignored during serialization and deserialization. Similarly, any serialPersistentFields or serialVersionUID field declarations are also ignored--all enum types have a fixed serialVersionUID of 0L. Documenting serializable fields and data for enum types is unnecessary, since there is no variation in the type of data sent.
So, I don't think that the Enum
is the right choice to test internal non-serializable classes work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With