【发布时间】:2011-06-07 11:11:07
【问题描述】:
Java 编译器是否能够从其上下文中推断出通用静态函数的类型作为另一个通用静态函数的参数?
例如,我有一个简单的 Pair 类:
public class Pair<F, S> {
private final F mFirst;
private final S mSecond;
public Pair(F first, S second) {
mFirst = checkNotNull(first);
mSecond = checkNotNull(second);
}
public static <F, S, F1 extends F, S1 extends S> Pair<F, S> of(F1 first, S1 second) {
return new Pair<F, S>(first, second);
}
public F first() {
return mFirst;
}
public S second() {
return mSecond;
}
// ...
}
我有以下通用静态函数:
public static <F, P extends Pair<F, ?>> Function<P, F> deferredFirst() {
return (Function<P, F>)DEFERRED_FIRST;
}
private static final Function<Pair<Object, ?>, Object> DEFERRED_FIRST =
new Function<Pair<Object,?>, Object>() {
@Override
public Object apply(Pair<Object, ?> input) {
return input.first();
}
};
我希望使用如下(Collections2.transform is from Google Guava):
List<Pair<Integer, Double>> values = ...
Collection<Integer> firsts = Collections2.transform(values,
Pair.deferredFirst());
编译器抱怨的对象:
The method transform(Collection<F>, Function<? super F,T>) in the type
Collections2 is not applicable for the arguments
(List<Pair<Integer,Double>>, Function<Pair<Object,?>,Object>)
因此,编译器似乎无法将为 transform() 推断的类型传播到 deferredFirst(),因为它认为它们是对象。
强制编译器以以下任何一种方式理解类型都有效:
Function<Pair<Integer, ?>, Integer> func = Pair.deferredFirst();
Collection<Integer> firsts = Collections2.transform(values, func);
Collection<Integer> firsts = Collections2.transform(values,
Pair.<Integer, Pair<Integer, ?>>deferredFirst());
是否可以更改任一函数的签名以允许编译器推断/传播类型?
编辑:对于波西米亚人来说,上面的示例可以用于以下一种可能的方法:
public static int sumSomeInts(List<Pair<Integer, Double>> values) {
Collection<Integer> ints = Collections2.transform(values,
Pair.deferredFirst());
int sum = 0;
for(int i : ints)
sum += i;
return sum;
}
【问题讨论】:
-
当你有
class A<F,S> { public <F,S> void method(){}}时要小心。我的猜测是方法中的F,S覆盖了你的类中的那些(即相当于class A<F,S> { public <P,Q> void method(){}}
标签: java generics guava type-inference