2017-05-23 1 views
1

모든 protobuf 메시지를 deserialize/parse하는 데 사용할 수있는 일반 Java 클래스를 작성하려고합니다.Java의 일반 protobuf deserializer

여기에 코드가 완벽한 세계에 보일 것입니다 방법은 다음과 같습니다

public abstract class ProtoDeserializer<T extends Message> { 

    public T deserialize(final byte[] bytes) throws Exception {  
     Parser<T> parser = T.getParserForType(); // Syntax Error: this method is not static! 

     T message = parser.parseFrom(bytes); 
     validate(message); 
     return message; 
    } 

    public abstract void validate(final T message) throws Exception; 
} 

을 그러나, 나는 일반적인 protobuf 메시지에 대한 올바른 파서를 얻을 수 아니에요. 그러한 일반적인 클래스를 구현하는 올바른 방법은 무엇입니까?

+0

현재 해결 방법은 구문 분석기를 생성자 인수로 전달하는 것입니다. 그러나 중복 된 정보이기 때문에 그것을 피하는 것이 좋을 것입니다. – maja

+1

'getParserForType'이'static'이 아닌지 물어볼 수도 있습니다. 어떻게 호출합니까? 'T'를 인스턴스화합니까? –

+0

@ JornVernee 위의 코드에서 구문 오류입니다. 실제로 작동하지 않습니다. 그것은 그것이 작동하기를 기대하는 방법의 예입니다. – maja

답변

1

간단한 생성자에 인수로 파서를 전달하는 것입니다 :

public abstract class ProtoDeserializer<T extends Message> { 

    private final Parser<T> parser; 

    public ProtoDeserializer(Parser<T> parser) { 
     this.parser = parser; 
    } 

    public T deserialize(final byte[] bytes) throws Exception {  
     T message = parser.parseFrom(bytes); 
     validate(message); 
     return message; 
    } 

    public abstract void validate(final T message) throws Exception; 
} 

파서를 전달하는 것이 나의 현재의 해결 방법입니다. 그러나 중복 된 정보이기 때문에 그것을 피하는 것이 좋을 것입니다.

중복 될 수 있지만 컴파일러/런타임에는 중복되지 않습니다.

당신이 클래스의 원시 구현을 만들 수 있음을 고려하는 경우 : T에서 온 것

ProtoDeserializer proto = new ProtoDeserializer() { 
    ... 
}; 

유형입니다.

이것은 지워진 제네릭의 현실입니다. generic 매개 변수의 유형 정보가 필요하면 수동으로 제공해야합니다.

private final Parser<T> parser; 

public ProtoDeserializer() { 
    Class<?> subclass = this.getClass(); 

    try { 
     ParameterizedType pType = (ParameterizedType) subclass.getGenericSuperclass(); 
     Class<T> tClass = (Class<T>) pType.getActualTypeArguments()[0]; 
     // In the case where the constructor for `T` takes no arguments. 
     parser = tClass.newInstance().getParserForType(); 
    } catch(Throwable t) { 
     throw new RuntimeException("Subclass not compatible", t); 
    } 
} 

이만큼 서브 클래스가 직접 구체적인 형식 인수와 ProtoDeserializer 구현으로 작동합니다 :


또 다른 당신이 시도 할 수이 구현 서브 클래스에서 구체적인 형식 매개 변수를 얻는 것입니다 해킹 . ie :

class MyDeserializer extends ProtoDeserializer<MyMessage> {...} 
+0

생성자 - 인수 옵션을 계속 사용합니다. – maja