Java lambda 参数转换
有如下类:
Class A {
public void a(Consumer<? extends Number> numberConsumer) {};
}
调用时有如下写法:
1. a.a((Long l) -> {});
2. a.a((Consumer<Long>) l -> {});
3. a.a(new Consumer<Long> {...});
那么问题来了:
- 写法1和写法2有什么关系,写法1是写法2的简化版?怎么能证明呢?
- 还有其它写法?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
1、2 两种形式,也算不得谁是谁的简写吧,他们只是用不同的方式告诉编译器如何推断/检查类型。
而我觉得更应该讨论的是采用
<? extends Number>
来定义参数类型,纯接口是没问题,但是实现不出来,看下面的代码:在
A.a
的函数体中,怎么调numberConsumer
都不对,因为它并不知道 consumer 会处理哪一种类型,所以传哪一种类型进去都不准确。首先,得明白 Java 的 Labmda 类型是通过 Functional Interface 来定义的。
所谓 Functional Interface,是指只有一个抽象方法的接口(有默认实现的接口方法不算抽象方法),Java 8 以后可以使用
@FunctionalInterface
来注解。那么Consumer<T>
的定义是这样:观察
accept(T t)
,它描述了一个泛型 Lambda 类型,参数是T
类型,不需要返回值。如果把T
具体化为Long
就是(Long v) -> {...}
这样类型的 Lambda,所以a.a((Long long) -> {})
符合Consumer<Long>
a.a((Consumer<Long>) long -> {})
,这里long
是关键字,不能当参数名使用,可以改为lv
。改过之后,lv
会是Long
类型,因为用(Consumer<Long>)
声明了其后 Lambda 的类型。a.a(new Consumer<Long> {...})
,这就更直接了,直接从Consumer<Long>
创建一个匿名类。(注:函数体前应该加()
。)Lambda 可以说是对单方法接口匿名实现的一个简化语法。观察下面这段代码: