[英]Mark generic type parameter as functional interface in Java 8
我想将函数的类型参数限制为功能接口。
像这样的东西:
public static <@FunctionalInterface T extends Function<A, B>> T foo () {
return a -> bar;
}
这里不允许使用@FunctionalInterface
。
目的是使得可以返回具有类型参数类型的lambda。 由于T
可以是普通类,因此不允许返回lambda。
是否有可能将类型参数限制为功能接口?
正如您在其他问题上已经讨论过的那样,这是不可能的 。 不仅要注释类型参数,还要特别是通过lambda表达式实现未知接口。
编译方法时
public static <@FunctionalInterface T extends Function<A, B>> T foo() {
return a -> bar;
}
编译器必须生成能够返回适当类型的实例的代码,但它不知道T
将是什么,因为这取决于foo()
的调用者,但编译foo()
和编译foo()
的调用者之间没有任何联系foo()
。 后者可能在几年之后发生在我们这个星球的另一边。
也许你不知道Type Erasure 。 您的方法foo()
只有一个编译版本,但它必须满足返回适当类型实例的通用协定。 不知道 T
是 什么 。
这在返回现有实例时有效,例如返回集合的元素或作为参数传递的值之一。 但是泛型方法无法返回类型参数的新实例。 不使用new
,也不使用lambda表达式。
请注意,如果让知道类型的调用者执行“up-level”操作,仍然可以使用所需函数的子接口实现。 假设你有一个Generic工厂方法,如:
public static <A,B> Function<A,B> getter(Map<?, ? extends B> map) {
return a->map.get(a);
}
这段代码适用于未知类型A
和B
以及Map
的未知参数化,因为唯一的约束是方法Map.get
接受它的A
实例,因为它接受任何东西并返回它做任何类型的B
实例? extends B
? extends B
将可分配给B
现在,如果你的调用者有一个任意子类型的Function
, X
,例如
interface X extends Function<String, Integer> {}
它可以使用你的工厂方法来生成一个装饰函数的X
实例,如:
Map<String, Integer> map=new HashMap<>();
X x=getter(map)::apply;
x.apply("foo");
这里,在调用者站点上检查对作为功能接口的 X
的约束。
我的仿制药很弱,但我认为这将是:
public static <T, R> Function<T, R> foo() {
// ...
}
但是我认为你不能实例化 R
,你必须能够从T
获得它。 您的代码不知道R
的运行时类型,因此new R()
超出范围。
但是,例如,如果T
可以给你R
,就像Map
:
public static <K, R, T extends Map<K,R>> Function<T, R> makeGetter(K key) {
return a -> a.get(key);
}
返回一个getter,当使用给定的map调用时,将返回带有用于创建getter的键的条目:
import java.util.function.Function;
import java.util.*;
public class Example {
public static final void main(String[] args) {
Map<String,Character> mapLower = new HashMap<String,Character>();
mapLower.put("alpha", 'a');
mapLower.put("beta", 'b');
Map<String,Character> mapUpper = new HashMap<String,Character>();
mapUpper.put("alpha", 'A');
mapUpper.put("beta", 'B');
Function<Map<String, Character>, Character> getAlpha = makeGetter("alpha");
System.out.println("Lower: " + getAlpha.apply(mapLower));
System.out.println("Upper: " + getAlpha.apply(mapUpper));
}
public static <K, R, T extends Map<K,R>> Function<T, R> makeGetter(K key) {
return a -> a.get(key);
}
}
输出:
Lower: a Upper: A
我认为类型擦除不会让你比这更接近,除非使用实例方法和参数化你的包含类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.