java - "V is not a functional interface"错误

标签 java elasticsearch java-8

我正在根据本教程编写一个 elasticsearch 插件: Creating an elasticsearch plugin, the basics

这里出现“V is not a functional interface”错误:

@Override
    public Map<String, AnalysisModule.AnalysisProvider<TokenFilterFactory>> getTokenFilters() {
        return Collections.singletonMap("jettro", MyTokenFilterFactory::new);
    }

MyTokenFilterFactory 的代码:

public class MyTokenFilterFactory extends AbstractTokenFilterFactory {

public MyTokenFilterFactory(IndexSettings indexSettings, String name, Settings settings) {
    super(indexSettings, name, settings);
}

@Override
public TokenStream create(TokenStream tokenStream) {
    return new TokenFilter(tokenStream);
}

最佳答案

AnalysisModule.AnalysisProvider的定义是

public interface AnalysisProvider<T> {
    T get(IndexSettings indexSettings, Environment environment,
          String name, Settings settings) throws IOException;
    // irrelevant default methods omitted
}

要通过方法引用将构造函数绑定(bind)到此接口(interface),它必须具有完全相同的签名,即您必须将声明更改为

public class MyTokenFilterFactory extends AbstractTokenFilterFactory {

    public MyTokenFilterFactory(IndexSettings indexSettings, Environment environment,
                                String name, Settings settings) {
        super(indexSettings, name, settings);
    }

    @Override
    public TokenStream create(TokenStream tokenStream) {
        return new TokenFilter(tokenStream);
    }
}

忽略那个额外的参数。如果不想让普通调用者提供不需要的参数,可以重载构造函数

public class MyTokenFilterFactory extends AbstractTokenFilterFactory {

    public MyTokenFilterFactory(IndexSettings indexSettings, Environment environment,
                                String name, Settings settings) {
        super(indexSettings, name, settings);
    }
    public MyTokenFilterFactory(IndexSettings indexSettings,
                                String name, Settings settings) {
        super(indexSettings, name, settings);
    }

    @Override
    public TokenStream create(TokenStream tokenStream) {
        return new TokenFilter(tokenStream);
    }
}

或者您只保留原始构造函数只声明所需的参数并将方法引用更改为 lambda 表达式:

public Map<String, AnalysisModule.AnalysisProvider<TokenFilterFactory>> getTokenFilters() {
    return Collections.singletonMap("jettro",
                                    (is, env, n, s) -> new MyTokenFilterFactory(is, n, s));
}

请注意,误导性编译器错误消息很可能是由于 singletonMap 调用的类型推断与方法引用之间的复杂交互造成的。如果您对 singletonMap 调用使用显式类型,即

public Map<String, AnalysisModule.AnalysisProvider<TokenFilterFactory>> getTokenFilters() {
    return Collections.
        <String, AnalysisModule.AnalysisProvider<TokenFilterFactory>>
        singletonMap("jettro", MyTokenFilterFactory::new);
}

您会立即收到有关构造函数签名不匹配的有意义的错误消息。作为一般经验法则,如果您在使用较新的 Java 语言结构时收到奇怪的错误消息,请尝试插入显式类型,直到您收到可以理解的错误消息为止。解决问题后,您可以再次删除当时不需要的显式类型。

关于java - "V is not a functional interface"错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46977311/

相关文章:

amazon-web-services - elasticsearch _reindex失败

elasticsearch - 如何在ubuntu中使用命令终端启动 Elasticsearch

elasticsearch - 如何防止 Elasticsearch 使用这么多内存?

java - 在 Nashorn 中使用 WebSocket

java - 用于转换 future 的流利语法

java - JFileChooser 即使在输入名称后也不保存文件

java - JPA 和 Lombok 在循环依赖中导致 StackOverflowError

java - 获取用户Android版本

java - 如何使用函数式接口(interface)组织 java 8 代码

java - 使用 REST API 实现属性/字段级安全