È possibile sovrascrivere il metodo ObjectOutputStream.writeStreamHeader()
per aggiungere o aggiungere dati all'intestazione. Tuttavia, se i dati si basa su un argomento passato al costruttore della classe derivata come:Come eseguire l'override di ObjectOutputStream.writeStreamHeader()?
public class MyObjectOutputStream extends ObjectOutputStream {
public MyObjectOutputStream(int myData, OutputStream out) throws IOException {
super(out);
m_myData = myData;
}
protected void writeStreamHeader() throws IOException {
write(m_myData); // WRONG: m_myData not initialized yet
super.writeStreamHeader();
}
private final int m_myData;
}
non funziona perché super()
viene chiamato prima m_myData
è inizializzato e super()
chiamate writeStreamHeader()
. L'unico modo che posso pensare per ovviare a questo è quello di utilizzare ThreadLocal
come:
public class MyObjectOutputStream extends ObjectOutputStream {
public MyObjectOutputStream(int myData, OutputStream out) throws IOException {
super(thunk(myData, out));
}
protected void writeStreamHeader() throws IOException {
write(m_myData.get().intValue());
super.writeStreamHeader();
}
private static OutputStream thunk(int myData, OutputStream out) {
m_myData.set(myData);
return out;
}
private static final ThreadLocal<Integer> m_myData = new ThreadLocal<Integer>();
}
Questo sembra funzionare, ma c'è un modo migliore (meno goffo)?
Mi piace questa soluzione perché sovrascrive writeStreamHeader() "come previsto" e l'intestazione viene scritta nel "momento giusto" e non fa ipotesi su quando il metodo viene chiamato dal costruttore della classe base. In quanto tale, è "a prova di futuro". –
Neat. Apparentemente l'ambito esterno viene inizializzato prima del costruttore della superclasse. – Thilo
Sì, le specifiche VM dovevano essere cambiate per consentire quel genere di cose. Può ancora diventare complicato - l'ultima volta che ho controllato un esempio nel JLS non funzionava con il javac del tempo. –