[英]How can I write an anonymous function in Java?
甚至有可能嗎?
如果您的意思是匿名函數,並且使用的是 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.length()
對String[]
進行排序的示例。
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
接受一個Alpha
並返回一個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);
}
(我最初在print
方法中使用node
而不是cur
來寫這個。對捕獲“隱式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");
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.