2

Java リフレクションまたはオブジェクトへの特別な格納操作を使用すると、未確認の警告が表示されることがあります。私はそれに慣れてしまい、どうすることもできなくなったときは、1 つの呼び出しがチェックされていない理由と、それが安全であると見なされるべき理由を文書化しています。

しかし、初めて、チェックされていない呼び出しに関するエラーが発生しました。この機能:

public <K,V extends SomeClass & SomeOtherClass<K>> void doSomethingWithSomeMap (Map<K,V> map, V data);

私はそれをこのように呼ぶと思った:

Map someMap = ...;
SomeClass someData = ...;
doSomethingWithSomeMap(someMap, someData);

未確認の呼び出しの警告が表示されます。Jikes は警告を出しますが、javac はエラーを出します:

エラー: SomeClass の <K,V>doSomethingWithSomeMap(java.util.Map<K,V>,V) は (java.util.Map,SomeClass) に適用できません

警告付きで強制的にコンパイルする方法はありますか?

ありがとう。

4

4 に答える 4

1

どのブードゥーであなたは自分自身を夢中にさせましたか:)?質問とコメントから、抽象クラスを拡張しSomeClass、インターフェイスも実装するオブジェクトがあることを確信していると思いSomeOtherClassました。この場合、これらのプロパティを共有する階層内の中間抽象クラスを提案します。

public abstract class Foo<K> extends SomeClass implements SomeOtherClass<K> {
  ...
}

そうすれば、静的メソッドのシグネチャを次のように単純化できます。

public <K,V extends Foo<K>> void doSomethingWithSomeMap (Map<K,V> map, V data);

現在のオブジェクト階層を変更したくない場合は、アダプタパターンで別のレベルの間接参照を使用してコンパイラをだますことができます。

「コンピュータサイエンスのすべての問題は、別のレベルの間接参照によって解決できます。」-デビッドウィーラー

public abstract class SomeClass {    
  public abstract void method1();
}

public interface SomeOtherClass<K> {
  void method2(K value);
}

public class MyClass extends SomeClass implements SomeOtherClass<Integer> {
  @Override
  public void method1() {
    System.out.println("MyClass.method1");
  }

  @Override
  public void method2(Integer value) {
    System.out.println("MyClass.method2(" + value + ")");
  }
}

public class Indirection<K> extends SomeClass implements SomeOtherClass<K> {
  private final Object objectValue;

  public Indirection(final Object value) {
    this.objectValue = value;
  }

  @Override
  public void method1() {
    ((SomeClass) objectValue).method1();
  }

  @Override
  public void method2(K value) {
    @SuppressWarnings("unchecked")
    SomeOtherClass<K> delegate = ((SomeOtherClass<K>) objectValue);

    delegate.method2(value);
  }
}

public static void main(String[] args) {
  Map someMap = new HashMap<Integer, MyClass>();
  SomeClass someData = new MyClass();
  Indirection a = new Indirection(someData);
  doSomethingWithSomeMap(someMap, a, 12);
}

public static <K,V extends SomeClass & SomeOtherClass<K>>
void doSomethingWithSomeMap (Map<K,V> map, V data, K value) {
  data.method1();
  data.method2(value);
}

これは印刷されます:

MyClass.method1
MyClass.method2(12)

于 2010-03-27T03:49:15.353 に答える
1

問題が のタイプであることはすでにわかっていますsomeData。残念ながら、Java では現在、intersection 型SomeClass & SomeOtherClassを変数を宣言するための型としても、cat ターゲットとしても使用できません。

しかし、偽の型変数X extends SomeClass & SomeOtherClassを導入してX someData.

これは、割り当てられる値を反射的に生成するメソッドで実行する必要がありますsomeData。安全性が証明されているチェックされていないキャスト(X)が必要になります。

全体として、次のようなものです。

public <X extends SomeClass & SomeOtherClass>
void doReflectionMagic() {
    Map someMap = ...;
    X someData = (X) ...;
    doSomethingWithSomeMap(someMap, someData);
}
于 2012-09-30T20:07:31.937 に答える
0

V の 2 番目の境界を指定して、SomeOtherClass を拡張します。しかし、私は SomeClass が SomeOtherClass を実装していないと仮定します (実装していれば、複数の境界は必要ありません)。そのため、 someData はこの境界に準拠していないため、コンパイラ エラーが発生します。変数 someData は、SomeClass を拡張し、SomeOtherClass を実装するクラスに属している必要があります。

于 2010-03-25T09:53:27.403 に答える
0

明示的に指定してみてください:

//Type2 is subclass of (or implements) SomeClass
Map<Type1, Type2> someMap = ...;
SomeClass someData = ...;
<Type1, Type2>doSomethingWithSomeMap(someMap, someData);
于 2010-03-24T21:26:00.750 に答える