"Morten Nedertoft" <mmn@pr-group.sdu.dk> skrev i en meddelelse
news:3A6EB3D6.8FF32753@pr-group.sdu.dk...
> "Niels Ull Harremoës" wrote:
> >
> > "Morten Nedertoft" <mmn@pr-group.sdu.dk> skrev i en meddelelse
> > news:3A6C8A7A.1347CE69@pr-group.sdu.dk...
> > > Hej
> > >
> > > Jeg sidder og taenker over hvorfor
> > >
> > > private synchronized void writeObject(java.io.ObjectOutputStream s)
> > > throws java.io.IOException
> > >
> > > ikke bare er public. Er der en der har svaret?
> >
> > Muligvis, fordi denne metode slet ikke behøver at findes. Det er jo op
til
> > den, der implementerer standardbibliotekerne for en given platform,
hvordan
> > han implementerer serialisering. Og det kunne jo være, at han bare
brugte en
> > hurtig native implementering til at gemme objekterne.
>
> Man kan da bare lade vaere med at overskrive Object-klassens
> writeObject.
Ja, men det er jo slet ikke sikkert, at det overhovedet er nødvendigt at
lave det funktionskald - det hele kunne jo være native. Nå, men pyt, det er
nokikke den væsentligste grund.
>
> > En anden grund til at metoden ikke findes, er at jo færre metoder, der
er i
> > Object, jo bedre. Ved de fleste implementeringer af JVM'en, giver hver
> > eneste metode i Object en ekstra indgang (antagelig 4 bytes) i
> > funktionstabellen for hver eneste klasse! Det gør faktisk en forskel i
det
> > lange løb.
>
> Er det noget du har laest, eller er det noget du selv har fundet ud af?
Det er noget jeg slutter mig til ud fra min viden om hvordan man
implementerer oversættere og fortolkere. En anden detalje er, at for at gøre
Java så simpelt som muligt at lære, bør Object have så få metoder som
muligt. Jeg kan komme på flere andre metoder, som kunne være praktiske - fx.
en isLocal() ifb. med RMI.
> > Den væsentligste grund er nok, at du aldrig selv bør kalde writeObject.
Hvis
> > du gør det, går du uden om den logik, der checker at hvert objekt kun
bliver
> > skrevet een gang til en stream, uanset hvor mange gange den forekommer i
en
> > datastruktur. Der er også andre ting, som fx skrivning af
> > klasse-information, som kortsluttes.
>
> Man kunne jo aendre signaturen for writeObject i Object-klassen, og lade
> den returnere en boolsk vaerdi for om objektet allerede er blevet
> serialiseret. Saa kunne man implementere writeObject noget a la:
>
> public boolean writeObject(ObjectOutStream s) throws IOException
> {
> if (!super.writeObject(s))
> {.....}
> }
Ja. Men hvad hvis man glemte det? Jo mere programmøren er nødt til at gøre,
jo større er sandsynligheden for at han laver fejl. Et godt API prøver at
forebygge fejl fra den, der bruger det.
Et andet eksempel:
Antag vi har tre klasser, A, B og C. B extender A, og C extender B.
A har en writeObject, B er bare markeret som Serializable og har et par
private felter, C skal også have en writeObject. Hvordan vil du implementere
writeObject i klasse C? Husk, da du skrev B anede du ikke, at du en dag
ville lave C. Og du bør jo heller ikke være nødt til at tænke over, om A nu
serialiserer med writeObject eller med standard serialiseringen.
Hvis man bruger den kode du foreslog ovenfor, får du ikke skrevet felterne i
B.
public boolean writeObject(ObjectOutStream s) throws IOException
{
if (!super.writeObject(s)) // Ups! kalder A's writeObject
{.....}
}
Det er derfor, at der i specifikationen af writeObject explicit står, at du
ikke behøver gemme værdier i forældreklasser - serialiseringsmekanismen
løber igennem hierarkiet og kalder enten writeObject eller gemmer
ikke-transient felter for hver kalsse efter tur.
Har du i øvrigt læst specifikationens afsnit om serialisering
(
http://java.sun.com/j2se/1.3/docs/guide/serialization/spec/serialTOC.doc.ht
ml) - den gennemgår
en hel del af detaljerne omkring serialisering. Jeg så en gang en bog, der
gik lidt bag om designet af Java og standard API'et - men jeg kan desværre
ikke huske hvad den hed eller for