2009-07-24 7 views
5

Javaジェネリック:警告には、<InterfaceName>に準拠するためのチェックされていないキャストが必要です

私はインターフェイスを持っています

interface x { 
    A getValue(); 
} 

と実装

class y implements x { 
    public B getValue() { return new B();} 
} 

BはAのサブクラスです。これは共変なオーバーライドのために動作します。

警告 へのチェックされていないキャストがA.getValue()に準拠している必要があります。

2つのバージョンのインターフェイスの違いは何ですか?私は彼らが同じだと思っていた。

+0

興味深いことに、 "interface x {T getValue();}' "に変更すると警告が消えます。 –

+0

ええ、私はこの場合、コンパイラはクラス宣言からTが何であるか把握する方法を持っていると思います。しかし、他の場合には、Tが何であるか把握する方法がありません。 – Surya

答えて

4

インターフェイスの2番目のバージョンが間違っています。 getValueは、あなたが求めているサブクラスを返します。戻り値の型は、左手の式に基づいて推測されます。

あなたはx(のはobjそれを呼びましょう)への参照を取得するのであれば、あなたが合法的にコンパイラの警告なしに次の呼び出しを行うことができます。

かの理由は、あなた、あなたの例では、おそらく間違ってい
x obj = ...; 
B b = obj.getValue(); 

あなたも合法的に電話をかけることができ、またAを拡張する別のクラスCを追加します。

C c = obj.getValue(); 

Tがに属する型変数ではありませんので、これは、インターフェイス、メソッド自体にのみ。

+0

Ahh ..so Tは左側から推測されています。意味をなさないだから、C#のような代入から型を推論しない言語では、どうなりますか? – Surya

3

基本的にあなたがあなただけ行うことができますので、あなたが、あなたはA、いないAの特定のサブクラスをしたいと言っている<T extends A>やっているとき:

A getValue(); 

コンパイラは「それができることを警告されたが特定の定義されたAのサブクラスが返されるようにします.A自身だけが返されます。

EDIT:これをよりよく説明するために、BはAのサブクラスですが、Aの唯一のサブクラスである必要はありません。次の階層を考えてみましょう。

Bは CがAを拡張して延びるが

今、私はこの方法持っBません。(他があるかもしれない何のランタイムクラスキャスト例外をコンパイルしないと保証すべきであるジェネリック医薬品、後

public void someMethod(x value) { 
    C c = x.getValue(); 
} 

をここにインターフェイスの問題がありますが、これを正しく実証するために使用できるケースがあります - 私はあなたの例を守っています)。

しかし、yのインスタンスをこのメソッドに渡すとどうなりますか?

今、私はCの代わりにBを取得しています。コンパイラはこれが起こる可能性があることを警告しています。

+0

BはAのサブクラスです。具体的なサブクラスの意味が分かりません – Surya

+1

'クラスC 'が' A'のサブクラスだった場合、 'anX'と書くことができます。 getValue() 'これは明らかに' y'に間違っています。 –

+0

(BTW:型名の選択肢が貧弱) –

0

ので、AlbertoPLとYishaiから2つの答えに構築するために、これを試してみてください。

class y implements x { 
    A getValue(){ return new B();} 
} 

Bが延び、それは大丈夫ですので。呼び出し元は、Aのサブクラスが返されるかどうかを知る必要はありません。したがって、Aを継承するだけです。

+0

元のコードは実際には(公開されています)動作しました。 –

1

ジェネリックを解決する方法がないということです。 Tは出力として以外にはどこにも定義されていません - あなたは何を話していますか?インタフェースは型Tであることを総称化された場合は、次の

interface x <T extends A> { 
    T getValue() 
} 

、これはうまくいく、または方法は、あなたが望んでいた戻り値の種類を定義する値を取った場合:

interface x { 
    <T extends A> T getValue(T someArgument) 
} 

または

interface x { 
    <T extends A> T getValue(Class<T> someArgument) 
} 

警告が表示されません。

編集:この特定の問題に対してジェネリックを使用しない理由については、waxwingの記事を参照してください。私はジェネリックがどのように適切であるかを単に示しています。

関連する問題