Java 8 下界通配符

标签 java generics java-8

我正在准备 OCP 证书,并且遇到了下界通配符的想法。如果我理解正确,当我们想让 Java 知道“有界类型”总是可以添加到我们的通用集合中时,会使用下界通配符。

例如:

public static void addInteger(List<? super Integer> list, Integer i)
{
    list.add(i);
}


public static void main(String[] args)
{   
    List<Number> list = new ArrayList<>();
    addInteger(list, 100);
    addInteger(list, 200);
    System.out.println(list);       // [100,200]

}

由于“? super Integer”表示类型必须是 Integer 或其父类(super class),因此在每种情况下都可以将 Integer 添加到列表中。

但是,这段代码仍然可以正常编译和运行:

public static void main(String[] args)
{   
    Predicate<? super String> pred = s -> s.startsWith("M"); // still compiles
    System.out.println(pred.test("Mon")); // Output true

}

现在我们有一个 Predicate 将采用 1 个参数,该参数是一个 String 或其父类(super class),但我们不确定它是否实际上是一个 String(如果它只是一个 Object 怎么办?)。但是,我们仍然可以访问 startsWith() 方法,就像 s 实际上是一个字符串。

为什么会这样?请给我解释一下。

最佳答案

Predicate<? super String> pred可以分配一个 Predicate<String>Predicate<Object> .您正在为其分配 Predicate<String> ,这是允许的。编译器推断 s -> s.startsWith("M")Predicate<String>因为你使用的是 String lambda 表达式中的方法。

例如,以下也会通过编译:

Predicate<? super String> pred = (Object o) -> o.hashCode() > 0;

您还可以看到以下内容通过了编译:

Predicate<String> preds = s -> s.startsWith("M");
Predicate<Object> predo = (Object o) -> o.hashCode() > 0;
Predicate<? super String> pred = preds;
pred = predo;

Predicate<? super String>可以同时分配 Predicate<String>和一个 Predicate<Object> .

也就是说,请注意 pred.test()只会接受 String s,而不是任何 Object .原因是 pred变量可以引用 Predicate<Object>Predicate<String>在运行时,只有一个 String双方都可以接受。

关于Java 8 下界通配符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56661303/

相关文章:

c# - 任何人都可以举一个很好的例子来说明泛型类的用途吗?

java - 泛型对象创建在 Eclipse 中显示错误,但在 Maven 中编译

Java 8 流 : can you capture/reuse a value calculated in a filter?

java - 延迟递归 Java 8 流

java - 如何获取目录的父目录

JAVA RESTFull服务器获取POST数据,其中 "%"(百分比)作为值@FormParam

java - import org.apache.poi.xssf 无法解析

java - 计算两个日历日期之间的工作日差异

java - 泛型继承 + 集合 + 方法 = 问题

java - 了解java中的 'TypeElement'和 'DeclaredType'接口(interface)