public void Main(){
//在这里定义代码块,并传入 Test 方法里
Test(
delegate(){
//代码逻辑
}
);
}
public void Test(dele a)
{
invoke(a);////在这里执行传入的代码块
}
这种写法类似 C#到委托,java 里能做到吗?
1
yikuo 315 天前 via Android ![]() 可以传递一个 Runnable 对象
|
2
xizismile 315 天前 via Android
方式 1:用对象来包装逻辑传递给其它方法
方式 2:用 java8 提供的函数式接口来实现 |
![]() |
3
xiangyuecn 315 天前
delegate ? C#打死也不用这么难懂的玩意(主要是这个单词手写敲不出来),还不如定义一个 interface 来的统一实在。。。实际上还是 Action 、Func 随便定义随便用,随便当参数,虽然本质上还是 delegate
java:interface,统一实在,没参数的用 Runnable 省去了一个 interface 定义 |
![]() |
4
KentY 315 天前
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 需要参数, 否则意义不大. |
5
chihiro2014 315 天前
可以传逻辑,例如使用 Function
|
![]() |
6
xgfan 315 天前
这不就是传个函数进去吗……
|
7
atfeel 315 天前
@xiangyuecn interface 不灵活,还要定义,麻烦啊
|
![]() |
8
MineDog 315 天前 via Android
lambda 表达式啊,前提是要函数式接口
|
![]() |
9
luckyrayyy 315 天前
完全,可能你得自己做一些工作。你可以动态生成一个 class 然后执行,直接执行代码块的话就不太确定行不行了。
|
![]() |
10
xiangyuecn 315 天前
@atfeel #7 不会,无参的直接用系统的 Runnable 不用定义。有参的自己写个,大不了参数全为 Object😂
interface Func<T>{ void fn(T...args); //Type safety: Potential heap pollution via varargs parameter args😂 这坨带码只是意思意思 } . . . 先定义几个全局通用的。要什么参数的、返回值的类里面直接嵌套定义,哪里要就定义到哪里 |
![]() |
11
ipwx 315 天前
Java 8 不是有语法糖么,配合 interface 可以 f(x -> x + 1) 之类的
|
![]() |
12
ipwx 315 天前 ![]() 不过我记得 java 8 lambda 最大的问题不是有没有语法糖,而是 exception 检查那套。。。
|
13
atfeel 315 天前
@xiangyuecn 你的方法看起来不错,能随便写个模型我看看吗,分水岭难于逾越
谢谢 |
![]() |
14
Febers 315 天前
遇到过同样的需求,在没有改写成 Kotlin 之前,使用的是 Runnable 然后手动调 run ;改写成 Kotlin 之后看起来还挺酷的:
//定义 var action: ()->Unit = { } //赋值 action = { //some code } //调用 action.invoke() //action() |
![]() |
15
xiangyuecn 315 天前
#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); } }); } } ![]() |
![]() |
16
liyanggyang 314 天前 ![]() Consumer<T>:消费型接口(有钱咱就花)
接收一个数据,并且处理这个数据,处理完成之后, 不需要返回任何数据,直接输出 con.accept(); Supplier<T>:供给型接口(后勤) 提供需要用到的数据 sup.get(); Function<T, R>:函数型接口(乾坤大挪移) 接收 T 类型转换为 R 类型 fun.apply(); Predicate<T>:断言型接口(包公断案) 判断对与错,把控 if 关卡 |
17
lff0305 314 天前
Java 有很多 Runtime Compiler, 比如 logback 在用的 Janino, 等等
以前实现类似的功能用的是 JDK8 里带的 js 引擎, js 当字符串传过去 eval 就 OK |
![]() |
18
Jrue0011 314 天前
JDK8 以后 java.util.function 下的接口基本能满足大部分日常需求了
|
20
atfeel 314 天前
@xiangyuecn 感谢
|
![]() |
23
gz233 314 天前
@liyanggyang 正解
|
![]() |
24
no1xsyzy 314 天前
感觉没什么分水岭的,只要你不是动态逻辑(即执行的代码是编译时决定的),那就可以用对象实现闭包,甚至如果不需要闭包就传个匿名类就行。
至于需要动态逻辑、动态构造代码并执行的,那需要重新来套 lexer, syntaxer, interpreter/compiler 等,而且手动拼装语句容易错,如果是远程给代码直接调用,不如直接用个 JVM 内的解释器。 或者含泪实践格林斯潘第十定律。 |
![]() |
25
Febers 314 天前
@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,就可以少写一个接口 |
![]() |
26
Febers 314 天前 ![]() 个人觉得 Kotlin 的很多东西很有趣,学习 Kotlin 反编译之后的 Java 代码,基本上就是用 Java 如何实现 Kotlin 特性的工业化答案。
这个问题很多同学都给了答案,重点在于:Java 是纯面向对象语言,一切方法参数都是对象(基本数据类型不谈),而匿名内部类的存在让我们可以使用 自定义方法的对象,虽然写法看起来比较啰嗦;引入 Lambda 之后的 Java 代码写起来更“函数式”了,但本质上还是使用对象的概念 |
![]() |
27
Febers 314 天前
如果要深究到语言特性的话,对于这样的需求,Java 字节码层面支持是 invokedynamic 指令的引入,语法层面的支持是 Lambda 的引入
|
![]() |
30
zclHIT 314 天前
functional interface
|
![]() |
31
no1xsyzy 314 天前
@Febers #29 Java 7 的时候 Callback 的写法只有这样吧…… 我 Java 用得不多,也是老早的事了,GUI 的 handler 就差不多只能这么玩,哪像 Qt 用槽。
|
32
sandrew1945 314 天前
使用 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); } ``` |
33
aguesuka 314 天前 via Android
effctive java 3rd 44 优先使用标准的函数式接口
|
![]() |
34
CoderGeek 314 天前
Functional
|
![]() |
35
stevenkang 314 天前
推荐文章 [Java8 新特性学习-函数式编程]( https://blog.csdn.net/icarusliu/article/details/79495534)
|
36
gmywq0392 314 天前
exec
|
![]() |
38
kingiis 313 天前
你是想问 动态生成 java 代码 动态执行么
不如切到 js 动态 js 倒是很容易 |