我正在構建一個客戶端/服務器應用程式,并將請求和回應訊息封裝在通用 Java 類中,如下所示:
@SuperBuilder
@Jacksonized
@Getter
@Setter
public class AppResponse<T extends AppResponse.Results> {
public static final String SUCCESS_ATTRIBUTE = "success";
public static final String MESSAGE_ATTRIBUTE = "message";
public static final String REQUEST_ID_ATTRIBUTE = AppRequest.REQUEST_ID_ATTRIBUTE;
public static final String RESULTS_ATTRIBUTE = "results";
@JsonProperty(SUCCESS_ATTRIBUTE)
boolean success;
@JsonProperty(MESSAGE_ATTRIBUTE)
String message;
@JsonProperty(REQUEST_ID_ATTRIBUTE)
String requestID;
@JsonProperty(RESULTS_ATTRIBUTE)
T results;
@SuperBuilder
@Jacksonized
@Getter
@Setter
public static class Results {
}
}
然后我有一個類擴展 AppResponse.Results 每個可以通過網路發送的命令回應資料包。例如:
@SuperBuilder
@Getter
@Setter
@Jacksonized
public class AppCreateForumPostResults extends AppResponse.Results {
@JsonProperty("id")
UUID id;
}
因此,當服務器使用 Jackson 將其編碼為 JSON 時,我得到一個如下所示的 JSON 檔案:
{
"success" : true,
"requestID" : "eL55P4Sz",
"results" : {
"id" : "0b48d389-2407-43c4-ad1b-ab52599c2d7f"
}
}
當客戶端應用程式收到此訊息時,它首先將其解碼為 ObjectNode:
objectNode = (ObjectNode) AppObjectMapper.OBJECT_MAPPER.readTree(message);
然后它將其解碼為泛型物件,因為它還不知道泛型的具體型別是什么:
JavaType genericType = AppObjectMapper.OBJECT_MAPPER.getTypeFactory().constructParametricType(
AppResponse.class,
AppResponse.Results.class
);
AppResponse<AppResponse.Results> genericResponse = AppObjectMapper.OBJECT_MAPPER.treeToValue(
objectNode,
genericType
);
然后它會查詢已發送的 requestID 的 HashMap,以找出它應該期待什么樣的結果類。HashMap 定義為:
private final Map<String, CallbackEntry<? extends AppResponse.Results>> callbacks = new HashMap<>();
CallbackEntry 定義為:
@Builder
@Value
public static class CallbackEntry<T extends AppResponse.Results> {
Callback<T> method;
Class<T> resultsClass;
}
最后回呼定義為:
public interface Callback<T extends AppResponse.Results> {
void handleResponse(AppResponse<T> results);
}
So once we have found the requestID in the HashMap, we know what concrete class the results contain, and we can decode it:
CallbackEntry<? extends AppResponse.Results> callbackEntry = callbacks.get(genericResponse.getRequestID());
callbacks.remove(genericResponse.getRequestID());
JavaType concreteType = AppObjectMapper.OBJECT_MAPPER.getTypeFactory().constructParametricType(
AppResponse.class,
callbackEntry.resultsClass
);
AppResponse<? extends AppResponse.Results> concreteResponse = AppObjectMapper.OBJECT_MAPPER.treeToValue(
objectNode,
concreteType
);
So far, so good. This all works exactly as expected. If I print out the concreteResponse object, it has exactly the correct data in it. However, when I go to actually call the callback method, I'm getting an error. The call looks like:
callbackEntry.method.handleResponse(concreteResponse);
And the error I get on that line of code is:
[127,49] incompatible types: com.whatever.app.common.AppResponse<capture#1 of ? extends com.whatever.app.common.AppResponse.Results> cannot be converted to com.whatever.app.common.AppResponse<capture#2 of ? extends com.whatever.app.common.AppResponse.Results>
I'm a bit confused by the error message. I'm guessing it has to do somehow with the way in which the generics are being handled, but I just can't figure out what the correct incantation is to get this to go. I've done a bunch of Googling, and find similar errors here and there, but they generally are due to someone using ? instead of T, which (I think) is not the case here.
So, what am I missing?
Any help is greatly appreciated!
uj5u.com熱心網友回復:
我可以通過像這樣轉換函式引數來使它作業:
callbackEntry.method.handleResponse(
(concreteResponse.getClass()).cast(concreteResponse)
);
這顯示了未經檢查的分配的警告,但它有效。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/437850.html
下一篇:使用forList的正確泛型
