甚至可能吗?
6 回答
如果您的意思是匿名函数,并且使用的是 Java 8 之前的 Java 版本,那么简而言之,不。(如果您使用 Java 8+,请阅读 lambda 表达式)
但是,您可以使用如下函数实现接口:
Comparator<String> c = new Comparator<String>() {
int compare(String s, String s2) { ... }
};
你可以将它与内部类一起使用来获得一个几乎匿名的函数:)
这是一个匿名内部类的示例。
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
长度就是这种情况)。
也可以看看
随着 Java 8 中 lambda 表达式的引入,您现在可以拥有匿名方法。
假设我有一堂课Alpha
,我想Alpha
在特定条件下过滤 s。为此,您可以使用Predicate<Alpha>
. 这是一个函数式接口,它有一个test
接受 aAlpha
并返回 a的方法boolean
。
假设 filter 方法有这个签名:
List<Alpha> filter(Predicate<Alpha> filterPredicate)
使用旧的匿名类解决方案,您需要:
filter(new Predicate<Alpha>() {
boolean test(Alpha alpha) {
return alpha.centauri > 1;
}
});
使用 Java 8 lambda,您可以:
filter(alpha -> alpha.centauri > 1);
有关更多详细信息,请参阅Lambda 表达式教程
实现或扩展现有类型接口的匿名内部类已在其他答案中完成,尽管值得注意的是可以实现多种方法(例如,通常使用 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
? )
是的,如果您使用的是最新的 Java 版本 8。Java8 使定义匿名函数成为可能,这在以前的版本中是不可能的。
让我们以java 文档为例来了解我们如何声明匿名函数、类
以下示例 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。
包含构造函数参数的括号,就像普通的类实例创建表达式一样。注意:当你实现一个接口时,没有构造函数,所以你使用一对空括号,如本例所示。
一个主体,它是一个类声明主体。更具体地说,在正文中,允许方法声明,但不允许声明。
您还可以使用Consumer
和BiConsumer
输入您需要多少参数。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");
}