がjava.lang.ClassのgetInterfaces()メソッドが、クラス []ではなく、クラス<?> []を返すのはなぜですか?
は一例として、次のアプリケーションを確認してください(質問をクリアするには、「T」のクラスで宣言された型パラメータを参照):
public class TestClass {
interface InterfaceA{}
interface InterfaceB{}
interface InterfaceC{}
class ClassA implements InterfaceA, InterfaceB, InterfaceC{}
public static void main(String[] args){
Class<? super ClassA> superClass1 = ClassA.class;
Class<? super ClassA> superclass2 = InterfaceA.class;
Class<? super ClassA> superclass3 = InterfaceB.class;
Class<? super ClassA> superclass4 = InterfaceC.class;
for(Class<?> clazz : ClassA.class.getInterfaces()){
System.out.println(clazz.getName());
}
}
}
出力は1つが期待するものです:
TestClass$InterfaceA
TestClass$InterfaceB
TestClass$InterfaceC
ので、上記の例に基づいて、我々は、コンパイラがInterfaceA が会う目をしていることを認識していることがわかります他のすべてのインタフェースと同様に、ワイルドカードの境界にも適用されます。
直感的に、私は次のように安全であると期待されるが、そうではありません。
Class<? super ClassA>[] interfaces = ClassA.class.getInterfaces();
署名は、それがクラスを返すことを言うので、コンパイラは、警告を与えます。しかし、クラスのJavadocは次のように述べている:
このオブジェクトがクラスを表す場合、戻り値は クラスによって実装されるすべてのインタフェースを表すオブジェクトを含む配列 あります。
「このオブジェクト」は、ここではClassA
です。我々は呼んでいる場合は、この声明に基づき、:
ClassA.class.getInterfaces()
その後、我々は返される配列内のすべてのClass<?>
がClassA
のスーパー型への参照が含まれていることを、論理的に、知っています。参照の追加点として
:
Java言語リファレンス第3版から:
クラスは、必ずしもその直接 スーパークラスと直接的上位が行うすべてのインタフェースを実装しています。この(複数の)インターフェイス の継承により、オブジェクトは実装を共有することなく(複数の)共通の動作をサポートできます。 本明細書の他の部分を読む
、I、クラスT
によって実装またはexteneded任意のクラスまたはインタフェースが境界<? super T>
に落ちるだろうと思うだろう。
EDITEDは:
私の質問のための具体的な理由が存在しないことが示唆されています。私は例を提供します:
1 import java.util.Map;
2 import java.util.HashMap;
3
4 public class MapWrapper<T> {
5 private final Map<Class<?>, OtherClass<T,?>> map = new HashMap <Class<?>, OtherClass<T,?>>();
6
7 public <W> void addToMap(Class<W> type, OtherClass<T,? super W> otherClass){
8 map.put(type, otherClass);
9 }
10
11 public <W> OtherClass<T,? super W> getOtherClassForAnyInterface(Class<W> type){
12 if(type.getInterfaces()!=null){
13 for(Class<?> interfaceType : type.getInterfaces()){
14 // Here, a cast is necessary. It throws a compiler warning for unchecked operations (rightfully so)
15 OtherClass<T,? super W> otherClass = (OtherClass<T,? super W>)getOtherClassForInterface(interfaceType);
16 if(null!=otherClass){
17 return otherClass;
18 }
19 }
20 }
21 return null;
22 }
23
24
25 public class OtherClass<T,V> {}
26
27 }
は、問題はあなたが正しい型を得るために<? super W>
にキャストする必要が線15です。コンパイラの警告を抑制することはできますが、それは正当化されますか?このキャストが真実でないシナリオがありますか?
クラスは、実際にはTのスーパークラスを使用するメソッドを持たないかもしれませんが、型自体を表すので、スーパータイプに関する情報を提供すると主張します。 ClassのgetSuperclass()メソッドを見ると、戻り値の型は 'Class super T>'です。この場合、getInterfaces()が私のように戻ってくるのがさらに適切です。彼らが考えているように、あなたが示唆しているように、そのクラスは決してワイルドカードを使用してアクセス可能なこれらのメソッドを使用しないでしょうから、クラスは ' super T>'と指定されたスーパークラスを提供します。 –
sager
APIデザイナーの間違いでしょう。とにかくそれは問題ではないと私は主張している。 – irreputable
このようにClassを使用する具体的なケースを追加しました。それは現在、探求自体にあります。 – sager