我對 Java 泛型和Class<> clazz型別非常陌生,我有一個介面
public interface MyInterface {
void doSomething(String arg1);
}
由多個類實作
class MyInterfaceImplFirst implements MyInterface {
private arg;
public MyInterfaceImplFirst(String arg) {
this.arg = arg;
}
@Override
void doSomething(String arg1) {
//...
}
}
class MyInterfaceImplSecond implements MyInterface {
private arg;
public MyInterfaceImplSecond(String arg) {
this.arg = arg;
}
@Override
void doSomething(String arg1) {
//...
}
}
我有一門課接受Class<MyInterface> type
public class Dummy {
public void load(Class<MyInterface> clazz) {
//...
}
public static void main(String[] args) {
Dummy dummy = new Dummy();
//The below does not compile
dummy.load(MyInterfaceImplFirst.class);
}
}
如果我將加載方法更改為public void load(Class clazz)它作業正常,有人可以告訴我如何將加載方法的引數限制為MyInterface的子型別(impl)嗎?
uj5u.com熱心網友回復:
PECS(Producer-Extends,Consumer-Super)就是問題所在。給定 a List<Number>,您當然可以呼叫.add(someDouble)。因此,當需要 a 時,不能通過List<Integer> aList<Number>。這個“寫”概念不適用于Class<X>,但 java 不“知道”這一點,因此不會讓你在需要 aClass<SomeImpl>時傳遞 a Class<TheInterface>。
PECS 有點用詞不當。它是從泛型型別(so、List、Class 等)的角度撰寫的。如果該類只產生東西并且不會消耗任何泛型型別的東西,這里就是這種情況,PECS 宣告你應該使用extends.
因此,public void load<Class<? extends MyInterface> clazz)就是你想要的。
幾點注意事項:
- 泛型用于鏈接事物。如果您宣告一個泛型變數并在 0 或 1 個地方使用它,正如來自 @RobSpoor 的誤導性評論錯誤地暗示的那樣,那么您就是在搞砸或破壞java 的型別系統(在某些合法的情況下,這是一個好主意,但相當稀有的)。鑒于你在任何地方都不需要那個 T,你會搞砸的。改用就好
?了。 - 混合泛型
Class通常很糟糕。有些東西Class可以表示,比如int(Class<?> c = int.class;是有效的java),哪些泛型不能(List<int>不是有效的java),反之亦然,泛型可以表示那個類不能。您不能擁有java.lang.Class代表的實體List<String>(僅 List - 原始型別)。Class<List<String>>不是東西;List<String>.class不起作用。List<List<String>>確實有效。 - 不管你怎么想:我知道!我會做一個介面,使用泛型,然后做一個
Class<? extends MyInterface>- 這可能是一個錯誤。你沒有解釋是什么讓你認為你需要這個。最有可能的是,正確的答案是工廠。工廠本質上是建構式的抽象。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/444348.html
上一篇:如何從用戶表中洗掉地址的外鍵?
