[英]Java compiler not able to infer type on generic chain
如下所述(請注意,因為我可能對自己的解釋很糟糕):
我想了解這個問題背后的原理,以便我可以將這些知識應用於實際問題。
問題開始
我在一個旨在成為許多子系統使用的抽象庫的系統中工作。 這個想法是有一個可通過實現擴展的標准行為。 我的問題是 java 編譯器無法推斷方法參數類型,即使它沒有任何意義,因為邊界在每個相關的泛型類/方法上都設置得很好。
下面是一個示例,是重現問題的最小示例。 我知道在這個例子中它看起來有點傻,但這是因為簡化:
public class Test {
public static void main(String[] args) {
Gen<? extends Base> gen = new HijaGen();
gen.applyTo(Hija.EXAMPLE);
}
private interface Base {
String getName();
}
private enum Hija implements Base {
EXAMPLE;
@Override
public String getName() {
return this.name();
}
}
private interface Gen<T extends Base> {
boolean applyTo(T base);
}
private static class HijaGen implements Gen<Hija> {
@Override
public boolean applyTo(Hija base) {
return false;
}
}
}
基本上它說 applyTo 期望 Base 和 Hija 的子類無效,從我的角度來看這是沒有意義的。
提前致謝。
編輯:
此代碼用於庫,因此解決方案無法指定類型,因為它無法通過特定實現進行擴展。
我已經知道,如果我指定泛型類型而不是拋出類型通配符,它將完美地工作。 但我的問題是,即使 Hija 是 Base 的子類,並且方法公司需要 Base 的子類,它怎么可能永遠不會編譯......
我想了解這個問題背后的原理,以便我可以將這些知識應用於實際問題。
Gen<? extends Base>
Gen<? extends Base>
是Gen
的東西,其延伸Base
。 它適用於某些特定類型的Base
但我們不知道是哪一種。 實際上,這意味着您將永遠無法對類型為Gen<? extends Base>
的變量調用applyTo
Gen<? extends Base>
Gen<? extends Base>
,除非傳遞空值。
將您的代碼更改為
Gen<Hija> gen = new HijaGen();
gen.applyTo(Hija.EXAMPLE);
我懷疑您可能會說您不能這樣做,因為您的代碼只是一個示例,而上述內容在實際代碼中是不可能的。 在這種情況下,您需要提供一個更好的示例
我覺得有一個類似的問題在文檔中解釋這里和問題,他們的建議是做一個輔助(或包裝)澄清類型。 所以我想你可以嘗試添加這個功能:
private static <T extends Base> boolean applyTo(Gen<T> gen, T base){
return gen.applyTo(base);
}
並將主要功能更改如下:
public static void main(String[] args) {
boolean b = applyTo(new HijaGen(), Hija.EXAMPLE);
}
根據 Carlos 所提到的,還有另一種方法可以解決此問題。 如果您確定Gen<T>
實現的供應商,則可以使用它。
在這里,我們定義了一個工廠方法來創建Gen
實現的實例並將其轉換為Gen<Base>
,而不是調用applyTo()
的助手,在我看來,這對於所有實際目的都是安全的。 請注意,工廠方法get()
不必是靜態的。 其余代碼與您的示例保持不變。
public static void main( String[] args ){
Gen<Base> gen = (Gen<Base>) get();
gen.applyTo( Hija.EXAMPLE );
}
static Gen<? extends Base> get(){
/* Create the instance of the Gen interface implementation here. */
return new HijaGen();
}
Gen<? extends Base>
Gen<? extends Base>
期望引用Gen
實現的實例,該實例使用Base
或其子類型的類型。 由於“子類型”可以來自從Base
向下的許多可能的層次結構之一(如下圖所示),因此無法確定傳遞給applyTo()
方法的參數是否屬於相同的子層次結構路徑,而不僅僅是具有相同祖先父母Base
的“親戚”。 這就是為什么它不允許調用applyTo()
並且它的引用是Gen<? extends Base>
Gen<? extends Base>
用於引用為Base
的參數。
然而,當引用是Gen<Base>
,它知道applyTo()
將接受任何Base
子類型的參數。 因此,它不再擔心類型不匹配。
我試圖通過不同的子層次結構路徑來展示我的意思。 這就像家譜的情況。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.