사용자 정의 열거 형도 직렬화 가능합니까?
Enum
직렬화 가능 하다는 것을 이해 합니다. 따라서 그렇게하는 것이 안전합니다. (selectedCountry는 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);
}
그러나 사용자 지정 열거 형 클래스에 직렬화 할 수없는 멤버가있는 경우 어떻게해야합니까? 예를 들어
원래 열거 형 고객 멤버 변수
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;
}
나는 테스트했다. 효과가있다. (직렬화 전후의 모든 멤버 변수 값을 인쇄하여 테스트했습니다. 이전과 이후는 동일합니다.)
그러나 왜 작동하는지 이해하지 못합니까? 인터페이스에서 요구하는대로 적절한 readObject
및을 제공하지 않습니다 .writeObject
Serializable
효과적인 Java 항목 75 : 사용자 정의 직렬화 된 양식을 사용하는 것을 고려하십시오 . 내 열거 형에 사용자 정의 멤버 변수가있는 경우 자체 readObject
및 을 제공해야 writeObject
합니까?
작동하는 이유 Enum
는의 직렬화 프로세스가 다른 클래스의 직렬화 프로세스와 다르기 때문입니다. 로부터 공식 문서 :
1.12 열거 형 상수 직렬화
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 no 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.
The serialization of enum members is not working. The nonSerializable field is never serialized as @vmironov answered. Here is a test:
public enum Country {
Australia;
public static class NonSerializableClass {
public NonSerializableClass() {}
public String dummy;
}
public NonSerializableClass nonSerializableClass;
}
The code writing the enum to the serialization stream:
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);
}
}
On writing the value of the dummy field is: abc
The code reading the enum from the serialization stream:
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);
}
}
But on reading, the value of the field nonSerializableClass
is: null
ReferenceURL : https://stackoverflow.com/questions/15521309/is-custom-enum-serializable-too
'Programing' 카테고리의 다른 글
TypeError : 유니 코드로 강제 변환 : 문자열 또는 버퍼 필요 (0) | 2020.12.31 |
---|---|
Java Set에서 * 모든 * 값을 얻는 좋은 방법은 무엇입니까? (0) | 2020.12.31 |
Spring MVC를 사용하여 생성 된 PDF 반환 (0) | 2020.12.30 |
두 열 테이블에서 두 열에 걸쳐 하나를 만드는 방법은 무엇입니까? (0) | 2020.12.30 |
Python : 디렉토리에서 확장자가 .MP3 인 최신 파일 찾기 (0) | 2020.12.30 |