[TOC]
# éå½:对象åºåå
å½ä½ å建对象æ¶ï¼åªè¦ä½ éè¦ï¼å®å°±ä¼ä¸ç´åå¨ï¼ä½æ¯å¨ç¨åºç»æ¢æ¶ï¼æ 论å¦ä½å®é½ä¸ä¼ç»§ç»åå¨ã尽管è¿ä¹åè¯å®æ¯ææä¹çï¼ä½æ¯ä»æ§åå¨æäºæ
åµï¼å¦æå¯¹è±¡è½å¤å¨ç¨åºä¸è¿è¡çæ
åµä¸ä»è½åå¨å¹¶ä¿åå
¶ä¿¡æ¯ï¼é£å°é常æç¨ãè¿æ ·ï¼å¨ä¸æ¬¡è¿è¡ç¨åºæ¶ï¼è¯¥å¯¹è±¡å°è¢«éå»ºå¹¶ä¸æ¥æçä¿¡æ¯ä¸å¨ç¨åºä¸æ¬¡è¿è¡æ¶å®ææ¥æçä¿¡æ¯ç¸åãå½ç¶ï¼ä½ å¯ä»¥éè¿å°ä¿¡æ¯åå
¥æä»¶ææ°æ®åºæ¥è¾¾å°ç¸åçææï¼ä½æ¯å¨ä½¿ä¸ç©é½æä¸ºå¯¹è±¡çç²¾ç¥ä¸ï¼å¦æè½å¤å°ä¸ä¸ªå¯¹è±¡å£°æä¸ºæ¯âæä¹
æ§âçï¼å¹¶ä¸ºæä»¬å¤çæææç»èï¼é£å°ä¼æ¾å¾ååæ¹ä¾¿ã
Java ç对象åºååå°é£äºå®ç°äº Serializable æ¥å£çå¯¹è±¡è½¬æ¢æä¸ä¸ªåèåºåï¼å¹¶è½å¤å¨ä»¥åå°è¿ä¸ªåèåºåå®å
¨æ¢å¤ä¸ºåæ¥ç对象ãè¿ä¸è¿ç¨çè³å¯éè¿ç½ç»è¿è¡ï¼è¿æå³çåºååæºå¶è½èªå¨å¼¥è¡¥ä¸åæä½ç³»ç»ä¹é´çå·®å¼ãä¹å°±æ¯è¯´ï¼å¯ä»¥å¨è¿è¡ Windows ç³»ç»çè®¡ç®æºä¸å建ä¸ä¸ªå¯¹è±¡ï¼å°å
¶åºååï¼éè¿ç½ç»å°å®åéç»ä¸å°è¿è¡ Unix ç³»ç»çè®¡ç®æºï¼ç¶åå¨é£éåç¡®å°éæ°ç»è£
ï¼èå´ä¸å¿
æ
å¿æ°æ®å¨ä¸åæºå¨ä¸ç表示ä¼ä¸åï¼ä¹ä¸å¿
å
³å¿å®èçé¡ºåºæè
å
¶ä»ä»»ä½ç»èã
å°±å
¶æ¬èº«æ¥è¯´ï¼å¯¹è±¡åºååå¯ä»¥å®ç°è½»é级æä¹
æ§ï¼lightweight persistenceï¼ï¼âæä¹
æ§âæå³çä¸ä¸ªå¯¹è±¡ççå卿并ä¸åå³äºç¨åºæ¯å¦æ£å¨æ§è¡å®å¯ä»¥çåäºç¨åºçè°ç¨ä¹é´ãéè¿å°ä¸ä¸ªåºåå对象å人ç£çï¼ç¶åå¨éæ°è°ç¨ç¨åºæ¶æ¢å¤è¯¥å¯¹è±¡ï¼å°±è½å¤å®ç°æä¹
æ§çææãä¹æä»¥ç§°å
¶ä¸ºâè½»é级âï¼æ¯å 为ä¸è½ç¨æç§"persistent"ï¼æä¹
ï¼å
³é®åæ¥ç®åå°å®ä¹ä¸ä¸ªå¯¹è±¡ï¼å¹¶è®©ç³»ç»èªå¨ç»´æ¤å
¶ä»ç»èé®é¢ï¼å°½ç®¡å°æ¥æå¯è½å®ç°ï¼ãç¸åï¼å¯¹è±¡å¿
é¡»å¨ç¨åºä¸æ¾å¼å°åºååï¼serializeï¼åååºååè¿åï¼deserializeï¼ï¼å¦æéè¦ä¸ªæ´ä¸¥æ ¼çæä¹
æ§æºå¶ï¼å¯ä»¥èèå Hibemate ä¹ç±»çå·¥å
·ã
对象åºååçæ¦å¿µå å
¥å°è¯è¨ä¸æ¯ä¸ºäºæ¯æä¸¤ç§ä¸»è¦ç¹æ§ã䏿¯ Java çè¿ç¨æ¹æ³è°ç¨ï¼Remote Method Invocationï¼RMIï¼ï¼å®ä½¿åæ´»äºå
¶ä»è®¡ç®æºä¸ç对象使ç¨èµ·æ¥å°±åæ¯åæ´»äºæ¬æºä¸ä¸æ ·ãå½åè¿ç¨å¯¹è±¡åéæ¶æ¯æ¶ï¼éè¦éè¿å¯¹è±¡åºååæ¥ä¼ è¾åæ°åè¿åå¼ã
åè
ï¼å¯¹ Java Beans æ¥è¯´ï¼å¯¹è±¡çåºåå乿¯å¿
éçï¼å¨æ°åæ¬ææ¶è¢«è§ä¸ºå¤±è´¥çææ¯ï¼ï¼ä½¿ç¨ä¸ä¸ª Bean æ¶ï¼ä¸è¬æ
åµä¸æ¯å¨è®¾è®¡é¶æ®µå¯¹å®çç¶æä¿¡æ¯è¿è¡é
ç½®ãè¿ç§ç¶æä¿¡æ¯å¿
é¡»ä¿å䏿¥ï¼å¹¶å¨ç¨åºå¯å¨æ¶è¿è¡åææ¢å¤ï¼è¿ç§å
·ä½å·¥ä½å°±æ¯ç±å¯¹è±¡åºåå宿çã
åªè¦å¯¹è±¡å®ç°äº Serializable æ¥å£ï¼è¯¥æ¥å£ä»
æ¯ä¸ä¸ªæ è®°æ¥å£ï¼ä¸å
æ¬ä»»ä½æ¹æ³ï¼ï¼å¯¹è±¡çåºååå¤çå°±ä¼é常ç®åãå½åºååçæ¦å¿µè¢«å å
¥å°è¯è¨ä¸æ¶ï¼è®¸å¤æ ååºç±»é½åçäºæ¹åï¼ä»¥ä¾¿å
·å¤åºååç¹æ§-å
¶ä¸å
æ¬ææåºæ¬æ°æ®ç±»åçå°è£
å¨ãææå®¹å¨ç±»ä»¥å许å¤å
¶ä»çä¸è¥¿ãçè³ Class 对象ä¹å¯ä»¥è¢«åºååã
è¦åºååä¸ä¸ªå¯¹è±¡ï¼é¦å
è¦å建æäº OutputStream 对象ï¼ç¶åå°å
¶å°è£
å¨ä¸ä¸ª ObjectOutputStream 对象å
ãè¿æ¶ï¼åªéè°ç¨ writeObject() å³å¯å°å¯¹è±¡åºååï¼å¹¶å°å
¶åéç» OutputStreamï¼å¯¹è±¡ååºåæ¯åºäºåèçï¼å è¦ä½¿ç¨ InputStream å OutputStream ç»§æ¿å±æ¬¡ç»æï¼ãè¦ååè¿è¡è¯¥è¿ç¨ï¼å³å°ä¸ä¸ªåºåè¿å为ä¸ä¸ªå¯¹è±¡ï¼ï¼éè¦å°ä¸ä¸ª InputStream å°è£
å¨ ObjectInputStream å
ï¼ç¶åè°ç¨ readObject()ãåå¾å¸¸ä¸æ ·ï¼æä»¬æåè·å¾çæ¯ä¸ä¸ªå¼ç¨ï¼å®æåä¸ä¸ªåä¸è½¬åç Objectï¼æä»¥å¿
é¡»åä¸è½¬åæè½ç´æ¥è®¾ç½®å®ä»¬ã
对象åºååç¹å«âèªæâçä¸ä¸ªå°æ¹æ¯å®ä¸ä»
ä¿åäºå¯¹è±¡çâå
¨æ¯å¾âï¼èä¸è½è¿½è¸ªå¯¹è±¡å
æå
å«çææå¼ç¨ï¼å¹¶ä¿åé£äºå¯¹è±¡ï¼æ¥çåè½å¯¹å¯¹è±¡å
å
å«çæ¯ä¸ªè¿æ ·çå¼ç¨è¿è¡è¿½è¸ªï¼ä¾æ¤ç±»æ¨ãè¿ç§æ
嵿æ¶è¢«ç§°ä¸ºâ对象ç½âï¼å个对象å¯ä¸ä¹å»ºç«è¿æ¥ï¼èä¸å®è¿å
å«äºå¯¹è±¡çå¼ç¨æ°ç»ä»¥åæå对象ã妿å¿
é¡»ä¿æä¸å¥èªå·±ç对象åºååæºå¶ï¼é£ä¹ç»´æ¤é£äºå¯è¿½è¸ªå°ææé¾æ¥ç代ç å¯è½ä¼æ¾å¾é常麻ç¦ãç¶èï¼ç±äº Java ç对象åºåå似乿¾ä¸åºä»ä¹ç¼ºç¹ï¼æä»¥è¯·å°½éä¸è¦èªå·±å¨æï¼è®©å®ç¨ä¼åçç®æ³èªå¨ç»´æ¤æ´ä¸ªå¯¹è±¡ç½ãä¸é¢è¿ä¸ªä¾åéè¿å¯¹é¾æ¥ç对象çæä¸ä¸ª wormï¼è è«ï¼å¯¹åºååæºå¶è¿è¡äºæµè¯ãæ¯ä¸ªå¯¹è±¡é½ä¸ worm ä¸çä¸ä¸æ®µé¾æ¥ï¼åæ¶åä¸å±äºä¸åç±»ï¼Dataï¼ç对象å¼ç¨æ°ç»é¾æ¥ï¼
```java
// serialization/Worm.java
// Demonstrates object serialization
import java.io.*;
import java.util.*;
class Data implements Serializable {
private int n;
Data(int n) { this.n = n; }
@Override
public String toString() {
return Integer.toString(n);
}
}
public class Worm implements Serializable {
private static Random rand = new Random(47);
private Data[] d = {
new Data(rand.nextInt(10)),
new Data(rand.nextInt(10)),
new Data(rand.nextInt(10))
};
private Worm next;
private char c;
// Value of i == number of segments
public Worm(int i, char x) {
System.out.println("Worm constructor: " + i);
c = x;
if(--i > 0)
next = new Worm(i, (char)(x + 1));
}
public Worm() {
System.out.println("No-arg constructor");
}
@Override
public String toString() {
StringBuilder result = new StringBuilder(":");
result.append(c);
result.append("(");
for(Data dat : d)
result.append(dat);
result.append(")");
if(next != null)
result.append(next);
return result.toString();
}
public static void
main(String[] args) throws ClassNotFoundException,
IOException {
Worm w = new Worm(6, 'a');
System.out.println("w = " + w);
try(
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("worm.dat"))
) {
out.writeObject("Worm storage\n");
out.writeObject(w);
}
try(
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("worm.dat"))
) {
String s = (String)in.readObject();
Worm w2 = (Worm)in.readObject();
System.out.println(s + "w2 = " + w2);
}
try(
ByteArrayOutputStream bout =
new ByteArrayOutputStream();
ObjectOutputStream out2 =
new ObjectOutputStream(bout)
) {
out2.writeObject("Worm storage\n");
out2.writeObject(w);
out2.flush();
try(
ObjectInputStream in2 = new ObjectInputStream(
new ByteArrayInputStream(
bout.toByteArray()))
) {
String s = (String)in2.readObject();
Worm w3 = (Worm)in2.readObject();
System.out.println(s + "w3 = " + w3);
}
}
}
}
```
è¾åºä¸ºï¼
```
Worm constructor: 6
Worm constructor: 5
Worm constructor: 4
Worm constructor: 3
Worm constructor: 2
Worm constructor: 1
w = :a(853):b(119):c(802):d(788):e(199):f(881)
Worm storage
w2 = :a(853):b(119):c(802):d(788):e(199):f(881)
Worm storage
w3 = :a(853):b(119):c(802):d(788):e(199):f(881)
```
æ´æè¶£çæ¯ï¼Worm å
ç Data 对象æ°ç»æ¯ç¨éæºæ°åå§åçï¼è¿æ ·å°±ä¸ç¨æçç¼è¯å¨ä¿çäºæç§åå§ä¿¡æ¯ï¼ï¼æ¯ä¸ª Worm 段é½ç¨ä¸ä¸ª char å 以æ è®°ã该 char æ¯å¨éå½çæé¾æ¥ç Worm å表æ¶èªå¨äº§ççãè¦å建ä¸ä¸ª Wormï¼å¿
é¡»åè¯æé å¨ä½ æå¸æçå®çé¿åº¦ãå¨äº§çä¸ä¸ä¸ªå¼ç¨æ¶ï¼è¦è°ç¨ Worm æé å¨ï¼å¹¶å°é¿åº¦å 1ï¼ä»¥æ¤ç±»æ¨ãæåä¸ä¸ª next å¼ç¨å为 nullï¼ç©ºï¼ï¼è¡¨ç¤ºå·²å°è¾¾ Worm çå°¾é¨
以ä¸è¿äºæä½é½ä½¿å¾äºæ
å徿´å 夿ï¼ä»èå 大äºå¯¹è±¡åºååçé¾åº¦ãç¶èï¼çæ£çåºååè¿ç¨å´æ¯é常ç®åçã䏿¦ä»å¦å¤æä¸ªæµåå»ºäº ObjectOutputstreamï¼writeObject() å°±ä¼å°å¯¹è±¡åºååãæ³¨æä¹å¯ä»¥ä¸ºä¸ä¸ª String è°ç¨ writeObject() ä¹å¯ä»¥ç¨ä¸ DataOutputStream ç¸åçæ¹æ³å人ææåºæ¬æ°æ®ç±»åï¼å®ä»¬å
·æåæ ·çæ¥å£ï¼ã
æä¸¤æ®µçèµ·æ¥ç¸ä¼¼çç¬ç«ç代ç ãä¸ä¸ªè¯»åçæ¯æä»¶ï¼èå¦ä¸ä¸ªè¯»åçæ¯åèæ°ç»ï¼ByteArrayï¼ï¼å¯å©ç¨åºååå°å¯¹è±¡è¯»åå°ä»»ä½ DatalnputStream æè
DataOutputStreamã
ä»è¾åºä¸å¯ä»¥çåºï¼è¢«è¿ååç对象确å®å
å«äºå对象ä¸çææé¾æ¥ã
注æå¨å¯¹ä¸ä¸ª Serializable 对象è¿è¡è¿åçè¿ç¨ä¸ï¼æ²¡æè°ç¨ä»»ä½æé å¨ï¼å
æ¬é»è®¤çæé å¨ãæ´ä¸ªå¯¹è±¡é½æ¯éè¿ä» InputStream ä¸å徿°æ®æ¢å¤èæ¥çã
## æ¥æ¾ç±»
ä½ æè®¸ä¼å¥æªï¼å°ä¸ä¸ªå¯¹è±¡ä»å®çåºååç¶æä¸æ¢å¤åºæ¥ï¼æåªäºå·¥ä½æ¯å¿
é¡»çå¢ï¼ä¸¾ä¸ªä¾åæ¥è¯´ï¼å妿们å°ä¸ä¸ªå¯¹è±¡åºååï¼å¹¶éè¿ç½ç»å°å
¶ä½ä¸ºæä»¶ä¼ éç»å¦ä¸å°è®¡ç®æºï¼é£ä¹ï¼å¦ä¸å°è®¡ç®æºä¸çç¨åºå¯ä»¥åªå©ç¨è¯¥æä»¶å
容æ¥è¿åè¿ä¸ªå¯¹è±¡åï¼
åçè¿ä¸ªé®é¢çæå¥½æ¹æ³å°±æ¯åä¸ä¸ªå®éªãä¸é¢è¿ä¸ªæä»¶ä½äºæ¬ç« çåç®å½ä¸ï¼
```java
// serialization/Alien.java
// A serializable class
import java.io.*;
public class Alien implements Serializable {}
```
èç¨äºå建ååºååä¸ä¸ª Alien 对象çæä»¶ä¹ä½äºç¸åçç®å½ä¸ï¼
```java
// serialization/FreezeAlien.java
// Create a serialized output file
import java.io.*;
public class FreezeAlien {
public static void main(String[] args) throws Exception {
try(
ObjectOutputStream out = new ObjectOutputStream(
new FileOutputStream("X.file"));
) {
Alien quellek = new Alien();
out.writeObject(quellek);
}
}
}
```
䏿¦è¯¥ç¨åºè¢«ç¼è¯åè¿è¡ï¼å®å°±ä¼å¨ c12 ç®å½ä¸äº§çä¸ä¸ªå为 X.file çæä»¶ã以ä¸ä»£ç ä½äºä¸ä¸ªå为 xiles çåç®å½ä¸ï¼
```java
// serialization/xfiles/ThawAlien.java
// Recover a serialized file
// {java serialization.xfiles.ThawAlien}
// {RunFirst: FreezeAlien}
package serialization.xfiles;
import java.io.*;
public class ThawAlien {
public static void main(String[] args) throws Exception {
ObjectInputStream in = new ObjectInputStream(
new FileInputStream(new File("X.file")));
Object mystery = in.readObject();
System.out.println(mystery.getClass());
}
}
```
è¾åºä¸ºï¼
```java
class Alien
```
ä¸ºäºæ£å¸¸è¿è¡ï¼å¿
é¡»ä¿è¯ Java èææºè½æ¾å°ç¸å
³ç.class æä»¶ã
## æ§å¶åºåå
æ£å¦å¤§å®¶æçå°çï¼é»è®¤çåºååæºå¶å¹¶ä¸é¾æçºµãç¶èï¼å¦ææç¹æ®çéè¦é£å该æä¹åå¢ï¼ä¾å¦ï¼ä¹è®¸è¦èèç¹æ®çå®å
¨é®é¢ï¼èä¸ä½ ä¸å¸æå¯¹è±¡çæä¸é¨å被åºååï¼æè
ä¸ä¸ªå¯¹è±¡è¢«è¿å以åï¼æå对象éè¦éæ°å建ï¼ä»èä¸å¿
å°è¯¥å对象åºååã
å¨è¿äºç¹æ®æ
åµä¸ï¼å¯éè¿å®ç° Externalizable æ¥å£ââ代æ¿å®ç° Serializable æ¥å£-æ¥å¯¹åºååè¿ç¨è¿è¡æ§å¶ãè¿ä¸ª Externalizable æ¥å£ç»§æ¿äº Serializable æ¥å£ï¼åæ¶å¢æ·»äºä¸¤ä¸ªæ¹æ³ï¼writeExternal0 å readExternal0ãè¿ä¸¤ä¸ªæ¹æ³ä¼å¨åºåååååºååè¿åçè¿ç¨ä¸è¢«èªå¨è°ç¨ï¼ä»¥ä¾¿æ§è¡ä¸äºç¹æ®æä½ã
ä¸é¢è¿ä¸ªä¾åå±ç¤ºäº Externalizable æ¥å£æ¹æ³çç®åå®ç°ã注æ Blip1 å Blip2 é¤äºç»å¾®çå·®å«ä¹å¤ï¼å ä¹å®å
¨ä¸è´ï¼ç ç©¶ä¸ä¸ä»£ç ï¼ççä½ è½å¦åç°ï¼ï¼
```java
// serialization/Blips.java
// Simple use of Externalizable & a pitfall
import java.io.*;
class Blip1 implements Externalizable {
public Blip1() {
System.out.println("Blip1 Constructor");
}
@Override
public void writeExternal(ObjectOutput out)
throws IOException {
System.out.println("Blip1.writeExternal");
}
@Override
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException {
System.out.println("Blip1.readExternal");
}
}
class Blip2 implements Externalizable {
Blip2() {
System.out.println("Blip2 Constructor");
}
@Override
public void writeExternal(ObjectOutput out)
throws IOException {
System.out.println("Blip2.writeExternal");
}
@Override
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException {
System.out.println("Blip2.readExternal");
}
}
public class Blips {
public static void main(String[] args) {
System.out.println("Constructing objects:");
Blip1 b1 = new Blip1();
Blip2 b2 = new Blip2();
try(
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("Blips.serialized"))
) {
System.out.println("Saving objects:");
o.writeObject(b1);
o.writeObject(b2);
} catch(IOException e) {
throw new RuntimeException(e);
}
// Now get them back:
System.out.println("Recovering b1:");
try(
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Blips.serialized"))
) {
b1 = (Blip1)in.readObject();
} catch(IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
// OOPS! Throws an exception:
//- System.out.println("Recovering b2:");
//- b2 = (Blip2)in.readObject();
}
}
```
è¾åºä¸ºï¼
```
Constructing objects:
Blip1 Constructor
Blip2 Constructor
Saving objects:
Blip1.writeExternal
Blip2.writeExternal
Recovering b1:
Blip1 Constructor
Blip1.readExternal
```
æ²¡ææ¢å¤ Blip2 对象çåå æ¯é£æ ·åä¼å¯¼è´ä¸ä¸ªå¼å¸¸ãä½ æ¾åº Blip1 å Blip2 ä¹é´çåºå«äºåï¼Blipl çæé 卿¯âå
Œ
±çâï¼pablicï¼ï¼Blip2 çæé å¨å´ä¸æ¯ï¼è¿æ ·å°±ä¼å¨æ¢å¤æ¶é æå¼å¸¸ãè¯è¯å° Blip2 çæé å¨åæ public çï¼ç¶åå é¤//æ³¨éæ è®°ï¼ççæ¯å¦è½å¾å°æ£ç¡®çç»æã
æ¢å¤ b1 åï¼ä¼è°ç¨ Blip1 é»è®¤æé å¨ãè¿ä¸æ¢å¤ä¸ä¸ª Serializable 对象ä¸åãå¯¹äº Serializable 对象ï¼å¯¹è±¡å®å
¨ä»¥å®åå¨çäºè¿å¶ä½ä¸ºåºç¡æ¥æé ï¼èä¸è°ç¨æé å¨ãè对äºä¸ä¸ª Externalizable å¯¹è±¡ï¼æææ®éçé»è®¤æé å¨é½ä¼è¢«è°ç¨ï¼å
æ¬å¨å段å®ä¹æ¶çåå§åï¼ï¼ç¶åè°ç¨ readExternal() å¿
须注æè¿ä¸ç¹--ææé»è®¤çæé å¨é½ä¼è¢«è°ç¨ï¼æè½ä½¿ Externalizable å¯¹è±¡äº§çæ£ç¡®çè¡ä¸ºã
ä¸é¢è¿ä¸ªä¾å示èäºå¦ä½å®æ´ä¿å忢å¤ä¸ä¸ª Externalizable 对象ï¼
```java
// serialization/Blip3.java
// Reconstructing an externalizable object
import java.io.*;
public class Blip3 implements Externalizable {
private int i;
private String s; // No initialization
public Blip3() {
System.out.println("Blip3 Constructor");
// s, i not initialized
}
public Blip3(String x, int a) {
System.out.println("Blip3(String x, int a)");
s = x;
i = a;
// s & i initialized only in non-no-arg constructor.
}
@Override
public String toString() { return s + i; }
@Override
public void writeExternal(ObjectOutput out)
throws IOException {
System.out.println("Blip3.writeExternal");
// You must do this:
out.writeObject(s);
out.writeInt(i);
}
@Override
public void readExternal(ObjectInput in)
throws IOException, ClassNotFoundException {
System.out.println("Blip3.readExternal");
// You must do this:
s = (String)in.readObject();
i = in.readInt();
}
public static void main(String[] args) {
System.out.println("Constructing objects:");
Blip3 b3 = new Blip3("A String ", 47);
System.out.println(b3);
try(
ObjectOutputStream o = new ObjectOutputStream(
new FileOutputStream("Blip3.serialized"))
) {
System.out.println("Saving object:");
o.writeObject(b3);
} catch(IOException e) {
throw new RuntimeException(e);
}
// Now get it back:
System.out.println("Recovering b3:");
try(
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Blip3.serialized"))
) {
b3 = (Blip3)in.readObject();
} catch(IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
System.out.println(b3);
}
}
```
è¾åºä¸ºï¼
```
Constructing objects:
Blip3(String x, int a)
A String 47
Saving object:
Blip3.writeExternal
Recovering b3:
Blip3 Constructor
Blip3.readExternal
A String 47
```
å
¶ä¸ï¼å段 s ååªå¨ç¬¬äºä¸ªæé å¨ä¸åå§åï¼è䏿¯å¨é»è®¤çæé å¨ä¸åå§åãè¿æå³çåå¦ä¸å¨ readExternal0 ä¸åå§å s å iï¼s å°±ä¼ä¸º nullï¼èå°±ä¼ä¸ºé¶ï¼å 为å¨å建对象çç¬¬ä¸æ¥ä¸å°å¯¹è±¡çåå¨ç©ºé´æ¸
ç为 0ï¼ãå¦ææ³¨éæè·éäº"You must do thisâåé¢ç两è¡ä»£ç ï¼ç¶åè¿è¡ç¨åºï¼å°±ä¼åç°å½å¯¹è±¡è¢«è¿ååï¼s æ¯ nullï¼è i æ¯é¶ã
æä»¬å¦æä»ä¸ä¸ª Externalizable 对象继æ¿ï¼é常éè¦è°ç¨åºç±»çæ¬ç writeExternal() å readExternal() æ¥ä¸ºåºç±»ç»ä»¶æä¾æ°å½çåå¨åæ¢å¤åè½ã
å æ¤ï¼ä¸ºäºæ£å¸¸è¿è¡ï¼æä»¬ä¸ä»
éè¦å¨ writeExternal() æ¹æ³ï¼æ²¡æä»»ä½é»è®¤è¡ä¸ºæ¥ä¸º Externalizable 对象åå
¥ä»»ä½æå对象ï¼ä¸å°æ¥èªå¯¹è±¡çéè¦ä¿¡æ¯åå
¥ï¼è¿å¿
é¡»å¨ readExternal() æ¹æ³ä¸æ¢å¤æ°æ®ãèµ·å
ï¼å¯è½ä¼æä¸ç¹è¿·æï¼å 为 Externalizable 对象çé»è®¤æé è¡ä¸ºä½¿å
¶çèµ·æ¥ä¼¼ä¹åæç§èªå¨åççåå¨ä¸æ¢å¤æä½ãä½å®é
ä¸å¹¶é妿¤ã
### transient å
³é®å
彿们坹åºååè¿è¡æ§å¶æ¶ï¼å¯è½æä¸ªç¹å®åå¯¹è±¡ä¸æ³è®© Java çåºååæºå¶èªå¨ä¿å䏿¢å¤ã妿åå¯¹è±¡è¡¨ç¤ºçæ¯æä»¬ä¸å¸æå°å
¶åºååçææä¿¡æ¯ï¼å¦å¯ç ï¼ï¼é常就ä¼é¢ä¸´è¿ç§æ
åµãå³ä½¿å¯¹è±¡ä¸çè¿äºä¿¡æ¯æ¯ privateï¼ç§æï¼å±æ§ï¼ä¸ç»åºååå¤çï¼äººä»¬å°±å¯ä»¥éè¿è¯»åæä»¶æè
æ¦æªç½ç»ä¼ è¾çæ¹å¼æ¥è®¿é®å°å®ã
æä¸ç§åæ³å¯é²æ¢å¯¹è±¡çææé¨å被åºååï¼å°±æ¯å°ç±»å®ç°ä¸º Externalizableï¼å¦åé¢æç¤ºãè¿æ ·ä¸æ¥ï¼æ²¡æä»»ä½ä¸è¥¿å¯ä»¥èªå¨åºååï¼å¹¶ä¸å¯ä»¥å¨ writeExternal() å
é¨åªå¯¹æéé¨åè¿è¡æ¾å¼çåºååã
ç¶èï¼å¦ææä»¬æ£å¨æä½çæ¯ä¸ä¸ª Seralizable 对象ï¼é£ä¹ææåºååæä½é½ä¼èªå¨è¿è¡ã为äºè½å¤äºä»¥æ§å¶ï¼å¯ä»¥ç¨ transientï¼ç¬æ¶ï¼å
³é®åéä¸ªåæ®µå°å
³éåºååï¼å®çæææ¯âä¸ç¨éº»ç¦ä½ ä¿åææ¢å¤æ°æ®ââæèªå·±ä¼å¤çç"ã
ä¾å¦ï¼å设æä¸ª Logon 对象ä¿åæä¸ªç¹å®çç»å½ä¼è¯ä¿¡æ¯ï¼ç»å½çåæ³æ§éè¿æ ¡éªä¹åï¼æä»¬æ³ææ°æ®ä¿å䏿¥ï¼ä½ä¸å
æ¬å¯ç ã为åå°è¿ä¸ç¹ï¼æç®åçåæ³æ¯å®ç° Serializableï¼å¹¶å° password åæ®µæ å¿ä¸º transientï¼ä¸é¢æ¯å
·ä½ç代ç ï¼
```java
// serialization/Logon.java
// Demonstrates the "transient" keyword
import java.util.concurrent.*;
import java.io.*;
import java.util.*;
import onjava.Nap;
public class Logon implements Serializable {
private Date date = new Date();
private String username;
private transient String password;
public Logon(String name, String pwd) {
username = name;
password = pwd;
}
@Override
public String toString() {
return "logon info: \n username: " +
username + "\n date: " + date +
"\n password: " + password;
}
public static void main(String[] args) {
Logon a = new Logon("Hulk", "myLittlePony");
System.out.println("logon a = " + a);
try(
ObjectOutputStream o =
new ObjectOutputStream(
new FileOutputStream("Logon.dat"))
) {
o.writeObject(a);
} catch(IOException e) {
throw new RuntimeException(e);
}
new Nap(1);
// Now get them back:
try(
ObjectInputStream in = new ObjectInputStream(
new FileInputStream("Logon.dat"))
) {
System.out.println(
"Recovering object at " + new Date());
a = (Logon)in.readObject();
} catch(IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
System.out.println("logon a = " + a);
}
}
```
è¾åºä¸ºï¼
```
logon a = logon info:
username: Hulk
date: Tue May 09 06:07:47 MDT 2017
password: myLittlePony
Recovering object at Tue May 09 06:07:49 MDT 2017
logon a = logon info:
username: Hulk
date: Tue May 09 06:07:47 MDT 2017
password: null
```
å¯ä»¥çå°ï¼å
¶ä¸ç date å username æ¯ä¸è¬çï¼ä¸æ¯ transient çï¼ï¼æä»¥å®ä»¬ä¼è¢«èªå¨åºååãè password æ¯ transient çï¼æä»¥ä¸ä¼è¢«èªå¨ä¿åå°ç£çï¼å¦å¤ï¼èªå¨åºååæºå¶ä¹ä¸ä¼å°è¯å»æ¢å¤å®ãå½å¯¹è±¡è¢«æ¢å¤æ¶ï¼password å°±ä¼åæ nullãæ³¨æï¼è½ç¶ toString() æ¯ç¨éè½½åç+è¿ç®ç¬¦æ¥è¿æ¥ String 对象ï¼ä½æ¯ null å¼ç¨ä¼è¢«èªå¨è½¬æ¢æå符串 nullã
æä»¬è¿å¯ä»¥åç°ï¼date åæ®µè¢«åå¨äºå°ç£çå¹¶ä»ç£çä¸è¢«æ¢å¤äºåºæ¥ï¼è䏿²¡æåéæ°çæãç±äº Externalizable 对象å¨é»è®¤æ
åµä¸ä¸ä¿åå®ä»¬çä»»ä½åæ®µï¼æä»¥ transient å
³é®ååªè½å Serializable 对象ä¸èµ·ä½¿ç¨ã
### Externalizable çæ¿ä»£æ¹æ³
妿䏿¯ç¹å«åæå®ç° Externalizable æ¥å£ï¼é£ä¹è¿æå¦ä¸ç§æ¹æ³ãæä»¬å¯ä»¥å®ç° Serializable æ¥å£ï¼å¹¶æ·»å ï¼æ³¨ææè¯´çæ¯âæ·»å âï¼èéâè¦çâæè
âå®ç°âï¼å为 writeObject() å readObject() çæ¹æ³ãè¿æ ·ä¸æ¦å¯¹è±¡è¢«åºååæè
被ååºååè¿åï¼å°±ä¼èªå¨å°åå«è°ç¨è¿ä¸¤ä¸ªæ¹æ³ãä¹å°±æ¯è¯´ï¼åªè¦æä»¬æä¾äºè¿ä¸¤ä¸ªæ¹æ³ï¼å°±ä¼ä½¿ç¨å®ä»¬è䏿¯é»è®¤çåºååæºå¶ã
è¿äºæ¹æ³å¿
é¡»å
·æåç¡®çæ¹æ³ç¹å¾ç¾åï¼
```java
private void writeObject(ObjectOutputStream stream) throws IOException
private void readObject(ObjectInputStream stream) throws IOException, ClassNotFoundException
```
ä»è®¾è®¡çè§ç¹æ¥çï¼ç°å¨äºæ
åå¾çæ¯ä¸å¯æè®®ãé¦å
ï¼æä»¬å¯è½ä¼è®¤ä¸ºç±äºè¿äºæ¹æ³ä¸æ¯åºç±»æè
Serializable æ¥å£çä¸é¨åï¼æä»¥åºè¯¥å¨å®ä»¬èªå·±çæ¥å£ä¸è¿è¡å®ä¹ã使¯æ³¨æå®ä»¬è¢«å®ä¹æäº privateï¼è¿æå³çå®ä»¬ä»
è½è¢«è¿ä¸ªç±»çå
¶ä»æåè°ç¨ãç¶èï¼å®é
ä¸æä»¬å¹¶æ²¡æä»è¿ä¸ªç±»çå
¶ä»æ¹æ³ä¸è°ç¨å®ä»¬ï¼èæ¯ ObjectOutputStream å ObjectInputStream 对象ç writeObject() å readobject() æ¹æ³è°ç¨ä½ ç对象ç writeObject() å readObject() æ¹æ³ï¼æ³¨æå
³äºè¿éç¨å°çç¸åæ¹æ³åï¼æå°½éæå¶ä½ä¸å»è°©éªãä¸å¥è¯ï¼æ··ä¹±ï¼ã读è
å¯è½æ³ç¥é ObjectOutputStream å ObjectInputStream å¯¹è±¡æ¯ææ ·è®¿é®ä½ çç±»ä¸ç private æ¹æ³çãæä»¬åªè½åè®¾è¿æ£æ¯åºååç¥å¥çä¸é¨åã
卿¥å£ä¸å®ä¹çææä¸è¥¿é½èªå¨æ¯ public çï¼å æ¤å¦æ writeObject() å readObject() å¿
é¡»æ¯ private çï¼é£ä¹å®ä»¬ä¸ä¼æ¯æ¥å£çä¸é¨åãå 为æä»¬å¿
é¡»è¦å®å
¨éµå¾ªå
¶æ¹æ³ç¹å¾ç¾åï¼æä»¥å
¶ææå°±åå®ç°äºæ¥å£ä¸æ ·ã
å¨è°ç¨ ObjectOutputStream.writeObject() æ¶ï¼ä¼æ£æ¥æä¼ éç Serializable 对象ï¼ççæ¯å¦å®ç°äºå®èªå·±ç writeObject()ã妿æ¯è¿æ ·ï¼å°±è·³è¿æ£å¸¸çåºååè¿ç¨å¹¶è°ç¨å®ç writeObiect()ãreadObject() çæ
形䏿¤ç¸åã
è¿æå¦å¤ä¸ä¸ªæå·§ãå¨ä½ ç writeObject() å
é¨ï¼å¯ä»¥è°ç¨ defaultWriteObject() æ¥éæ©æ§è¡é»è®¤ç writeObject()ã类似å°ï¼å¨ readObject() å
é¨ï¼æä»¬å¯ä»¥è°ç¨ defaultReadObject()ï¼ä¸é¢è¿ä¸ªç®åçä¾åæ¼ç¤ºäºå¦ä½å¯¹ä¸ä¸ª Serializable 对象çåå¨ä¸æ¢å¤è¿è¡æ§å¶ï¼
```java
// serialization/SerialCtl.java
// Controlling serialization by adding your own
// writeObject() and readObject() methods
import java.io.*;
public class SerialCtl implements Serializable {
private String a;
private transient String b;
public SerialCtl(String aa, String bb) {
a = "Not Transient: " + aa;
b = "Transient: " + bb;
}
@Override
public String toString() { return a + "\n" + b; }
private void writeObject(ObjectOutputStream stream)
throws IOException {
stream.defaultWriteObject();
stream.writeObject(b);
}
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
b = (String)stream.readObject();
}
public static void main(String[] args) {
SerialCtl sc = new SerialCtl("Test1", "Test2");
System.out.println("Before:\n" + sc);
try (
ByteArrayOutputStream buf =
new ByteArrayOutputStream();
ObjectOutputStream o =
new ObjectOutputStream(buf);
) {
o.writeObject(sc);
// Now get it back:
try (
ObjectInputStream in =
new ObjectInputStream(
new ByteArrayInputStream(
buf.toByteArray()));
) {
SerialCtl sc2 = (SerialCtl)in.readObject();
System.out.println("After:\n" + sc2);
}
} catch(IOException | ClassNotFoundException e) {
throw new RuntimeException(e);
}
}
}
```
è¾åºä¸ºï¼
```
Before:
Not Transient: Test1
Transient: Test2
After:
Not Transient: Test1
Transient: Test2
```
å¨è¿ä¸ªä¾åä¸ï¼æä¸ä¸ª String åæ®µæ¯æ®éåæ®µï¼èå¦ä¸ä¸ªæ¯ transient åæ®µï¼ç¨æ¥è¯æé transient åæ®µç± defaultWriteObject() æ¹æ³ä¿åï¼è transient åæ®µå¿
é¡»å¨ç¨åºä¸æç¡®ä¿å忢å¤ãåæ®µæ¯å¨æé å¨å
é¨è䏿¯å¨å®ä¹å¤è¿è¡åå§åçï¼ä»¥æ¤å¯ä»¥è¯å®å®ä»¬å¨ååºååè¿åæé´æ²¡æè¢«ä¸äºèªå¨åæºå¶åå§åã
妿æä»¬æç®ä½¿ç¨é»è®¤æºå¶åå
¥å¯¹è±¡çé transient é¨åï¼é£ä¹å¿
é¡»è°ç¨ defaultwriteObject() ä½ä¸º writeObject() ä¸ç第ä¸ä¸ªæä½ï¼å¹¶è®© defaultReadObject() ä½ä¸º readObject() ä¸ç第ä¸ä¸ªæä½ãè¿äºé½æ¯å¥æªçæ¹æ³è°ç¨ãä¾å¦ï¼å¦ææä»¬æ£å¨ä¸º ObjectOutputStream è°ç¨ defaultWriteObject() 䏿²¡æä¼ éä»»ä½åæ°ï¼ç¶èä¸ç¥ä½æ
å®å´å¯ä»¥è¿è¡ï¼å¹¶ä¸ç¥é对象çå¼ç¨ä»¥åå¦ä½åå
¥é transient é¨åãçæ¯å¥æªä¹æã
对 transient 对象çåå¨åæ¢å¤ä½¿ç¨äºæä»¬æ¯è¾çæç代ç ã请åèèä¸ä¸å¨è¿éæåççäºæ
ãå¨ main0ï¼ä¸ï¼å建 SerialCtl 对象ï¼ç¶åå°å
¶åºååå° ObjectOutputStreamï¼æ³¨æå¨è¿ç§æ
åµä¸ï¼ä½¿ç¨çæ¯ç¼å²åºè䏿¯æä»¶-è¿å¯¹äº ObjectOutputStream æ¥è¯´æ¯å®å
¨ä¸æ ·çï¼ãåºåååçå¨ä¸é¢è¿è¡ä»£ç å½ä¸
```java
o.writeObject(sc);
```
writeObject() æ¹æ³å¿
é¡»æ£æ¥ scï¼å¤æå®æ¯å¦æ¥æèªå·±ç writeObject() æ¹æ³ï¼ä¸æ¯æ£æ¥æ¥å£ââè¿éæ ¹æ¬å°±æ²¡ææ¥å£ï¼ä¹ä¸æ¯æ£æ¥ç±»çç±»åï¼èæ¯å©ç¨åå°æ¥çæ£å°æç´¢æ¹æ³ï¼ã妿æï¼é£ä¹å°±ä¼ä½¿ç¨å®ã对 readObject() ä¹éç¨äºç±»ä¼¼çæ¹æ³ãæè®¸è¿æ¯è§£å³è¿ä¸ªé®é¢çå¯ä¸åå®å¯è¡çæ¹æ³ï¼ä½å®ç¡®å®æç¹å¤æªã
### çæ¬æ§å¶
ææ¶å¯è½æ³è¦æ¹åå¯åºååç±»ççæ¬ï¼æ¯å¦æºç±»ç对象å¯è½ä¿å卿°æ®åºä¸ï¼ãè½ç¶ Java æ¯æè¿ç§åæ³ï¼ä½æ¯ä½ å¯è½åªå¨ç¹æ®çæ
åµä¸æè¿æ ·åï¼æ¤å¤ï¼è¿éè¦å¯¹å®æç¸å½æ·±ç¨åº¦çäºè§£ï¼å¨è¿éæä»¬å°±ä¸åè¯å¾è¾¾å°è¿ä¸ç¹ï¼ãä» http://java.oracle.com ä¸ç JDK ææ¡£ä¸å¯¹è¿ä¸ä¸»é¢è¿è¡äºé常彻åºç论述ã
## ä½¿ç¨æä¹
å
个æ¯è¾è¯±äººç使ç¨åºååææ¯çæ³æ³æ¯ï¼åå¨ç¨åºçä¸äºç¶æï¼ä»¥ä¾¿æä»¬éåå¯ä»¥å¾å®¹æå°å°ç¨åºæ¢å¤å°å½åç¶æã使¯å¨æä»¬è½å¤è¿æ ·åä¹åï¼å¿
é¡»åçå 个é®é¢ã妿æä»¬å°ä¸¤ä¸ªå¯¹è±¡-å®ä»¬é½å
·ææå第ä¸ä¸ªå¯¹è±¡çå¼ç¨-è¿è¡åºååï¼ä¼åçä»ä¹æ
åµï¼å½æä»¬ä»å®ä»¬çåºååç¶ææ¢å¤è¿ä¸¤ä¸ªå¯¹è±¡æ¶ï¼ç¬¬ä¸ä¸ªå¯¹è±¡ä¼åªåºç°ä¸æ¬¡åï¼å¦æå°è¿ä¸¤ä¸ªå¯¹è±¡åºååæç¬ç«çæä»¶ï¼ç¶åå¨ä»£ç çä¸åé¨å对å®ä»¬è¿è¡ååºååè¿åï¼åä¼ææ ·å¢ï¼
ä¸é¢è¿ä¸ªä¾å说æäºä¸è¿°é®é¢ï¼
```java
// serialization/MyWorld.java
import java.io.*;
import java.util.*;
class House implements Serializable {}
class Animal implements Serializable {
private String name;
private House preferredHouse;
Animal(String nm, House h) {
name = nm;
preferredHouse = h;
}
@Override
public String toString() {
return name + "[" + super.toString() +
"], " + preferredHouse + "\n";
}
}
public class MyWorld {
public static void main(String[] args) {
House house = new House();
List