有如下类:
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的简化版?怎么能证明呢?
- 还有其它写法?
有如下类:
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> {...});那么问题来了:
4 回答968 阅读
4 回答869 阅读
584 阅读
486 阅读
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 可以说是对单方法接口匿名实现的一个简化语法。观察下面这段代码: