2010-01-22 1 views
6

C'è una classe che desidero serializzare e implementa Serializable, ma uno degli oggetti che contiene non implementa Serializable.In java, è possibile aggiungere l'interfaccia Serializable alla classe che non ce l'ha in fase di runtime?

C'è un modo per modificare la classe in fase di esecuzione per implementare l'interfaccia Serializable in modo che possa serializzarlo? Non posso cambiarlo in fase di compilazione perché è una libreria di terze parti.

Forse dovrei usare una sorta di scrittore di bytecode o qualcosa del genere?

MODIFICA: Sia la classe contenente che la classe contenuta si trovano nella libreria di terze parti, quindi non penso di poter contrassegnare qualcosa come transitorio. La classe contenente è contrassegnata come serializzabile, ma contiene un oggetto che non lo è.

Sto bene scrivendo un metodo di serializzazione personalizzato per la classe, non sono sicuro di come lo farei, dovrei usare la reflection per ottenere i valori delle variabili private?

risposta

5

Leggendo il javadoc per Serializable, vedo:

Le classi che richiedono una gestione speciale durante la serializzazione e processo di deserializzazione deve implementare metodi speciali con queste esatte firme:

private void writeObject(java.io.ObjectOutputStream out) 
    throws IOException 
private void readObject(java.io.ObjectInputStream in) 
    throws IOException, ClassNotFoundException; 
private void readObjectNoData() 
    throws ObjectStreamException; 

che è possibile utilizzare per serializzare manualmente i campi non cooperativi. È possibile esaminare l'utilizzo di ASM, ma sembra difficile credere che sia una soluzione gestibile.

+0

Utilizzare l'interfaccia Externalizable http://java.sun.com/j2se/1.3/docs/api/java/io/Externalizable.html –

+0

La classe contenente è anche nella libreria di terze parti, quindi non penso di poter aggiungere quei metodi ad esso. – Kyle

+0

Quindi immagino sia ora di imparare ASM. – bmargulies

3

I campi possono essere saltati utilizzando il modificatore transient. È possibile aggiungere ulteriori dati allo stream fornendo i metodi readObject e writeObject. Le classi possono essere suddivise in sottoclassi per renderle serializzabili (sebbene sia necessario gestire i dati della superclasse) o utilizzare un proxy seriale (vedere Java efficace).

0

Se una classe non è contrassegnata come serializzabile, potrebbe essere una buona ragione (prendere le connessioni al database come esempio). Quindi, prima di tutto renditi chiaro se hai davvero bisogno di serializzare anche quell'oggetto. Se hai solo bisogno di serializzare l'oggetto circostante, potresti considerare di contrassegnare l'oggetto contenuto come transitorio.

1

Prima di tutto, hai davvero bisogno di fare questo ? Forse la classe nella libreria di terze parti non è serializzabile dal design. Anche se è solo un'omissione piuttosto che una decisione deliberata, è abbastanza facile scrivere un metodo di serializzazione personalizzato in una classe helper. Se hai hai per farlo (come ho dovuto, per qualcosa di simile). Dai un'occhiata a Javassist. Si può fare qualcosa di simile:

ClassPool pool = ClassPool.getDefault(); 
CtClass cc = pool.get("mypackage.MyClass"); 
cc.addInterface(pool.get("java.io.Serializable")) 

EDIT: È possibile utilizzare una serializzazione API di terze parti come XStream invece di fare tutto il lavoro sporco da soli.

+0

Informazioni sulla scrittura del metodo di serializzazione personalizzato in una classe helper: Come dovrei farlo? Devo usare la reflection per ottenere i valori delle variabili private? – Kyle

+0

LOL. Questa risposta è _already_ il terzo risultato di Google per "serializzazione java di terze parti" 32 minuti dopo che la domanda è stata posta. –

0

È possibile utilizzare java.lang.reflect.Proxy per aggiungere l'interfaccia Serializable alle istanze dell'oggetto su cui non si ha il controllo del ciclo di vita (cioè non è possibile eseguire la sottoclassificazione) e ottenerle serializzate in questo modo. Ma allora non saresti ancora in grado di leggerli senza un altro trucco (cioè introducendo una classe surrogata).

Si consiglia di cercare un'alternativa al meccanismo Serializable Java in generale. È praticamente rotto dalla progettazione in diversi modi.

+0

È strano che così tanti sviluppatori stiano bene con la serializzazione "broken by design" di Java. Rollare la propria serializzazione è una soluzione orribile - così tante librerie/framework Java standard utilizzano Serializable - si suppone di programmare una soluzione alternativa per ognuno di essi? – Nate