μλ°κ° 1996λ μ μ²μ λ±μ₯ν μ΄νλ‘ λ λ²μ ν° λ³νκ° μμλλ°, νλ²μ JDK 1.5λΆν° μΆκ°λ μ§λ€λ¦μ€(generics)μ λ±μ₯μ΄κ³ , λ ν λ²μ JDK 1.8λΆν° μΆκ°λ λλ€μ(lambda expression)μ λ±μ₯μ΄λ€. μ΄ λ κ°μ§ μλ‘μ΄ λ³νμ μν΄ μλ°λ λ μ΄μ μμ μ μλ°κ° μλκ² λμλ€.
νΉν JDK 1.8λΆν° λ±μ₯ν λλ€μμΌλ‘ μΈν΄ μλ°λ κ°μ²΄μ§ν₯μΈμ΄μΈ λμμ ν¨μν μΈμ΄κ° λμλ€.
λλ€μμ΄λ?
κ°λ¨ν λ§ν΄μ λ©μλλ₯Ό νλμ μ(expression)μΌλ‘ ννν κ²μ΄λ€. ν¨μλ₯Ό κ°λ΅νλ©΄μλ λͺ νν μμΌλ‘ ννν μ μκ² ν΄μ€λ€.
μ΄μ μ λ΄λΆ ν΄λμ€λ₯Ό μ 리νλ©΄μ μ΅λͺ ν¨μ(anonymous function) μΈκΈν λ κ°μ΄ κ°λ³κ² μ΄ν΄λ΄€λ―μ΄ λλ€μλ μ΅λͺ ν¨μμ΄λ€. λ©μλλ₯Ό λλ€μμΌλ‘ νννλ©΄ λ©μλμ μ΄λ¦μ΄ μμ΄μ§κΈ° λλ¬Έμ΄λ€.
μμ
1 2 3 | int[] arr = new int[5]; // arr = [1,5,2,1,1] Arrays.setAll(arr, () -> (int) (Math.random() * 5) + 1); | cs |
μμ λλ€μμΌλ‘ ννλ λ©μλλ₯Ό λ°λ‘ λ§λ€λ©΄ μλμ κ°λ€.
1 2 3 | int method() { return (int) (Math.random() * 5) + 1; } | cs |
λλ€μμΌλ‘ μΈν΄μ κ°κ²°νκ³ μ΄ν΄νκΈ° μ¬μμ§λ©° νλμ λ©μλλ₯Ό ꡬννκΈ° μν΄μ ν΄λμ€λ₯Ό λ§λ€μ΄μ£Όκ³ κ°μ²΄λ μμ±ν΄μ£Όμ΄μΌ νλ λ²κ±°λ‘μ΄ μμ μ μλ΅ν μ μλ€. κ²λ€κ° λ©μλμ 맀κ°λ³μλ‘ λλ€μμ ν΅ν΄ λ©μλλ₯Ό μ λ¬ν μλ μκ³ , λ©μλμ κ²°κ³Όλ‘ λ°νλ μλ μλ€. μ¦, λ©μλλ₯Ό λ³μμ²λΌ λ€λ£° μ μκ² λ κ²μ΄λ€. μ΄λ₯Ό ν΅ν΄ μΌλ§λ κ°κ²°νκ³ μ μ°νκ² μλ°λ₯Ό λ³νμν¬ μ μλμ§μ λν΄μ μμ보μ.
Q. λ©μλμ ν¨μμ μ°¨μ΄?
A. μ ν΅μ μΌλ‘ νλ‘κ·Έλλ°μμ ν¨μλΌλ μ΄λ¦μ μνμμ λ°μ¨ κ²μ. μνμ ν¨μμ κ°λ μ΄ μ μ¬νκΈ° λλ¬Έ. κ·Έλ¬λ κ°μ²΄μ§ν₯κ°λ μμλ ν¨μλ₯Ό κ°μ²΄μ νμλ λμμ μ³λ―Ένλ λ©μλλΌλ μ©μ΄λ‘ μ¬μ©. λ©μλλ ν¨μμ κ°μ μλ―Έμ§λ§, νΉμ ν΄λμ€μ λ°λμ μν΄μΌ νλ€λ μ μ½μ΄ μκΈ° λλ¬Έμ κΈ°μ‘΄μ ν¨μμ κ°μ μλ―Έμ λ€λ₯Έ μ©μ΄λ₯Ό μ νν΄μ μ¬μ©ν κ². κ·Έλ¬λ μ΄μ λ€μ λλ€μμ ν΅ν΄ λ©μλκ° νλμ λ 립μ μΈ κΈ°λ₯μ νκΈ° λλ¬Έμ λ€μ ν¨μλΌλ μ©μ΄λ₯Ό μ¬μ©νκ² λμμ.
λλ€μ μμ±νκΈ°
μ΅λͺ ν¨μ λ΅κ² λ©μλμμ μ΄λ¦κ³Ό λ°ννμ μ μ κ±°νκ³ λ§€κ°λ³μ μ μΈλΆμ λͺΈν΅{} μ¬μ΄μ νμ΄ν '->' λ₯Ό μΆκ°νλ€.
λ°ννμ
λ©μλμ΄λ¦(맀κ°λ³μ μ μΈ) {
Β· Β· Β·
}
λ°ννμ
λ©μλμ΄λ¦(맀κ°λ³μ μ μΈ) -> {
Β· Β· Β·
}
μμ
1 2 3 | int max(int a, int b) { return a > b ? a : b; } | cs |
μμ λ©μλλ₯Ό λλ€μμΌλ‘ λ³ννλ©΄ μλμ κ°μ΄ λλ€.
1 2 3 | (int a, int b) -> { return a > b ? a : b; } | cs |
λ°νκ°μ΄ μλ λ©μλμ κ²½μ° return λ¬Έ λμ 'μ(expression)'μΌλ‘ λμ ν μ μλ€. μμ μ°μ°κ²°κ³Όκ° μλμΌλ‘ λ°νκ°μ΄ λμ΄ λ°νλλ€. μ΄λλ 'λ¬Έμ₯(statement)'κ° μλ 'μ'μΌλ‘ λμ΄ λλ―λ‘ λμ μΈλ―Έμ½λ‘ (;)μ λΆμ΄μ§ μλλ€. λ€μκ³Ό κ°μ΄.
1 | (int a, int b) -> a > b ? a : b | cs |
λν λλ€μμ μ μΈλ 맀κ°λ³μμ νμ μ μΆλ‘ μ΄ κ°λ₯ν κ²½μ° μλ΅ κ°λ₯νλ€. (λλΆλΆμ κ²½μ° μλ΅ κ°λ₯)
λλ€μμ λ°ννμ μ΄ μλ μ΄μ λ κ°μ μ΄μ λ€. ( κ±°μ νμ μΆλ‘ μ΄ κ°λ₯ ) λ€μκ³Ό κ°μ΄.
1 | (a, b) -> a > b ? a : b | cs |
β» μ£Όμ : (int a, b) -> a > b ? a : b μ κ°μ΄ λ 맀κ°λ³μ μ€ μ΄λ νλμ νμ
λ§ μλ΅νλ κ²μ νμ©λμ§ μλλ€.
κ΄νΈ μλ΅ μμ
맀κ°λ³μκ° νλλΏμΈ κ²½μ°μλ μμ 맀κ°λ³μλ₯Ό λλ¬ μΈκ³ μλ κ΄νΈ()λ₯Ό μλ΅ν μ μλ€. λ¨, 맀κ°λ³μμ νμ μ΄ λͺ μλμ΄ μμΌλ©΄ μλ΅μ΄ λΆκ°λ₯νλ€.
1 2 | (a) -> a * a (int a) -> a * a | cs |
μλμ κ°μ΄ κ΄νΈ μλ΅
1 2 | a -> a * a // OK int a -> a * a // μλ¬ | cs |
맀κ°λ³μμ λ§μ°¬κ°μ§λ‘ λͺΈν΅{} μμ λ¬Έμ₯μ΄ νλμΌ λμλ λΈλ{}μ μλ΅ν μ μλ€.
1 2 3 | (String name, int i) -> { System.out.println(name + "=" + i); } | cs |
μλμ κ°μ΄ κ΄νΈ μλ΅
1 2 | (String name, int i) -> System.out.println(name + "=" + i) | cs |
μ΄ λ μ£Όμν μ μ λ¬Έμ₯μ λμ μΈλ―Έμ½λ‘ (;)μ λΆμ΄μ§ μμμΌνλ€. λν κ·Έ λ¬Έμ₯μ΄ returnλ¬ΈμΌ κ²½μ°μλ μλ΅ν μ μλ€.
1 2 | (int a, int b) -> { return a > b ? a : b; } // OK (int a, int b) -> return a > b ? a : b // μλ¬ | cs |
ν¨μν μΈν°νμ΄μ€
μλ°μ κ°μ²΄μ§ν₯ νΉμ±μ μνλ©΄ λͺ¨λ λ©μλλ ν΄λμ€ λ΄μ ν¬ν¨λμ΄μΌ νλλ°, λλ€μμ μ΄λ€ ν΄λμ€μ ν¬ν¨λλ κ²μΌκΉ? λκΈ΄ νλ κ²μΌκΉ? μ§κΈκΉμ§ λλ€μμ΄ λ©μλμΈ κ²μ²λΌ μ 리λ₯Ό ν΄μμ§λ§, μ¬μ€ λλ€μμ μ΅λͺ ν΄λμ€μ κ°μ²΄λ€.
1 | (int a, int b) -> a > b ? a : b | cs |
μμ λλ€μμ μλμ κ°λ€.
1 2 3 4 5 | new Object() { int max(int a, int b) { return a > b ? a : b; } } | cs |
μμ μ½λμμ λ©μλ μ΄λ¦ maxλ μμλ‘ λΆμΈ κ² λΏ μλ―Έλ μλ€. μ¬κΈ°μ μ€μν κ²μ λλ€μμΌλ‘ μ μλ μ΅λͺ κ°μ²΄μ λ©μλλ₯Ό μ΄λ»κ² νΈμΆν κ²μΈκ°? μ΄λ―Έ μκ³ μλ κ²μ²λΌ μ°Έμ‘°λ³μκ° μμ΄μΌ κ°μ²΄μ λ©μλλ₯Ό νΈμΆν μ μλ€. λ°λΌμ μΌλ¨ μ΄ μ΅λͺ κ°μ²΄μ μ£Όμλ₯Ό fλΌλ μ°Έμ‘°λ³μμ μ μ₯ν΄λ³΄μ.
1 | νμ
f = (int a, int b) -> a > b ? a : b; | cs |
μμμ μ°Έμ‘°λ³μμ νμ μ λλ‘ ν΄μΌν κΉ? μ°Έμ‘°λ³μμ΄κΈ° λλ¬Έμ ν΄λμ€ λλ μΈν°νμ΄μ€κ° κ°λ₯νλ€. κ·Έλ¦¬κ³ λλ€μκ³Ό λλ±ν λ©μλκ° μ μλμ΄ μλ κ²μ΄μ΄μΌ νλ€. κ·ΈλμΌλ§ μ°Έμ‘°λ³μλ‘ μ΅λͺ κ°μ²΄(λλ€μ)μ λ©μλλ₯Ό νΈμΆν μ μκΈ° λλ¬Έμ.
μλ₯Όλ€μ΄, λ€μκ³Ό κ°μ μΈν°νμ΄μ€κ° λ μ μλ€.
1 2 3 | interface MyInterface { public abstract int max(int a, int b); } | cs |
μμ μΈν°νμ΄μ€λ₯Ό ꡬνν μ΅λͺ ν΄λμ€μ κ°μ²΄λ λ€μκ³Ό κ°μ΄ μμ±ν μ μλ€.
1 2 3 4 5 6 7 8 | javaMyInterface f = new MyInterface() { public int max(int a, int b) { return a > b ? a : b; } }; // μ΅λͺ
κ°μ²΄μ λ©μλ νΈμΆ int big = f.max(5, 3); | cs |
MyInterface μΈν°νμ΄μ€μ μ μλ λ©μλ max()λ λλ€μκ³Ό μ μΈλΆκ° μΌμΉνλ€. κ·Έλμ μ μ½λμ μ΅λͺ κ°μ²΄λ₯Ό λλ€μμΌλ‘ λ체ν μ μλ€.
1 2 3 4 | MyInterface f = (int a, int b) -> a > b ? a : b; // μ΅λͺ
κ°μ²΄μ λ©μλ νΈμΆ int big = f.max(5, 3); | cs |
μ΄μ²λΌ λλ€μμΌλ‘ λ체 κ°λ₯ν μ΄μ λ λλ€μλ μ€μ λ‘λ μ΅λͺ κ°μ²΄μ΄κ³ , MyInterfaceμΈν°νμ΄μ€μ λ©μλ max()μ λλ€μμ 맀κ°λ³μμ νμ κ³Ό κ°μ κ·Έλ¦¬κ³ λ°νκ°μ΄ μΌμΉνκΈ° λλ¬Έμ΄λ€. μ΄λ κ² νλμ λ©μλκ° μ μΈλ μΈν°νμ΄μ€λ₯Ό μ μν΄μ λλ€μμ λ€λ£¨λ κ²μ κΈ°μ‘΄μ μλ°μ κ·μΉλ€μ μ΄κΈ°μ§ μμΌλ©΄μ μμ°μ€λ½λ€ νλ¨νμ¬ μΈν°νμ΄μ€λ₯Ό ν΅ν΄ λλ€μμ λ€λ£¨κΈ°λ‘ κ²°μ μ΄ λμλ€κ³ νλ€. κ·Έλ‘ μΈν΄ μ΄λ Έν μ΄μ μ΄ νλ μΆκ°λμλλ° μ§λ μκ°μ΄ μ κΉ μκ°ν ν¨μν μΈν°νμ΄μ€(Functional Interface)λΌλ μλ―Έλ₯Ό λͺ μνλ μ΄λ Έν μ΄μ μ΄ λ±μ₯νλ€.
1 2 3 4 5 | // ν¨μν μΈν°νμ΄μ€ @FunctionalInterface interface MyInterface { public abstract max(int a, int b); } | cs |
β» @FunctionalInterfaceλ₯Ό λΆμ΄λ©΄ μ»΄νμΌλ¬κ° μΈν°νμ΄μ€λ₯Ό μ¬λ°λ₯΄κ² μ μνμλμ§ νμΈν΄μ£Όλ―λ‘, κΌ λΆμ΄μ.
κΈ°μ‘΄μλ μλμ κ°μ΄ 볡μ‘νκ² νμ΄μΌ νλλ°
1 2 3 4 5 6 7 | List<String> list = Arrays.asList("abx", "aaa", "bbb", "ddd", "aaa"); Collections.sort(list, new Comparator<String>() { public int compare(String s1, String s2) { return s2.compareTo(s1); } } | cs |
μ΄μ λλ€μμΌλ‘ μλμ κ°μ΄ κ°λ¨ν μ²λ¦¬ν μ μκ² λμλ€.
1 2 | List<String> list = Arrays.asList("abc", "aaa", "bbb", "ddd", "aaa"); Collections.sort(list, (s1, s2) -> s2.compareTo(s1)); | cs |
ν¨μν μΈν°νμ΄μ€ νμ μ 맀κ°λ³μμ λ°ννμ
ν¨μν μΈν°νμ΄μ€ MyFunctionμ΄ μλμ κ°μ΄ μ μλμ΄ μμ λ,
1 2 3 4 | @FunctionalInterface interface MyFunction { void myMethod(); // μΆμ λ©μλ } | cs |
λ©μλμ 맀κ°λ³μκ° MyFunctionνμ μ΄λ©΄, ν΄λΉ λ©μλλ₯Ό νΈμΆν λ λλ€μμ μ°Έμ‘°νλ μ°Έμ‘°λ³μλ₯Ό 맀κ°λ³μλ‘ μ§μ ν΄μΌνλ€λ λ»μ΄λ€. μλ₯Ό λ€μ΄ aMethodλΌλ λ©μλλ₯Ό μ μν΄λ³΄μ.
1 2 3 4 5 6 7 8 9 | // 맀κ°λ³μμ νμ
μ΄ ν¨μν void aMethod(MyFunction f) { f.myMethod(); // MyFunctionμ μ μλ λ©μλ νΈμΆ } . . . MyFunction f = () -> System.out.println("myMethod()"); aMethod(f); | cs |
β» μμμ MyFunction f λΌλ μ°Έμ‘°λ³μμ λλ€μμ λμ ν λ λ€μκ³Ό κ°μ΄ νλ³νμ΄ μ΄λ£¨μ΄μ§λ€.
MyFunction f = (MyFunction) ( () -> System.out.println("myMethod()") );
λλ€μμ μ΅λͺ κ°μ²΄μ΄κ³ μ΅λͺ κ°μ²΄λ νμ μ΄ μλ€. (λ μ ννλ νμ μ΄ μκΈ΄ μμ§λ§ μ»΄νμΌλ¬κ° μμλ‘ μ΄λ¦μ μ νκΈ° λλ¬Έμ μ μ μλ κ²) κ·Έλμ λμ μ°μ°μμ μλ³μ νμ μ μΌμΉμν€κΈ° μν΄ μμ κ°μ΄ νλ³νμ΄ νμνλ€.
λλ€μμ MyFunctionμΈν°νμ΄μ€λ₯Ό μ§μ ꡬννμ§ μμμ§λ§, μ΄ μΈν°νμ΄μ€λ₯Ό ꡬνν ν΄λμ€μ κ°μ²΄μ μμ ν λμΌνκΈ° λλ¬Έμ μμ κ°μ νλ³νμ νμ©νλ€. κ·Έλ¦¬κ³ μ΄ νλ³νμ μλ΅ κ°λ₯νλ€.
μ¬κΈ°μ νκ°μ§ λ μ£Όμν μ μ λλ€μμ Objectνμ μΌλ‘ νλ³ν ν μ μλ€. μ€μ§ ν¨μν μΈν°νμ΄μ€λ‘λ§ νλ³νμ΄ κ°λ₯νλ€. κ΅³μ΄ Objectνμ μΌλ‘ νλ³νμ΄ νμνλ€λ©΄ λ¨Όμ ν¨μν μΈν°νμ΄μ€λ‘ λ³νν νμ Objectνμ μΌλ‘ λ³ννλ©΄ λλ€.
Object obj = (Object) ( () -> System.out.println("myMethod()") ); // μλ¬
Object obj = (Object) (MyFunction) ( () -> System.out.println("myMethod()") );
String str = ((Object) (MyFunction) ( () -> System.out.println("myMethod()") ) ).toString();
λλ μ°Έμ‘°λ³μ μμ΄ μλμ κ°μ΄ μ§μ λλ€μμ 맀κ°λ³μλ‘ μ λ¬νλ κ²λ κ°λ₯νλ€.
1 | aMethod(() -> System.out.println("myMethod()")); | cs |
κ°μ μλ¦¬λ‘ λ©μλμ λ°ννμ μ΄ ν¨μν μΈν°νμ΄μ€ νμ μ΄λΌλ©΄, λκ°μ΄ ν¨μν μΈν°νμ΄μ€μ μΆμ λ©μλμ λλ±ν λλ€μμ κ°λ¦¬ν€λ μ°Έμ‘°λ³μλ₯Ό λ°ννκ±°λ λλ€μμ μ§μ λ°νν μ μλ€.
1 2 3 4 | MyFunction myMethod() { MyFunction f = () -> {}; return f; // νμ€λ‘ μ€μ΄λ©΄ return () -> {}; } | cs |
μ¦, μμμ λ§νλ―μ΄ λ©μλλ₯Ό λ³μμ²λΌ μ£Όκ³ λ°λ κ²μ΄ κ°λ₯ν΄μ§ κ²μ΄λ€. (μ¬μ€μ λ©μλκ° μλλΌ κ°μ²΄λ₯Ό μ£Όκ³ λ°λ κ²μ΄λΌ μ€μ λ‘ λ¬λΌμ§ κ²μ μ무κ²λ μμ§λ§, λλ€μ λλΆμ μμ λ³΄λ€ μ½λκ° λ κ°κ²°νκ³ μ΄ν΄νκΈ° μ¬μμ§)
νλ³ν μμ
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @FunctionalInterface interface MyFunction { void myMethod(); // public abstract void myMethod(); } class LambdaEx2 { public static void main(String[] args) { MyFunction f = ()->{}; // MyFunction f = (MyFunction)(()->{}); Object obj = (MyFunction)(()-> {}); // Objectνμ
μΌλ‘ νλ³νμ΄ μλ΅λ¨ String str = ((Object)(MyFunction)(()-> {})).toString(); System.out.println(f); System.out.println(obj); System.out.println(str); // System.out.println(()->{}); // μλ¬. λλ€μμ Objectνμ
μΌλ‘ νλ³ν μλ¨ System.out.println((MyFunction)(()-> {})); // System.out.println((MyFunction)(()-> {}).toString()); // μλ¬ System.out.println(((Object)(MyFunction)(()-> {})).toString()); } } | cs |
[μ€ν κ²°κ³Ό]
LambdaEx2$$Lambda$1/531885035@6ce253f1
LambdaEx2$$Lambda$2/135721597@53d8d10a
LambdaEx2$$Lambda$3/142257191@3e3abc88
LambdaEx2$$Lambda$4/245257410@65ab7765
LambdaEx2$$Lambda$5/455659002@eed1f14
μ€νκ²°κ³Όλ₯Ό 보면, μ»΄νμΌλ¬κ° λλ€μμ νμ μ μ΄λ€ νμμΌλ‘ λ§λ€μ΄λ΄λμ§ μ μ μλ€. μΌλ°μ μΈ μ΅λͺ κ°μ²΄λΌλ©΄, κ°μ²΄μ νμ μ΄
'μΈλΆν΄λμ€μ΄λ¦$λ²νΈ' μ κ°μ νμμΌλ‘ νμ μ΄ κ²°μ λμμ ν λ°, λλ€μμ νμ μ
'μΈλΆν΄λμ€μ΄λ¦$$Lambda$λ²νΈ' μ κ°μ νμμΌλ‘ λμ΄ μλ κ²μ νμΈν μ μλ€.
μΈλΆ λ³μλ₯Ό μ°Έμ‘°νλ λλ€μ μμ
λλ€μλ μ΅λͺ κ°μ²΄, μ¦ μ΅λͺ ν΄λμ€μ μΈμ€ν΄μ€μ΄λ―λ‘ λλ€μμμ μΈλΆμ μ μΈλ λ³μμ μ κ·Όνλ κ·μΉμ μμ μ΅λͺ ν΄λμ€μμ λ°°μ΄ κ²κ³Ό λμΌνλ€.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | @FunctionalInterface interface MyFunction { void myMethod(); } class Outer { int val=10; // Outer.this.val class Inner { int val=20; // this.val void method(int i) { // void method(final int i) { int val=30; // final int val=30; // i = 10; // μλ¬. μμμ κ°μ λ³κ²½ν μ μμ. MyFunction f = () -> { System.out.println(" i :" + i); System.out.println(" val :" + val); System.out.println(" this.val :" + ++this.val); System.out.println("Outer.this.val :" + ++Outer.this.val); }; f.myMethod(); } } // Innerν΄λμ€μ λ } // Outerν΄λμ€μ λ class LambdaEx3 { public static void main(String args[]) { Outer outer = new Outer(); Outer.Inner inner = outer.new Inner(); inner.method(100); } } | cs |
[μ€ν κ²°κ³Ό]
i :100
val :30
this.val :21
Outer.this.val :11
β» μΌλ°μ μΌλ‘ μ΅λͺ
κ°μ²΄ λ΄λΆμμ thisλ μ΅λͺ
κ°μ²΄μ μ°Έμ‘°μ΄μ§λ§, λλ€μμμ thisλ λλ€μμ μ€νν κ°μ²΄μ μ°Έμ‘°.
μμ μμ λ λλ€μ λ΄λΆμμ μΈλΆμ μ μΈλ λ³μμ μ κ·Όνλ λ°©λ²μ 보μ¬μ€λ€. λλ€μ λ΄μμ μ°Έμ‘°νλ μ§μλ³μλ finalμ΄ λΆμ§ μμλ μμλ‘ κ°μ£Όλλ€. λλ€μ λ΄μμ μ§μλ³μ iμ valμ μ°Έμ‘°νκ³ μμΌλ―λ‘ λλ€μ λ΄μμλ λ€λ₯Έ μ΄λ κ³³μμλ μ΄ λ³μλ€μ κ°μ λ³κ²½νλ κ²μ νμ©λμ§ μλλ€.
JDK 1.8 μ΄μ μλ finalμ λͺ μνμ§ μμΌλ©΄ μ»΄νμΌμ΄ λμ§ μμμΌλ JDK 1.8λΆν°λ μ΅μ’ μ μΌλ‘ finalμΈ κ²½μ° final νκΈ°λ₯Ό νμ§ μμλ μ»΄νμΌμ΄ λλ€. (νλ§λλ‘ λλ€μ μμμλ μ°Έμ‘°νλ μ§μλ³μλ€μ΄ finalμ μ°λ μ μ°λ κ°μ λ³κ²½νλ κ²μ νμ©λμ§ μμ)
λ°λ©΄μ Innerν΄λμ€μ Outerν΄λμ€μ μΈμ€ν΄μ€ λ³μμΈ this.valκ³Ό Outer.this.valμ μμλ‘ κ°μ£Όλμ§ μμΌλ―λ‘ κ°μ λ³κ²½ν΄λ λλ€.
κ·Έλ¦¬κ³ μΈλΆ μ§μλ³μμ κ°μ μ΄λ¦μ λλ€μ 맀κ°λ³μλ μ¬μ©ν μ μλ€.
1 2 3 4 5 6 7 8 9 10 | void method(int i) { int val=30; MyFunction f = (i) -> { // μλ¬. μΈλΆ μ§μλ³μμ μ΄λ¦μ΄ μ€λ³΅λ¨. System.out.println(" i :" + i); System.out.println(" val :" + val); System.out.println(" this.val :" + ++this.val); System.out.println("Outer.this.val :" + ++Outer.this.val); }; } | cs |
java.util.function ν¨ν€μ§
λλΆλΆμ λ©μλλ νμ μ΄ λΉμ·νκ³ λ§€κ°λ³μκ° μκ±°λ ν κ° λλ λ κ°, λ°ν κ°μ μκ±°λ ν κ°.
μ§λ€λ¦ λ©μλλ‘ μ μνλ©΄ 맀κ°λ³μλ λ°ν νμ μ΄ λ¬λΌλ λ¬Έμ κ° λμ§ μλλ€. κ·Έλμ java.util.funcationν¨ν€μ§μ μΌλ°μ μΌλ‘ μμ£Ό μ°μ΄λ νμμ λ©μλλ₯Ό ν¨μν μΈν°νμ΄μ€λ‘ 미리 μ μν΄ λμλ€. λ§€λ² μλ‘μ΄ ν¨μν μΈν°νμ΄μ€λ₯Ό μ μνμ§ λ§κ³ κ°λ₯νλ©΄ μ΄ ν¨ν€μ§μ μΈν°νμ΄μ€λ₯Ό νμ©νλ κ²μ΄ μ’λ€. κ·ΈλμΌ ν¨μν μΈν°νμ΄μ€μ μ μλ λ©μλ μ΄λ¦λ ν΅μΌλκ³ , μ¬μ¬μ©μ±μ΄λ μ μ§λ³΄μ μΈ‘λ©΄μμλ μ’λ€. μμ£Ό μ°μ΄λ κ°μ₯ κΈ°λ³Έμ μΈ ν¨μν μΈν°νμ΄μ€λ λ€μκ³Ό κ°λ€.
ν¨μν μΈν°νμ΄μ€ |
λ©μλ |
μ€λͺ |
java.lang.Runnable |
void run() |
맀κ°λ³μλ μκ³ , λ°νκ°λ μμ. |
Supplier<T> |
T get() |
맀κ°λ³μλ μκ³ , λ°νκ°λ§ μμ. |
Consumer<T> |
void accept(T t) |
Supplierμ λ°λλ‘ λ§€κ°λ³μλ§ μκ³ , λ°νκ°μ μμ. |
Function<T, R> |
R apply(T t) |
μΌλ°μ μΈ ν¨μ. νλμ 맀κ°λ³μλ₯Ό λ°μμ κ²°κ³Όλ₯Ό λ°ν |
Predicate<T> |
boolean test(T t) |
쑰건μμ νννλλ° μ¬μ©λ¨. 맀κ°λ³μλ νλ, λ°ν νμ μ boolean |
맀κ°λ³μμ λ°νκ°μ μ 무μ λ°λΌ 4κ°μ ν¨μν μΈν°νμ΄μ€κ° μ μλμ΄ μκ³ , Functionμ λ³νμΌλ‘ Predicateκ° μλλ°, λ°νκ°μ΄ booleanμ΄λΌλ κ²λ§ λΉΌκ³ Functionκ³Ό κ°λ€.
쑰건μμ ννμ μ¬μ©λλ Predicate
Predicateλ 쑰건μμ λλ€μμΌλ‘ νννλλ° μ¬μ©λλ€.
[μ°Έκ³ ] μνμμ κ²°κ³Όλ‘ true λλ falseλ₯Ό λ°ννλ ν¨μλ₯Ό predicateλΌκ³ νλ€.
1 2 3 4 5 | Predicate<String> isEmptyStr = s -> s.length() == 0; String s = ""; if (isEmptyStr.test(s)) // if (s.length==0) System.out.println("s is an empty String"); | cs |
[μ€ν κ²°κ³Ό]
s is an empty String
맀κ°λ³μκ° λ κ°μΈ ν¨μν μΈν°νμ΄μ€
맀κ°λ³μκ° 2κ°μΈ ν¨μν μΈν°νμ΄μ€λ μ΄λ¦ μμ μ λμ¬ 'Bi'κ° λΆλλ€.
[μ°Έκ³ ] 맀κ°λ³μμ νμ
μΌλ‘ λ³΄ν΅ 'T'λ₯Ό λ§μ΄ μ¬μ©νκΈ° λλ¬Έμ μνλ²³μμ 'T' λ€μ λ¬ΈμμΈ 'U', 'V', 'W'λ₯Ό 맀κ°λ³μμ νμ
μΌλ‘ μ¬μ©νλ κ²μΌ λΏ λ³ λ€λ₯Έ μλ―Έλ μλ€.
ν¨μν μΈν°νμ΄μ€ |
λ©μλ |
μ€λͺ |
BiConsumer<T,U> |
void accept(T t, U u) |
λκ°μ 맀κ°λ³μλ§ μκ³ , λ°νκ°μ΄ μμ |
BiPredicate<T,U> |
boolean test(T t, U u) |
쑰건μμ νννλλ° μ¬μ©λ¨. 맀κ°λ³μλ λ, λ°νκ°μ boolean |
BiFunction<T, U, R> |
R apply(T t, U u) |
λ κ°μ 맀κ°λ³μλ₯Ό λ°μμ νλμ κ²°κ³Όλ₯Ό λ°ν |
λ κ° μ΄μμ 맀κ°λ³μλ₯Ό κ°λ ν¨μν μΈν°νμ΄μ€κ° νμνλ€λ©΄ μ§μ λ§λ€μ΄μ μ¨μΌνλ€. λ€μκ³Ό κ°μ΄.
1 2 3 4 | @FunctionalInterface interface TriFunction<T, U, V, R> { R apply(T t, U u, V v); } | cs |
UnaryOperatorμ BinaryOperator
Functionμ λ λ€λ₯Έ λ³νμΌλ‘ UnaryOperatorμ BinaryOperatorκ° μλλ°, 맀κ°λ³μμ νμ κ³Ό λ°ννμ μ νμ μ΄ λͺ¨λ μΌμΉνλ€λ μ λ§ λΉΌκ³ λ Functionκ³Ό κ°λ€.
[μ°Έκ³ ] UnaryOperatorμ BinaryOperatorμ μ‘°μμ κ°κ° Functionκ³Ό BiFunctionμ΄λ€.
ν¨μν μΈν°νμ΄μ€ |
λ©μλ |
μ€λͺ |
UnaryOperator<T> |
R apply(T t) |
Functionμ μμ, Functionκ³Ό λ¬λ¦¬ 맀κ°λ³μμ κ²°κ³Όμ νμ μ΄ κ°λ€. |
BinaryOperator<T> |
R apply(T t, T t) |
BiFunctionμ μμ, BiFunctionκ³Ό λ¬λ¦¬ 맀κ°λ³μμ κ²°κ³Όμ νμ μ΄ κ°λ€. |
λ©μλ μ°Έμ‘°
λλ€μμ λμ± κ°κ²°νκ² ννν μ μλ λ°©λ²μ΄ μλ€. νμ ν μ μλ κ²μ μλκ³ λλ€μμ΄ νλμ λ©μλλ§ νΈμΆνλ κ²½μ°μλ 'λ©μλ μ°Έμ‘°(method reference)'λΌλ λ°©λ²μΌλ‘ λλ€μμ κ°λ΅ν ν μ μλ€. μλ₯Όλ€μ΄ λ¬Έμμ΄μ μ μλ‘ λ³ννλ λλ€μμ μλμ κ°μ΄ μμ±ν μ μλ€.
1 | Function<String, Integer> f = (String s) -> Integer.parseInt(s); | cs |
μμ λλ€μμ μλμ κ°μ΄ λμ± κ°λ΅νκ² ν μ μλ€.
1 2 | // λ©μλ μ°Έμ‘° Function<String, Integer> f = Integer::parseInt; | cs |
λλ€μ μΌλΆκ° μλ΅λμμ§λ§, μ»΄νμΌλ¬λ μλ΅λ λΆλΆμ μ°λ³μ parseIntλ©μλμ μ μΈλΆλ‘λΆν°, λλ μ’λ³μ FunctionμΈν°νμ΄μ€μ μ§μ λ μ§λ€λ¦ νμ μΌλ‘λΆν° μ½κ² μμλΌ μ μλ€.
ν κ°μ§ μλ₯Ό λ λ€μ΄μ μλμ λλ€μμ λ©μλ μ°Έμ‘°λ‘ λ³κ²½ν΄λ³΄μ.
1 | BiFunction<String, String, Boolean> f = (s1, s2) -> s1.equals(s2); | cs |
μ°Έμ‘°λ³μ fμ νμ λ§ λ΄λ λλ€μμ΄ λ κ°μ String νμ μ 맀κ°λ³μλ₯Ό λ°λ λ€λ κ²μ μ μ μμΌλ―λ‘, λλ€μμ 맀κ°λ³μλ€μ μμ΄λ λλ€. μμ λλ€μμμ 맀κ°λ³μλ€μ μ κ±°ν΄μ λ©μλ μ°Έμ‘°λ‘ λ³κ²½νλ©΄ λλ€.
λ©μλ μ°Έμ‘°λ₯Ό μ¬μ©ν μ μλ κ²½μ°κ° ν κ°μ§ λ μλλ°, μ΄λ―Έ μμ±λ κ°μ²΄μ λ©μλλ₯Ό λλ€μμμ μ¬μ©ν κ²½μ°μλ ν΄λμ€ μ΄λ¦ λμ κ·Έ κ°μ²΄μ μ°Έμ‘°λ³μλ₯Ό μ μ΄μ£Όμ΄μΌ νλ€.
1 2 3 4 | MyClass obj = new MyClass(); Function<String, Boolean> f = (x) -> obj.equals(x); // λλ€μ Function<String, Boolean> f2 = obj::equals; // λ©μλ μ°Έμ‘° | cs |
3κ°μ§ λ©μλ μ°Έμ‘° μ νμ μ 리ν΄λ΄€λλ° νλ‘ μ 리νλ©΄ λ€μκ³Ό κ°λ€.
μ’ λ₯ |
λλ€ |
λ©μλ μ°Έμ‘° |
static λ©μλ μ°Έμ‘° |
(x) -> ClassName.method(x) |
ClassName::method |
μΈμ€ν΄μ€λ©μλ μ°Έμ‘° |
(obj.x) -> obj.method(x) |
ClassName::method |
νΉμ κ°μ²΄ μΈμ€ν΄μ€λ©μλ μ°Έμ‘° |
(x) -> obj.method(x) |
obj::method |
μ°Έκ³ μλ£ : μλ°μ μ μ 3rd