首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >意料之外的Java函数接口转换

意料之外的Java函数接口转换
EN

Stack Overflow用户
提问于 2018-12-27 12:00:49
回答 4查看 861关注 0票数 11

我有下面的代码,它使用java函数接口进行编译,但不清楚为什么要编译:

代码语言:javascript
复制
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有一个方法(很明显),它接收两个params
  • doUpdateForEach的第二个参数是方法引用(DatabaseOperator::updateInfo)。
  • DatabaseOperator::updateInfo方法接收单个参数

这是如何编译的?如何将DatabaseOperator::updateInfo方法引用转换为功能接口?我漏掉了什么明显的东西吗?还是功能接口的某个角落?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-12-27 12:16:26

如何将DatabaseOperator::updateInfo方法引用转换为功能接口?

方法引用的有效lambda表示是:

代码语言:javascript
复制
updateManager.doUpdateForEach(it, (databaseOperator, r) -> databaseOperator.updateInfo(r));

它是匿名类的进一步表示:

代码语言:javascript
复制
new FunctionalStuff<MyRecord>() {
    @Override
    public void execute(DatabaseOperator databaseOperator, MyRecord r) throws Exception {
        databaseOperator.updateInfo(r);
    }
});
票数 7
EN

Stack Overflow用户

发布于 2018-12-27 12:22:02

首先,FunctionalStuff<T>的定义如下:

代码语言:javascript
复制
@FunctionalInterface
interface FunctionalStuff<T> {
    void execute(final DatabaseOperator database, final T iterator) throws Exception;
}

方法引用DatabaseOperator::updateInfo被转换为类似于此的FunctionalStuff<MyRecord>实例(我保留了实际类型以进行分类,但可以省略它们):

代码语言:javascript
复制
FunctionalStuff<MyRecord> func = (DatabaseOperator database, MyRecord r) -> database.updateInfo(r);

或者如果您想将它用作匿名类:

代码语言:javascript
复制
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),其中ab是用于更好地描述此示例的任意名称。方法引用将调用方法a.compareToIgnoreCase(b)

票数 2
EN

Stack Overflow用户

发布于 2018-12-27 12:29:40

有4种不同类型的方法引用,您正在使用特定类型对象的实例方法引用

现在乍一看,它类似于static method reference,即Class::staticType,但它有以下区别:

代码语言:javascript
复制
- 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中的另外两种方法引用类型。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53944736

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档