Java 能把代码块当参数传递到其他方法并执行吗?

2020-04-27 20:34:48 +08:00
 atfeel
public void Main(){

    //在这里定义代码块,并传入 Test 方法里
    Test(
        delegate(){
            //代码逻辑
        }
    );
}    
    
public void  Test(dele a)
{
    invoke(a);////在这里执行传入的代码块
}

这种写法类似 C#到委托,java 里能做到吗?

8294 次点击
所在节点    Android
38 条回复
yikuo
2020-04-27 20:37:50 +08:00
可以传递一个 Runnable 对象
xizismile
2020-04-27 20:45:16 +08:00
方式 1:用对象来包装逻辑传递给其它方法
方式 2:用 java8 提供的函数式接口来实现
xiangyuecn
2020-04-27 20:48:04 +08:00
delegate ? C#打死也不用这么难懂的玩意(主要是这个单词手写敲不出来),还不如定义一个 interface 来的统一实在。。。实际上还是 Action 、Func 随便定义随便用,随便当参数,虽然本质上还是 delegate

java:interface,统一实在,没参数的用 Runnable 省去了一个 interface 定义
KentY
2020-04-27 20:59:30 +08:00
java 的源代码需要编译才能在 jvm 里执行. 所以你不能传递一个动态的 string, 然后希望 java 执行它.
java 可以动态读取源代码文件并编译成 class, 比如通过 JavaCompiler 编译, 然后再通过 reflection 执行编译好的 class 里的 method.但是我猜这不是你需要的.
如果我没理解错的话, 你大概需要一个类似 callback 的东西, 如果 java 版本是 8+, 它提供了一些现成的接口, 也可以就定义一个 classFooCallback {delegate(){...}}, 然后传递 FooCallback fooCallback instead of "dele a" . 当执行的时候, fooCallback.delegate()就可以了.
按一般来说, 你的 delegate method 需要参数, 否则意义不大.
chihiro2014
2020-04-27 21:00:39 +08:00
可以传逻辑,例如使用 Function
xgfan
2020-04-27 21:02:00 +08:00
这不就是传个函数进去吗……
atfeel
2020-04-27 21:11:59 +08:00
@xiangyuecn interface 不灵活,还要定义,麻烦啊
MineDog
2020-04-27 21:15:28 +08:00
lambda 表达式啊,前提是要函数式接口
luckyrayyy
2020-04-27 21:15:42 +08:00
完全,可能你得自己做一些工作。你可以动态生成一个 class 然后执行,直接执行代码块的话就不太确定行不行了。
xiangyuecn
2020-04-27 21:23:59 +08:00
@atfeel #7 不会,无参的直接用系统的 Runnable 不用定义。有参的自己写个,大不了参数全为 Object😂

interface Func<T>{
void fn(T...args); //Type safety: Potential heap pollution via varargs parameter args😂 这坨带码只是意思意思
}

.
.
.
先定义几个全局通用的。要什么参数的、返回值的类里面直接嵌套定义,哪里要就定义到哪里
ipwx
2020-04-27 21:39:26 +08:00
Java 8 不是有语法糖么,配合 interface 可以 f(x -> x + 1) 之类的
ipwx
2020-04-27 21:39:53 +08:00
不过我记得 java 8 lambda 最大的问题不是有没有语法糖,而是 exception 检查那套。。。
atfeel
2020-04-27 21:43:16 +08:00
@xiangyuecn 你的方法看起来不错,能随便写个模型我看看吗,分水岭难于逾越
谢谢
Febers
2020-04-27 21:46:31 +08:00
遇到过同样的需求,在没有改写成 Kotlin 之前,使用的是 Runnable 然后手动调 run ;改写成 Kotlin 之后看起来还挺酷的:
//定义
var action: ()->Unit = { }
//赋值
action = {
//some code
}
//调用
action.invoke() //action()
xiangyuecn
2020-04-27 21:56:19 +08:00
#13 没格式,自己格式化一下再看

static class aaa{
static void exec(Func<Integer, Boolean, String> func1, Runnable action1, Action<String,Object,Integer> action2) {
String val=func1.call(123, true);
action1.run();
action2.call(val, new java.util.Date(), 456);
}
interface Action<T1,T2,T3>{
void call(T1 a1,T2 a2,T3 a3);
}
interface Func<T1, T2, ReturnType>{
ReturnType call(T1 a1,T2 a2);
}
static public void test() {
exec(new Func<Integer, Boolean, String>(){
@Override public String call(Integer a1, Boolean a2) {
return a1+" "+a2;
}
},new Runnable() {
@Override public void run() {
System.out.println("Runnable");
}
},new Action<String, Object, Integer>() {
@Override public void call(String a1, Object a2, Integer a3) {
System.out.println(a1+" "+a2+" "+a3);
}
});
}
}


liyanggyang
2020-04-28 09:41:19 +08:00
Consumer<T>:消费型接口(有钱咱就花)
接收一个数据,并且处理这个数据,处理完成之后,
不需要返回任何数据,直接输出
con.accept();

Supplier<T>:供给型接口(后勤)
提供需要用到的数据
sup.get();

Function<T, R>:函数型接口(乾坤大挪移)
接收 T 类型转换为 R 类型
fun.apply();

Predicate<T>:断言型接口(包公断案)
判断对与错,把控 if 关卡
lff0305
2020-04-28 10:04:17 +08:00
Java 有很多 Runtime Compiler, 比如 logback 在用的 Janino, 等等
以前实现类似的功能用的是 JDK8 里带的 js 引擎, js 当字符串传过去 eval 就 OK
Jrue0011
2020-04-28 10:19:16 +08:00
JDK8 以后 java.util.function 下的接口基本能满足大部分日常需求了
atfeel
2020-04-28 10:28:24 +08:00
@Febers 我没用 Kotlin,还是 java
atfeel
2020-04-28 10:30:09 +08:00
@xiangyuecn 感谢

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/666727

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX