The method ObjectOutputStream.writeStreamHeader()
can be overridden to prepend or append data to the header. However, if that data is based on an argument passed to the derived class's constructor like:
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;
}
it doesn't work because super()
is called before m_myData
is initialized and super()
calls writeStreamHeader()
. The only way I can think to work around this is by using ThreadLocal
like:
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>();
}
This seems to work, but is there a better (less clunky) way?
There is a general way to solve this sort of problem. Make the class and inner class and reference a variable in the outer scope. (Note, this only works with -target 1.4
or greter, which is the default in current versions of javac. With -target 1.3
you will get an NPE.)
public static ObjectOutputStream newInstance(
final int myData, final OutputStream out
) throws IOException {
return new ObjectOutputStream(out) {
@Override
protected void writeStreamHeader() throws IOException {
write(myData);
super.writeStreamHeader();
}
};
}
But, it's probably easier just to write the data out before constructing the ObjectOuputStream
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With