2011-12-25 19 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.

Problemi correlati