匿名類能夠使你代碼更簡潔,它們使你可以同時聲明和實例化一個類,它們就像局部類,除了它們沒有名稱,若是你只須要使用局部類一次,請使用它們。java
雖然局部類是類聲明,但匿名類是表達式,這意味着你在另外一個表達式中定義該類,如下示例HelloWorldAnonymousClasses
在局部變量frenchGreeting
和spanishGreeting
的初始化語句中使用匿名類,但使用局部類初始化變量englishGreeting
:segmentfault
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(); } }
如前所述,匿名類是表達式,匿名類表達式的語法相似於構造函數的調用,除了代碼塊中包含類定義。oracle
考慮frenchGreeting
對象的實例化:app
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); } };
匿名類表達式包含如下內容:ide
new
運算符。HelloWorld
。由於匿名類定義是表達式,因此它必須是語句的一部分,在此示例中,匿名類表達式是實例化frenchGreeting
對象的語句的一部分(這解釋了爲何在閉合花括號後有一個分號)。函數
與局部類同樣,匿名類能夠捕獲變量,它們對封閉範圍的局部變量具備相同的訪問權限:spa
final
或者實際爲final
的局部變量。匿名類對其成員也具備與局部類相同的限制:code
請注意,你能夠在匿名類中聲明如下內容:htm
可是,你不能在匿名類中聲明構造函數。對象
匿名類一般用於圖形用戶界面(GUI)應用程序。
考慮JavaFX示例HelloWorld.java
(來自Hello World的部分,來自JavaFX入門的JavaFX樣式),此示例建立一個包含Say 'Hello World'按鈕的frame:
import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.layout.StackPane; import javafx.stage.Stage; public class HelloWorld extends Application { public static void main(String[] args) { launch(args); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Hello World!"); Button btn = new Button(); btn.setText("Say 'Hello World'"); btn.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { System.out.println("Hello World!"); } }); StackPane root = new StackPane(); root.getChildren().add(btn); primaryStage.setScene(new Scene(root, 300, 250)); primaryStage.show(); } }
在此示例中,方法調用btn.setOnAction
指定當你選擇Say 'Hello World'
按鈕時會發生什麼,此方法須要EventHandler<ActionEvent>
類型的對象,EventHandler<ActionEvent>
接口只包含一個方法handle
。該示例使用匿名類表達式,而不是使用新類實現此方法,請注意,此表達式是傳遞給btn.setOnAction
方法的參數。
由於EventHandler<ActionEvent>
接口只包含一個方法,因此能夠使用lambda表達式而不是匿名類表達式,有關更多信息,請參閱Lambda表達式一節。
匿名類是實現包含兩個或更多方法的接口的理想選擇,如下JavaFX示例來自UI控件的自定義部分,匿名類代碼建立一個只接受數值的文本字段,它經過重寫從TextInputControl
類繼承的replaceText
和replaceSelection
方法,使用匿名類從新定義TextField
類的默認實現。
import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.stage.Stage; public class CustomTextFieldSample extends Application { final static Label label = new Label(); @Override public void start(Stage stage) { Group root = new Group(); Scene scene = new Scene(root, 300, 150); stage.setScene(scene); stage.setTitle("Text Field Sample"); GridPane grid = new GridPane(); grid.setPadding(new Insets(10, 10, 10, 10)); grid.setVgap(5); grid.setHgap(5); scene.setRoot(grid); final Label dollar = new Label("$"); GridPane.setConstraints(dollar, 0, 0); grid.getChildren().add(dollar); final TextField sum = new TextField() { @Override public void replaceText(int start, int end, String text) { if (!text.matches("[a-z, A-Z]")) { super.replaceText(start, end, text); } label.setText("Enter a numeric value"); } @Override public void replaceSelection(String text) { if (!text.matches("[a-z, A-Z]")) { super.replaceSelection(text); } } }; sum.setPromptText("Enter the total"); sum.setPrefColumnCount(10); GridPane.setConstraints(sum, 1, 0); grid.getChildren().add(sum); Button submit = new Button("Submit"); GridPane.setConstraints(submit, 2, 0); grid.getChildren().add(submit); submit.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent e) { label.setText(null); } }); GridPane.setConstraints(label, 0, 1); GridPane.setColumnSpan(label, 3); grid.getChildren().add(label); scene.setRoot(grid); stage.show(); } public static void main(String[] args) { launch(args); } }