Java / / 2023. 1. 31. 00:34

[Java] 람다식과 작성 방법 - 함수형 인터페이스 사용 (매개변수, 반환타입)

반응형

 

자바는의 큰 변화

  • JDK 1.5 - 지네릭스(generics)
  • JDK 1.8 - 람다(lambda) : 자바는 객체지향언어 + 함수형 언어

람다식이란?

메서드를 하나의 식(expression)으로 표현한 것이다.

함수를 간략하면서도 명확한 식으로 표현할 수 있게 해준다.

메서드를 람다식으로 표현하게 되면 메서드의 이름과 반환값이 없어지므로, 람다식을 '익명 함수(anonymous function)'이라고도 한다.

 

int[] arr = new int[5];
Arrays.setAll(arr, (i) -> (int)(Math.random()*5)+1);

----------------------------------------------------

int method() {
	return (int)(Math.random()*5)+1;
}

 

람다식은 메서드의 매개변수로 전달되는 것이 가능하고, 메서드의 결과로 반환될 수도 있다. 이로 인해 메서드를 변수처럼 다루는 것이 가능해진 것이다.


람다식 작성방법

기존 메서드

int test (int a, int b) {
	return a > b ? a : b;
}

 

  1. 이름과 반환타입 제거 + 매개변수 선언부와 몸통{ } 사이에  -> 추가
  2. 반환값이 있는 메서드의 경우, return문 대신 식(expression)으로 대신할 수 있다. ('식'은 끝에 ';'을 붙이지 않는다.)
  3. 매개변수의 타입은 추론이 가능한 경우 생략 가능하다.
  • 참고로 선언된 매개변수가 하나뿐인 경우 괄호()를 생략할 수 있다. 하지만 매개변수의 타입이 있으면 생략 불가.
  • 또한 괄호{ } 안의 문장이 하나일 경우 괄호{ } 생략이 가능하다. 하지만 문장 끝에 ':'를 붙이지 않는다.

람다식으로 변경

(a, b) -> a > b ? a : b

람다식 = 익명 객체

람다식은 익명 함수가 아니라 익명 객체이다.

  • 따라서 람다식(익명 객체)을 다루기 위해서는 참조변수가 필요하다.

아래의 예를 살펴보자.

 

Objcet obj = new Object() {
	int max(int a, int b) {
    	return a > b ? a : b;
    }
}
//Object obj = (a, b) -> a > b ? a : b; //람다식 익명 객체 사용 - 어떤 타입인가?

int value = obj.max(3,5); // error. Object class에 max()라는 함수가 없다.

 

하지만 해당 코드는 error가 발생한다.  Object class에 max()라는 함수가 없다.

 

해당 문제를 해결하기 위해서는 Type이 필요한데 Object 타입으로는 안된다.

따라서 함수형 인터페이스가 필요하다. 아래에서 살펴보고 변경해 보자.

 

 

 


💡 람다식을 다루기 위한 '함수형 인터페이스' (해결방법)

하나의 메서드가 선언된 인터페이스를 정의해서 람다식으로 다루는 것이 기존의 자바 규칙들을 어기지 않으면서도 가장 자연스러운 방법이다. 

 

람다식(익명객체)을 다루기 위한 참조변수의 타입은 함수형 인터페이스로 해야 한다.

 

  • 단, 함수형 인터페이스에는 오직 하나의 추상 메서드만 정의되어 있어야 한다는 제약이 존재한다.
    •  @FunctionalInterface
    • 람다식과 인터페이스의 메서드가 1:1로 매핑
  • 반면, static메서드와 dafualt메서드의 개수에는 제약이 없다.
@FunctionalInterface//함수형 인터페이스를 올바르게 작성했는지 컴파일러가 확인한다.
interface TestFunction {
    //public abstract int max(int a, int b);//아래와 동일
    int max(int a, int b);
}
--------------------------------------------
//익명클래스(class 선언 + 객체 생성)
TestFunction f = new TestFunction() {
	public int max(int a, int b) {//override - 접근 제어자는 더 좁게 못바꾼다.
    	return a > b ? a : b;
    }
}
//TestFunction f = (a, b) -> a > b ? a : b; //람다식 사용 - 익명 객체

int value = f.max(3, 5);// 익명 객체의 메서드 호출 TestFunction에 max()존재

 

함수형 인터페이스 사용 예제

따라서 아래처럼 복잡했던 인터페이스의 메서드 하나도 간단하게 구현할 수 있다.

 

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

Collections.sort(list, new Comparator<String>() {//함수형 인터페이스 Comparator<T>
	public int compare(String s1, String s2) {
    	return s2.compareTo(s1);
    }
})

------------------------람다식으로 변경----------------------------
List<String> list = Arrays.asList("abc", "aaa", "bbb", "ddd". "aaa");

Collections.sort(list, (s1, s2) -> s2.compareTo(s1));

 

더보기

 참고

Comparator 인터페이스는 다음과 같은 메서드를 사용하여 객체를 정렬합니다.

int compare(T o1, T o2) 전달된 두 객체의 순서를 비교.
boolean equals(Object obj) 해당 comparator와 전달된 객체가 같은지를 확인
default Comparator<T> reversed() 해당 comparator의 역순인 comparator를 반환

함수형 인터페이스 타입의 매개변수 및 반환타입

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

@FunctionalInterface
interface TestFunction {
    void testMethod();
}
------------------------------------------------------
void tMethod(TestFunction f) {
    f.testMethod();//TestFunction에 정의된 메서드 호출
}
------------------------------------------------------
TestFunction f = () -> System.out.println("myMethod()");
tMethod(f);
//위의 두줄을 하나로 합침.
//tMethod(()-> System.out.println("myMethod()");

 

  • 람다식에 이름을 testMethod()라고 붙여주고 그것을 호출하는 것이라고 보면 된다.

 

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

  • 람다식 반환
TestFunction testMethod() {
    TestFunction f = () -> {};
    return f;
    //위 문장을 하나로 합침
    //return () -> {};
}

 

 

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유