Java泛型通配符捕获警告

jav*_*vaj 3 java generics

下面的 SCCE 显示了实现接口 Marker 的 2 个类(B 和 C)。对于每个实现 Marker 的类,都有一个相应的类实现通用 Handler 接口(B_Handler、C_Handler)。映射用于将 Pair.second 的类类型与其关联的处理程序相关联。代码按预期执行;但是,我收到一个编译时警告:

警告:[unchecked] unchecked cast Handler h1 = (Handler) (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());
    }
}
Run Code Online (Sandbox Code Playgroud)

fla*_*kes 5

Consider the following example:

List<? extends List> test1 = new ArrayList<>();
List<List> test2 = (List<List>) test1;
Run Code Online (Sandbox Code Playgroud)

Here we get the warning:

 warning: [unchecked] unchecked cast
        List<List> test2 = (List<List>) test1;
                                        ^
  required: List<List>
  found:    List<CAP#1>
  where CAP#1 is a fresh type-variable:
    CAP#1 extends List from capture of ? extends List
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为无法确保List<List> will的通用约束匹配List<? extends List>。想象一下,我们将此示例重写为以下内容:

List<? extends List> test1 = new ArrayList<ArrayList>();
List<List> test2 = (List<List>) test1;
test1.add(new LinkedList<>());//ERROR no suitable method found for add(LinkedList<Object>)
test2.add(new LinkedList<>());//Will work fine!!
Run Code Online (Sandbox Code Playgroud)

这里更明显的是初始合约被破坏了。定义为包含的列表ArrayList现在包含一个LinkedList. 这是不安全的,也是您收到此警告的原因。所以没有办法从Handler<? extends Marker>toHandler<Marker>安全地投射。