La méthode ObjectOutputStream.writeStreamHeader()
peut être remplacée pour ajouter ou ajouter des données à l'en-tête. Toutefois, si ces données est basée sur un argument transmis au constructeur de la classe dérivée comme:Comment remplacer 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;
}
cela ne fonctionne pas parce que super()
est appelé avant m_myData
est initialisé et super()
appels writeStreamHeader()
. La seule façon que je peux penser à contourner c'est en utilisant ThreadLocal
comme:
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>();
}
Cela semble fonctionner, mais est-il un moyen de mieux (moins maladroits)?
J'aime cette solution car elle écrase writeStreamHeader() "comme prévu" et l'en-tête est écrit au "bon moment" et ne fait aucune hypothèse sur le moment où la méthode est appelée par le constructeur de la classe de base. En tant que tel, il est "à l'épreuve du futur". –
Neat. Apparemment, la portée externe est initialisée avant le constructeur de la superclasse. – Thilo
Oui, la spécification de la VM a dû être changée pour permettre ce genre de chose. Cela peut encore se compliquer - la dernière fois que j'ai vérifié un exemple dans la JLS ne fonctionnait pas avec le javac de l'époque. –