这似乎是一个非常愚蠢的问题,但我无法理解为什么使用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/