在Java中的运行时确定的实例上使用方法引用
我正在测试使用方法引用的规则,但我编写的代码无法编译。编译器一直告诉我不能从静态上下文引用非静态方法。然而,在Java文档中,它明确指出可以使用“:”to“引用特定类型的任意对象的实例方法”。有人能指出我的代码有什么问题吗?谢谢大家!在Java中的运行时确定的实例上使用方法引用,java,java-8,method-reference,Java,Java 8,Method Reference,我正在测试使用方法引用的规则,但我编写的代码无法编译。编译器一直告诉我不能从静态上下文引用非静态方法。然而,在Java文档中,它明确指出可以使用“:”to“引用特定类型的任意对象的实例方法”。有人能指出我的代码有什么问题吗?谢谢大家! package Test; import java.util.function.BiPredicate; class Evaluation { public boolean evaluate(int a, int b) { if (a-b
package Test;
import java.util.function.BiPredicate;
class Evaluation {
public boolean evaluate(int a, int b) {
if (a-b ==5){
return true ;
}
return false;
}
public void methodTest() {
BiPredicate<Integer, Integer> biPredicate = Evaluation::evaluate;
System.out.println(biPredicate.test(6,1));
}
}
封装测试;
导入java.util.function.BiPredicate;
课堂评价{
公共布尔求值(int a,int b){
如果(a-b==5){
返回true;
}
返回false;
}
公共无效方法测试(){
BiPredicate BiPredicate=评估::评估;
系统输出打印LN(双预测测试(6,1));
}
}
编辑:在阅读了答案之后,我想知道是否通过类名引用实例方法只在某些函数接口中有效,而在其他接口中无效?比如说,
BiPredicate <String, Integer> biPredicate = String::startsWith;
BiPredicate BiPredicate=String::startsWith;
不编译,而:
Predicate <String> predicate = String::isEmpty;
谓词=字符串::isEmpty;
编译。
如果是这种情况,是否有一个页面/教程/任何人可以向我介绍的内容,解释哪些功能接口兼容,哪些不兼容 如果您的方法是实例方法,则必须在某个实例上调用它,例如:
public void methodTest(){
BiPredicate<Integer, Integer> biPredicate = this::evaluate;
System.out.println(biPredicate.test(6,1));
}
public-void-methodTest(){
BiPredicate BiPredicate=this::evaluate;
系统输出打印LN(双预测测试(6,1));
}
由于您没有使用任何实例变量或方法,因此可以简单地将其设置为静态并保持不变。静态引用实例方法时,返回的函子将使用表示实例的附加参数
interface Func {
boolean evaluate(Evaluation instance, int a, int b);
}
...
Func biPredicate = Evaluation::evaluate;
System.out.println(biPredicate.evaluate(new Evaluation(), 6, 1));
但是在调用它时,需要传递求值
的实例
由于您的
evaluate
方法不使用任何实例字段,您不妨将其设置为静态
,这样您就不需要传递实例,只需像您尝试的那样使用BiPredicate
。我仍在尝试找出适用的规则,但如果您使用
BiPredicate<Integer, Integer> biPredicate = this::evaluate;
BiPredicate BiPredicate=this::evaluate;
我一直在费解,但尽可能接近我所能,因为Evaluation::evaluate
强制编译器创建一个类型为Evaluation
的任意对象,并且您从该类型的对象中调用它,规则是不同的。您需要从出现methodTest
方法的特定对象调用它
虽然我没有解释,但解决方案是使用this::evaluate
。它明确地将方法引用绑定到调用它的对象
旁注:从
布尔值
导出布尔值
时,不需要将布尔值作为条件求值。您可以返回a-b==5代码>我回答这个问题可能太迟了,但由于这个问题仍然没有答案,我想尝试一个答案
我认为OP试图实现的目标有一个缺陷
我理解OP试图理解,为什么这样的事情会起作用:
String str = "abc";
Predicate<String> methodRef = str::startsWith;
methodRef.test("s");
String str=“abc”;
谓词methodRef=str::startsWith;
方法参考试验(“s”);
然后呢,
Predicate <String> predicate = String::isEmpty
谓词=字符串::isEmpty
以类似的方式工作,为什么不呢
Predicate <String> predicate = String::startsWith;
谓词=字符串::startsWith;
采用字符串类名Compile的Compile
这仅仅是因为谓词基本上接受任何参数并返回布尔值。这不是解决此问题的正确设置
你可以试试
BiFunction<String, String, Boolean> methodRef2 = String::startsWith;
methodRef2.apply("sdsdfsd", "sdfsdf");
BiFunction methodRef2=String::startsWith;
方法参考2.应用(“SDFSD”、“sdfsdf”);
这是可行的,因为startswith需要一个源字符串,用于检查和返回值的字符串。在Java8中,基本上有4种方法可以调用方法引用
静态方法调用
实例方法调用
类方法调用
建设者
我在写同样的答案;)由于该方法不使用实例变量/方法,所以我认为您的答案是错误的,OP应该简单地将方法改为static
。或者,既然代码是在一个非静态方法中,为什么要创建一个新实例呢?使用this::evaluate
@Andreas再试一次,我在那里输入了一个错误。这对我来说很好:)@Andreas这是一个不同的解决方案,但我想解释为什么OP的版本不起作用,以及如何使它起作用。我的建议是将该方法设置为静态。@Andreas我的代码显示了静态引用实例方法的实际工作原理,这是一个冗长的过程,因为在java.util.function
中没有可以使用的标准接口。我打算发布这个。这表明您可以引用具有类名的实例方法,前提是您可以提供正确的函数接口。@Andreas:这个答案解决了OP的实际问题。newevaluation()
的参数只是一个例子,因为OP没有提供参数。但是您可以在每次调用时传递不同的实例…另请参见String::startsWith
将使用3个参数;1.要调用的字符串
实例,2。字符串
参数前缀
和3。int
参数toffset
。但是,Bipredicate
只能解释其中的两个String::isEmpty
,接受1个参数,即要调用的实例,因此谓词
将起作用。@jornverne您完全正确。然而,为什么谓词=String::isEmpty代码>工作?比如我为什么不需要传递一个新的String()
(如下所示)实例