# [Java] λžŒλ‹€μ‹ - 2. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ— λŒ€ν•΄
Study Repository

[Java] λžŒλ‹€μ‹ - 2. ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ— λŒ€ν•΄

by rlaehddnd0422

ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ - @FunctionalInterface

단 ν•˜λ‚˜μ˜ 좔상 λ©”μ†Œλ“œλ§Œ μ„ μ–Έλœ μΈν„°νŽ˜μ΄μŠ€ 

interface MyFunction {
	public abstract int max(int a, int b);
}
MyFunction f = new MyFunction(){
		public int max(int a, int b){
        	return a > b ? a : b;
        }
    };

μœ„μ²˜λŸΌ μΈν„°νŽ˜μ΄μŠ€μ— μΆ”μƒλ©”μ†Œλ“œλ‘œ 선언해두면 λžŒλ‹€μ‹μœΌλ‘œ μš΄μ˜λ˜ν•œ κ°€λŠ₯ν•©λ‹ˆλ‹€.

MyInterface f = (int a, int b) -> a > b ? a : b; 
int big = f.max(5, 3);

 

이처럼 MyInterface μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 읡λͺ… 객체λ₯Ό λžŒλ‹€μ‹μœΌλ‘œ λŒ€μ²΄κ°€ κ°€λŠ₯ν•œ μ΄μœ λŠ”, λžŒλ‹€μ‹μ€ μ‹€μ œλ‘œλŠ” 읡λͺ… 객체이고, MyInterface λ₯Ό κ΅¬ν˜„ν•œ 읡λͺ… 객체의 λ©”μ†Œλ“œμ™€ λžŒλ‹€μ‹μ˜ λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…κ³Ό 개수, 그리고 리턴값이 μΌμΉ˜ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

λ”°λΌμ„œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ •μ˜ν•΄μ„œ λžŒλ‹€μ‹μ„ λ‹€λ£¨λŠ” 것이 μΌλ°˜μ μž…λ‹ˆλ‹€.

λžŒλ‹€μ‹μ„ 닀루기 μœ„ν•œ μΈν„°νŽ˜μ΄μŠ€ ➑️ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€
@FunctionalInterface
interface MyFunction {
	public abstract int max(int a, int b);
}
@FunctionalInterfaceλ₯Ό 뢙이면 μ»΄νŒŒμΌλŸ¬κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό μ˜¬λ°”λ₯΄κ²Œ μ •μ˜ν•˜μ˜€λŠ”μ§€ μ•Œλ €μ£ΌκΈ° 떄문에 κΌ­ λΆ™μ΄λŠ” 것이 μ’‹μŠ΅λ‹ˆλ‹€.

+ 참고둜 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ—μ„œ default, static λ©”μ†Œλ“œμ—λŠ” 개수 μ œμ•½μ΄ μ—†μŒ
// κΈ°μ‘΄ 방식
List<String> list = Arrays.asList("abc","aaa","bbb");

Collections.sort(list, new Comparator<String>() {
	public int compare(String s1, String s2) {
    	return s2.compareTo(s1);
    }
});

// λžŒλ‹€μ‹μœΌλ‘œ μ²˜λ¦¬ν•œ 방식 
@FunctionalInterface
interface Comparator<T>(){
	public abstract int compare(T o1, T o2);
}

List<String> list = Arrays.asList("abc","aaa","bbb");
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));

이제 λžŒλ‹€μ‹μœΌλ‘œ μ΄λ ‡κ²Œ κ°„λ‹¨νžˆ μ²˜λ¦¬ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€.


λ§€κ°œλ³€μˆ˜κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μΈ 경우

λ§Œμ•½ λ©”μ†Œλ“œμ˜ λ§€κ°œλ³€μˆ˜κ°€ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μΈ 경우 μ˜λ―Έν•˜λŠ” λ°”λŠ” 이 λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•  λ•Œ λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•˜λŠ” μ°Έμ‘°λ³€μˆ˜λ₯Ό λ§€κ°œλ³€μˆ˜λ‘œ 지정해야 ν•œλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

 

@FunctionalInterface
interface MyInterface {
	public abstract void myMethod();
}

void aMethod(MyInterfcae f){ // λ§€κ°œλ³€μˆ˜μ˜ νƒ€μž…μ΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μΈ λ©”μ†Œλ“œ.
	f.myMethod(); //ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ— μ •μ˜λœ λ©”μ†Œλ“œ 호좜 
} 

MyInterface f = () -> System.out.println("myMethod()");
aMethod(f);

이 λ•ŒλŠ” μ°Έμ‘°λ³€μˆ˜ 없이 λžŒλ‹€μ‹μ„ λ§€κ°œλ³€μˆ˜λ‘œ μ§€μ •ν•˜λŠ” 것 λ˜ν•œ κ°€λŠ₯ν•©λ‹ˆλ‹€.!

aMethod( () -> System.out.println("myMethod()") );

λ¦¬ν„΄νƒ€μž…μ΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ νƒ€μž…μΈ 경우

