2011-12-25 7 views
28

Diciamo che avete queste due classi, Foo e Bar dove barra si estende Foo e realizza SerializableJava serializzazione degli oggetti e l'eredità

class Foo { 

public String name; 

public Foo() { 
    this.name = "Default"; 
} 

public Foo(String name) { 
    this.name = name; 
} 
} 

class Bar extends Foo implements java.io.Serializable { 

public int id; 

public Bar(String name, int id) { 
    super(name); 
    this.id = id; 
} 
} 

noti che Foo non implementa Serializable. Quindi cosa succede quando la barra viene serializzata?

public static void main(String[] args) throws Exception { 

    FileOutputStream fStream=new FileOutputStream("objects.dat"); 
    ObjectOutputStream oStream=new ObjectOutputStream(fStream); 
    Bar bar=new Bar("myName",21); 
    oStream.writeObject(bar); 

    FileInputStream ifstream = new FileInputStream("objects.dat"); 
    ObjectInputStream istream = new ObjectInputStream(ifstream); 
    Bar bar1 = (Bar) istream.readObject(); 
    System.out.println(bar1.name + " " + bar1.id); 

} 

stampa "Predefinito 21". La domanda è: perché il costruttore predefinito viene chiamato quando la classe non è serializzata?

+1

Non è possibile creare improvvisamente istanze di una classe innocente senza chiamare il suo costruttore, quindi la specifica seriale richiede di chiamare un costruttore di classi non serializzabili./Potresti volere un proxy seriale. –

risposta

20

Serializable è solo una "interfaccia marker" per una determinata classe.

Ma quella classe deve rispettare alcune regole:

http://docs.oracle.com/javase/1.5.0/docs/api/java/io/Serializable.html

Per consentire sottotipi di classi non serializzabili da serializzare, il sottotipo può assumersi la responsabilità di salvare e ripristinare lo stato di i campi pubblici, protetti e (se accessibili) del supertipo, . Il sottotipo può assumere questa responsabilità solo se la classe si estende con un costruttore no-arg accessibile per inizializzare lo stato della classe . È un errore dichiarare una classe serializzabile se questo non è il .

per rispondere @Sleiman Jneidi domanda posta in commento, nella documentazione di Oracle di cui sopra, il suo chiaramente menzionato

durante la deserializzazione, i campi di classi non serializzabili verranno inizializzate con il pubblico o protetto costruttore no-arg della classe. Un costruttore no-arg deve essere accessibile alla sottoclasse che è serializzabile. I campi delle sottoclassi serializzabili verranno ripristinati dallo stream.

Così, il costruttore no-arg predefinito della classe Foo chiamato, ha provocato l'inizializzazione.

+0

Lo so. ma perché chiama il costruttore predefinito. Non sto chiedendo cosa è serializzabile? –

+5

@sleimanjneidi perché "Per consentire la serializzazione di sottotipi di classi non serializzabili, il sottotipo può assumersi la responsabilità ** di salvare e ripristinare lo stato dei campi del pacchetto pubblico, protetto e (se accessibile) del supertipo **". Ciò significa che 'Bar' dovrebbe impostare il campo' nome' di 'Foo'" a mano ", dato che' Foo' non è serializzabile – fge

4

può essere che the defaultWriteObject can only write the non-static and non-transient fields of the current class. Una volta che la superclasse non implementa l'interfaccia Serializable, i campi nella superclasse non possono essere serializzati nello stream.

+0

Sì se la superclasse non implementa Serializable, non sarà serializzato, quindi quando deserializzato, il suo costruttore predefinito sarà chiamato e i valori di default saranno assegnati a tutte le sue variabili. – Akash5288

0

In realtà quando si leggerà l'oggetto classe gen come non è serializzato affatto .. quindi per le non serializzabili di nuovo JVM passa attraverso lo stesso processo che usa per andare quando creiamo il nuovo oggetto usando la nuova parola chiave.