在Java8中通过::new初始化时如何将参数传递给类构造函数 [英] How to pass argument to class constructor when initialzed thru ::new in Java8

查看:20
本文介绍了在Java8中通过::new初始化时如何将参数传递给类构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 java 8 流 API 对 Store 对象列表执行操作.

I am using java 8 stream API to perform action on a list of Store objects.

Store 接受一个 String 参数和一个 Mapper 对象.Mapper 对于所有 Store 对象都是相同的.

Store takes a String argument and a Mapper object. Mapper will be same for all Store object.

问题:当我在 .map(Store::new) 初始化 Store 时如何传递 Mapper 对象?

Question: How can I pass Mapper object when I initialize Store here .map(Store::new)?

public class Store {
    public Store(String name, Mapper mapper) {
    }
}

public class Mapper {
}

public class Test {
    public static void main(String[] args) {
        List<String> names = new ArrayList<String>();

        Mapper mapper = new Mapper();
         // compile time problem at Store::new because it takes 2 arguments
         List<Store> actions = 
             names.stream()
              .map(Store::new)
              .collect(Collectors.toList());
    }
}

推荐答案

对于需要接收自由变量(即来自上下文的变量)的构造函数,您不能使用方法引用.

You can't use a method reference for a constructor that needs to receive a free variable, i.e. a variable from the context.

请参阅Java 教程,方法参考部分查找有关方法引用的更多信息.

Please refer to the Java Tutorial, section Method References to find more info about method references.

您可以改用 lambda 表达式:

You can use a lambda expression instead:

Mapper mapper = new Mapper();

List<Store> actions = 
    names.stream()
        .map(name -> new Store(name, mapper))
        .collect(Collectors.toList());

如果出于某种原因,您坚持使用方法引用,您仍然可以,虽然解决方案更加复杂和麻烦.事实上,从所有可能的角度来看,使用 lambda 表达式而不是我在下面介绍的 hack 要好得多.我写它只是为了表明只有当你已经有一个签名与预期匹配的方法或构造函数时,方法引用才是好的.

If, for whatever reason, you insist on using a method reference, you still can, though the solution is more complex and cumbersome. In fact, it's much better from all possible points of view to use a lambda expression instead of the hack I'm introducing below. I'm writing it just to show that method references are good only if you already have a method or constructor whose signature matches the expected one.

假设你声明了这个辅助方法:

Suppose you declare this helper method:

public static <T, U, R> Function<T, R> bindSecond(
        BiFunction<T, U, R> biFunction, 
        U free) {
    return t -> biFunction.apply(t, free);
}

在这里,我正在创建并返回一个 1 参数函数,该函数将其唯一一个参数应用于给定的双函数(2 参数函数)以及给定的自由变量.换句话说,我将给定的自由变量绑定到给定的双函数作为它的第二个参数.

Here I'm are creating and returning a 1-argument function that applies its only one argument to the given bifunction (a 2-argument function), as well as the given free variable. In other words, I'm binding the given free variable to the given bifunction as its second argument.

在您的示例中,Store::new 实际上是一个双函数,它接受两个参数(namemapper)并返回一个值(新的 Store 实例),并且您会收到该编译错误,因为 Stream.map 需要一个 1-argument 函数,该函数将流的元素作为其唯一一个参数.

In your example, Store::new is actually a bifunction that takes two arguments (name and mapper) and returns a value (the new Store instance), and you are getting that compilation error because Stream.map expects a 1-argument function that takes the element of the stream as its only one parameter.

bindSecond 辅助方法实际上将给定的双函数和自由变量转换为与 Stream.map 方法的签名相匹配的单参数函数.

The bindSecond helper method actually transforms the given bifunction and free variable into a 1-argument function that matches the signature of the Stream.map method.

你可以这样使用它:

Mapper mapper = new Mapper();

List<Store> actions = 
    names.stream()
        .map(bindSecond(Store::new, mapper))
        .collect(Collectors.toList());

但是,我认为在简单的 lambda 表达式上使用它没有意义.

这篇关于在Java8中通过::new初始化时如何将参数传递给类构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