λ©”μ†Œλ“œμ˜ λ¦¬ν„΄νƒ€μž…μ΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μΈ κ²½μš°μ— 이 ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ 좔상 λ©”μ†Œλ“œμ™€ λ™λ“±ν•œ λžŒλ‹€μ‹μ„ κ°€λ¦¬ν‚€λŠ” μ°Έμ‘°λ³€μˆ˜λ₯Ό λ¦¬ν„΄ν•˜κ±°λ‚˜, λžŒλ‹€μ‹μ„ 직접 λ°˜ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

말이 μ’€ μ–΄λ €μš΄λ° μ˜ˆμ‹œλ₯Ό λ΄…μ‹œλ‹€.

@FunctionalInterface
interface MyFunction {
    public abstract void run();
}

class Example {

    static MyFunction getMyFunction() {
        MyFunction f = () -> System.out.println("f3.run()");
        return f;
    };
	
//	static MyFunction getMyFunction() {
//		return () -> System.out.println("f3.run()");
//    };

    public static void main(String[] args) {
        MyFunction f1 = () -> System.out.println("f1.run()");

        MyFunction f2 = new MyFunction() {
            @Override
            public void run() {
                System.out.println("f2.run");
            }
        };

        MyFunction f3 = getMyFunction(); // λžŒλ‹€μ‹μ„ 직접 λ°˜ν™˜

        f1.run();
        f2.run();
        f3.run(); 
    }
}

 

λžŒλ‹€μ‹μ„ μ°Έμ‘°λ³€μˆ˜λ‘œ λ‹€λ£° 수 μžˆλ‹€ ? 
-> 덕뢄에 μœ„μ™€ 같이 λ©”μ†Œλ“œλ₯Ό 톡해 λžŒλ‹€μ‹μ„ 주고받을 수 있음
-> λ‹€μ‹œ 말해 λžŒλ‹€μ‹μ„ "객체"처럼 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

λ©”μ†Œλ“œκ°€ μ•„λ‹ˆλΌ 객체λ₯Ό μ£Όκ³ λ°›λŠ” 것이라 근본적으둜 달라진 것은 μ—†μ§€λ§Œ, λžŒλ‹€μ‹ 덕뢄에 μ˜ˆμ „λ³΄λ‹€ μ½”λ“œκ°€ 훨씬 더 κ°„κ²°ν•˜κ³  μ΄ν•΄ν•˜κΈ° μ‰¬μ›Œμ‘ŒμŠ΅λ‹ˆλ‹€.


λžŒλ‹€μ‹μ˜ νƒ€μž…, ν˜•λ³€ν™˜

ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ‘œ λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•  μˆ˜λŠ” μžˆμ§€λ§Œ, κ·Έ 말이 곧 λžŒλ‹€μ‹μ˜ νƒ€μž…μ΄ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ˜ νƒ€μž…κ³Ό μΌμΉ˜ν•˜λŠ” 것은 μ•„λ‹™λ‹ˆλ‹€.

  • λžŒλ‹€μ‹ -> "읡λͺ… 객체" -> νƒ€μž…μ΄ μ—†μŒ 
  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€ -> λ‹¨μˆœνžˆ λžŒλ‹€μ‹μ„ μ°Έμ‘°ν•  수 μžˆλŠ” νƒ€μž…λ³€μˆ˜

μ—„λ°€νžˆ λžŒλ‹€μ‹μ—λ„ νƒ€μž…μ€ μžˆμŠ΅λ‹ˆλ‹€λ§Œ, μ»΄νŒŒμΌλŸ¬κ°€ μž„μ˜λ‘œ 이름을 μ •ν•˜κΈ° λ•Œλ¬Έμ— μ•Œ μˆ˜λŠ” μ—†μŠ΅λ‹ˆλ‹€.

κ·Έλž˜μ„œ μ—°μ‚°μžμ˜ μ–‘ λ³€μ˜ νƒ€μž…μ„ μΌμΉ˜μ‹œν‚€κΈ° μœ„ν•΄ μ•„λž˜μ™€ 같이 ν˜•λ³€ν™˜μ΄ ν•„μš”ν•©λ‹ˆλ‹€. 
@FunctionalInterface
interface MyFunction(){
	public abstract void myMethod();
}
MyFunction f = (MyFunction) ( ()-> {} );

λ¬Όλ‘  λžŒλ‹€μ‹μ΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 객체( () -> {} )와 μ™„μ „νžˆ λ™μΌν•˜κΈ° λ•Œλ¬Έμ— μœ„μ™€κ°™μ€ ν˜•λ³€ν™˜μ„ ν—ˆμš©ν•˜μ§€λ§Œ, 이 κ²½μš°μ—λŠ” μƒλž΅ λ˜ν•œ κ°€λŠ₯ν•©λ‹ˆλ‹€.


μ™ΈλΆ€ λ³€μˆ˜λ₯Ό μ°Έμ‘°ν•˜λŠ” λžŒλ‹€μ‹

