λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

λͺ©λ‘μ΄ μ—†μŠ΅λ‹ˆλ‹€.

[JAVA] λžŒλ‹€μ‹ (Lambda Expression)

πŸ—£ Language/JAVA
    λ°˜μ‘ν˜•

    μžλ°”κ°€ 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    // 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(53);    
    cs


    MyInterface μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜λœ λ©”μ„œλ“œ max()λŠ” λžŒλ‹€μ‹κ³Ό μ„ μ–ΈλΆ€κ°€ μΌμΉ˜ν•œλ‹€. κ·Έλž˜μ„œ μœ„ μ½”λ“œμ˜ 읡λͺ… 객체λ₯Ό λžŒλ‹€μ‹μœΌλ‘œ λŒ€μ²΄ν•  수 μžˆλ‹€.


    1
    2
    3
    4
    MyInterface f = (int a, int b) -> a > b ? a : b;
     
    // μ΅λͺ… κ°μ²΄μ˜ λ©”μ„œλ“œ ν˜ΈμΆœ
    int big = f.max(53);    
    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<StringString, 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

    λ°˜μ‘ν˜•