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 里能做到吗?

8605 次点击
所在节点    Android
38 条回复
atfeel
2020-04-28 10:33:25 +08:00
@Febers 你的这个方法就是我想要的了
atfeel
2020-04-28 10:34:45 +08:00
@Febers Runnable 的用法,能举个例子吗
gz233
2020-04-28 10:58:12 +08:00
@liyanggyang 正解
no1xsyzy
2020-04-28 11:19:12 +08:00
感觉没什么分水岭的,只要你不是动态逻辑(即执行的代码是编译时决定的),那就可以用对象实现闭包,甚至如果不需要闭包就传个匿名类就行。

至于需要动态逻辑、动态构造代码并执行的,那需要重新来套 lexer, syntaxer, interpreter/compiler 等,而且手动拼装语句容易错,如果是远程给代码直接调用,不如直接用个 JVM 内的解释器。
或者含泪实践格林斯潘第十定律。
Febers
2020-04-28 12:03:49 +08:00
@atfeel #22
Kotlin 代码的本质是,定义一个类型属于 () -> Unit 的变量,然后动态赋值,通过 invoke 方法执行,反编译 Kotlin 的字节码之后可以发现,其对应的 Java 类型是 Function0 接口,位于 kotlin.jvm.functions,仿照其写法

//使用了 @FunctionalInterface 以使用 Lambda
@FunctionalInterface
interface Action {
void invoke();
}

//定义与赋值
Action action;
action = () -> {
//some code 1
};
//非 Lambda 写法
action = new Action() {
@Override
public void invoke() {
//some code 2
}
};

//调用
action1.invoke();

使用 Runnable 的原因很简单,它是系统定义的一个 FunctionalInterface,而且很普通,调用 run 方法也跟多线程没有关系,把 Runnable 替换成上面的 Action,就可以少写一个接口
Febers
2020-04-28 12:14:40 +08:00
个人觉得 Kotlin 的很多东西很有趣,学习 Kotlin 反编译之后的 Java 代码,基本上就是用 Java 如何实现 Kotlin 特性的工业化答案。
这个问题很多同学都给了答案,重点在于:Java 是纯面向对象语言,一切方法参数都是对象(基本数据类型不谈),而匿名内部类的存在让我们可以使用 自定义方法的对象,虽然写法看起来比较啰嗦;引入 Lambda 之后的 Java 代码写起来更“函数式”了,但本质上还是使用对象的概念
Febers
2020-04-28 12:21:33 +08:00
如果要深究到语言特性的话,对于这样的需求,Java 字节码层面支持是 invokedynamic 指令的引入,语法层面的支持是 Lambda 的引入
no1xsyzy
2020-04-28 12:53:48 +08:00
@Febers #25 这个匿名子类的做法,swing 的样例代码里就有……
Febers
2020-04-28 12:59:45 +08:00
@no1xsyzy #28 😮可能因为写起来比较好理解?
zclHIT
2020-04-28 13:03:38 +08:00
functional interface
no1xsyzy
2020-04-28 13:11:47 +08:00
@Febers #29 Java 7 的时候 Callback 的写法只有这样吧…… 我 Java 用得不多,也是老早的事了,GUI 的 handler 就差不多只能这么玩,哪像 Qt 用槽。
sandrew1945
2020-04-28 13:21:37 +08:00
使用 Lambda,参考 vert.x
```
vertx.executeBlocking(this::blockingCode, this::resultHandler);

private void blockingCode(Promise<JsonObject> promise)
{
// do something
}

private void resultHandler(AsyncResult<JsonObject> ar)
{
// get result
}
```
其中 executeBlocking 是这样定义的
```
<T> void executeBlocking(Handler<Promise<T>> var1, Handler<AsyncResult<T>> var2);


public interface Handler<E> {
void handle(E var1);
}
```
aguesuka
2020-04-28 13:50:44 +08:00
effctive java 3rd 44 优先使用标准的函数式接口
CoderGeek
2020-04-28 14:45:43 +08:00
Functional
stevenkang
2020-04-28 14:48:12 +08:00
推荐文章 [Java8 新特性学习-函数式编程]( https://blog.csdn.net/icarusliu/article/details/79495534)
gmywq0392
2020-04-28 14:59:26 +08:00
exec
atfeel
2020-04-28 16:08:34 +08:00
@Febers 完美,可以了,可以了,可以结贴了,感谢,非常感谢!!
kingiis
2020-04-29 14:10:18 +08:00
你是想问 动态生成 java 代码 动态执行么
不如切到 js 动态 js 倒是很容易

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

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

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

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

© 2021 V2EX