我有这段代码
public <T> someMethod(Supplier<T> supplier) {
Objects.requireNonNull(supplier);
SupplierThrowsException<T, Throwable> supplierThrowsException = supplier::get;
return withThrowable(supplierThrowsException);
}
我这样称呼
obj.someMethod(() -> myMethod(message))
我100%确定myMethod()
返回的对象的类未实现Supplier接口。 get()
的实现在哪里。
我通过了Javadoc,但没有得到任何帮助。我想了解这里发生了什么。
答案 0 :(得分:3)
在此次通话中:
obj.someMethod(() -> myMethod(message))
您正在使用lambda表达式-Supplier
实现() -> myMethod(message)
接口。
就好像您创建了一个内部类,实现了Supplier
一样(我说“好像”,因为这不是幕后实际发生的事情。Here就是幕后发生的事情)。这个:
static class MyInnerClass implements Supplier<SomeClass> {
public SomeClass get() {
return myMethod(message);
}
}
然后将new MyInnerClass()
传递给someMethod
。
答案 1 :(得分:3)
我100%确定
myMethod()
返回的对象的类未实现Supplier
接口。
可以,但是表达式() -> myMethod(message)
可以。
请阅读15.27.4. Run-Time Evaluation of Lambda Expressions。
在运行时,只要正常完成会生成对对象的引用,对lambda表达式的评估就类似于对类实例创建表达式的评估。对lambda表达的评估与对lambda主体的执行不同。
分配和初始化具有以下属性的类的新实例,或者引用具有以下属性的类的现有实例。
lambda表达式的值是对具有以下属性的类实例的引用:
- 该类实现目标功能接口类型,如果目标类型是路口类型,则在路口中提及的所有其他接口类型。
简而言之,lambda表达式() -> myMethod(message)
将解析为Supplier
的实例。
get
()的实现在哪里?
您已在lambda主体中提供了它。
() -> myMethod(message)
(这是一个语句表达式,是构造lambda主体的较短形式)
() -> {
return myMethod();
}
(这是一个值兼容的块,是一个扩展的版本,可以在其中声明许多语句)
答案 2 :(得分:0)
我认为这份文件可能会阐明您的问题: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html#target-typing
为了确定lambda表达式的类型,Java编译器使用找到lambda表达式的上下文或情况的目标类型。因此,您只能在Java编译器可以确定目标类型的情况下使用lambda表达式:
变量声明
任务
返回声明
数组初始化器
方法或构造函数参数
Lambda表达主体
条件表达式,?:
广播表达式
答案 3 :(得分:0)
Supplier
是一个功能接口,包含以下单个抽象方法:
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
现在,您通过以下调用提供了definition
方法中的get
和instantiation
:
obj.someMethod(() -> myMethod(message))
以上行的翻译如下:
obj.someMethod(new Supplier() {
@Override
public T get()
{
return myMethod(message);
}
});