java - 什么方法声明接受有界和无界的多级泛型?

标签 java bounded-wildcard

给定:

public class Testcase {

    public static <E> List<List<E>> transform(List<List<E>> list) {
        return list;
    }

    public static <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
        return list;
    }

    public static void main(String[] args) {
        List<List<Integer>> known = new ArrayList<>();
        List<List<? extends Number>> unknown = new ArrayList<>();

        transform(known);    // works
        transform(unknown);  // fails

        transform2(known);   // fails
        transform2(unknown); // works
    }
}

编译器接受 transform(known)但提示:

cannot infer type-variable(s) E
    (argument mismatch; List<List<? extends Number>> cannot be converted to List<List<E>>)
  where E is a type-variable:
    E extends Object declared in method <E>transform(List<List<E>>)

transform(unknown) .我得到了 transform2() 的相反问题.我咨询过PECS我相信 transform()是正确的方法声明,但我终其一生都无法弄清楚如何获得一个方法来处理这两种情况。

请注意,此问题仅发生在多级泛型中。 List<? extends Number>工作得很好。该问题并非特定于列表。你会得到它 Future<Task<X>>等等。

什么方法声明可以同时处理有界和无界泛型?如果不可能,为什么?

最佳答案

这项工作最具体的类型似乎是 ? extends List<? extends ?> :

class Testcase {

    public <E> List<List<E>> transform(List<List<E>> list) {
        return list;
    }

    public <E> List<List<? extends E>> transform2(List<List<? extends E>> list) {
        return list;
    }

    public <E> List<? extends List<? extends E>> transform3(List<? extends List<? extends E>> list) {
        return list;
    }    

    public void test(String[] args) {
        List<List<Integer>> known = new ArrayList<>();
        List<List<? extends Number>> unknown = new ArrayList<>();

        transform(known);    // works
        // transform(unknown);  // fails

        // transform2(known);   // fails
        transform2(unknown); // works

        transform3(known);
        transform3(unknown);
    }
}

这里解释了为什么这是有道理的。

A List<? extends Number>显然不是 List<E>对于任何 E ,因为它不必能够插入最一般的 E 的实例,因此第一个定义失败。

A List<Integer>符合 List<? extends Number> , 但这没有帮助,因为这些类型仍然不相等,因此类型 List<List<Integer>>List<List<? extends Number>>完全无关。因此,第二个定义也不成立。

您想要的是 List<List<Integer>> 的使用站点最小上限和 List<List<? extends Number>> .您可以使用以下规则获取它:List<A> 的use-site-LUB和 List<B>是:

USLUB(List<A>, List<B>) = List<? extends USLUB(A, B)>

现在,一步一步:

  1. 对于 A = IntegerB = ? extends Number , 最小上限为 ? extends Number ,因为 Integer符合 ? extends Number .
  2. 对于 List<Integer>List<? extends Number>最小上限变为 ? extends List<? extends Number>
  3. 因此最终结果是List<? extends List<? extends Number>> .

为使用地点差异欢呼 ;)

关于java - 什么方法声明接受有界和无界的多级泛型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49123950/

相关文章:

java - 如何将元数据添加到html文件

强制在 Jtextfield 中包含数字和字符的 Java 代码

java - 为什么泛型类和方法声明中不能使用通配符?

java - java中的通配符只适用于集合吗?

java - 为什么在函数式接口(interface)中使用下界

java - 从文本文件中选择一个随机单词

java - 如何在 Java 中创建 3D 标签云

带有通配符的 Java 泛型

java.io.NotSerializedException : android. app.PendingIntent