java 属性不序列化_怎样对带有不可序列化属性的Java对象进行序列化
原標題:怎樣對帶有不可序列化屬性的Java對象進行序列化
出于很多原因我們想使用自定義的序列化方法取代Java默認的機制。一個最常見的原因是提高性能,而另一個原因是有時候我們無法使用默認的序列化方法。在這篇文章中,我們具體來討論怎樣通過定制的序列化方法,對一個較大的、帶有不可序列化屬性的對象進行序列化。
下面這段代碼定義了一個簡單的類。它可以把一個給定的對象序列化到一個指定的文件,或者從相同的文件中把對象反序列化出來。在這片文章中,我將使用這個類進行演示。
SerializationDemonstrator.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package dustin.examples.serialization;
import static java.lang.System.out;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
* Simple serialization/deserialization demonstrator.
*
* @author Dustin
*/
public class SerializationDemonstrator
{
/**
* Serialize the provided object to the file of the provided name.
* @param objectToSerialize Object that is to be serialized to file; it is
* best that this object have an individually overridden toString()
* implementation as that is used by this method for writing our status.
* @param fileName Name of file to which object is to be serialized.
* @throws IllegalArgumentException Thrown if either provided parameter is null.
*/
public static void serialize(final T objectToSerialize, final String fileName)
{
if (fileName == null)
{
throw new IllegalArgumentException(
"Name of file to which to serialize object to cannot be null.");
}
if (objectToSerialize == null)
{
throw new IllegalArgumentException("Object to be serialized cannot be null.");
}
try (FileOutputStream fos = new FileOutputStream(fileName);
ObjectOutputStream oos = new ObjectOutputStream(fos))
{
oos.writeObject(objectToSerialize);
out.println("Serialization of Object " + objectToSerialize + " completed.");
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
}
/**
* Provides an object deserialized from the file indicated by the provided
* file name.
*
* @param Type of object to be deserialized.
* @param fileToDeserialize Name of file from which object is to be deserialized.
* @param classBeingDeserialized Class definition of object to be deserialized
* from the file of the provided name/path; it is recommended that this
* class define its own toString() implementation as that will be used in
* this method's status output.
* @return Object deserialized from provided filename as an instance of the
* provided class; may be null if something goes wrong with deserialization.
* @throws IllegalArgumentException Thrown if either provided parameter is null.
*/
public static T deserialize(final String fileToDeserialize, final Class classBeingDeserialized)
{
if (fileToDeserialize == null)
{
throw new IllegalArgumentException("Cannot deserialize from a null filename.");
}
if (classBeingDeserialized == null)
{
throw new IllegalArgumentException("Type of class to be deserialized cannot be null.");
}
T objectOut = null;
try (FileInputStream fis = new FileInputStream(fileToDeserialize);
ObjectInputStream ois = new ObjectInputStream(fis))
{
objectOut = (T) ois.readObject();
out.println("Deserialization of Object " + objectOut + " is completed.");
}
catch (IOException | ClassNotFoundException exception)
{
exception.printStackTrace();
}
return objectOut;
}
}
下面這段代碼給出了一個使用SerializationDemonstrator類序列化和反序列化標準的Java字符串的例子。字符串是支持序列化的。代碼之后的截圖顯示了在Netbeans中運行該類的serialize和deserialize方法后的輸出。
Running SerializationDemonstrator Methods on String
1
2
SerializationDemonstrator.serialize("Inspired by Actual Events", "string.dat");
final String stringOut = SerializationDemonstrator.deserialize("string.dat", String.class);
下面這兩段代碼定義了Person和CityState兩個類。CityState是Person的一個屬性。可以看到盡管Person實現了Serializable接口,CityState卻沒有。
Person.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package dustin.examples.serialization;
import java.io.Serializable;
/**
* Person class.
*
* @author Dustin
*/
public class Person implements Serializable
{
private String lastName;
private String firstName;
private CityState cityAndState;
public Person(
final String newLastName, final String newFirstName,
final CityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}
public String getFirstName()
{
return this.firstName;
}
public String getLastName()
{
return this.lastName;
}
@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}
}
CityState.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package dustin.examples.serialization;
/**
* Simple class storing city and state names that is NOT Serializable.
*
* @author Dustin
*/
public class CityState
{
private final String cityName;
private final String stateName;
public CityState(final String newCityName, final String newStateName)
{
this.cityName = newCityName;
this.stateName = newStateName;
}
public String getCityName()
{
return this.cityName;
}
public String getStateName()
{
return this.stateName;
}
@Override
public String toString()
{
return this.cityName + ", " + this.stateName;
}
}
下面這段代碼演示了使用SerializationDemonstrator序列化Person類。由于包含了一個不可序列化的屬性CityState,在之后截圖里,我們可以看到Netbean拋出了異常。
Running SerializationDemonstrator Methods on Serializable Person with Non-Serializable CityState
1
2
3
4
final Person personIn = new Person("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person.dat");
final Person personOut = SerializationDemonstrator.deserialize("person.dat", Person.class);
在這個例子里,由于CityState類是我們自己寫的,我們可以使它支持序列化。但是如果這個類屬于一個第三方的框架或者庫,我們就很難去修改這個類。但是我們可以修改Person類,通過使用自定義的序列化和反序列化方法,使它和CityState類一起正常工作。下面這段代碼定義了一個從Person類改過來的SerializablePerson類。
SerializablePerson.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package dustin.examples.serialization;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* Person class.
*
* @author Dustin
*/
public class SerializablePerson implements Serializable
{
private String lastName;
private String firstName;
private CityState cityAndState;
public SerializablePerson(
final String newLastName, final String newFirstName,
final CityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}
public String getFirstName()
{
return this.firstName;
}
public String getLastName()
{
return this.lastName;
}
@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}
/**
* Serialize this instance.
*
* @param out Target to which this instance is written.
* @throws IOException Thrown if exception occurs during serialization.
*/
private void writeObject(final ObjectOutputStream out) throws IOException
{
out.writeUTF(this.lastName);
out.writeUTF(this.firstName);
out.writeUTF(this.cityAndState.getCityName());
out.writeUTF(this.cityAndState.getStateName());
}
/**
* Deserialize this instance from input stream.
*
* @param in Input Stream from which this instance is to be deserialized.
* @throws IOException Thrown if error occurs in deserialization.
* @throws ClassNotFoundException Thrown if expected class is not found.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
{
this.lastName = in.readUTF();
this.firstName = in.readUTF();
this.cityAndState = new CityState(in.readUTF(), in.readUTF());
}
private void readObjectNoData() throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
}
在上面這段代碼中,SerializablePerson有自定義的writeobject和readObject方法。它們以適當的方式處理CityState的序列化和反序列化。下面這段代碼使用SerializationDemonstrator運行了這個類,我們可以看到這次的運行是成功的。
Running SerializationDemonstrator on SerializablePerson
1
2
3
4
final SerializablePerson personIn = new SerializablePerson("Flintstone", "Fred", new CityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person1.dat");
final SerializablePerson personOut = SerializationDemonstrator.deserialize("person1.dat", SerializablePerson.class);
上面描述的這個方法可以允許我們在一個可序列化的類中使用不可序列化的屬性,而且不需要transient。現在看上去已經挺不錯了,但是如果前面這個CityState要在多個需要序列化的類中使用,更好的方式是用一個支持序列化的Decorator去修飾CityState。然后在那些需要做序列化的類中使用這個Decorator。下面這段代碼定義了SerializableCityState。它是CityState的一個支持序列化的Decorator版本。
SerializableCityState.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package dustin.examples.serialization;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* Simple class storing city and state names that IS Serializable. This class
* decorates the non-Serializable CityState class and adds Serializability.
*
* @author Dustin
*/
public class SerializableCityState implements Serializable
{
private CityState cityState;
public SerializableCityState(final String newCityName, final String newStateName)
{
this.cityState = new CityState(newCityName, newStateName);
}
public String getCityName()
{
return this.cityState.getCityName();
}
public String getStateName()
{
return this.cityState.getStateName();
}
@Override
public String toString()
{
return this.cityState.toString();
}
/**
* Serialize this instance.
*
* @param out Target to which this instance is written.
* @throws IOException Thrown if exception occurs during serialization.
*/
private void writeObject(final ObjectOutputStream out) throws IOException
{
out.writeUTF(this.cityState.getCityName());
out.writeUTF(this.cityState.getStateName());
}
/**
* Deserialize this instance from input stream.
*
* @param in Input Stream from which this instance is to be deserialized.
* @throws IOException Thrown if error occurs in deserialization.
* @throws ClassNotFoundException Thrown if expected class is not found.
*/
private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException
{
this.cityState = new CityState(in.readUTF(), in.readUTF());
}
private void readObjectNoData() throws ObjectStreamException
{
throw new InvalidObjectException("Stream data required");
}
}
這個可序列化的Decorator可以在Person類中直接使用。由于所有的屬性都支持序列化,Person類可以使用默認的序列化方法。下面這段代碼定義了一個從Person類改過來的Person2類。
Person2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package dustin.examples.serialization;
import java.io.Serializable;
/**
* Person class.
*
* @author Dustin
*/
public class Person2 implements Serializable
{
private final String lastName;
private final String firstName;
private final SerializableCityState cityAndState;
public Person2(
final String newLastName, final String newFirstName,
final SerializableCityState newCityAndState)
{
this.lastName = newLastName;
this.firstName = newFirstName;
this.cityAndState = newCityAndState;
}
public String getFirstName()
{
return this.firstName;
}
public String getLastName()
{
return this.lastName;
}
@Override
public String toString()
{
return this.firstName + " " + this.lastName + " of " + this.cityAndState;
}
}
下面這段代碼運行了這個類。之后是NetBeans輸出的截圖。
Running SerializationDemonstrator Against Person2/SerializableCityState
1
2
3
4
final Person2 personIn = new Person2("Flintstone", "Fred", new SerializableCityState("Bedrock", "Cobblestone"));
SerializationDemonstrator.serialize(personIn, "person2.dat");
final Person2 personOut = SerializationDemonstrator.deserialize("person2.dat", Person2.class);
通過使用定制的序列化方法,可以在不使用transient的情況下,對一個帶有不可序列化屬性的類進行序列化。當你要在一個需要序列化的類中使用不可序列化的類型,并且這些類型不能被修改時,這是一個有用的技術。
【免責聲明】本賬號旨在介紹更多的最新信息,部分信息轉載自各類紙媒、網媒之所有作品,版權歸作者本人所有,轉載文章目的在于分享信息、提供閱讀,不代表本平臺贊同其觀點和對其真實性負責!若作者或版權人不愿被使用,請即與我方公眾號tedu_java聯系,如有侵權本賬號將迅速給您回應并做處理返回搜狐,查看更多
責任編輯:
總結
以上是生活随笔為你收集整理的java 属性不序列化_怎样对带有不可序列化属性的Java对象进行序列化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怀孕右附件囊肿怎么办
- 下一篇: 不知道怎么编辑图片在电脑上如何编辑照片