Java 8 方法引用-使用使用者参数将函数传递给方法
我正在学习Java8中的方法引用,我很难理解为什么会这样做Java 8 方法引用-使用使用者参数将函数传递给方法,java-8,method-reference,functional-interface,Java 8,Method Reference,Functional Interface,我正在学习Java8中的方法引用,我很难理解为什么会这样做 class Holder { private String holded; public Holder(String holded) { this.holded = holded; } public String getHolded() { return holded; } } private void run() { Function<Hold
class Holder {
private String holded;
public Holder(String holded) {
this.holded = holded;
}
public String getHolded() {
return holded;
}
}
private void run() {
Function<Holder, String> getHolded = Holder::getHolded;
consume(Holder::getHolded); //This is correct...
consume(getHolded); //...but this is not
}
private void consume(Consumer<Holder> consumer) {
consumer.accept(null);
}
类持有者{
私有字符串保持不变;
公共持有人(字符串持有){
this.holded=holded;
}
公共字符串getHolded(){
持有回执;
}
}
私家车{
函数getHolded=Holder::getHolded;
消费(Holder::getHolded);//这是正确的。。。
消费(被抓住);/…但这不是
}
私有无效消费(消费者){
consumer.accept(null);
}
正如您在run
method-Holder::getHolded
中看到的,返回未绑定的方法引用,您可以通过将类型为Holder
的对象作为参数传递来调用该方法引用。像这样:getHolded.apply(holder)
但是,当它作为方法参数直接调用时,为什么它将这个未绑定的方法引用强制转换为
使用者
,而当我显式地传递函数
时它却不这样做呢?这里有两件事,lambda表达式是多表达式——它们是由编译器使用上下文(例如泛型)推断出来的
当您声明消费时(Holder::getHolded)代码>,编译器(根据所谓的特殊无效兼容性规则)将其推断为消费者
这看起来可能不明显,但想想一个简化的例子。一般来说,调用一个方法并放弃它的返回类型是很正常的,对吗?例如:
List<Integer> list = new ArrayList<>();
list.add(1);
因此,这些都是可能的和有效的声明:
Consumer<Holder> consumer = Holder::getHolded;
Function<Holder, String> function = Holder::getHolded;
Consumer=Holder::getHolded;
Function=Holder::getHolded;
但是在本例中,我们明确地告诉您什么类型是Holder::getHolded
,这不是编译器的推断,因此consume(getHolded)代码>失败,消费者
!=<代码>功能
毕竟 Java8在包Java.util.function
中引入了4个重要的“函数形状”
- 使用者->接受接受接受一个参数但不返回任何内容的方法引用(或lambda表达式)
- 供应商->接受不带参数并返回对象的方法引用(或lambda表达式)
- 函数->接受方法引用(或lambda表达式),该引用接受一个参数并返回一个对象
- 谓词->接受方法引用(或lambda表达式),该引用接受一个参数并返回布尔值
有关更多详细信息,请阅读
要回答为什么第一个有效,但第二个错误,请阅读以下内容:
第二句话
消费(getHolded)代码>
不起作用,因为参数getHolded
的类型是函数
,而consume
方法需要类型为Consumer
的参数。由于函数
和使用者
之间没有父子关系,因此需要显式强制转换,否则编译器将正确地出错
第一句话
消费(Holder::getHolded)代码>
之所以有效,是因为方法getHolded
被声明为公共字符串getHolded()
,这意味着它不接受任何参数并返回字符串。根据新规则,void类型被推断为包含引用方法的类。考虑下面的陈述:
Consumer=Holder::getHolded代码>
即使方法getHolded
不接受任何参数,这也是一条有效的语句。这有助于推断空洞类型。还有一个例子是你提到的:
函数getHolded=Holder::getHolded代码>
这也是一个有效的语句,您已经说过,函数对象getholder
是一个函数
,它返回String
,并接受类型Holder
,即使指定的方法引用不带任何参数 请注意,您还应该能够消费者(getHolded::apply)
。顺便说一下,“holded”应该是“hold”。@Holger:)您无处不在!我甚至没有注意到,很好consumer(getholder::apply)
将完全符合所提供的相同的无效兼容性规则consumer(Holder::getholder)
;)规则是由@Eugene belowThanks提到的!这真的帮助我理解了这里正在发生的一切。特别是特殊的空隙相容性rule@TomaszBielaszewski请注意,并非所有内容都符合该规则,如果我没有记错的话,只有4种类型,方法调用、构造函数调用、递增/递减,我忘记了最后一种:)如果需要,搜索JLS。。。
Consumer<Holder> consumer = Holder::getHolded;
Function<Holder, String> function = Holder::getHolded;