在功能界面中包装输入时出现问题

时间:2018-07-04 10:56:42

标签: java java-8

此问题与Issue in abstracting common code using function interfaceException handling in Function interface有关。从我下面写的那些书中得到想法:

  public void act(Input1 input) throws NonRetriableException, InvalidInputException {

    Function<UpdateTaskInput, Boolean> func = item -> {
        try {
            activityManager.update(item);
            return true;
        } catch (InterruptedException | JSONException e) {

            throw new NonRetriableException(e);
        } catch (LockUnavailableException e) {

            throw new NonRetriableException(e);
        }
    };

    try {
        lockManager.executeWithLock(input.getTaskID(), input, func);
    } catch (LockUnavailableException e) {
        log.error("{}",e);
        throw new NonRetriableException(e);
    }
   }

和:

 public void perform()
    throws AutoAllocationException {

     Function<UpdateTaskInput, Boolean> func = item -> {
        try {
            activityManager.allocateTask(item);
            return true;
        } catch (AutoAllocationException ex) {
            log.error("{}",ex);
        }
        return false;
    };

    try {
        lockManager.executeWithLock(input.getTaskID(), input, func);
    } catch (LockUnavailableException e) {
        log.error("{}",e);
    }
  }
LockManager中的

executeWithLock()如下:

 @Override
 public <T,R> R executeWithLock(String lockName, T input, Function<T,R> func) throws LockUnavailableException {
    LockItem lockItem = acquireLock(lockName);
   try  {
      R output = func.apply(input);
      return output;
   } finally {
      releaseLock(lockItem);
   }
  }

现在executeWithLock()函数的问题是,它始终希望将输入作为参数,我无法为其他没有doStuff()输入的函数调用此函数。

但是我只想使用Function接口来实现它,例如以下代码(因此可以看到,T被省略了)。

    @Override
 public <R> R executeWithLock(String lockName, Function<R> func) throws LockUnavailableException {
    LockItem lockItem = acquireLock(lockName);
   try  {
      R output = func.apply(input);
      return output;
   } finally {
      releaseLock(lockItem);
   }
  }

有什么方法可以通过功能界面做到这一点?

2 个答案:

答案 0 :(得分:0)

您可以使用中间帮助程序方法,该方法接受Supplier<R>但不接受input。然后创建一个Function<?, R>并委托给另一个方法:

public <R> R executeWithLock(String lockName, Supplier<R> supplier) throws LockUnavailableException{
    return executeWithLock(
        lockName, 
        null,                     // input is ignored by our function
        ignored -> supplier.get() // this lambda will create Function<?, R> from the Supplier<R>
    );
}

然后可以这样使用:

executeWithLock("mylock", () -> "Some Value");

() -> "Some Value"Supplier<String>


如果您无法更改该代码,因此无法添加中间帮助程序方法。您可能只想将null作为参数传递,然后在lambda中将其忽略:

executeWithLock("myLock", null, ignored -> doStuff());

答案 1 :(得分:0)

您需要两种方法。第一个应该使用Supplier而不是Function和输入。优选使用Supplier,因为它使您可以灵活地使用零个或多个输入参数。使用Function意味着您被限制为一个。

您还需要第二种使用Runnable的方法,该方法支持零个或多个输入参数和无效的返回值:

public static <R> R executeWithLock(String lockName, Supplier<R> func) {
    Lock lockItem = acquireLock(lockName);
    try  {
        return func.get();
    } finally {
        releaseLock(lockItem);
    }
}

public static void executeWithLock(String lockName, Runnable func) {
    Lock lockItem = acquireLock(lockName);
    try  {
        func.run();
    } finally {
        releaseLock(lockItem);
    }
}

这些示例方法的示例用法:

private static String foo(String input) { return input; }
private static void bar(String input)   { }

看起来像:

String ret = executeWithLock("lockName", () -> foo("someInput"));
executeWithLock("lockName", () -> bar("someInput")); // void return

Java能够根据是否有返回类型来推断所需的executeWithLock版本。如果要明确,可以为方法指定不同的名称。