Java 8 Supplier在构造函数中包含参数

cah*_*hen 63 java lambda functional-programming java-8 functional-interface

为什么供应商只支持no-arg构造函数?

如果存在默认构造函数,我可以这样做:

create(Foo::new)
Run Code Online (Sandbox Code Playgroud)

但如果唯一的构造函数采用String,我必须这样做:

create(() -> new Foo("hello"))
Run Code Online (Sandbox Code Playgroud)

Lou*_*man 54

这只是方法引用语法的限制 - 您无法传入任何参数.这就是语法的工作原理.


Bri*_*etz 51

但是,1-arg构造函数T需要StringFunction<String,T>以下内容兼容:

Function<String, Foo> fooSupplier = Foo::new;
Run Code Online (Sandbox Code Playgroud)

根据目标类型的形状,选择哪个构造函数被视为重载选择问题.


Tag*_*eev 37

如果你非常喜欢方法引用,你可以bind自己编写一个方法并使用它:

public static <T, R> Supplier<R> bind(Function<T,R> fn, T val) {
    return () -> fn.apply(val);
}

create(bind(Foo::new, "hello"));
Run Code Online (Sandbox Code Playgroud)


the*_*472 12

为什么供应商只与无参数构造函数一起工作?

因为1-arg构造函数与具有1个参数和1个返回值的SAM接口同构,例如java.util.function.Function<T,R>'s R apply(T).

另一方面Supplier<T>,T get()它与零arg构造函数同构.

它们根本不兼容.您的create()方法需要是多态的,以接受各种功能接口,并根据提供的参数采取不同的行为,或者您必须编写一个lambda主体作为两个签名之间的粘合代码.

你在这里有什么未满足的期望?什么应该在您看来怎样?

  • 如果在编写时稍微强调沟通,那将是一个更好的答案。在第一句话中同时具有“同构”和“ SAM界面”似乎对于存在于一个可以帮助人们提供其不了解的内容的网站来说是一种过大的杀伤力。 (2认同)

Jac*_*man 10

Supplier<T>接口与代表的签名功能() -> T,这意味着它不带任何参数和返回类型的东西T.作为参数提供的方法引用必须遵循该签名才能传入.

如果你想创建一个Supplier<Foo>适用于构造函数的东西,你可以使用@Tagir Valeev建议的常规绑定方法,或者你可以使用更专业的方法.

如果您希望Supplier<Foo>始终使用该"hello"String,则可以使用以下两种方式之一来定义它:作为方法或Supplier<Foo>变量.

方法:

static Foo makeFoo() { return new Foo("hello"); }
Run Code Online (Sandbox Code Playgroud)

变量:

static Supplier<Foo> makeFoo = () -> new Foo("hello");
Run Code Online (Sandbox Code Playgroud)

您可以使用方法reference(create(WhateverClassItIsOn::makeFoo);)传递方法,并且可以使用名称传递变量create(WhateverClassItIsOn.makeFoo);.

该方法更优选,因为它更容易在作为方法引用传递的上下文之外使用,并且它也能够在某人需要他们自己的专用功能接口的实例中使用,该接口也是() -> T或者() -> Foo具体的.

如果你想使用一个Supplier可以将任何String作为参数的东西,你应该使用类似于提到的绑定方法@Tagir,绕过提供以下内容的需要Function:

Supplier<Foo> makeFooFromString(String str) { return () -> new Foo(str); }
Run Code Online (Sandbox Code Playgroud)

您可以将此作为参数传递,如下所示: create(makeFooFromString("hello"));

虽然,也许您应该将所有"make ..."调用改为"提供......"调用,只是为了让它更清晰一点.