簡體   English   中英

在java中為通用protobuffer類調用parseFrom()方法

[英]Calling parseFrom() method for generic protobuffer class in java

我正在調用api來獲取輸入流,然后調用靜態方法parseFrom(inputstream)將其轉換為protobuffclass。

如果我使用特定的類來實現它的工作原理:

public CustomerDTOOuterClass.CustomerDTO GetCustomer()
{
    CustomerDTOOuterClass.CustomerDTO customer = null;
    try
    {
        URL url = new URL("https://localhost:44302/Api/customer/1?");

        HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/x-protobuf");
        conn.connect();

        InputStream is = conn.getInputStream();

        CustomerDTOOuterClass.CustomerDTO customer =
                CustomerDTOOuterClass.CustomerDTO.parseFrom(is);

        conn.disconnect();
    }
    catch(Exception ex)
    {
        System.out.println("[ "+ex.getMessage()+" ]");
    }

    return customer;
}

但是如果我將它改為泛型類型它會失敗,因為T沒有方法parseFrom,我可以在T中實現任何接口,所以我可以調用parseFrom方法嗎?

public T GetObject()
{
    T object = null;
    try
    {
        URL url = new URL("https://localhost:44302/Api/customer/1?");

        HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Content-Type", "application/x-protobuf");
        conn.connect();

        InputStream is = conn.getInputStream();

        T object = T.parseFrom(is);

        conn.disconnect();
    }
    catch(Exception ex)
    {
        System.out.println("[ "+ex.getMessage()+" ]");
    }

    return object;
}

這是我得到的錯誤:錯誤:(68,27)錯誤:找不到符號方法parseFrom(InputStream)

每個生成的protobuf類型都包含一個名為PARSER的靜態成員,它是com.google.protobuf.Parser<T>接口的一個實現。 您的getObject方法只需要將Parser<T>作為參數。 所以你會稱之為:

Foo foo = getObject(Foo.PARSER);

如果你想為T做這個,那么將Class<T> (即Proto類的類)傳遞給你的類的構造函數會更容易,更自然,然后從中獲取Parser

public class Thing<T extends Message> {
    final Parser<T> parser;

    Thing(Class<T> cls) {
        parser = (Parser<T>) cls.getMethod("parser").invoke(null);
    }

    T deserialize(byte[] bytes) {
        parser.parseFrom(bytes);  // try/catch etc
    }
}

擴展Kenton Varda的答案:

首先,我將您的方法重構為單獨的方法,以獲取輸入流並解析它。 只有后者有任何理由是通用的。

public InputStream getInputStream() {
  // get it
}

現在,您打算解析輸入流並從protobuf構建POJO。 IMO理所當然地希望在這一點上你的代碼必須知道你將要獲得什么類型的對象,否則你將如何使用它來做一些聰明的事情呢? 例如

InputStream is = getInputStream();
Object o = parseGenericInputStream(is);
doSomethingWithParsedObject(o); // how to do this if you don't know o's type?

一旦解析了它,你就必須知道o的類型(因此在你解析它之前),否則你無法用它做任何有意義的事情。

所以...再次歸功於Kenton Varda:

public void doStuff() {
  ...
  InputStream is = getInputStream();
  MyProtobufClass pojo = parseGenericInputStream(MyProtobufClass.PARSER, is);
  doSomethingWithParsedObject(pojo);
  ...
}

private <T> T parseGenericInputStream(Parser<T> parser, InputStream inputStream)
    throws InvalidProtocolBufferException {
  return parser.parseFrom(inputStream);
}

此時雖然您正在為一行代碼編寫通用方法,但如果您問我,這種方法是不值得的。

不,那里沒有; 你不能在不知道它的類型的情況下反序列化原型。

如果您確實知道它的類型,那么您可以為其類型傳入Builder。

(另外,你不能在像T這樣的類型變量上調用靜態方法。)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM