Java 返回参数类型受泛型类型参数约束的lambda函数

Java 返回参数类型受泛型类型参数约束的lambda函数,java,generics,lambda,types,type-inference,Java,Generics,Lambda,Types,Type Inference,假设我想编写一个方法buildBiFxnWithSameTypeArgs,它生成一个双参数BiFunction,其输入参数的类型相同。具体是什么类型(即调用buildBiFxnWithSameTypeArgs时)是未知的——我只是希望编译器强制执行,每当调用buildBiFxnWithSameTypeArgs返回的函数时,提供给它的参数类型必须匹配。本质上,最终效果应该是lambda,相当于在方法定义中对两个参数的类型使用相同的泛型类型参数 我最初的尝试如下所示: public interfac

假设我想编写一个方法
buildBiFxnWithSameTypeArgs
,它生成一个双参数
BiFunction
,其输入参数的类型相同。具体是什么类型(即调用
buildBiFxnWithSameTypeArgs
时)是未知的——我只是希望编译器强制执行,每当调用
buildBiFxnWithSameTypeArgs
返回的函数时,提供给它的参数类型必须匹配。本质上,最终效果应该是lambda,相当于在方法定义中对两个参数的类型使用相同的泛型类型参数

我最初的尝试如下所示:

public interface ConstrainedBiFunction<I, O> extends BiFunction<I, I, O> {}

public static ConstrainedBiFunction<?, String> buildBiFxnWithSameTypeArgs() {
    return (inputOne, inputTwo) -> String.valueOf(inputOne) + String.valueOf(inputTwo);
}

public void test() {
    buildBiFxnWithSameTypeArgs().apply(Integer.valueOf(1), Integer.valueOf(2));
}
是否可以返回一个lambda函数,该函数的参数类型是推断的,然后以这种方式相互约束

编辑:为这个不太好的问题道歉;我有一个更复杂的问题,我试图抓住这个问题的本质,以便提出最简单的问题,但看起来我把问题简化得太多了。当然,我知道所有类都继承自
对象
,因此在这个过于简化的问题呈现中,@shmosel和@JB提出的解决方案是有效的。一旦我能更好地提取原始问题,我将发布一个新问题。

通配符的意思是“特定但未知的类型”。您不能传递任何满足类型为
的参数的参数,因为它可能是错误的类型。将返回类型更改为
ConstrainedBiFunction
,它将能够接受任何输入类型,因为每个类都隐式扩展
对象

public static ConstrainedBiFunction<Object, String> buildBiFxnWithSameTypeArgs() {
    return (inputOne, inputTwo) -> String.valueOf(inputOne) + String.valueOf(inputTwo);
}
publicstaticconstrainedbiffunction buildBiFxnWithSameTypeArgs(){
return(inputOne,inputwo)->String.valueOf(inputOne)+String.valueOf(inputwo);
}
注意,这仍然可以用于使用原则对输入类型有限制的方法。例如:

// input parameter must be of type Integer or any supertype,
// so that we can safely pass in an Integer
String combine(ConstrainedBiFunction<? super Integer, String> function) {
    return function.apply(1, 2);
}

void test() {
    ConstrainedBiFunction<Object, String> concat = buildBiFxnWithSameTypeArgs();
    ConstrainedBiFunction<Integer, String> sum = (a, b) -> String.valueOf(a + b);
    System.out.println(combine(concat)); // "12"
    System.out.println(combine(sum));    // "3"
}
//输入参数的类型必须为Integer或任何超类型,
//这样我们就可以安全地传递一个整数
String combine(ConstrainedBiFunction正确地指出,对于遵循PECS规则的所有API,使用
对象
作为输入类型应该足够了,但是可以修复您最初的尝试

您必须添加类型参数,而不是通配符,该参数允许调用者选择类型:

public interface ConstrainedBiFunction<I, O> extends BiFunction<I, I, O> {}

public static <T> ConstrainedBiFunction<T, String> buildBiFxnWithSameTypeArgs() {
    return (inputOne, inputTwo) -> String.valueOf(inputOne) + String.valueOf(inputTwo);
}

public void test() {
    ConstrainedBiFunction<Integer, String> f1 = buildBiFxnWithSameTypeArgs();
    String s1 = f1.apply(1, 1);
    ConstrainedBiFunction<String, String>  f2 = buildBiFxnWithSameTypeArgs();
    String s2 = f2.apply("hello ", "world");
}

您认为
ConstrainedBUIFunction所有类最终都会从对象继承,因此,即使您传递香蕉和卡车,编译器也会将其推断为ConstrainedBUIFunction,除非您显式指定类型。
public interface ConstrainedBiFunction<I, O> extends BiFunction<I, I, O> {}

public static <T> ConstrainedBiFunction<T, String> buildBiFxnWithSameTypeArgs() {
    return (inputOne, inputTwo) -> String.valueOf(inputOne) + String.valueOf(inputTwo);
}

public void test() {
    ConstrainedBiFunction<Integer, String> f1 = buildBiFxnWithSameTypeArgs();
    String s1 = f1.apply(1, 1);
    ConstrainedBiFunction<String, String>  f2 = buildBiFxnWithSameTypeArgs();
    String s2 = f2.apply("hello ", "world");
}
Comparator<Integer> c1 = Comparator.naturalOrder();
c1.compare(10, 42);
Comparator<String> c2  = Comparator.naturalOrder();
c2.compare("foo", "bar");