2016-07-28 70 views
3

考慮使用非靜態內部類的以下泛型類Base<ID>爲什麼Eclipse Java編譯器會抱怨內部派生類型未經檢查強制轉換?

public class Base<ID> { 
    ID id; 

    public Base(ID id) { 
    this.id = id; 
    } 

    public ID getId() { 
    return id; 
    } 

    protected class BaseInner { 
    String text = "Inner"; 
    } 

    protected void method(BaseInner o) { 
    o.text = "Foo"; 
    } 
} 

Base.method需要BaseInner類型的參數的方法。現在考慮下面的派生類。

public class Sub<ID> extends Base<ID> { 
    public Sub(ID id) { 
    super(id); 
    } 

    @Override 
    protected void method(BaseInner o) { 

    if (o instanceof Sub.SubInner) { 
     SubInner sub = (SubInner) o; // Why does this cast emit an "unchecked cast" warning 

     sub.text = "Bar"; 
     sub.value = 1337; 
    } 
    } 

    protected class SubInner extends BaseInner { 
    Number value = 42; 
    } 
} 

SubBase派生和內部類SubInner從內類BaseInner派生。 Sub的泛型類型參數ID作爲類型參數傳遞給基類Base

我的問題:爲什麼編譯器抱怨從BaseInner投給SubInnerSub首要method

爲了理解這個警告,我嘗試構造一個用例,其中調用Sub<A>method的某些Sub<B>.SubInner證明警告正確。但是任何我能想到的(包括? extends? super)都會在方法調用時發出編譯器錯誤,如果這些類型不兼容的話。

所以我想沒有理由在method的未經檢查的演員的警告。我錯過了什麼?

由於方法覆蓋發生在Sub<ID>實現中,編譯器能夠將SubInner的通用類型減去Sub<ID>.SubInner。所以這個問題是不是重複!

Eclipse編譯器警告

類型安全:未選中從基礎施法< ID> .BaseInner到子< ID> .SubInner

華林不會改變既不如果我使用Base<ID>.BaseInner作爲方法參數,如果我在演員表達中使用Sub<ID>.SubInner

+2

只是一個猜測,但既然你在if語句中使用'instanceof Sub.SubInner',你不應該在下面的語句中使用'Sub.SubInner'嗎? – nbro

+0

我已經試過了,並且在劇組中也使用了'Sub .SubInner',但它總是產生相同的警告。 – niks

+1

你使用什麼編譯器?我沒有得到任何與javac 8警告。 – assylias

回答

0

在這種情況下,未經檢查的轉換意味着您正在從非限定類型轉換爲泛型類型。

Set<String> set = new HashSet(); 

此行也會產生未檢查的分配警告。

發生此警告是因爲如果編譯時安全轉換,編譯器無法扣除。

SubInner實例具有對Sub實例的引用。您正在從Base.BaseInner中投射,因此您也正在從基本投射到Sub < ID>。因此,你有這個警告。

編輯

解決方案是使用泛型參數。

public class Base<ID> { 
    ID id; 

    public Base(ID id) { 
     this.id = id; 
    } 

    public ID getId() { 
     return id; 
    } 

    protected class BaseInner { 
     String text = "Inner"; 
    } 

    protected void method(Base<ID>.BaseInner o) { 
     o.text = "Foo"; 
    } 
} 


public class Sub<ID> extends Base<ID> { 
    public Sub(ID id) { 
     super(id); 
    } 

    @Override 
    protected void method(Base<ID>.BaseInner o) { 
     SubInner sub = (SubInner) o; 
     sub.text = "Bar"; 
     sub.value = 1337; 
    } 

    protected class SubInner extends BaseInner { 
     Number value = 42; 
    } 
} 
+0

「這條線也會產生未經檢查的投射警告。」不,它會產生原始類型警告。那裏沒有演員。 –

+0

是的,你是對的 –

+0

我已經嘗試將泛型類型參數添加到SubInner和方法沒有成功。 – niks

1

這是一個Eclipse編譯器問題。

Oracle編譯器(javac)在此不會省略任何警告。

相關問題