Java:如何使用 Optional.empty() 编译?

标签 java java-8

这似乎是一个非常愚蠢的问题,但我无法理解为什么使用Optional<T>编译:

import java.util.Optional;

public class Driver {
    static void foo(Optional<String> x) { }

    public static void main() {
        foo(Optional.empty());
    }
}

Optional::empty 被定义为返回一个 Optional<T> . Driver::main 内部, 表达式 Optional.empty()似乎它会返回 Optional<Object> ,因为我没有参数化 Optional 的使用所以我希望它会回落到 Object作为类型参数。然后,我传递 Optional<Object>到一个需要 Optional<String> 的函数,这是参数的向下转换,不应被允许。我希望看到类似的内容:

incompatible types: Optional<Object> cannot be converted to Optional<String>

但是,代码编译得非常好。显然,我在这里的思考过程是不正确的……但是在哪里呢?


让我澄清一下我在这里的答案中寻找的是什么......我知道什么是类型推断。我不明白这里发生了什么如何以及从 Java 7 到 Java 8 语言发生了什么变化。例如,这段代码在 Java 8 中编译得很好,但在 Java 7 中却失败了:

final class Opt<T> {
    private final T value;

    Opt(T x) {
        value = x;
    }

    public static <T> Opt<T> empty() {
        return new Opt<T>(null);
    }
}

public class Driver {
    static void bar(Opt<String> x) { }

    public static void main() {
        bar(Opt.empty());
    }
}

当您必须处理诸如重载之类的事情时,这在 Java 8 中如何工作?是否有 Java 语言规范的特定部分讨论此类事情?

最佳答案

这是因为 empty() 方法在 Optional 中定义的方式:

public static<T> Optional<T> empty() {
    @SuppressWarnings("unchecked")
    Optional<T> t = (Optional<T>) EMPTY;
    return t;
}

注意上面的方法类型参数:

public static<T> Optional<T> empty() {
             ^^^ method type parameter

这意味着当调用 empty() 时,它将 T 绑定(bind)到其调用者的上下文,在您的例子中是 String。有关详细信息,请参阅 Java 教程中此页面中有关目标类型的部分:

http://docs.oracle.com/javase/tutorial/java/generics/genTypeInference.html

关于Java:如何使用 Optional.empty() 编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26129564/

相关文章:

list - 如何从 map 中获取 optional 值作为 optional 列表?

java - 正则表达式从复杂字符串中提取子字符串

java - 在 JFreeChart 中创建简单的箱线图

java - 将时间跨度(long 和 TimeUnit)添加到 java.util.Date 的最佳方法是什么?

java - 这段代码是否滥用了观察者模式?

java-8 带参数谓词

java - 映射条目的每个键的流,包含列表作为值

java - Collectors.joining 与 StringBuilder.append

java - 如何查找java项目中未使用/死的代码

java - 成员类(内部类)如何访问外部类的实例变量?