在Java中,如何将一个函数作为另一个函数的参数传递?
当前回答
Lambda表达式
加上jk。的完美回答,现在你可以使用Lambda表达式(在Java 8中)更容易地传递一个方法。函数式接口是具有且仅有一个抽象方法的接口,尽管它可以包含任意数量的默认方法(Java 8新增)和静态方法。lambda表达式可以快速实现抽象方法,如果不使用lambda表达式,则无需使用所有不必要的语法。
没有lambda表达式:
obj.aMethod(new AFunctionalInterface() {
@Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
使用lambda表达式:
obj.aMethod(i -> i == 982);
以下是Java Lambda表达式教程的节选:
Syntax of Lambda Expressions A lambda expression consists of the following: A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.Note: You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid: p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 The arrow token, -> A body, which consists of a single expression or a statement block. This example uses the following expression: p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement: p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression: email -> System.out.println(email) Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.
下面是如何使用lambda表达式“传递一个方法”:
注意:这使用了一个新的标准函数接口java.util.function.IntConsumer。
class A {
public static void methodToPass(int i) {
// do stuff
}
}
import java.util.function.IntConsumer;
class B {
public void dansMethod(int i, IntConsumer aMethod) {
/* you can now call the passed method by saying aMethod.accept(i), and it
will be the equivalent of saying A.methodToPass(i) */
}
}
class C {
B b = new B();
public C() {
b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here
}
}
上面的例子可以使用::运算符进一步简化。
public C() {
b.dansMethod(100, A::methodToPass);
}
其他回答
Java(目前)不支持闭包。但是还有其他语言,如Scala和Groovy,它们运行在JVM中,并且确实支持闭包。
Java很好地支持闭包。它只是不支持函数,所以您习惯的闭包语法更加笨拙和笨重:您必须用一个方法将所有内容包装在一个类中。例如,
public Runnable foo(final int x) {
return new Runnable() {
public void run() {
System.out.println(x);
}
};
}
将返回一个Runnable对象,其run()方法“关闭”传入的x,就像在任何支持一级函数和闭包的语言中一样。
我使用的命令模式是@jk。提到,添加一个返回类型:
public interface Callable<I, O> {
public O call(I input);
}
Lambda表达式
加上jk。的完美回答,现在你可以使用Lambda表达式(在Java 8中)更容易地传递一个方法。函数式接口是具有且仅有一个抽象方法的接口,尽管它可以包含任意数量的默认方法(Java 8新增)和静态方法。lambda表达式可以快速实现抽象方法,如果不使用lambda表达式,则无需使用所有不必要的语法。
没有lambda表达式:
obj.aMethod(new AFunctionalInterface() {
@Override
public boolean anotherMethod(int i)
{
return i == 982
}
});
使用lambda表达式:
obj.aMethod(i -> i == 982);
以下是Java Lambda表达式教程的节选:
Syntax of Lambda Expressions A lambda expression consists of the following: A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p, which represents an instance of the Person class.Note: You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid: p -> p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 The arrow token, -> A body, which consists of a single expression or a statement block. This example uses the following expression: p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25 If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement: p -> { return p.getGender() == Person.Sex.MALE && p.getAge() >= 18 && p.getAge() <= 25; } A return statement is not an expression; in a lambda expression, you must enclose statements in braces ({}). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression: email -> System.out.println(email) Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.
下面是如何使用lambda表达式“传递一个方法”:
注意:这使用了一个新的标准函数接口java.util.function.IntConsumer。
class A {
public static void methodToPass(int i) {
// do stuff
}
}
import java.util.function.IntConsumer;
class B {
public void dansMethod(int i, IntConsumer aMethod) {
/* you can now call the passed method by saying aMethod.accept(i), and it
will be the equivalent of saying A.methodToPass(i) */
}
}
class C {
B b = new B();
public C() {
b.dansMethod(100, j -> A.methodToPass(j)); //Lambda Expression here
}
}
上面的例子可以使用::运算符进一步简化。
public C() {
b.dansMethod(100, A::methodToPass);
}
我知道这是一个相当老的帖子,但我有另一个稍微简单的解决方案。 您可以在其中创建另一个类并使其抽象。接下来,创建一个抽象方法,命名为任何你喜欢的名字。在原来的类中创建一个以新类为参数的方法,在这个方法中调用抽象方法。它看起来是这样的。
public class Demo {
public Demo(/.../){
}
public void view(Action a){
a.preform();
}
/**
* The Action Class is for making the Demo
* View Custom Code
*/
public abstract class Action {
public Action(/.../){
}
abstract void preform();
}
}
现在您可以执行类似的操作来从类内部调用一个方法。
/...
Demo d = new Demo;
Action a = new Action() {
@Override
void preform() {
//Custom Method Code Goes Here
}
};
/.../
d.view(a)
就像我说的,我知道它很旧,但我认为这样更容易一些。希望能有所帮助。
推荐文章
- 在流中使用Java 8 foreach循环移动到下一项
- 访问限制:'Application'类型不是API(必需库rt.jar的限制)
- 用Java计算两个日期之间的天数
- 如何配置slf4j-simple
- 在Jar文件中运行类
- 带参数的可运行?
- 我如何得到一个字符串的前n个字符而不检查大小或出界?
- 我可以在Java中设置enum起始值吗?
- Java中的回调函数
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 在Java中,流相对于循环的优势是什么?
- Jersey在未找到InjectionManagerFactory时停止工作
- 在Java流是peek真的只是调试?
- Recyclerview不调用onCreateViewHolder
- 将JSON字符串转换为HashMap