簡體   English   中英

接受通用通配符,但不接受T型

[英]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.

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