如果我有这个界面:
public interface Foo {
void bar();
}
Run Code Online (Sandbox Code Playgroud)
为什么我不能像这样实现呢?
public class FooImpl implements Foo {
@Override
public Object bar() {
return new Object();
}
}
Run Code Online (Sandbox Code Playgroud)
似乎无效应该与一切协变.我错过了什么吗?
编辑:我应该更清楚我正在寻找设计理由,而不是它不会编译的技术原因.对所有事物进行空洞协变是否会产生负面影响?
正如Bounding泛型中使用'super'关键字所讨论的那样,当涉及到方法泛型的下限时,Java类型系统被破坏/不完整.由于Optional现在是JDK的一部分,我开始更多地使用它,并且Guava遇到的问题与他的可选性开始变得困难.我提出了一个体面的工作,但我不确定它是否安全.首先,让我设置一个例子:
public class A {}
public class B extends A {}
Run Code Online (Sandbox Code Playgroud)
我希望能够声明一个方法,如:
public class Cache {
private final Map<String, B> cache;
public <T super B> Optional<T> find(String s) {
return Optional<T>.ofNullable(cache.get(s));
}
}
Run Code Online (Sandbox Code Playgroud)
以下两项工作:
A a = cache.find("A").orElse(new A())
B b = cache.find("B").orElse(new B())
Run Code Online (Sandbox Code Playgroud)
作为一种解决方法,我有一个静态实用方法如下:
public static <S, T extends S> Optional<S> convertOptional(Optional<T> optional) {
return (Optional<S>)optional;
}
Run Code Online (Sandbox Code Playgroud)
所以我的最后一个问题是,这是上述"理想"代码的类型安全吗?
A a = OptionalUtil.<A,B>convertOptional(cache.find("A")).orElse(new A());
Run Code Online (Sandbox Code Playgroud) 我对通配符边界的规则感到困惑.似乎有时可以声明一个方法参数,其边界不满足类声明的边界.在下面的代码中,方法foo(...)编译很好,但bar(...)没有编译.我不明白为什么要允许任何一个.
public class TestSomething {
private static class A<T extends String> {}
public static void foo(A<? extends Comparable<?>> a) {
}
public static void bar(A<? extends Comparable<Double>> a) {
}
}
Run Code Online (Sandbox Code Playgroud)