在Java 8中返回泛型函数接口 [英] Return generic functional interface in Java 8
问题描述
那么,为了更好的理解,最好看看
condition3
。 问题是,它没有编译。我认为,因为编译器无法弄清楚,函数接口
H
可以通过实现来实现。 没有泛型,它工作正常。
@FunctionalInterface
public interface Finder< T,S> {
Stream< S> findBest(T t);
//有效代码
static< P,Q> Finder< P,Q> condition1(){
return p - >空值;
}
//有效的代码,但是当方法被调用时只选择其中一个H
static< P,Q,H扩展Finder< P,Q>> ; H条件2(Pair< Predicate< P>,H> ... hs){
return hs [0] .getRight();
}
//应该返回一个方法,当它用P
调用时,它会选择合适的H
// //编译器抱怨:
//该表达式的目标类型必须是功能接口
static< P,Q,H扩展Finder< P,Q>> H条件3(Pair< Predicate< P>,H> ... hs){
return p - > stream(hs).filter(pair - > pair.getLeft().test(p))
.findFirst()
.map(Pair :: getRight)
.map(h - > h.findBest(p))
。orElseGet(Stream :: empty);
}
}
那么这里有什么问题?我可以解决它,如果它可能与Java:如何?
看看你的方法的签名,并试图告诉什么确切的返回类型是:
static
Lambdas只能实现界面
在编译时已知,但编译器不知道 H
的实际类型参数。
你的第一个方法是可行的,因为它返回lambda可以实现的类型 Finder< P,Q>
,你的第二个方法可以工作,因为它不使用lambda来实现返回类型 H扩展Finder< P,Q>
。
只有第三种方法试图为类型指定lambda表达式参数 H扩展Finder< P,Q>
。
A解决方案并不是让调用者自由地将特定的 Finder
子类型作为方法的返回类型:
< $ P $ Q $> $ P $ Q $>静态< P,Q>条件3(Pair< Predicate< P>,H> ;. .. hs){
请看下面的例子:
final class HImpl实现了Finder< String,String> {
public Stream< String> findBest(String t){
return null; //只是为了说明,我们从来没有真正使用过类
}
}
...
HImpl x = Finder。< String,String,HImpl> condition3();
考虑到您的原始方法签名,这个编译没有任何错误。但是如何使用lambda表达式 condition3
在这里提供一个 HImpl
的实例?
I want to write kind of function factory. It should be a function, which is called once which different strategies as parameters. It should return a function, which selects one of this strategies dependent on the parameter, which is to be fulfilled by a predicate.
Well, better look at condition3
for better understanding.
The problem is, that it is not compiling. I think because the compiler can't figure out, that the functional interface H
can be realized by the implementation.
Without generics it is working fine.
@FunctionalInterface
public interface Finder<T, S> {
Stream<S> findBest (T t);
// Valid code
static <P, Q> Finder<P, Q> condition1 () {
return p -> null;
}
// Valid code, but selects just one of the H's when the method is invoked
static <P, Q, H extends Finder<P, Q>> H condition2 (Pair<Predicate<P>, H>... hs) {
return hs[0].getRight ();
}
// Should return a method, which selects the appropiate H
// whenever it is invoked with an P
// Compiler complain:
// The target type of this expression must be a functional interface
static <P, Q, H extends Finder<P, Q>> H condition3 (Pair<Predicate<P>, H>... hs) {
return p -> stream (hs).filter (pair -> pair.getLeft ().test (p))
.findFirst ()
.map (Pair::getRight)
.map (h -> h.findBest (p))
.orElseGet (Stream::empty);
}
}
So what's the problem here? Can I solve it and if it's possible with Java: how?
Look at the signature of your method and try to tell what the exact return type is:
static <P, Q, H extends Finder<P, Q>> H condition3(…
Lambdas can only implement an interface
known at compile-time. But the actual type argument for H
is not known to the compiler.
Your first method works because it returns the type Finder<P, Q>
which the lambda can implement, your second works because it doesn’t use a lambda for implementing the return type H extends Finder<P, Q>
.
Only your third method attempts to specify a lambda expression for a type argument H extends Finder<P, Q>
.
A solution is not to give the caller the freedom to mandate a particular sub-type of Finder
as the method’s return type:
static <P, Q, H extends Finder<P, Q>>
Finder<P, Q> condition3(Pair<Predicate<P>, H>... hs) {
To illustrate what implications your original method signature has, look at the following example:
final class HImpl implements Finder<String,String> {
public Stream<String> findBest(String t) {
return null; // just for illustration, we never really use the class
}
}
…
HImpl x=Finder.<String,String,HImpl>condition3();
Given your original method signature this compiles without any error. But how ought the method condition3
provide an instance of HImpl
here using your lambda expression?
这篇关于在Java 8中返回泛型函数接口的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!