我有下面的代码,它使用java函数接口进行编译,但不清楚为什么要编译:
public class App {
public static void main(String[] args) throws Exception {
final RecordIterator it = new RecordIterator<MyRecord>();
final UpdateManager updateManager = new UpdateManager();
updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);
}
}
class UpdateManager {
public void doUpdateForEach(final RecordIterator recordIterator,
final FunctionalStuff<MyRecord> updateAction) throws Exception {
updateAction.execute(new DatabaseOperator(), new MyRecord());
}
}
class RecordIterator<E> {
}
@FunctionalInterface
interface FunctionalStuff<T> {
void execute(final DatabaseOperator database, final T iterator) throws Exception;
}
class DatabaseOperator {
public void updateInfo(final MyRecord r) {
}
}
class MyRecord {
}因此,我的困惑是在main方法中:
updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);UpdateManager#doUpdateForEach方法需要一个RecordIterator (确定,有道理)和一个FunctionalStuffFunctionalStuff有一个方法(很明显),它接收两个paramsdoUpdateForEach的第二个参数是方法引用(DatabaseOperator::updateInfo)。DatabaseOperator::updateInfo方法接收单个参数这是如何编译的?如何将DatabaseOperator::updateInfo方法引用转换为功能接口?我漏掉了什么明显的东西吗?还是功能接口的某个角落?
发布于 2018-12-27 12:16:26
如何将
DatabaseOperator::updateInfo方法引用转换为功能接口?
方法引用的有效lambda表示是:
updateManager.doUpdateForEach(it, (databaseOperator, r) -> databaseOperator.updateInfo(r));它是匿名类的进一步表示:
new FunctionalStuff<MyRecord>() {
@Override
public void execute(DatabaseOperator databaseOperator, MyRecord r) throws Exception {
databaseOperator.updateInfo(r);
}
});发布于 2018-12-27 12:22:02
首先,FunctionalStuff<T>的定义如下:
@FunctionalInterface
interface FunctionalStuff<T> {
void execute(final DatabaseOperator database, final T iterator) throws Exception;
}方法引用DatabaseOperator::updateInfo被转换为类似于此的FunctionalStuff<MyRecord>实例(我保留了实际类型以进行分类,但可以省略它们):
FunctionalStuff<MyRecord> func = (DatabaseOperator database, MyRecord r) -> database.updateInfo(r);或者如果您想将它用作匿名类:
FunctionalStuff<MyRecord> func = new FunctionalStuff<MyRecord>() {
void execute(final DatabaseOperator database, final MyRecord r) {
database.updateInfo(r);
}
}请参见教程中的以下示例:
对特定类型的任意对象的实例方法的引用 以下是对特定类型的任意对象的实例方法的引用的示例: String[] stringArray ={ "Barbara“、"James”、"Mary“、"John”、"Patricia“、"Robert”、"Michael“、"Linda”};Arrays.sort(stringArray,String:compareToIgnoreCase); 方法引用
String::compareToIgnoreCase的等效lambda表达式将具有形式参数列表(String a, String b),其中a和b是用于更好地描述此示例的任意名称。方法引用将调用方法a.compareToIgnoreCase(b)。
发布于 2018-12-27 12:29:40
有4种不同类型的方法引用,您正在使用特定类型对象的实例方法引用
现在乍一看,它类似于static method reference,即Class::staticType,但它有以下区别:
- the method should be present in the class same as type of first argument in functional interface
- The method used should have one less argument as opposed to number of arguments in the method declared in functional interface as the **this** reference is taken as first argument.因此,在您的示例中,方法DatabaseOperator#updateInfo存在于DatabaseOperator类中,它与函数接口中execute方法的第一个参数的类型DatabaseOperator相同,并且在将this引用作为第一个参数时,该方法中的参数数减少了一个。
如果您将DatabaseOperator#updateInfo更改为使用两个参数,那么编译器将显示一个错误,即Cannot make a static reference to the non-static method updateInfo from the type DatabaseOperator。因此,您可以创建方法,作为引用,静态的,或者必须使用new DatabaseOperator()#updateInfo,这是java中的另外两种方法引用类型。
https://stackoverflow.com/questions/53944736
复制相似问题