このようなコンパイル時の制限を課すことは不可能です。汎用型パラメータは、参照型のスタンドインです。クラス型とインタフェース型を区別しません。タイプパラメタの宣言における追加の境界がインタフェース型でなければならないという事実は単に偶発的なものであり、インタフェースを巧みにタイプする手段としてこれを活用する戦略は、型パラメータcan't be used in multiple boundsという制限によって打ち破られました。
あなたの唯一のオプションは、ルイ・ワッサーマンpointed outようClass.isInterface()
を使用して実行時のチェックのために解決するために、またはそれがで渡すものに責任があると、呼び出し元にそれを残すことがある。いずれにせよ、法の期待を明確に文書化していることを確認し、動作。
B
クライアントが信頼に基づいてキャストを行うすることなくSomeClass
とA
両方ある単一のオブジェクトを取得することができるように、ワイルドカードのプレースホルダであることを意図しています。クライアントはSomeClass
とA
これは私には矛盾のように思えるが、実際の実装クラスの名前にアクセスすることはできません。呼び出し元が評価するものをおそらく知ることができない場合は、B
と宣言する必要はありません。注意:ジェネリックメソッドの呼び出し側は型引数を提供します。だから、B
を決める呼び出し元は、それを基にすることができず、推測することができます。それは決して型安全ではありません。
あなたが本当にあなたのメソッドが返すようにしたいことはSomeClass
とA
の両方でいくつかのタイプであるが、彼らは共通のスーパータイプを共有していないので、これはトリッキーであるように思え:
public static <A> SomeClass&A makeSomeClass(A thing) {...}
(この
回避方法として、SomeClass
と一部のインターフェイスタイプの両方を表す別の方法を検討してください。例えば、候補インタフェースはSomeClass
を返すための一般的な方法を持つことができます:
public interface IsSomeClass {
SomeClass asSomeClass();
}
public interface Foo extends IsSomeClass { }
asSomeClass
の実装では、実際にはちょうどthis
を返します。
public static <A extends IsSomeClass> A makeSomeClass(Class<A> type) {...}
をそのメソッドの呼び出し元は、いずれかのタイプとして返されたオブジェクトを使用することができるだろう:次に、あなたは何ができるのインタフェース自体は、その後、別のオプションを変更することができない場合は
final Foo foo = makeSomeClass(Foo.class);
final SomeClass someClass = foo.asSomeClass();
ラッパークラス、代わりに組成物を使用することである。
final class SomeClassWrapper<A> {
private final SomeClass someClass;
private final A a;
//constructor and getters, etc.
}
そしてに実装のインスタンスを割り当てる代わりに、ラッパーのインスタンスを返しますあなたの方法someClass
とa
両方:
public static <A> SomeClassWrapper<A> makeSomeClass(Class<A> type) {...}
いいえ、それは不可能です。 –
これは私に悲しい顔を与えます:( – torquestomp
一方、反射主義のものを望むならば、クラスを渡し、明示的にClass.isInterface()を呼び出すことができます。 –