n24*_*47s 6 java generics compiler-errors java-8
我遇到了泛型问题让我对编译器实际处理泛型类型的方式感到困惑.考虑以下:
// simple interface to make it a MCVE
static interface A<F, S> {
public F getF();
public S getS();
}
static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
return (L, R) -> c.compare(L.getS(), R.getS());
}
Run Code Online (Sandbox Code Playgroud)
以下将不会编译,因为两个泛型类型都减少为Object调用时thenComparing:
Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R))
.thenComparing(wrap((L, R) -> Integer.compare(L, R)));
Run Code Online (Sandbox Code Playgroud)
但是如果我像下面的例子那样将它们分解,那么一切都正确地编译(并运行):
Comparator<A<String, Integer>> c = wrap((L, R) -> Integer.compare(L, R));
c = c.thenComparing(wrap((L, R) -> Integer.compare(L, R)));
Run Code Online (Sandbox Code Playgroud)
所以问题是:这里发生了什么?我怀疑这是由于编译器的一些奇怪行为而不是预期的语言规范?或者我错过了一些明显的东西?
第二次尝试正确编译,因为您自己指定了变量的类型,告诉编译器它是什么,因为编译器没有足够的信息来解决它.
看看这个简化的例子,它来自vavr(顺便说一下).有一个Try<T>类表示某些操作的结果.通用参数T是该结果的类型.有一个静态工厂可以立即创建失败,这意味着我们没有结果,但泛型参数仍然存在:
static <T> Try<T> failure(Throwable exception) {
return new Try.Failure(exception);
}
Run Code Online (Sandbox Code Playgroud)
这里T来自哪里?用法如下:
public Try<WeakHashMap> method() {
return Try.failure(new IllegalArgumentException("Some message"));
}
Run Code Online (Sandbox Code Playgroud)
这Try<WeakHashMap>是我的选择,而不是编译器,你实际上可以在那里放任何你想要的东西,因为你正在选择类型.
在你的例子中同样的事情,只有Comparator泛型参数String,因为你指定了它并且编译器同意它(比如Try<WeakHashMap>).当你添加一个链式调用时,你强迫编译器推断出类型本身,它是Object,因为它可能是另一种类型?
你还能做什么(注意Testing.<String, Integer>wrap):
public class Testing {
static interface A<F, S> {
public F getF();
public S getS();
}
static <V, S> Comparator<A<V, S>> wrap(Comparator<S> c) {
return (L, R) -> c.compare(L.getS(), R.getS());
}
public static void main(String[] args) {
Comparator<A<String, Integer>> comp = Testing.<String, Integer>wrap((L, R) -> Integer.compare(L, R))
.thenComparing(wrap((L, R) -> Integer.compare(L, R)));
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
62 次 |
| 最近记录: |