2015-04-13 11 views
6

Sto cercando di capire come funziona la serializzazione con Java e la sua ultima versione. Sto cercando di serializzare un lambda come questo:lambda serializzato e nessun serialVersionUID?

Runnable r = (Runnable & Serializable)() -> {System.out.println("This is a test");}; 

ma noto che non ho alcun avvertimento circa l'assenza di una variabile serialVersionUID. È normale ?

so che verrà generato in fase di esecuzione tuttavia è fortemente raccomandato per definirla: https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html

Se una classe serializzabile non dichiara esplicitamente un serialVersionUID, quindi il runtime serializzazione calcolerà un predefinita serialVersionUID valore per quella classe in base ai vari aspetti della classe, come descritto nella Specifica di serializzazione Java (TM) Object . Tuttavia, si raccomanda che tutti classi serializzabili espressamente dichiarano valori serialVersionUID, poiché default serialVersionUID calcolo è molto sensibile alla classe particolari che possono variare a seconda implementazioni compilatore e può quindi favorire InvalidClassExceptions imprevisti durante deserializzazione. Pertanto, per garantire un valore serialVersionUID costante tra diverse implementazioni del compilatore java, una classe serializzabile deve dichiarare un valore serialVersionUID esplicito. Si consiglia inoltre esplicitamente che le dichiarazioni esplicite serialVersionUID utilizzino il modificatore privato laddove possibile, poiché tali dichiarazioni si applicano solo a la classe immediatamente dichiarante - i campi serialVersionUID non sono utili come membri ereditati. Le classi di array non possono dichiarare un serialVersionUID esplicito , in modo che abbiano sempre il valore calcolato predefinito, ma il requisito per la corrispondenza dei valori serialVersionUID non è valido per le classi di array .

Cosa devo fare? Come posso definirlo nel mio Lambda?

Grazie

+1

Sembra che non ci sia modo di dichiarare un campo 'serialVersionUID' a causa della mancanza di una classe di definizione. E questo porta direttamente alla domanda successiva: per quale motivo dovrebbe essere serializzabile un lambda? Non ha campi e quindi nessun dato! – Seelenvirtuose

+1

@Seelenvirtuose Un lambda serializzato contiene valori che sono stati catturati nel momento in cui è stata valutata la lambda. Se una lambda viene valutata più volte con diversi valori catturati, gli oggetti che incarnano i lambda saranno diversi, così come le loro rappresentazioni serializzate. –

+0

@StuartMarks Ovviamente non ho pensato abbastanza lontano. Grazie per averlo indicato. In effetti, mi ha aiutato a cambiare (costruire?) La mia mente. – Seelenvirtuose

risposta

6

Il serialVersionUID è rilevante solo per le classi che generano un stream identifier. Questo non è il caso se la classe serializzabile ha un metodo writeReplace() (descritto anche nello Serializable documentation) che restituisce un oggetto sostituto di una classe diversa, in quanto tale rappresentazione è completamente disaccoppiata dalla classe originale. Questo è ciò che accade con le istanze lambda serializzabili, vedi SerializedLambda:

Implementors di lambda serializzabili, come i compilatori o le librerie di runtime lingua, sono tenuti a garantire che le istanze deserializzare correttamente. Uno dei mezzi per farlo è assicurarsi che il metodo writeReplace restituisca un'istanza di SerializedLambda, piuttosto che consentire la serializzazione predefinita per procedere.

Quindi è un'istanza di SerializedLambda che finisce nello stream e quindi la responsabilità di quella classe di avere una rappresentazione serializzata stabile. Sfortunatamente ciò non ti protegge da possibili incompatibilità.

Su deserializzazione, un metodo di sintesi della classe definire l'espressione lambda verrà chiamato (confrontarle this e this answer) che respinge tentativi deserializzazione che non hanno una definizione esistente di un'espressione lambda all'interno di tale classe, mentre il corrispondente può dipendere da aspetti sottili della definizione di lambda. Si noti che anche la ricompilazione della classe di definizione con Eclipse anziché javac potrebbe interrompere la compatibilità di serializzazione.

Non lo security impacts of Serializable lambdas. In generale, consiglio di evitare di usarlo.

Problemi correlati