当前位置: 首页 > 面试题库 >

不兼容的通用通配符捕获

卞安邦
2023-03-14
问题内容

在以下代码段中:

package test;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

public class WildcardsTest<K, V> {
    private Iterator<Map.Entry<K, ? extends Collection<V>>> iterator;
    public WildcardsTest(Map<K, ? extends Collection<V>> map) {
        iterator = map.entrySet().iterator();
        /* Type mismatch: cannot convert from
           Iterator<Map.Entry<K,capture#1-of ? extends Collection<V>>> to
           Iterator<Map.Entry<K,? extends Collection<V>>> */
    }
}

尽管类型似乎完全匹配,但分配是错误的。

我通过将Collection的类型指定为另一个通用参数,设计出了一种肮脏的解决方法,如下所示:

public class WildcardsTest<K, V, C extends Collection<V>> {
    private Iterator<Map.Entry<K, C>> iterator;
    public WildcardsTest(Map<K, C> map) {
        iterator = map.entrySet().iterator();
    }
}

但是该C参数实际上是“无关”类型,只会使API复杂化,在保持类型安全的同时,有没有什么方法可以摆脱它呢?

谢谢。


问题答案:

这样做就可以了:

private final Iterator<? extends
    Map.Entry<K, ? extends Collection<V>>
> iterator;

您仍然可以像这样使用迭代器:

public void foo(){
    while(iterator.hasNext()){
        Entry<K, ? extends Collection<V>> entry = iterator.next();
        Collection<V> value = entry.getValue();
    }
}

作为参考,请阅读get and
put原理
(最初来自Java
Generics和Collections



 类似资料:
  • 以下是这个问题,它提供了一个解决方案,但没有解释它(不幸的是,答案中的链接现在没有了): WTF???在上调用返回一个,该不能赋值给类型为的变量,但可以赋值给类型为的变量?扩展Map.Entry >????? 有人能说说这是怎么回事吗?这是否意味着,每当我使用至少2层深度的通配符类型编写方法时,我都必须记住将其设置为在什么地方?

  • 方法在类型不适用于参数

  • 在这个问题中,我看到我可以使用帮助方法将通配符泛型“捕获”到类型T中以执行类型安全操作,如下所示: 但是当我尝试使用关键字执行此操作时,它不起作用: 我得到以下错误: 当使用扩展关键字时,有没有办法捕获通配符? 我的背景是,我有一个扩展给定类a的类列表,每个类都有一个不同的泛型参数T。对于每个类,我想获得对其T类的引用,我试图安全地进行类型转换。

  • 问题内容: 阅读Java在线教程,我对通配符捕获一无所知。例如: 为什么编译器无法保留分配的安全性?它知道,例如,通过执行带有整数列表的方法,它可以从i.get中获取一个整数值。因此,它尝试将索引0处的Integer值设置为相同的Integer列表(i)。那么,怎么了?为什么要编写通配符助手? 问题答案: 为什么编译器无法保留分配的安全性? 编译器不知道 任何 关于类型中的元素通过定义。通配符并

  • 在阅读Java在线教程时,我对通配符捕获一无所知。例如:

  • 下面的SCCE显示了实现接口标记的两个类(B和C)。对于实现Marker的每个类,都有一个实现泛型处理程序接口的对应类(B_处理程序、C_处理程序)。映射用于关联Pair的类类型。其次是它的关联处理程序。代码按预期执行;但是,我得到一个编译时警告: 警告:[未检查]未检查的强制转换处理程序h1=(处理程序)(dispatch.get(p1.second.get类()));需要:处理程序找到:处理程