繁体   English   中英

将泛型类型参数标记为Java 8中的功能接口

[英]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);
}

这段代码适用于未知类型AB以及Map的未知参数化,因为唯一的约束是方法Map.get接受它的A实例,因为它接受任何东西并返回它做任何类型的B实例? extends B ? extends B将可分配给B

现在,如果你的调用者有一个任意子类型的FunctionX ,例如

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM