문제

방법 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;
}

작동하지 않기 때문입니다 super() 전에 호출됩니다 m_myData 초기화되고 super() 전화 writeStreamHeader(). 이 문제를 해결할 수있는 유일한 방법은 사용하는 것입니다. ThreadLocal 처럼:

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>();
}

이것은 작동하는 것 같지만 더 나은 (덜 어리석은) 방법이 있습니까?

도움이 되었습니까?

해결책

이런 종류의 문제를 해결하는 일반적인 방법이 있습니다. 클래스와 내부 클래스를 만들고 외부 범위에서 변수를 참조하십시오. (참고, 이것은 만 작동합니다 -target 1.4 또는 현재 버전의 Javac의 기본값 인 Greter. 와 함께 -target 1.3 당신은 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();
        }
    };
}

그러나 구성하기 전에 데이터를 작성하는 것이 더 쉬울 것입니다. ObjectOuputStream.

다른 팁

이렇게 할 수 없었습니다. 필요한 필드를 초기화 한 경우 슈퍼 생성자의 WritesTreamEader 호출을 무시하고 직접 수행하십시오.

public class MyObjectOutputStream extends ObjectOutputStream {

private boolean initalized = false;
private final int m_myData;

protected MyObjectOutputStream(int myData, OutputStream out) throws IOException, SecurityException {
    super(out);
    m_myData = myData;
    initalized = true;
    writeStreamHeader();
}

protected void writeStreamHeader() throws IOException {

    if(!initalized){
        return;
    }

    write( m_myData );
    super.writeStreamHeader();
}
}

편집하다:

또는 제안한대로 thilo, 그것은 다음과 같이 쓸 수 있습니다.

public class MyObjectOutputStream extends ObjectOutputStream {

    private final int m_myData;

    protected MyObjectOutputStream(int myData, OutputStream out) throws IOException, SecurityException {
        super(out);
        m_myData = myData;
        write( m_myData );
        super.writeStreamHeader();
    }

    protected void writeStreamHeader() throws IOException {
        // work is done in the constructor
    }
}

일반적으로 생성자로부터 비 결절 방법을 호출하는 것은 나쁜 생각입니다 (정확히 당신이 제시 한 이유).

ObjectOutputStream을 확장하지 않고 사용자 정의 직렬화를 달성 할 수 있습니까? 스트림 구성에 대해 생각하고 있습니다. 예를 들어, ObjectOutputStream 이전에 기본 출력 스트림에 헤더를 작성하여 헤더를 선불로 작성할 수 있습니다. 이것은 분명히 ObjectOutputStream의 서브 클래스에서 수행 할 수 없지만 외부에서 쉽게 수행 할 수 있습니다.

   out.write(myExtraHeader);
   ObjectOutputStream oos = new ObjectOutputStream(out);

원한다면 Stu Thompson이 그의 대답에서 제안한 것처럼 ObjectOutput 인터페이스 뒤에이 모든 것을 멋지게 감싸서 외부를 거의 ObjectOutputStream처럼 볼 수 있습니다.

업데이트:

ObjectOutputStream의 javadocs 및 소스를 보면 호출하지 않는 두 번째 (보호 된) 생성자가 있습니다. writeStreamHeader().

그러나이 생성자는 다른 내부 구조를 초기화하지 않습니다. 문서를 인용하기 위해, "대상의 PutputStream의 구현에 사용 된 개인 데이터를 할당 할 필요가 없도록 ObjectOutputStream을 완전히 상환하는 서브 클래스의 경우"입니다. 이 경우 "writeObjectOverRide"와 같은 다른 방법도 호출됩니다. 지저분한...

상속 대신 구성을 사용하십시오.

public class MyObjOutStream implements DataOutput, ObjectOutput, ObjectStreamConstants {
    //same interfaces that ObjectOutputStream implements

    private ObjectOutputStream objOutStream;

    //implement all the methods below
}

대상이 될 때만 ObjectOutputStream 인스턴스. 인터페이스에서 구현 해야하는 나머지 방법은 동일한 메소드를 호출 할 수 있습니다. objOutStream

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top