将方法引用分配给功能接口

问题描述 投票:0回答:2

Java 8+ 允许将方法引用分配给函数式接口。

那么下面的代码有什么问题(jdoodle 链接)-

public void newMethod(){
    
    Predicate p = String::isBlank;
    
}

不同于 jdoodle 编译中的错误,在我的本地(gist 链接)我得到错误:

不能从静态上下文中引用非静态方法

但是-下面的东西起作用了

 Predicate<String> pp = String::isBlank; //this thing works
lambda java-8 method-reference functional-interface
2个回答
1
投票

这是因为您使用的是原始类型 -

Predicate
。原始功能接口的功能类型是:

泛型函数接口原始类型的函数类型

I<...>
是泛型函数接口函数类型的擦除
I<...>
.

泛型

Predicate<T>
的函数类型是
(T) -> boolean
(请原谅我自己的原始语法),一个接受
T
并返回
boolean
的函数。因此,原始
Predicate
的函数类型是
(Object) -> boolean
(T) -> boolean
的擦除。

这意味着可以将

Objects::isNull
分配给这样一个原始功能接口(但你不应该首先使用原始类型):

// Objects::isNull takes an Object and returns a boolean, so this compiles
Predicate x = Objects::isNull;

方法参考

String::blank
只需要一个
String
,而不是任何一种
Object
。因此它与函数类型(Object) -> boolean
一致
因此不能分配给
Predicate
类型的变量。

如果

Predicate p = String::isBlank;
有效,那么你就可以做像
p.test(1)
这样的事情。并且
String::isBlank
必须神奇地确定
1
是否“是空白”。

这里的错误信息确实有点令人困惑。

对于

Predicate<String>
,其函数类型的定义不同,它具有函数类型
(String) -> boolean
,方法引用
String::isBlank
是全等的。

参数化函数接口类型

I<A1...An>
的函数类型,其中A1...An是类型,I的相应类型参数是P1...Pn,通过应用替换[P1:=A1, .. ., Pn:=An]到泛型函数式接口的函数类型
I<P1...Pn>
.


1
投票

Predicate p
并不意味着“推断类型参数”。这意味着您已经声明了一个原始的
Predicate
,它在
Object
上运行。

String::isBlank
String
上运行。它可以用于
Predicate<String>
,但不能用于原始的
Predicate

© www.soinside.com 2019 - 2024. All rights reserved.