簡體   English   中英

Java 編譯器無法推斷泛型鏈上的類型

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

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