Ruby块很方便用于将一些代码包装在调用方定义的某些块周围。
如何用Java做到这一点?
def myf(i)
puts "start"
yield i
puts "end"
end
myf(3){ |i| puts i * 10 }
myf(4){ |i| puts i - 10 }
# outputs:
# start
# 30
# end
# start
# -6
# end
答案 0 :(得分:4)
如何用Java做到这一点?
在Java中没有等效于Ruby块。 Ruby块在语法上是轻量级的,在语义上是轻量级的,它们不是对象。它们主要是语法结构,后面带有一些轻量级语义。在这种情况下,它们更像Java中增强的for
循环。
您在Java中最接近的等效项是将functional interface与lambda expression组合在一起。使用java.util.function
包中的预定义功能接口之一,即接口java.util.function.Consumer<T>
,就是这样:
void myf(int i, java.util.function.Consumer<Integer> proc) {
System.out.println("start");
proc.accept(i);
System.out.println("end");
}
您可以这样使用它:
myf(3, i -> System.out.println(i * 10));
myf(4, i -> System.out.println(i - 10));
// start
// 30
// end
// start
// -6
// end
但是,这不等效于Ruby的块。这等效于Ruby的Proc
和lambda literals,换句话说,它等效于此:
def myf(i, proc)
puts "start"
proc.(i)
puts "end"
end
myf(3, -> i { puts i * 10 })
myf(4, -> i { puts i - 10 })
# start
# 30
# end
# start
# -6
# end
请注意,示例中的myf
不使用块的结果,因此使用java.util.function.Function<T, R>
对其进行建模将是不正确的。 Consumer<T>
是用于“消耗”其参数但不返回任何内容的“函数”(实际上是一个过程)的正确接口,而Function<T, R>
是用于“函数”的正确接口。需要一个参数并返回结果的函数。
答案 1 :(得分:3)
您的own answer是正确的,lambdas(与功能接口结合)使Java成为可能,但是它比使用java.util.function
中的类型要简单得多。这是使用Function<T,R>
的代码:
myf
:
public static int myf(int i, Function<Integer,Integer> fn) {
System.out.println("start");
int retval = fn.apply(i);
System.out.println(retval);
System.out.println("end");
return retval;
}
使用它:
public static void main(String[] args) {
myf(3, i -> i * 10);
// ^^^^^^^^^^^−−−−−−−−−−−− lambda expression
myf(4, i -> i - 10);
// ^^^^^^^^^^^−−−−−−−−−−−− lambda expression
}
我使用Function
是因为您的Java代码似乎表明您想要返回值。如果您不希望返回值,只需使用Consumer<T>
。
答案 2 :(得分:0)
在Java 1.8中,可以使用Lambda表达式获得所需的结果:
public class Temp {
interface BlockBody {
int op(int b);
}
public static int myf(int i, Temp.BlockBody blockBody) {
System.out.println("start");
int out = blockBody.op(i);
System.out.println(out);
System.out.println("end");
return out;
}
public static void main(String[] args) {
// block lambda function defined here
Temp.BlockBody blockBody = (int a) -> {
int c = a * 10;
return c;
};
int result = Temp.myf(3, blockBody);
// block body is changed
Temp.BlockBody blockBody2 = (int a) -> {
int c = a - 10;
return c;
};
int result2 = Temp.myf(4, blockBody2);
}
}
// outputs:
// start
// 30
// end
// start
// -6
// end