[英]generic wildcard is accepted but not Type T
對於以下情況,假設AModel.class擴展了ABCModel,則情況1
案例1有效
public static Class<? extends ABCModel> getModel(String objectModel) {
if(objectModel.equalsIgnoreCase("")) {
return AModel.class;
}
return null;
}
情況2(引發編譯錯誤)
public static <T extends ABCModel> Class<T> getModel(String objectModel) {
if(objectModel.equalsIgnoreCase("")) {
return AModel.class;
}
return null;
}
目的不只是一樣嗎?
在第二種情況下,您將約束類型變量T
來擴展ABCModel
並承諾返回Class<T>
。 但是T
不會在任何地方綁定,因此在編譯時無法確定T
是什么。
示例1的不同之處在於返回類型定義為Class<? extends ABCModel>
Class<? extends ABCModel>
,其上限為ABCModel
。
在第二種情況下,在編譯時綁定T
一種方法是將其作為方法的參數,例如:
public static <T extends ABCModel> Class<T> getModel(String objectModel, Class<T> clazz) {
現在, T
是根據傳遞給方法的參數進行綁定的(這就是為什么您看到許多使用Class
參數的通用方法的原因)。
當然,這對您的方法無濟於事,因為您想要檢索Class
,如果您已經將其傳遞進來,則沒有必要。但這僅意味着您應該使用示例1或修復您的設計。
兩者有很大的不同。
在第一種情況下,你將一些類,它擴展ABCModel
, 你決定 。 調用者不能假定有關類型參數的身份的任何信息。
在第二種情況下,您保證將返回T
類,無論調用者想要什么T
! 調用者可以使用您想要的 T
來調用您的方法,在這種情況下,您的方法必須神奇地返回該類型參數的類,而根本不知道T
是什么。 這意味着您的方法必須同時返回具有相同代碼的Class<AModel>
和Class<BModel>
等。 這顯然是不可能的(除非它總是返回null
)。
解決問題的方法取決於您的用例:
如果您的方法確定了特定類型並返回了它,則第一個示例就是正確的方法。 嘗試進一步指定返回類型沒有用,因為如果調用者需要指定該類型,則無法回答問題“哪個子類型”。
但是,如果您的方法有多個調用,並且每個調用將始終返回期望的子類型,則通用返回類型很有用。 在這種情況下,您的呼叫者將知道特定的返回類型,並可以使用該參數來避免在呼叫站點上進行強制轉換。 您需要做的就是在實現中進行轉換: return (Class<T>) AModel.class;
第一種情況示例:
// The caller does not know the return type, so a simple unknown type is appropriate
Class<?> determineType(Object myObject) {
return myObject.getClass();
}
第二種情況示例:
// The caller will already know that a property named 'street' will be of type String, so he can invoke <String>getTypedProperty("street") and avoid having to cast himself
<T> T getTypedProperty(String name) {
return (T) genericPropertyStore.get(name);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.