特定のクラス A と別のインターフェイス I を拡張する特定の型 T のオブジェクトを作成するファクトリを作成しようとしています。ただし、T を認識してはなりません。最低限の宣言は次のとおりです。
public class A { }
public interface I { }
これはファクトリメソッドです:
public class F {
public static <T extends A & I> T newThing() { /*...*/ }
}
これはすべてうまくコンパイルされます。
メソッドを使用しようとすると、次のように動作します。
A $a = F.newThing();
...これはそうではありませんが:
I $i = F.newThing();
コンパイラは不平を言います:
範囲の不一致: 型 F のジェネリック メソッド newThing() は、引数 () には適用できません。推定されたタイプ I&A は、制限付きパラメーターの有効な代替ではありません
理由がわかりません。「newThing は、クラス A を拡張し、インターフェース I を実装する特定の型 T のものを返す」と明確に述べられています。A に代入するとすべてが機能します (T は A を拡張するため) が、I に代入すると機能しません (何が原因で、返されるものは明らかにAとI の両方です)
また、オブジェクトを返すとき、たとえば B の型class B extends A implements I
を返す場合、 B は境界に一致しますが、戻り値の型 T にキャストする必要があります。
<T extends A & I> T newThing() {
return (T) new B();
}
ただし、コンパイラは UncheckedCast などの警告をスローしません。
したがって、私の質問:
- ここで何がうまくいかないのですか?
- ファクトリメソッドでキャストによって戻り型の問題を解決する場合のように、目的の動作 (つまり、静的型 A または I の変数への割り当て) を達成する簡単な方法はありますか?
- A への割り当てが機能するのに、I への割り当てが機能しないのはなぜですか?
--
編集:ここでは、Eclipse 3.7 を使用して完全に機能する完全なコード スニペット、JDK 6 用に設定されたプロジェクト:
public class F {
public static class A { }
public static interface I { }
private static class B extends A implements I { }
public static <T extends A & I> T newThing() {
return (T) new B();
}
public static void main(String... _) {
A $a = F.newThing();
// I $i = F.newThing();
}
}
編集:実行時に機能するメソッドと呼び出しの完全な例を次に示します。
public class F {
public static class A {
int methodA() {
return 7;
}
}
public static interface I {
int methodI();
}
private static class B extends A implements I {
public int methodI() {
return 12;
}
}
public static <T extends A & I> T newThing() {
return (T) new B();
}
public static void main(String... _) {
A $a = F.newThing();
// I $i = F.newThing();
System.out.println($a.methodA());
}
}