Java 在lamdas中工作的方法引用分配

Java 在lamdas中工作的方法引用分配,java,java-8,Java,Java 8,嗨,问题很简单 String::startWith和>::startWith之间的区别是什么?String::startWith将startWith()方法应用于lambda的第一个参数。 ::startWith将startWith()方法应用于“文本,或以更广泛的方式应用于未声明为lambda参数的变量。 更详尽地说,这两种提供方法参考的方法是不可替代的。 假设您希望对公共布尔startsWith(字符串前缀)方法使用方法引用。我将其指定为方法重载。 使用lambda参数的方法引用设计用于Bi

嗨,问题很简单


String::startWith
>::startWith
之间的区别是什么?

String::startWith
startWith()
方法应用于lambda的第一个参数。

::startWith
startWith()
方法应用于
文本,或以更广泛的方式应用于未声明为lambda参数的变量。

更详尽地说,这两种提供方法参考的方法是不可替代的。

假设您希望对
公共布尔startsWith(字符串前缀)
方法使用方法引用。
我将其指定为方法重载。

使用lambda参数的方法引用设计用于
BiPredicate
功能接口,而使用lambda参数中未声明的变量的方法引用设计用于
谓词
功能接口

  • 将变量作为方法引用的目标传递的方式:

    字符串myVariable;
    myVariable::startWith

已提供应用方法引用的字符串。此处:
myVariable

因此,只需在lambda中传递前缀参数。
所以
谓词
适合

  • 使用lambda参数的第一个参数作为方法引用的目标的方法:

    String::startsWith

不提供应用方法引用的字符串
因此,应该调用方法的字符串和前缀参数都需要在lambda中传递。
因此,
BiPredicate
适合。

下面是一个示例代码来说明:

public static void main(String[] args) {

    // using method reference with lambda parameter
    myMethodWithBiPredicate((s, prefix) -> s.startsWith(prefix), "mystring", "my");
    myMethodWithBiPredicate(String::startsWith, "mystring", "my");

    // using method reference with variable not in lambda parameter
    String stringNotInLambdaParams = "stringNotInParam";
    Predicate<String> functionPredicate = stringNotInLambdaParams::startsWith;

    System.out.print("myMethodWithBiPredicate with string "
            + "(included in the method reference)=" 
            + stringNotInLambdaParams 
            + " and prefix= string | Result = ");

    myMethodWithPredicate(functionPredicate, "string");

}

public static void myMethodWithBiPredicate(BiPredicate<String, String> function,
         String string,
         String prefix) {

    System.out.println("myMethodWithBiPredicate with string=" 
            + string + " and prefix= " + prefix 
            + " | Result = " + function.test(string, prefix));
}

public static void myMethodWithPredicate(Predicate<String> function, String prefix) {
    System.out.println(function.test(prefix));
}
publicstaticvoidmain(字符串[]args){
//使用带有lambda参数的方法引用
MyMethodWithBipCredite((s,前缀)->s.startsWith(前缀),“mystring”,“my”);
MyMethodWithBipCredite(字符串::startsWith,“mystring”,“my”);
//使用不在lambda参数中的变量的方法引用
字符串stringnotinlambdarams=“stringNotInParam”;
谓词函数Predicate=stringNotInLambdaParams::StartWith;
System.out.print(“myMethodWithBiPredicate with string”
+“(包括在方法参考中)=”
+StringNotInlambdarams
+“and prefix=string | Result=”);
myMethodWithPredicate(函数谓词,“字符串”);
}
公共静态无效myMethodWithBiPredicate(BiPredicate函数,
字符串字符串,
字符串前缀){
System.out.println(“myMethodWithBiPredicate with string=”
+字符串+”和前缀=“+前缀”
+“| Result=“+function.test(字符串,前缀));
}
公共静态void myMethodWithPredicate(谓词函数,字符串前缀){
System.out.println(function.test(前缀));
}
产生此输出的:

myMethodWithBiPredicate,字符串=mystring,前缀=my | Result =正确

myMethodWithBiPredicate,字符串=mystring,前缀=my | Result =正确

myMethodWithPredicate带字符串(包含在方法中 参考)=stringNotInParam,前缀=字符串|结果=真


我刚刚在你最近的一篇评论中回答了这个问题,你在上一个问题中也提出了同样的问题。我找到了我的答案,请看我的回答。对于设计师来说,使用这种语法是多么令人困惑。不管怎样,谢谢你的解释。@Aluan Haddad:我看不出有什么令人困惑的地方<代码>对象::方法将调用
对象
上的
方法
Class::method
没有对象,因此,如果
method
不是
static
,则目标对象将成为第一个函数参数。换句话说,
String::startsWith
相当于
(a,b)->a.startsWith(b)
::startsWith
相当于
b->”。startsWith(b)
(这相当于
b->b.isEmpty()
)@Aluan Haddad:忘记
在其他语言中的含义:。在java中,访问一个成员,它总是在爪哇中通过<代码> .<代码>(DOT),而不管成员是否是代码> static < /代码>。在Java中使用
::
(双冒号)而不是点并不会改变解析方法的方式,相反,这意味着该方法不是直接调用的,而是绑定到将调用该方法的函数。@Aluan Haddad语法并不那么混乱,即使它可能令人不安,但用法确实不同。我添加了一个示例来说明这些方法是不可互换的。@davidxxx:但是您可以有一个
静态
方法和一个具有相同名称但不同签名的实例方法,其功能签名是相同的,从而使方法引用不明确,如中所示。