# Java - 匿名內部類別 & Lambda Expressions ###### tags: `Java` `Basic Java` ## 匿名內部類別 ### 1. Syntax: ``` new (class name) or (interface name) () { @Override method(); }; ``` For example: 先建立一個游泳的interface ``` public interface Swim { public abstract void swim(); } ``` 在主方法直接用new的寫法 ``` public static void main(String[] args) { new Swim() { @Override public void swim() { System.out.println("I can swim!!"); } }; } ``` 所謂的"匿名",其實就是指沒有名字的類別 也就是下面這一段 ``` { @Override public void swim() { System.out.println("I can swim!!"); } }; ``` 我們可以使用建立物件的方式把這個沒有名字的類別創建出來,就會變成用new Swim() + 匿名類別 結果就會形成上面所提到的syntax 換句話說,我們這一段code在做的事情,其實就是用匿名內部類別去建立一個物件 ``` new Swim() { @Override public void swim() { System.out.println("I can swim!!"); } }; ``` 所以如果直接執行這一段code,並不會產生任何結果,因為物件才剛被做出來而已,都還沒call任何方法 ### 2. 使用目的: 正常的流程是:先寫一個子類別去繼承父類別,或是接上interface,重寫裡面的方法之後,再到主方法當中用new建立物件,之後用.調用方法。 但是如果這個類/interface**只需要被使用到一次而已**,透過這個流程會相當繁瑣跟多餘。此時就可以使用匿名內部類別的方式進行創立物件與方法使用,會比較方便 完整寫法如下: ``` public class Test { public static void main(String[] args) { method(new Swim() { @Override public void swim() { System.out.println("I can swim!!"); } } ); } public static void method(Swim s) { s.swim(); } } ``` 或是利用多型的寫法 ``` public class Test { public static void main(String[] args) { Swim s = new Swim() { @Override public void swim() { System.out.println("I can swim!!"); } }; s.swim(); } } ``` 或是直接invoke方法 ``` public class Test { public static void main(String[] args) { new Swim() { @Override public void swim() { System.out.println("I can swim!!"); } }.swim(); } } ``` ## Lambda Expressions ### 1. 使用目的:簡化匿名內部類別的寫法 舉例說明: 一個正常的匿名內部類別寫法 ``` public static void main(String[] args) { userInterfaceA(new InterfaceA() { @Override public void display() { System.out.println("Display Anonymous inner class"); } }); } public static void userInterfaceA (InterfaceA a) { a.display(); } interface InterfaceA { void display(); } ``` 改成Lambda Expression ``` userInterfaceA(() -> { System.out.println("Display Anonymous inner class"); }); ``` ### 2. 寫法解釋: Lambda的概念其實就是一個個函數,你可以根據輸入這個函數的值去決定輸出的值 ``` ()->{} (): 匿名內部類別的形式參數 {}: 被覆寫之方法的方法體 ``` 以上面的code為例 (): 匿名內部類別的形式參數 內部類別InterfaceA()裡面的參數是空白,故寫()即可 {}: 被覆寫之方法的方法體 覆寫的方法為System.out.println("Display Anonymous inner class"),所以就在{}裡面放入這一段code 拼起來就會變這樣: () -> {System.out.println("Display Anonymous inner class");} ### 3. 能用Lambda Expression簡化的條件: **只有functional interface才能利用lambda expression (functional interface是指僅有一個抽象方法的interface)** 如何判斷interface是否為functional interface? 可以利用在interface上面加上@FunctionalInterfaces來判斷,如果產生IDE產生錯誤就代表該interface非functional interface ### 4. Lambda Expression的省略寫法: #### a. 若覆寫的方法體只有一行,可以將{};都省略不寫 省略前: ``` userInterfaceA(() -> { System.out.println("Display Anonymous inner class"); }); ``` 省略後: ``` userInterfaceA(() -> System.out.println("Display Anonymous inner class")); ``` #### b. 若只有一個參數,則參數類型與()都可以省略 ``` public class Test2 { public static void main(String[] args) { useDisplayTool(new DisplayTool() { @Override public void display(String msg) { System.out.println("Anonymous inner class " + msg); } }); System.out.println("------------------"); //msg就是省略參數類型與()的表達 useDisplayTool(msg -> System.out.println("Lambda Expression " + msg)); } public static void useDisplayTool(DisplayTool displayTool) { displayTool.display("print a message"); } interface DisplayTool { void display(String msg); } } ``` #### c. 若方法體只有一行且有return,必須省略return並去掉 ``` public class Test3 { public static void main(String[] args) { useRandomNumber(new RandomNumber() { @Override public int getNumber() { return new Random().nextInt(100) + 1; } }); System.out.println("-------------"); useRandomNumber(() -> new Random().nextInt(100) + 1); } public static void useRandomNumber(RandomNumber randomNumber) { int result = randomNumber.getNumber(); System.out.println(result); } interface RandomNumber { int getNumber(); } } ``` #### d. 有多個參數,參數類型可省略不寫 ``` public class Test4 { public static void main(String[] args) { useCalculator(new Calculator() { @Override public int calculate(int a, int b) { return a + b; } }); System.out.println("------------------"); // 這邊可以不宣告a和b的int類型 useCalculator((a, b) -> a + b); } public static void useCalculator(Calculator calculator) { int result = calculator.calculate(10, 20); System.out.println(result); } interface Calculator { int calculate(int a, int b); } } ``` ### 5. 大絕招:利用IDEA自動產生 寫完匿名內部類別之後,直接把游標移到class name或interface name上面,按alt + enter,就會出現replace with lambda的提示,直接自動生成
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up