/ JAVAJUNGSUK

Ch14-5~6. 함수형 인터페이스

자바의 정석 기초편

0. 목차



Chapter14. 람다와 스트림

Ch14 - 5. 함수형 인터페이스(Functional Interface)

Ch14 - 6. 함수형 인터페이스 타입 매개변수, 반환타입



Ch14 - 5. 함수형 인터페이스(Functional Interface)


▶ 함수형 인터페이스(Functional Interface)란?

▷ 단 하나의 추상 메서드만 선언 된 인터페이스
interface MyFunction {
    public abstract int max(int a, int b); // 추상 메서드 하나 → 함수형 인터페이스
}

// 함수형 인터페이스는 @FunctionalInterface 애너테이션 붙이기 → 올바로 작성했는가 확인 해 줌
@FunctionalInterface
interface MyFunction {
public abstract int max(int a, int b);
}

// 구현하면?
// 익명 클래스이지만 위에 함수형 인터페이스 생성 했기 때문에 Object 타입 아닌 MyFunction 타입
MyFunction f = new MyFunction() { // new 조상 이름(클래스나 인터페이스) { 멤버 }
    public int max(int a, int b) {
        return a > b; a : b;
    }
};

// 호출하면?
int value = f.max(3, 5) // OK, f에도 max()있고, MyFunction(리모콘)에 max() 있으니까

// int value = obj.max(3, 5) // ERROR, obj에 max() 있지만 Object(리모콘)에는 max() 없어서


▶ 함수형 인터페이스의 타입의 참조변수로 람다식 참조 가능

▷ 단, 함수형 인터페이스의 메서드
람다식의 매개변수 개수와 반환타입이 일치해야 함
MyFunction f = (a, b) -> a > b ? a : b;

// 위 람다식과 같은 것
MyFunction f = new MyFunction() { // new 조상 이름(클래스나 인터페이스) { 멤버 }
    public int max(int a, int b) {
        return a > b; a : b;
    }
};

int value = f.max(3, 5); // 실제로는 람다식(익명 함수)이 호출


▶ 실습

▷ 함수형 인터페이스 생성


▷ 익명 객체 생성
MyFunction function = new MyFunction() {
    
    @Override
    public int max(int a, int b) { // public : 오버라이딩 시, 접근제어자는 좁게 못바꿈 int max니까 default 보다 커야함
        return a > b ? a : b;
    }
};
▷ 람다식(익명 객체) 생성
▷ 익명 객체로 생성할 때보다 람다식 코드가 훨씬 간결
// 람다식을 다루기 위한 참조 변수의 타입은 함수형 인터페이스
MyFunction f = (a, b) -> a > b ? a : b
▷ 호출
package baek;

class Play3 {
	public static void main(String[] args) {
		
	MyFunction f = (a, b) -> a > b ? a : b;

	int value = f.max(3, 5);
	System.out.println("value : " + value);
	}
}

@FunctionalInterface
interface MyFunction {
	int max(int a, int b);
}

// console
value : 5
▷ 람다식과 함수형 인터페이스



▶ 함수형 인터페이스를 사용한 예

▷ sort
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ccc", "ddd");

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

// ↓↓↓↓ 익명 객체'new Comparator<String>()'를 람다식으로 대체 ↓↓↓↓

@FunctionalInterface
interface comparator<T> {
    int compare(T o1, T o2);
}

List<String> list = Arrays.asList("abc", "aaa", "bbb", "ccc", "ddd");

Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
// sort가 받는 것
sort(List list, Comparator c)

// Comparator c에 람다식 'list, (s1, s2) -> s2.compareTo(s1)'을 넣은 것
Comparator c = (s1, s2) -> s2.compareTo(s1);

// Comparater c를 람다식이 참조 변수로 사용?
// Comparater c도 함수형 인터페이스 였던 것




Ch14 - 6. 함수형 인터페이스 타입 매개변수, 반환타입


▶ 함수형 인터페이스 타입의 매개변수

▷ 람다식을 매개변수로 넣어 호출
@FunctionalInterface
interface MyFunction {
    void myMethod();
}

void aMethod(MyFunction f) {
    f.myMethod(); // MyFunction에 정의 된 메서드 호출, 람다식 사용하려고 이름 붙여 둔 메서드
}

// aMethod에 람다식 넣어서 호출하는 법 
MyFunction f = () -> System.out.println("myMethod()");
aMethod(f);

// ↓↓↓↓ 한 줄로 줄이면? ↓↓↓↓
aMethod( () -> System.out.println("myMethod()"));


▶ 함수형 인터페이스 타입의 반환타입

▷ 람다식을 반환하는 메서드
MyFunction myMethod() {
    MyFunction f = () -> {};
    return f;
}

// ↓↓↓↓ 한 줄로 줄이면? ↓↓↓↓
MyFunction myMethod() {
    return () -> {};
}


▶ 예시

▷ 함수형 인터페이스 생성
▷ 이름이 run()인 메서드
@FunctionalInterface
interface MyFunction {
	void run();  // public abstract void run();
}
▷ 매개변수의 타입이 MyFunction(함수형 인터페이스)인 메서드 생성
static void execute(MyFunction f) {
    f.run();
}
▷ 반환 타입이 MyFunction인 메서드 생성
static MyFunction getMyFunction() { 
    MyFunction f = () -> System.out.println("f3.run()");
    return f;
}

// ↓↓↓↓ 한 줄로 줄이면? ↓↓↓↓
static MyFunction getMyFunction() { 
    return () -> System.out.println("f3.run()");
}
▷ 람다식으로 MyFunction의 run()을 구현
public static void main(String[] args) {
    MyFunction f1 = ()-> System.out.println("f1.run()");
}
▷ 익명 클래스로 MyFunction의 run()을 구현
public static void main(String[] args) {
    MyFunction f2 = new MyFunction() {
        public void run() {   // public을 반드시 붙여야 함
        System.out.println("f2.run()");
        }
    };
▷ getMyFunction() f3에 넣어 놓기
public static void main(String[] args) {
    MyFunction f3 = getMyFunction();
▷ 전체
@FunctionalInterface
interface MyFunction {
	void run();  // public abstract void run();
}

class Ex14_1 {
	static void execute(MyFunction f) { // 매개변수의 타입이 MyFunction인 메서드
		f.run();
	}

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

	public static void main(String[] args) {
		// 람다식으로 MyFunction의 run()을 구현
		MyFunction f1 = ()-> System.out.println("f1.run()");

		MyFunction f2 = new MyFunction() {  // 익명클래스로 run()을 구현
			public void run() {   // public을 반드시 붙여야 함
				System.out.println("f2.run()");
			}
		};

		MyFunction f3 = getMyFunction();

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

		execute(f1);
		execute(()-> System.out.println("run()"));
	}
}

// console
f1.run()
f2.run()
f3.run()
f1.run()
run()