Java 可调用<;T>;可以传递参数的替换

Java 可调用<;T>;可以传递参数的替换,java,Java,我有很多代码,每个函数都以相同的方式开始和结束。所以我开始使用Callable来让它更清晰。但是我想做的是以某种方式将“check”对象发送到每个函数(foo/doo/roo),但是调用方法不允许发送参数。有更好的方法吗 public void foo(String something, Boolean flag, Object obj) { callSafe(something, flag, () => /*some code capturing obj*/); } publi

我有很多代码,每个函数都以相同的方式开始和结束。所以我开始使用Callable来让它更清晰。但是我想做的是以某种方式将“check”对象发送到每个函数(foo/doo/roo),但是调用方法不允许发送参数。有更好的方法吗

public void foo(String something, Boolean flag, Object obj) {
    callSafe(something, flag, () => /*some code capturing obj*/);
}

public void doo(String something, Boolean flag) {
    callSafe(something, flag, () => /*different code using check*/);
}

public void roo(String something, Boolean flag, Integer id) {
    callSafe(something, flag, () => /*some code using check*/);
}

private void callSafe(string something, Boolean flag, Callable<T> c) {
    try {
        Object check = someFunction(flag, something);
        if (check.IsTrue()) {
            c.call(); 
            //c.call(check); //What I want to do.
        }
    } catch(Exception e) {
        // handle exception
    }
}
public void foo(字符串、布尔标志、对象obj){
callSafe(something,flag,()=>/*一些代码捕获obj*/);
}
公共void doo(字符串、布尔标志){
callSafe(something,flag,()=>/*使用check*/)的不同代码;
}
公共void roo(字符串、布尔标志、整数id){
callSafe(something,flag,()=>/*一些代码使用check*/);
}
私有void callSafe(字符串、布尔标志、可调用c){
试一试{
对象检查=某个函数(标志,某物);
if(检查.IsTrue()){
c、 call();
//c、 打电话(检查);//我想做什么。
}
}捕获(例外e){
//处理异常
}
}
我想我可以只运行“someFunction”两次(一次在可调用函数中运行,一次在实际函数中运行),但函数很慢,我不想这样做

编辑:通过添加一个界面和使用@Eran建议的方法来修复它。界面:

@FunctionalInterface
public interface CheckedFunction<T, R> {
    R apply(T t) throws Exception;
}
@FunctionalInterface
public interface ThrowingCheckResultConsumer {
     void accept(CheckResult obj) throws MyException;
}
@functioninterface
公共接口检查功能{
R apply(T)抛出异常;
}

但我不确定这是否是一种好的做法。有什么想法吗?

首先,我不确定
可调用
是否合适,因为
调用
方法返回一个值,您可以忽略该值

您可以使用
消费者
,它有一个
接受(SomeClass t)
方法

private void callSafe(String something, Boolean flag, Consumer<SomeClass> c) {
    try {
        SomeClass check = someFunction(flag, something);
        if (check.IsTrue()) {
            c.accept (check);
        }
    } catch(Exception e) {
        // handle exception
    }
}

public void roo(String something, Boolean flag, Integer id) {
    callSafe(something, flag, (SomeClass check) -> /*some code using check*/);
}

是的,有更好的办法

您应该研究面向方面的编程。如果您使用的是Spring,那么为您的任务集成Spring的运行时代理应该相当轻松

您将需要创建包装函数的方面,创建标记函数的注释(必须是Spring组件,具有组件接口中的公共方法),配置方面

有关详细信息,请参阅


在Spring的运行时方面,这似乎是一个简单的示例驱动的介绍:。

表面上看,您想要一个
消费者:

。。。或者更一般地说:

@FunctionalInterface
public interface ThrowingConsumer<T,E extends Exception> {
     void accept(T obj) throws E;
}
或者在你的情况下:

callSafe(something, flag, cr -> doSomethingWith(cr));
。。。及

private void callSafe(String something, Boolean flag, ThrowingCheckResultConsumer consumer) {
    try {
        SomeClass check = someFunction(flag, something);
        if (check.IsTrue()) {
            consumer.accept(check);
        }
    } catch(MyException e) {
        // handle exception
    }
}
在你的问题中,你抓住了异常。我使用了
MyException
,因为广泛地捕捉
Exception
通常被认为是不好的风格。只有catch
RuntimeException
和您调用的代码声明的选中异常

但是,如果必须,您可以将此代码中的
MyException
替换为
Exception


有些库提供了
选中的*
功能接口。这是一个。Vavr的
CheckedConsumer.accept()
抛出
Throwable



尝试并找到一个不抛出已检查异常的消费者可能更容易。如果您控制异常,请考虑将它们扩展为<代码>运行时异常< /代码>。或者在您的消费者中捕获它们,然后用
运行时异常

重新包装,这对我来说不起作用。当我在两个地方都使用SomeClass时,出现了一个“不兼容类型”错误。@Wolfyaskingstuff您能举一个实际lambda表达式的例子吗?问题可能出在“/*some代码使用check*/”部分。lambda表达式返回一些值,我想这就是给我的答案problems@Wolfyaskingstuff因为在您的示例中,您没有使用您使用的原始
Callable
返回的值执行任何操作,所以我假设您不需要返回值。因此lambda不应该返回值。如果需要返回值,请使用
函数
界面,而不是
使用者
。该函数将无法处理异常。
    ThrowingCheckResultConsumer c = cr -> doSomethingWith(cr);
    c.accept("");
callSafe(something, flag, cr -> doSomethingWith(cr));
private void callSafe(String something, Boolean flag, ThrowingCheckResultConsumer consumer) {
    try {
        SomeClass check = someFunction(flag, something);
        if (check.IsTrue()) {
            consumer.accept(check);
        }
    } catch(MyException e) {
        // handle exception
    }
}