2011-12-25 6 views
28

Załóżmy, że masz te dwie klasy Foo i bar, gdzie Foo Bar rozszerza i wdraża Serializableserializacji obiektu Java i dziedziczenie

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; 
} 
} 

Zauważ, że Foo nie wykona Serializable. Co się dzieje, gdy pasek jest serializowany?

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); 

} 

wyświetla "Domyślnie 21". Pytanie brzmi, dlaczego domyślny konstruktor jest wywoływany, gdy klasa nie jest serializowana?

+1

Nie można nagle utworzyć instancji niewinnej klasy bez wywoływania jej konstruktora, więc specyfikacja szeregowa wymaga wywołania konstruktora klas, które nie mogą być szeregowane./Możesz chcieć seryjnego proxy. –

Odpowiedz

20

Serializowalny to tylko "interfejs znacznika" dla danej klasy.

Ale że klasa musi stosować się do pewnych zasad:

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

Aby umożliwić podtypy klasy non-serializable być szeregowane, podtyp może przejąć odpowiedzialność za zapisywanie i przywracanie stanu od pola publiczne, chronione i (jeśli są dostępne) pakietu nadrzędnego supertype: . Podtyp ten może przyjąć tę odpowiedzialność tylko wtedy, gdy klasa rozszerza się o dostępny konstruktor no-arg w celu zainicjowania stanu klasy . Błędem jest zadeklarowanie klasy Serializable, jeśli nie ma to miejsca w przypadku .

odpowiedzieć @Sleiman Jneidi pytanie zadane w komentarzu, w dokumentacji systemu Oracle wspomniano powyżej, jego wyraźnie wymienione

Podczas deserializacji, pola klas non-serializować zostanie zainicjowany za pomocą publicznych lub chronione konstruktor no-arg klasy. Konstruktor no-arg musi być dostępny dla podklasy nadającej się do serializacji. Pola podlegających serializacji podklas zostaną przywrócone ze strumienia.

W ten sposób domyślny konstruktor no-arg klasy Foo wywołał, spowodował inicjalizację.

+0

Wiem o tym. ale dlaczego wywołuje domyślny konstruktor. Nie pytam, co jest Serializable? –

+5

@sleimanjneidi ponieważ "Aby umożliwić nadawanie podtypów klas niezdatnych do serializacji, podtyp może przejąć odpowiedzialność ** za zapisanie i przywrócenie stanu pól pakietu publicznego nadprogramowych, chronionych i (jeśli to możliwe) **". Oznacza to, że 'Bar' powinien ręcznie ustawić' pole 'nazwy' Foo ', ponieważ' Foo' nie jest serializowalny – fge

4

może to być the defaultWriteObject can only write the non-static and non-transient fields of the current class. Gdy klasa nadrzędna nie implementuje interfejsu Serializable, pola w superklasie nie mogą zostać przekształcone do postaci szeregowej w strumieniu.

+0

Tak, jeśli nadklasa nie implementuje Serializowalne, nie będzie serializowana, więc gdy deserializowany, jej domyślny konstruktor zostanie wywołana, a wartości domyślne zostaną przydzielone do wszystkich jej zmiennych. – Akash5288

0

Właściwie po przeczytaniu obiektu klasy nadrzędnej z powrotem, ponieważ nie jest on w ogóle serializowany. Tak więc, aby ponownie nie serializować, JVM przechodzi ten sam proces, jakiego używa się do utworzenia nowego obiektu za pomocą nowego słowa kluczowego.