如何在Java中编写匿名函数?

时间:2010-05-02 23:31:33

标签: java anonymous-function

甚至可能吗?

6 个答案:

答案 0 :(得分:76)

如果你的意思是匿名函数,并且在Java 8之前使用的是Java版本,那么一句话就没有。 (Read about lambda expressions if you use Java 8+

但是,您可以使用如下函数实现接口:

Comparator<String> c = new Comparator<String>() {
    int compare(String s, String s2) { ... }
};

你可以在内部类中使用它来获得一个几乎匿名的函数:)

答案 1 :(得分:43)

这是一个匿名内部类的例子。

System.out.println(new Object() {
    @Override public String toString() {
        return "Hello world!";
    }
}); // prints "Hello world!"

这不是很有用,但它显示了如何创建extends Object@Override toString()方法的匿名内部类的实例。

另见


当您需要实现可能不具有高度可重用性的interface时,匿名内部类非常方便(因此不值得对其自己的命名类进行重构)。一个有启发性的示例是使用自定义java.util.Comparator<T>进行排序。

以下是基于String[]String.length()进行排序的示例。

import java.util.*;
//...

String[] arr = { "xxx", "cd", "ab", "z" };
Arrays.sort(arr, new Comparator<String>() {
    @Override public int compare(String s1, String s2) {
        return s1.length() - s2.length();
    }           
});
System.out.println(Arrays.toString(arr));
// prints "[z, cd, ab, xxx]"

请注意这里使用的逐比较减法技巧。应该说这种技术一般是破碎的:它只适用于你能保证它不会溢出的情况(例如String长度的情况)。

另见

答案 2 :(得分:11)

通过在Java 8中引入lambda表达式,您现在可以使用匿名方法。

假设我有一个课程Alpha,我想在特定条件下过滤Alpha。为此,您可以使用Predicate<Alpha>。这是一个功能界面,其方法test接受Alpha并返回boolean

假设过滤方法具有此签名:

List<Alpha> filter(Predicate<Alpha> filterPredicate)

使用旧的匿名类解决方案,您需要:

filter(new Predicate<Alpha>() {
   boolean test(Alpha alpha) {
      return alpha.centauri > 1;
   }
});

使用Java 8 lambdas,你可以做到:

filter(alpha -> alpha.centauri > 1);

有关详细信息,请参阅Lambda Expressions tutorial

答案 3 :(得分:9)

实现或扩展现有类型接口的匿名内部类已在其他答案中完成,但值得注意的是,可以实现多个方法(例如,通常使用JavaBean样式的事件)。

一个鲜为人知的特征是虽然匿名内部类没有名称,但它们确实有一个类型。可以在界面中添加新方法。这些方法只能在有限的情况下调用。主要直接在new表达式本身和类中(包括实例初始化程序)。它可能会让初学者感到困惑,但它对递归来说可能很“有趣”。

private static String pretty(Node node) {
    return "Node: " + new Object() {
        String print(Node cur) {
            return cur.isTerminal() ?
                cur.name() :
                ("("+print(cur.left())+":"+print(cur.right())+")");
        }
    }.print(node);
}

(我最初在node方法中使用cur而不是print来写这个。拒绝“隐式final”本地人?

答案 4 :(得分:0)

如果您使用的是版本8的最新版本,则为“是”.Java8可以定义匿名函数,这在以前的版本中是不可能的。

让我们从java docs获取示例,以了解我们如何声明匿名函数,类

  

以下示例HelloWorldAnonymousClasses使用匿名   局部变量的初始化语句中的类   frenchGreeting和spanishGreeting,但是使用当地的一个类   初始化变量englishGreeting:

public class HelloWorldAnonymousClasses {

    interface HelloWorld {
        public void greet();
        public void greetSomeone(String someone);
    }

    public void sayHello() {

        class EnglishGreeting implements HelloWorld {
            String name = "world";
            public void greet() {
                greetSomeone("world");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hello " + name);
            }
        }

        HelloWorld englishGreeting = new EnglishGreeting();

        HelloWorld frenchGreeting = new HelloWorld() {
            String name = "tout le monde";
            public void greet() {
                greetSomeone("tout le monde");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Salut " + name);
            }
        };

        HelloWorld spanishGreeting = new HelloWorld() {
            String name = "mundo";
            public void greet() {
                greetSomeone("mundo");
            }
            public void greetSomeone(String someone) {
                name = someone;
                System.out.println("Hola, " + name);
            }
        };
        englishGreeting.greet();
        frenchGreeting.greetSomeone("Fred");
        spanishGreeting.greet();
    }

    public static void main(String... args) {
        HelloWorldAnonymousClasses myApp =
            new HelloWorldAnonymousClasses();
        myApp.sayHello();
    }            
}

匿名类的语法

考虑frenchGreeting对象的实例化:

    HelloWorld frenchGreeting = new HelloWorld() {
        String name = "tout le monde";
        public void greet() {
            greetSomeone("tout le monde");
        }
        public void greetSomeone(String someone) {
            name = someone;
            System.out.println("Salut " + name);
        }
    };

匿名类表达式包含以下内容:

  • new运算符
  • 要实现的接口的名称或要扩展的类。在这 例如,匿名类正在实现该接口 的HelloWorld。

  • 包含构造函数参数的括号,就像一个 普通类实例创建表达式。注意:实施时 一个接口,没有构造函数,所以你使用一对空 括号,如本例所示。

  • 一个正文,它是一个类声明体。更具体地说,在 body,方法声明是允许的,但声明不允许。

答案 5 :(得分:0)

您还可以使用 ConsumerBiConsumer 类型来确定您需要多少参数。 Consumer 接受一个参数,BiConsumer 接受两个。

public void myMethod() {
  // you can declare it here
  Consumer<String> myAnonymousMethod = s -> {
    System.out.println(s);
  };

  // you can call it here
  muAnonymousMethod.apply("Hello World");
}