¿Es personalizado enum Serializable también?

Entiendo que Enum es Serializable. Por lo tanto, es seguro hacerlo. (selectedCountry es enum Country )

Enum original sin variables miembro del cliente

 public enum Country { Australia, Austria, UnitedState; } 

Fragmento

 @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); } 

Sin embargo, ¿qué sucede si tengo miembros no serializables en la clase enum personalizada? Por ejemplo,

Variables originales del cliente enum

 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; } 

Probé. Funciona. (Probé imprimiendo todo el valor de las variables miembro antes y después de la serialización. Son iguales antes y después)

Sin embargo, no entiendo por qué funciona? Como no proporciono readObject y writeObject , como lo requiere la interfaz Serializable .

Como se señala en el elemento efectivo de Java 75: Considere el uso de un formulario serializado personalizado , ¿necesito proporcionar mi propio objeto de readObject y de writeObject , si tengo variables de miembro personalizadas en mi enumeración?

La razón por la que funciona es que el proceso de serialización para Enum es diferente del proceso de serialización para otras clases. De la documentación oficial :

1.12 Serialización de constantes de Enum

Las constantes de Enum se serializan de forma diferente a los objetos serializables o externalizables ordinarios. La forma serializada de una constante enum consiste únicamente en su nombre; los valores de campo de la constante no están presentes en la forma. Para serializar una constante enum, ObjectOutputStream escribe el valor devuelto por el método de nombre de la constante enum. Para deserializar una constante enum, ObjectInputStream lee el nombre constante de la secuencia; la constante deserializada se obtiene llamando al método java.lang.Enum.valueOf, pasando el tipo de enumeración de la constante junto con el nombre de la constante recibida como argumentos. Al igual que otros objetos serializables o externalizables, las constantes enum pueden funcionar como los objectives de las referencias posteriores que aparecen posteriormente en la secuencia de serialización.

Eso significa que todos sus campos personalizados no serán serializados. En su caso, todo funciona bien porque su proceso de solicitud aún se está ejecutando y obtendrá la misma instancia de Enum que pasó a savedInstanceState.putSerializable .

Pero imagine una situación en la que su aplicación muere porque Android no tiene suficiente memoria. La próxima vez que el usuario abra la aplicación, obtendrá una nueva instancia de Enum y todos los campos personalizados se habrán perdido y reiniciado por el constructor. Por lo tanto, los campos mutables en una enumeración son siempre efectivamente transient .

Según la documentación de Serializable , readObject y writeObject no son necesarios en absoluto, por lo que su pregunta podría no ser del todo correcta.

Serializable es una interfaz de marcador y no tiene ningún método.

Lo remito a esta respuesta que proporciona detalles adicionales sobre la implementación de Serialización (lo que explica por qué no es necesario que necesite escribir y leer funciones).

Y, como se menciona aquí por Dianne Hackborn, Parcelable es mucho más eficiente para Android.

Si está particularmente interesado en Enum, consulte el párrafo siguiente :

1.12 Serialización de constantes de Enum

Las constantes de Enum se serializan de forma diferente a los objetos serializables o externalizables ordinarios. La forma serializada de una constante enum consiste únicamente en su nombre; los valores de campo de la constante no están presentes en la forma. Para serializar una constante enum, ObjectOutputStream escribe el valor devuelto por el método de nombre de la constante enum. Para deserializar una constante enum, ObjectInputStream lee el nombre constante de la secuencia; la constante deserializada se obtiene llamando al método java.lang.Enum.valueOf, pasando el tipo de enumeración de la constante junto con el nombre de la constante recibida como argumentos. Al igual que otros objetos serializables o externalizables, las constantes enum pueden funcionar como los objectives de las referencias posteriores que aparecen posteriormente en la secuencia de serialización.

El proceso por el que se serializan las constantes enum no se puede personalizar: cualquier método writeObject específico de clase, readObject, readObjectNoData, writeReplace y readResolve definidos por tipos de enumeración se ignoran durante la serialización y la deserialización. De forma similar, cualquier statement de campo serialPersistentFields o serialVersionUID también se ignora: todos los tipos de enum tienen un ID de serialVersionUID fijo de 0L. No es necesario documentar campos y datos serializables para los tipos enum, ya que no hay variación en el tipo de datos enviados.

Por lo tanto, no creo que el Enum sea ​​la opción correcta para probar el trabajo interno de clases no serializables.

La serialización de los miembros enum no está funcionando. El campo no serializable nunca se serializa cuando se responde @vmironov. Aquí hay una prueba:

 public enum Country { Australia; public static class NonSerializableClass { public NonSerializableClass() {} public String dummy; } public NonSerializableClass nonSerializableClass; } 

El código que escribe la enumeración a la secuencia de serialización:

 public class SerializationTestWrite { public static void main(String[] args) throws Exception{ FileOutputStream f = new FileOutputStream("tmp"); ObjectOutput s = new ObjectOutputStream(f); Country.Australia.nonSerializableClass = new Country.NonSerializableClass(); Country.Australia.nonSerializableClass.dummy = "abc"; s.writeObject(Country.Australia); s.flush(); System.out.println(Country.Australia.nonSerializableClass.dummy); } } 

Al escribir el valor del campo ficticio es: abc

El código que lee la enumeración de la secuencia de serialización:

 public class SerializationTestRead { public static void main(String[] args) throws Exception{ FileInputStream in = new FileInputStream("tmp"); ObjectInputStream so = new ObjectInputStream(in); Country readed = (Country) so.readObject(); System.out.println(readed.nonSerializableClass); } } 

Pero al leer, el valor del campo nonSerializableClass es: nulo