λžŒλ‹€μ‹μ€ "읡λͺ… 객체", 즉 "읡λͺ… 클래슀"의 μΈμŠ€ν„΄μŠ€μ΄λ―€λ‘œ λžŒλ‹€μ‹μ—μ„œ 외뢀에 μ„ μ–Έλœ λ³€μˆ˜μ— μ ‘κ·Όν•˜λŠ” κ·œμΉ™μ€ 읡λͺ… ν΄λž˜μŠ€μ™€ λ™μΌν•©λ‹ˆλ‹€.

@FunctionalInterface
interface MyFunction {
    void myMethod();
}

class Outer {
    int val = 10;

    class Inner {
        int val = 20;

        void method(int i) {
            int val = 30;
            
            // val = 10 ; -> μ—λŸ¬
            // 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 = " + ++Outer.this.val);
            };
            f.myMethod();
        }
    }
}

class Example {
    public static void main(String[] args) {
        Outer outer = new Outer();
        Outer.Inner inner = outer.new Inner();
        inner.method(10);
    }
}

λžŒλ‹€μ‹ λ‚΄μ—μ„œ μ‚¬μš©ν•˜λŠ” μ§€μ—­λ³€μˆ˜λŠ” μƒμˆ˜λ‘œ κ°„μ£Όλ˜κΈ° λ•Œλ¬Έμ— final이 λΆ™μ§€μ•Šμ•˜μ–΄λ„ μƒμˆ˜λ‘œ κ°„μ£Ό λ©λ‹ˆλ‹€.

μœ„μ˜ 경우 μ§€μ—­λ³€μˆ˜ i와 μ§€μ—­λ³€μˆ˜ val을 λžŒλ‹€μ‹μ—μ„œ μ°Έμ‘°ν•˜κ³  있기 λ•Œλ¬Έμ—, 이 값을 λ³€κ²½ν•˜λŠ” 것을 μ–΄λŠ κ³³μ—μ„œλ„ ν—ˆμš©ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 

ν•˜μ§€λ§Œ μ§€μ—­λ³€μˆ˜κ°€ μ•„λ‹Œ μΈμŠ€ν„΄μŠ€ λ³€μˆ˜μΈ Outer.val, Outter.Inner.val은 μƒμˆ˜λ‘œ κ°„μ£Όλ˜μ§€ μ•ŠμœΌλ―€λ‘œ κ°’μ˜ 변경이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

 


<정리>

  • λžŒλ‹€μ‹μ€ "읡λͺ… ν•¨μˆ˜", "읡λͺ… λ©”μ†Œλ“œ"κ°€ μ•„λ‹Œ "읡λͺ… 객체" μž…λ‹ˆλ‹€.
  • λžŒλ‹€μ‹μ˜ μ°Έμ‘°λ³€μˆ˜λ‘œ ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€λ₯Ό ν™œμš©ν•©λ‹ˆλ‹€.
  • ν•¨μˆ˜ν˜• μΈν„°νŽ˜μ΄μŠ€μ—λŠ” ν•˜λ‚˜μ˜ 좔상 λ©”μ†Œλ“œλ§Œ μ •μ˜ν•  수 μžˆμ§€λ§Œ, default, static λ©”μ†Œλ“œμ—λŠ” 개수의 μ œμ•½μ΄ μ—†μŠ΅λ‹ˆλ‹€.
  • λžŒλ‹€μ‹μ„ μ΄μš©ν•˜μ—¬ μ½”λ“œλ₯Ό κ°„κ²°ν•˜κ²Œ 쀄일 수 μžˆμ—ˆμŠ΅λ‹ˆλ‹€.
  • μ—°μ‚°μžμ˜ μ–‘ λ³€μ˜ νƒ€μž…μ„ μΌμΉ˜μ‹œν‚€κΈ° μœ„ν•΄ ν˜•λ³€ν™˜μ΄ ν•„μš”ν•©λ‹ˆλ‹€.
  • ν•˜μ§€λ§Œ λžŒλ‹€μ‹μ΄ μΈν„°νŽ˜μ΄μŠ€λ₯Ό κ΅¬ν˜„ν•œ 클래슀의 객체와 μ™„μ „νžˆ λ™μΌν•œ κ²½μš°μ—λŠ” 이 ν˜•λ³€ν™˜μ„ μƒλž΅ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • λžŒλ‹€μ‹ λ‚΄μ—μ„œ μ°Έμ‘°ν•˜λŠ” μ§€μ—­λ³€μˆ˜λŠ” μƒμˆ˜λ‘œ κ°„μ£Όλ˜λ―€λ‘œ λžŒλ‹€μ‹ λ‚΄λΆ€μ μœΌλ‘œλ‚˜ μ™ΈλΆ€μ μœΌλ‘œ 변경이 λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€.

λΈ”λ‘œκ·Έμ˜ 정보

Study Repository

rlaehddnd0422

ν™œλ™ν•˜κΈ°