2016-07-28 8 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"; 
    } 
} 
BaseInner

タイプの引数を取るBase.method方法。次に、次の派生クラスについて考えてみましょう。

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由来します。ジェネリック型パラメータIDSubの場合は、型引数として基本クラスBaseに渡されます。

私の質問:はなぜコンパイラはSubのオーバーライドmethodSubInnerBaseInnerからのキャストに文句を言うのでしょうか?

警告を理解するために、Sub<A>methodが呼び出され、警告が正当化されるSub<B>.SubInnerというユースケースを作成しようとしました。しかし、私が考えることができるもの(? extends? superなど)は、型が互換性がない場合は、メソッド呼び出しでコンパイラエラーが発生します。

だから、methodのチェックされていないキャストに関する警告の理由はないと思います。私は何か見落としてますか?

Sub<ID>実装内でメソッドオーバーライドが発生するため、コンパイラはSubInnerの汎用タイプをSub<ID>.SubInnerに差し引くことができます。だから質問ではない重複!

Eclipseのコンパイラの警告が

型の安全性である:オフは、私が使用している場合ワーリングはどちらも変化しませんサブ< ID> .SubInner

にベース< ID> .BaseInnerからキャストメソッドのパラメータとしてBase<ID>.BaseInnerを使用しても、キャスト式にSub<ID>.SubInnerを使用してもいけません。

+2

ifステートメントで 'o instanceof Sub.SubInner'を使用しているので、次のステートメントで' Sub.SubInner'も使用しないでください。 – nbro

+0

私はすでにキャストで 'Sub .SubInner'を使用していますが、常に同じ警告が生成されます。 – niks

+1

どのコンパイラを使用していますか?私はjavac 8で警告を受け取りません。 – assylias

答えて

0

この場合、チェックされていないキャストとは、非修飾型から汎用型へのキャストを意味します。

Set<String> set = new HashSet(); 

この行は未確認の割り当て警告を生成します。

この警告は、コンパイル時にキャストが安全かどうかをコンパイラが差し引く方法がないために発生します。

SubInnerインスタンスには、Subインスタンスへの参照があります。 Base.BaseInnerからキャストしているので、BaseからSubID>にもキャストしています。したがって、この警告が表示されています。

編集

ソリューションは、一般的なパラメータを使用することです。

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)では、ここでの警告は省略されません。

関連する問題