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

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

问题描述

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

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

商店获取 String 参数和 Mapper 对象。所有商店对象的 Mapper 都相同。

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

问题:初始化 Store Mapper 对象$ c>这里 .map(Store :: new)

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 实际上是一个带有两个参数的双功能( name mapper )并返回一个值(新的 Store 实例),你得到的编译错误是因为 Stream.map 期望一个1参数函数,它将流的元素作为其唯一的一个参数。

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 helper方法实际上将给定的双函数和自由变量转换为与 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.

您可以按如下方式使用它:

You could use it as follows:

Mapper mapper = new Mapper();

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

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

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

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