此问题与Issue in abstracting common code using function interface和Exception 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);
}
}
有什么方法可以通过功能界面做到这一点?
答案 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
版本。如果要明确,可以为方法指定不同的名称。