Visualizzazione dei risultati da 1 a 8 su 8
  1. #1

    serializzazione con metodi defaultWrite/ReadObject

    Ciao!
    Sto cercando di capire il funzionamento della serializzazione usando i metodi readObject e writeObject. Non ho chiaro pero' il funzionanemento e l'utilita' dei metodi custom defaultWrite/ReadObject da usare in essi. Qualcuno saprebbe darmi delucidazioni a riguardo?
    grazie

  2. #2
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284

    Re: serializzazione con metodi defaultWrite/ReadObject

    Originariamente inviato da maninblack
    Sto cercando di capire il funzionamento della serializzazione usando i metodi readObject e writeObject. Non ho chiaro pero' il funzionanemento e l'utilita' dei metodi custom defaultWrite/ReadObject da usare in essi. Qualcuno saprebbe darmi delucidazioni a riguardo?
    grazie
    I metodi defaultReadObject()/defaultWriteObject() servono per gestire la (de)serializzazione automatica dei campi che sono serializzabili "normalmente".

    Ma questi due metodi non vanno mai usati direttamente invocandoli su un ObjectInputStream /ObjectOutputStream! Vanno usati solo all'interno dei metodi privati writeObject/readObject che si implementano nella classe per prendersi la responsabilità di (de)serializzare dello "stato" che non potrebbe essere gestito in automatico.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  3. #3
    Si si, questo e' abbastanza chiaro, ma non capisco bene il funzionamento.
    Per esempio qui cerco di serializzare semplicemente un intero ma ottengo un IOException sulla chiamata a "oos.defaultWriteObject()".
    Il codice sembra corretto pero'.

    codice:
    	static public <T> void main(String pp[]) throws IOException{
    
    	Tests test = new Tests("babbo", "natale");
    
        try {
    	
    		ObjectOutputStream os = new ObjectOutputStream(new FileOutputStream("c:\\myFile.txt"));
    		test.writeObject(os);
    
    		ObjectInputStream is = new ObjectInputStream(new FileInputStream("c:\\myFile.txt"));
    		test.readObject(is);
    
    	   }
    	    catch (IOException ex)
    		{System.out.println("IOEx");}
    		catch (ClassNotFoundException ex)
    		{System.out.println("class");
    		}
    	    catch (Exception ex)
        	{System.out.println("exc");
           }
        	
    	}
    
    	private void writeObject(ObjectOutputStream oos) throws IOException{
    
    		oos.defaultWriteObject();
    		oos.writeInt(2);
    		oos.flush();
    		oos.close();
    
    	}
    	private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException{
    		in.defaultReadObject();
    	    int i = in.readInt();
    	    in.close();
    	}

  4. #4
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da maninblack
    Si si, questo e' abbastanza chiaro, ma non capisco bene il funzionamento.
    Per esempio qui cerco di serializzare semplicemente un intero ma ottengo un IOException sulla chiamata a "oos.defaultWriteObject()".
    Il codice sembra corretto pero'.
    No, non lo è. Innanzitutto non vedo il senso (se non per questioni di esempio) nel serializzare una costante. Ma a parte questo in quei metodi privati non devi fare tu flush o close!!!
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  5. #5
    ok supponiamo di avere variabili transient e static cioe' non serializzabili e di eliminare il codice superfluo(flush etc etc)...significa che i due metodi default si prenderanno carico di tutta la deserializzazione in maniera automatica, in quanto, non servira' piu' aggiungere del codice manualmente. Ma ai fini dell'utilita' quale vantaggio danno?

  6. #6
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da maninblack
    ok supponiamo di avere variabili transient e static cioe' non serializzabili e di eliminare il codice superfluo(flush etc etc)...significa che i due metodi default si prenderanno carico di tutta la deserializzazione in maniera automatica, in quanto, non servira' piu' aggiungere del codice manualmente. Ma ai fini dell'utilita' quale vantaggio danno?
    No alt. Nei due metodi privati l'uso di defaultWriteObject/defaultReadObject consente la (de)serializzazione di quei campi che sono serializzabili in automatico e senza problemi particolari. Per campi 'transient' dopo i defaultXXX() sarai tu in quei metodi privati a gestire la serializzazione in modo "personalizzato".

    Esempio: una classe MiaClasse che è serializzabile ha un campo String e uno di tipo CoppiaNum (modella 2 numeri). Questa classe non è serializzabile e supponiamo che non l'hai fatta tu (non hai accesso al sorgente) o magari, per varie ragioni, non deve essere serializzabile.
    Anche se MiaClasse implementa Serializable ... il problema c'è eccome e sbucherebbe fuori a runtime!!

    Ecco la soluzione:

    codice:
    class MiaClasse implements Serializable {
        private String str;
        private transient CoppiaNum coppiaNum;    // transient!!!
    
        public MiaClasse() {
            coppiaNum = new CoppiaNum();
        }
    
        public void setStr(String str) { this.str = str; }
        public void setCoppia(CoppiaNum coppiaNum) { this.coppiaNum = coppiaNum; }
        public String getStr() { return str; }
        public CoppiaNum getCoppiaNum() { return coppiaNum; }
    
        public String toString() { return str + " " + coppiaNum; }
    
        private void writeObject(ObjectOutputStream oos) throws IOException {
            oos.defaultWriteObject();
            oos.writeInt(coppiaNum.getNum1());
            oos.writeInt(coppiaNum.getNum2());
        }
    
        private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException {
            ois.defaultReadObject();
            coppiaNum = new CoppiaNum();
            coppiaNum.setNum1(ois.readInt());
            coppiaNum.setNum2(ois.readInt());
        }
    }
    
    class CoppiaNum {
        private int num1;
        private int num2;
    
        public void setNum1(int num1) { this.num1 = num1; }
        public void setNum2(int num2) { this.num2 = num2; }
        public int getNum1() { return num1; }
        public int getNum2() { return num2; }
    
        public String toString() { return num1 + " " + num2; }
    }
    (ho compattato i setter/getter solo per questioni di spazio e quindi brevità!)

    Nota cosa fanno i due metodi privati writeObject/readObject, usano i defaultXXXObject() per dire: ok ObjectXXXStream, preoccupati di (de)serializzare quello che sei in grado di gestire (nel caso sopra il campo 'str' che è String e pertanto Serializable). Poi mi preoccupo io di (de)serializzare il dati del campo 'coppiaNum' che la serializzazione non saprebbe gestire.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

  7. #7
    Grazie per l'ottimo esempio. Ma visto che i campi static e transient non sono serializzabili, che motivo ce' di gestirli?? Tanto solo il costruttore della classe non serializzabile verra' eseguito dopo la serializzazione mentre quello della classe serializzabile no.

  8. #8
    Utente di HTML.it L'avatar di andbin
    Registrato dal
    Jan 2006
    residenza
    Italy
    Messaggi
    18,284
    Originariamente inviato da maninblack
    Ma visto che i campi static e transient non sono serializzabili, che motivo ce' di gestirli??
    I campi static no appunto, non fanno parte dello "stato" di un oggetto. Quindi comunque, in ogni caso, non devono mai essere trattati a livello della serializzazione.

    Marcare un campo di istanza come 'transient' vuol solo dire che la serializzazione automatica, quella di default fatta dai defaultXXXObject() non deve trattarlo.

    E i motivi potrebbero essere due:

    - Il campo non ha proprio senso che sia serializzato. Supponi ad esempio un contatore che conta le modifiche allo stato dell'oggetto. Avrebbe senso serializzarlo? Direi di no. E in tal caso non devi fare nulla di particolare (chiaramente alla deserializzazione il campo avrà il valore di default, se non gestito diversamente tramite quei metodi privati).

    - Il campo referenzia un oggetto di una classe non serializzabile ma il suo "stato" va comunque serializzato perché importante per lo stato complessivo dell'oggetto. Ma non essendo possibile farlo in automatico (pena eccezione, se non fosse transient) va gestito esplicitamente in quei metodi privati.
    Andrea, andbin.devSenior Java developerSCJP 5 (91%) • SCWCD 5 (94%)
    java.util.function Interfaces Cheat SheetJava Versions Cheat Sheet

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2025 vBulletin Solutions, Inc. All rights reserved.