使用Lambdas创建和填充对象作为参数

问题描述

与其他语言更直接的lambda相比,我发现Java lambda语法具有独特的晦涩和混乱之处。

我的理解是,您可以使用lambda代替对象作为方法的参数,并且语法类似

method(() -> { /*code to return value*/ } )

但是我无法获得有效的语法。

我想建立一个对象列表,并想用唯一的数据填充每个新对象(比如说Math.random()值)。所以我正在尝试这样做:

ArrayList<MyType> mytypes = new ArrayList<>();
mytypes.add( () -> { MyType m = new MyType(); m.populate(Math.random()); return m } );

但这显然不是合法的,尽管这似乎与目前执行此操作的最小示例相匹配。我也尝试过

mytypes.add( t -> { MyType m = new MyType(); m.populate(Math.random()); return m } );

mytypes.add( MyType t -> { MyType m = new MyType(); m.populate(Math.random()); return m } );

mytypes.add( (MyType t) -> { MyType m = new MyType(); m.populate(Math.random()); return m } );

mytypes.add( { MyType m = new MyType(); m.populate(Math.random()); return m } );

基于在线上看到的各种语法,这些语法几乎没有提供信息。

那么这有什么问题吗?这该怎么做?只是不可能吗? (很遗憾,因为大多数其他使用lambda的语言似乎都可以直观地做到这一点。)

解决方法

Lambda仅可用于需要功能接口实例的地方。功能接口是具有单个抽象方法的接口。将lambda编译为实现该接口的实例,然后lambda主体成为该单个接口方法的实现。

这里:

ArrayList<MyType> mytypes = new ArrayList<>();
mytypes.add( () -> { MyType m = new MyType(); m.populate(Math.random()); return m } );

add的任何重载都不会将功能接口作为参数。因此,以上内容无法编译。而是应将其写为单独的语句:

ArrayList<MyType> mytypes = new ArrayList<>();
MyType m = new MyType();
m.populate(Math.random());
mytypes.add(m);

出于完整性考虑,您可以使用带有技巧的lambda来编写它,方法是将lambda转换为{em>是一个功能接口的Supplier<MyType>,然后调用{{ 1}}来在lambda中实际运行代码。

get

但是请不要编写这样的代码... 我不知道可以接受哪种“其他语言”,但这不是我们在中的做法Java