我有下面的代码,它们使用java Functional Interfaces进行编译,但是不清楚为什么编译:
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
(好的,很合理)和一个FunctionalStuff
FunctionalStuff
有一个方法(显然),可以接收2个参数doUpdateForEach
的第二个参数是方法引用(DatabaseOperator::updateInfo
)DatabaseOperator::updateInfo
方法只接收一个参数如何编译? DatabaseOperator::updateInfo
方法引用如何转换为功能接口?我是否缺少明显的东西?还是功能接口有些特殊情况?
答案 0 :(得分:7)
如何转换
dfc= df.groupby(['Identification_person']).Day.nunique().reset_index()
方法参考 进入功能界面?
方法引用的有效lambda表示形式是:
DatabaseOperator::updateInfo
这是匿名类的进一步表示:
updateManager.doUpdateForEach(it, (databaseOperator, r) -> databaseOperator.updateInfo(r));
答案 1 :(得分:2)
首先,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);
}
}
通过以下示例查看tutorial:
引用特定类型的任意对象的实例方法
以下是对一个实例方法的引用示例 特定类型的任意对象:
String[] stringArray = { "Barbara", "James", "Mary", "John", "Patricia", "Robert", "Michael", "Linda" }; Arrays.sort(stringArray, String::compareToIgnoreCase);
等效lambda表达式,供方法参考
String::compareToIgnoreCase
将具有正式的参数列表(String a, String b)
,其中a
和b
是用于 更好地描述这个例子。方法参考将调用 方法a.compareToIgnoreCase(b)
。
答案 2 :(得分:0)
有4种不同类型的方法引用,您正在使用Instance method reference of an object of a particular type
现在乍一看,它类似于static method reference
的{{1}},但有以下区别:
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
方法的第一个参数的类型DatabaseOperator
相同该方法中的参数个数要少一些,因为将execute
引用作为第一个参数。
如果将DatabaseOperator#updateInfo更改为采用两个参数,则编译器将显示错误this
。因此,您可以将要用作引用的方法设为静态,或者必须使用Cannot make a static reference to the non-static method updateInfo from the type DatabaseOperator
这是Java中另外两种方法引用。
答案 3 :(得分:-2)
这实际上不是lambda的工作方式,但实际上您可以看到
updateManager.doUpdateForEach(it, DatabaseOperator::updateInfo);
为
DatabaseOperator referencedMethodOwner = instanceGivenAsMethodExpression;
updateManager.doUpdateForEach(it,
new FunctionalStuff{
void execute(final T iterator) throws Exception{
referencedMethodOwner.updateInfo(iterator)
}
});