![](/img/trans.png)
[英]A strange generics edge case with Mockito.when() and generic type inference
[英]Generics and type inference for a generic factory
對於這個問題中的任何不良英語,請提前抱歉。
我想到了創建一種工廠,它只能創建由具體工廠實例類實現的列表中定義的類的實例。 首先,我定義了這個界面:
public interface ValuesSystem {
public interface AllowedValue<T extends Class<? extends SystemValue>>{};
AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id);
Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues();
<T extends SystemValue> T create(AllowedValue<Class<T>> allowedClass, ValueData data) throws InvalidValueException;
}
AllowedValue接口只是一個“標記包裝器”接口,使用泛型來定義我的工廠“允許”創建的Class實例。
getAllowedValue是一個方法,用於從我允許的類“列表”中獲取包裝的允許類實例,使用實現此接口的具體類的內部枚舉(具體類的示例將會出現)。
create方法旨在最終創建allowedClass參數中給出的允許的Class實例的實例。
以下是實現此接口的具體類的示例:
public class BasicValueSystem implements ValuesSystem {
public BasicValueSystem() {
super();
allowedValues = (Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>) getAllowedValues();
}
public static enum VALUES_ID {
MODIFIER
}
private static Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowedValues;
private class BasicAllowedValue<T extends Class<? extends SystemValue>>
implements AllowedValue<Class<? extends SystemValue>> {
}
@Override
public <T extends SystemValue> T create(
AllowedValue<Class<T>> allowedClass, ValueData data)
throws InvalidValueException {
if (!(allowedClass instanceof BasicAllowedValue)) {
throw new InvalidValueException();
}
return null;
}
@Override
public AllowedValue<Class<? extends SystemValue>> getAllowedValue(Enum<?> id) {
return allowedValues.get(id);
}
@Override
public Map<? extends Enum<?>, AllowedValue<Class<? extends SystemValue>>> getAllowedValues() {
Map<VALUES_ID, AllowedValue<Class<? extends SystemValue>>> allowed = new EnumMap<VALUES_ID, AllowedValue<Class<? extends SystemValue>>>(VALUES_ID.class);
allowed.put(VALUES_ID.MODIFIER, new BasicAllowedValue<Class<ModifierValue>>());
return allowed;
}
}
目前,create方法返回null,但問題出在其他地方,這不是我的問題
當我嘗試使用以下代碼創建一個“允許”值實例的實例時,會發生此問題:
BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<Class<? extends SystemValue>> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());
編譯器告訴我:
The method create(ValuesSystem.AllowedValue<Class<T>>, ValueData) in the type BasicValueSystem is not applicable for the arguments (ValuesSystem.AllowedValue<Class<? extends SystemValue>>, ModifierValueData)
我想我錯過了泛型一般的類型推斷。
任何人都可以解釋我創建方法簽名在這種情況下不適用以及如何解決它?
提前感謝您抽出寶貴時間。
請注意, public interface AllowedValue<T extends Class<? extends SystemValue>>
public interface AllowedValue<T extends Class<? extends SystemValue>>
沒有多大意義。 T
的唯一有效類型是Class<? extends SystemValue>
Class<? extends SystemValue>
因為類Class
是final,不能有子類。 所以你可以用interface AllowedValue<Class<? extends SystemValue>>
替換它interface AllowedValue<Class<? extends SystemValue>>
interface AllowedValue<Class<? extends SystemValue>>
而不改變語義,但你真正的意思是(imho)是interface AllowedValue<T extends SystemValue>
。 不要在類型簽名中亂用Class
。 接口仍然可能有引用Class<T>
方法。
public interface ValuesSystem {
public interface AllowedValue<T extends SystemValue>{};
AllowedValue<? extends SystemValue> getAllowedValue(Enum<?> id);
public <T extends SystemValue> T create
(AllowedValue<T> allowedClass, ValueData data);
}
相應地調整實現, BasicAllowedValue
成為
private class BasicAllowedValue<T extends SystemValue> implements AllowedValue<T>
然后你使用代碼的問題就消失了。
BasicValueSystem bvs = new BasicValueSystem();
AllowedValue<? extends SystemValue> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());
將編譯。
請注意,如果AllowedValue
仍然是一個沒有方法的標記接口,則不需要, Class<T>
已經履行了這個角色。 這樣做時也會起作用:
public interface ValuesSystem {
Class<? extends SystemValue> getAllowedValue(Enum<?> id);
public <T extends SystemValue> T create(Class<T> allowedClass, ValueData data);
}
和
BasicValueSystem bvs = new BasicValueSystem();
Class<? extends SystemValue> allowed = bvs
.getAllowedValue(BasicValueSystem.VALUES_ID.MODIFIER);
bvs.create(allowed, new ModifierValueData());
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.