参数不匹配; lambda 表达式的无效函数描述符

Posted

技术标签:

【中文标题】参数不匹配; lambda 表达式的无效函数描述符【英文标题】:argument mismatch; invalid functional descriptor for lambda expression 【发布时间】:2021-11-12 12:59:51 【问题描述】:

我正在使用jdbi 库,如下所示:

try 
    return jdbi.withHandle(handle -> handle
        .createQuery("...")
        .mapTo(String.class)
        .one());
 catch (final JdbiException e) 
    if (DatabaseExceptionChecker.isTransientException(e)) 
        throw new MyCustomException("Transient database exception", e);
     else 
        throw e;
    

这种 try catch 模式会重复几次,将各种不同的查询传递给 jdbi.withHandle 方法。另一个例子:

try 
    return jdbi.withHandle(handle -> handle
        .createUpdate("...")
        .execute());
 catch (final JdbiException e) 
    if (DatabaseExceptionChecker.isTransientException(e)) 
        throw new MyCustomException("Transient database exception", e);
     else 
        throw e;
    

jdbi.withHandle 方法有这个签名:

public <R, X extends Exception> R withHandle(HandleCallback<R, X> callback) throws X 

我正在尝试找到一种方法来减少 try-catch 周围的重复,以便我可以使用类似的东西:

handleTransientExceptions(() -> jdbi.withHandle(handle -> handle
        .createQuery("...")
        .mapTo(String.class)
        .one())

handleTransientExceptions 函数将包含 try-catch 样板。

我从以下开始:

@FunctionalInterface
private interface JdbiCall

    public <R, X extends Exception> R call() throws X;


public <R, X extends Exception> R handleTransientExceptions(final JdbiCall jdbiCall) throws MyCustomException

    try 
        return jdbiCall.call();
     catch (final JdbiException e) 
        if (DatabaseExceptionChecker.isTransientException(e)) 
            throw new MyCustomException("Transient database exception", e);
         else 
            throw e;
        
    

但是,当我尝试这样称呼它时:

return handleTransientExceptions(() -> jdbi.withHandle(handle -> handle
        .createQuery("...")
        .mapTo(String.class)
        .one())

我得到错误:

  reason: cannot infer type-variable(s) R,X
    (argument mismatch; invalid functional descriptor for lambda expression
      method <R,X>()R in interface com.acmecorp.MyService.JdbiCall is generic)

【问题讨论】:

【参考方案1】:

无法推断类型,因为您的函数式接口 JdbiCall 既没有类声明级别的泛型,也没有用于推断这些类型的 call 方法的参数。因此,您的 FI 可能如下所示:

@FunctionalInterface
interface JdbiCall<R, X extends Exception> 
    R call() throws X;
 

handleTransientExceptions 方法:

public <R, X extends Exception> R handleTransientExceptions(final JdbiCall<R, X> jdbiCall) throws Exception 
    try 
        return jdbiCall.call();
     catch (final JdbiException e) 
        if (DatabaseExceptionChecker.isTransientException(e)) 
            throw new MyCustomException("Transient database exception", e);
         else 
            throw e;
        
    

也可以简化为:

@FunctionalInterface
interface JdbiCall<R> 
    R call() throws Exception;
 

handleTransientExceptions方法:

public <R> R handleTransientExceptions(final JdbiCall<R> jdbiCall) throws Exception 
    try 
        return jdbiCall.call();
     catch (final JdbiException e) 
        if (DatabaseExceptionChecker.isTransientException(e)) 
            throw new MyCustomException("Transient database exception", e);
         else 
            throw e;
        
    

【讨论】:

以上是关于参数不匹配; lambda 表达式的无效函数描述符的主要内容,如果未能解决你的问题,请参考以下文章

Java Lambda 表达式介绍

Lambda 无效语法

函数进阶4

lambda表达式

理解 Java 方法引用(方法引用符:“双冒号 :: ”)

java8