以下のSCCEは、インターフェイスマーカーを実装する2つのクラス(BおよびC)を示しています。 Markerを実装する各クラスには、汎用ハンドラインタフェース(B_Handler、C_Handler)を実装する対応するクラスがあります。マップは、Pair.secondのクラス型をそれに関連付けられたHandlerに関連付けるために使用されます。コードは予期したとおりに実行されます。ただし、コンパイル時の警告が表示されます。Java Genericsワイルドカードキャプチャ警告
警告:[未チェック]未チェックキャスト ハンドラh1 =(ハンドラ)(dispatch.get(p1.second.getClass())); 必須:ハンドラー が見つかりました:ハンドラー ここで、CAP#1は新しいタイプ変数です。 CAP#1はマーカーのキャプチャーを延長しますか?マーカーを伸ばす
@SuppressWarnings(value = "unchecked")以外にこれを解決する最もクリーンな方法は何ですか?
package genericpair;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingUtilities;
public class GenericPair
{
public class A
{
}
public interface Marker
{
}
public class B implements Marker
{
}
public class C implements Marker
{
}
public Pair<A, Marker> getTarget()
{
A a = new A();
C c = new C();
return new Pair<>(a, c);
}
public interface Handler<T extends Marker>
{
void handle(Pair<A, T> target);
}
public class B_Handler implements Handler<B>
{
@Override
public void handle(Pair<A, B> target)
{
System.out.println("B");
}
}
public class C_Handler implements Handler<C>
{
@Override
public void handle(Pair<A, C> target)
{
System.out.println("C");
}
}
public class Pair<F, S>
{
public final F first;
public final S second;
public Pair(F first, S second)
{
this.first = first;
this.second = second;
}
}
private void executeSCCE()
{
// register a handler for each Marker type
Map<Class, Handler<? extends Marker>> dispatch = new HashMap<>();
dispatch.put(B.class, new B_Handler());
dispatch.put(C.class, new C_Handler());
// get a target (e.g., Pair<A,C>)
Pair<A, Marker> p1 = getTarget();
// select handler based on the class type of the second parameter
Handler<Marker> h1 = (Handler<Marker>) (dispatch.get(p1.second.getClass()));
h1.handle(p1);
}
public static void main(String[] args)
{
SwingUtilities.invokeLater(() -> new GenericPair().executeSCCE());
}
}