2016-11-09 31 views
3
abstract class AbsClass {} 

class MyAbs extends AbsClass {} 

class MyClass<S extends AbsClass> { 
    S getObj() { 
     return new MyAbs(); 
    } 
} 

コンパイラの問題を取得する:のJavaジェネリック&互換性のない型

Error:(33, 16) java: incompatible types: MyAbs cannot be converted to S

これを実行するための正しい方法は何ですか?

編集: 私はMyClass {MyAbs}を初期化してから、私にMyAbsオブジェクトを返すgetObj()を呼び出すことができると考えていました。アンディの答えで、AbsClassをMyAbsやMySecondAbsにキャストする必要がありました。これは避けようとしていたものです。

+2

'' を削除し、 'MyAbs getObj(どちらかに' S getObjを() 'に変更) 'または' AbsClass getObj() 'を呼び出します。それがそのままで、型変数を持つ理由はありません。 –

+1

「これをする」と言ったときに何を言いたいのですか? – Simon

+0

私はMyClass を初期化できることを望んでいたので、getObj()を呼び出すとMyAbsオブジェクトが返されます。アンディの答えでは、AbsClassをMyAbsやMySecondAbsにキャストしなければならなかったでしょう。 – mwong56

答えて

3

SMyAbsは、それ以外の方法ではありません。タイプSのオブジェクトはすべてMyAbsにキャストできますが、MyAbsをその派生クラスにキャストできません。

達成しようとしていることを説明してください。

+1

すべてのプードルは犬ですが、すべての犬がプードルではありません。 – Taylor

5

Andyは問題を解決する方法を説明しました。理由を説明しようとします。

SMyAbsに割り当てられることは保証されておらず、AbsClassにのみ割り当てられ、各インスタンスはAbsClassのサブクラスを指定します。

は考えてみましょう:

class MyOtherAbs extends AbsClass {} 

MyClass myClass = new MyClass<MyOtherAbsClass>{}; 

これはあなたが持っているものと競合します。

UPDATE:あなたのコメントに基づいて

あなたは上記を達成したいように見えます。問題は、MyOtherAbsに引数を持つコンストラクタがある場合はどうなりますか?あるいは、シングルトン(すなわち、プライベートコンストラクタとスタティックgetInstance())として実装されています。一言で言えば、これらを構築するための統一された統一方法はありません。さらに、実行時に、消去を入力に起因するが、Sの概念がなくなっているので、あなたのような何かをすることはできません。

public interface AbsClassFactory<S extends AbsClass>{ //takes the place of MyClass 
    public S getInstance(); 
} 

MyAbsFactory implements AbsClassFactory<MyAbs>{ 
    public MyAbs getInstance(){ 
     return new MyAbs(); //or however MyAbs is instantiated 
    } 
} 

:あなたは基本的に2つの選択肢を持っている

return new S(); 

を、一つはサブクラス化を使用することです第二は、可能な引数なしのコンストラクタがあると仮定し、1でない場合は、ランタイム例外をスローすることを

class MyClass { 
    public <S extends AbsClass> S getObj(Class<S> clazz) throws InstantiationException, IllegalAccessException { 
     return clazz.newInstance(); 
    } 
} 

注:他のオプションが反映しています。

+0

あなたの例は、私が達成しようとしていることです、不明なことを申し訳ありません。 – mwong56

+0

回答を拡大して代替案を提示します – Taylor

1

あなたのコメントから、あなたがSupplierインタフェースを使用して同じことを達成することができているようです:

Supplier<MyAbs> supp = MyAbs::new; // Constructor reference 
MyAbs obj = supp.get(); 

Supplier<MySecondAbs> supp2 = MySecondAbs::new; 
MySecondAbs obj2 = supp2.get(); 
関連する問題