【问题标题】:Parametrise a Runnable object at runtime在运行时参数化一个 Runnable 对象
【发布时间】:2022-02-25 00:52:29
【问题描述】:

我有一个 Runnable 任务 (doSomething),我需要根据谁调用 run() 对其进行参数化。

    Class SomeClass {
    
        Public void foo(ScheduledExecutorService execService, ){
            ...
            Runnable doSomething = () -> {
                /*Code that I DON’T want to duplicate*/
                ...
                /* small piece of code that I need to parametrise */
            };
            ...
        
            // after someDelayInSeconds doSomething.run() will be called
            execService.schedule(doSomething, someDelayInSeconds, TimeUnit.SECONDS); 

            // this might or might not call doSomething.run()
            bar(doSomething); 
    
            ...
        
        }

        private void bar(Runnable doSomething){

           ...
           if(/* some conditions are met */)
              doSomething.run();
           ...
        }
    }

到目前为止,我唯一的选择是将匿名类转换为命名类并创建两个具有所需参数的对象。

会有更优雅的方式吗?

【问题讨论】:

  • 参数从何而来?
  • 参数将来自调用者,这些参数将表示调用 run() 的人员和原因。

标签: java lambda runnable functional-interface


【解决方案1】:

我建议您将doSomething 更改为接受您的参数的Consumer

public void foo(ScheduledExecutorService execService) {
    Consumer<YourParams> doSomething = (params) -> {
        /*Code that I DON’T want to duplicate*/
        /* small piece of code that I need to parametrise */
        // use params
    };

    // after someDelayInSeconds doSomething.run() will be called
    YourParams asyncParams = /* parameters for async execution */;
    execService.schedule(() -> doSomething.accept(asyncParams), someDelayInSeconds, TimeUnit.SECONDS);

    // this might or might not call doSomething.run()
    bar(doSomething);

}

private void bar(Consumer<YourParams> doSomething) {
    if (/* some conditions are met */) {doSomething.accept(otherParams);}
}

在计划执行中,您然后通过传递异步执行的默认参数将doSomething 转换为Runnable,而在bar() 中您直接传递您选择的替代参数。

【讨论】:

  • 这有帮助,谢谢!我最终使用了 BiConsumer,因为我有两个参数。在 N 个参数的情况下,@tavark 的答案给出了一个很好的提示。或者可以使用这样的东西:stackoverflow.com/a/19649473/2022175
  • 如果你有 N 个参数,你总是可以将它们包装在一个参数对象中,或者确实实现一个自定义功能接口。
【解决方案2】:

我不确定,如果这是您正在寻找的:

  // provide config 
  Map<String, String> config = new HashMap<>();
  config.put( "someKey", "someValue" );

  Consumer<Map<String, String>> consumer = cfg -> {
     Runnable doSth = () -> {
        if ( cfg.get( "someKey" ).equals( "someValue" ) ) {

        }
     };
     doSth.run();
  };

  // apply different configurations depending on your needs
  consumer.accept( config );

【讨论】:

  • 不确定。但是具有嵌套匿名 Runnable 的 Consumer 可能是一个很好的提示。我会考虑的。
  • 谢谢@Tavark。这实际上是一个很好的提示。
猜你喜欢
  • 2019-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-14
  • 2014-09-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多