-
람다 표현식은 자바 코드가 한 줄 또는 블록 단위로 이루어져 있으며 0개 이상의 매개변수를 갖고 값을 반환할 수 있다.
간단하게 람다는 어떠한 객체도 속하지 않은 익명 메서드와 비슷하다는 것이다.
() -> System.out.println("Hello!");
이처럼 람다 문법은 매개변수, 화살표, 바디로 구분되며, 아래와 같이 표기할 수 있다.
(<Parameters>) -> { <Body> } /* 매개변수(<Parameters>) : 인수(argument)와 마찬가지로 쉼표(,)로 구분된다. 그러나 메서드의 인수와는 다르게 컴파일러가 매개변수의 타입을 추론할 수 있는 경우 매개변수의 타입을 생략할 수 있다. 화살표( -> ) : 화살표는 람다의 매개변수와 람다 바디를 구분하기 위해 사용된다. 바디( <Body> ) : 람다 바디는 단일 표현식 또는 코드 블럭으로 구성된다. 한 줄의 코드로만 작성된 표현식은 중괄호가 필수가 아니며, 계산된 결과는 암시적으로 return문 없이 반환된다. 하나 이상의 표현식으로 작성되는 경우 일반적인 자바 코드 블록을 사용한다. 이때 중괄호로 삼싸져 있으며 값을 반환할 경우, 명시적으로 return을 사용해야 한다. */
람다의 구분은 이것이 끝이다.
이 것을 조합하여 아래처럼 다양한 람다 선언 방법을 사용할 수 있다.
아래의 4가지 코드는 모두 같은 같은 함수이다. (input이 아니라면 true 리턴)
(String input) -> { return input != null; } input -> { return input != null; } (String input) -> input != null; input -> input != null
어떤 방식을 사용할지는 문맥과 개인의 스타일, 선호도에 따라 다르다
사람은 컴파일러처럼 최단 코드를 이해하는 것에 능숙하지 않다.
개발자는 깔끔하고 간결한 코드를 추구해야 하지만, 그렇다고 가장 짧은 코드가 가장 좋은 코드를 의미하는 것 또한 아니다. 어느 정도의 장황함은 코드를 이해하는 것에 도움을 주기도 한다.
메서드 참조
위의 람다 표현식을 생성하는 방법이 하나 더 있다.
바로 메서드 참조(Method reference)로, 새로운 연산자인 인중 콜론 (::)을 사용하는 간결한 문법으로, 기존의 메서드로부터 람다 표현식을 생성하는 대신 기존의 메서드를 참조하여 보다 간소화 하는 역할을 한다.
아래는 람다를 메서드 참조로 변환하여 스트림 파이프라인의 가독성을 개선하는 방법을 보여준다.
List<Customer> customers = ...; //람다 customers.stream() .filter(customer -> customer.isActive()) .map(customer -> customer.getNaem()) .map(name -> name.toUpperCase()) .peek(name -> System.out.println(name)) .toArray(count -> new String[count]); //메서드 참조 customers.stream() .filter(Customer::isActive) .map(Customer::getName) .map(String::toUpperCase) .peek(System.out::println) .toArray(String[]::new);
람다 표현식을 대체하려는 내용과 참조하려는 메서드의 종류에 따라 대략 네가지의 참조 방식의 사용이 가능하다.
1. 정적 메서드 참조
2. 바운드 비정적 메서드 참조
3. 언바운드 비정적 메서드 참조
4. 생성자 참조
1. 정적 메서드 참조 :
정적 메서드 참조는 특정 타입의 정적 메서드를 가르킨다.
가령 Integer에서 사용 가능한 toHexString이 있다.
//람다 Function<Integer, String> asLambda = i -> Integer.toHexString(i); //정적 메서드 참조 Function<Integer, String> asRef = Integer::toHexString;
위에서 보이듯이, 정적 메서드 참조는 일반적으로 ClassName::StaticMethodName 모양으로 사용된다.
2. 바운드 비정적 메서드 참조
바운드 비정적 메서드 참조는, 이미 존재하는 객체의 비정적 메서드를 참조하기 위해 사용된다.
람다 인수는 그 특정 객체의 메서드 참조의 인수로 전달된다.
var now = LocalDate.now(); //기존 객체를 기반으로 한 람다 Predicate<LocalDate> isAfterNowAsLambda = date -> $.isAfter(now); //바운드 비정적 메서드 참조 Predicate<LocalDate> isAfterNowAsRef = now::isAfter; /* 다른 메서드 호출 또는 필드 접근의 반환값을 직접 ::(이중 콜론)연산자와 결합할 수 있어 중간 변수조차 필요치 않다. */ //반환값 바인딩 Predicate<LocalDate> isAfterNowAsRef = LocalDate.now()::isAfter; //정적 필드 바인딩 Function<Object, String> castToStr = String.class::cast;
3. 언바운드 비정적 메서드 참조
언바운드 비정적 메서드 참조는 이름에서 알 수 있듯이, 특정 객체에 바운딩되지 않는다. 대신 타입의 인스턴스 메서드를 참조한다.
//람다 Function<String, String> toLowerCaseLambda = str -> str.toLowerCase(); //언바운드 비정적 메서드 참조 Function<String,String> toLowerCaseRef = String::toLowerCase();
언바운드 비정적 메서드 참조의 일반적인 구문들은 다음과 같은 패턴을 따른다.
ClassName::instanceMethodNmae
이런 종류의 메서드 참조는 정적 메서드 참조와 혼동의 여지가 다분하다.
그러나 언바운드 정적 메서드 참조의 경우 ClassName은 참조된 인스턴스 메서드가 정의된 인스턴스 유형을 나타낸다
4. 생성자 참조
생성자 참조는 정적, 또는 언바운드 정적 메서드 참조와 유사해 보이나 참조된 메서드는 실제 메서드가 아닌 new 키워드를 통해 생성자를 참조한다. 생성자 참조는 일반적으로 ClassName::new 키워드로 사용된다.
//람다 Function<String, Locale> newLocaleLambda = language -> new Locale(language); //생성자 참조 Function<String, Locale> newLocaleRef = Locale::new
'Devloper > 자바JAVA' 카테고리의 다른 글
자바 - 스트림(Stream) (0) 2025.01.23 자바 - 레코드(Record) (0) 2025.01.23 자바 - 함수형 인터페이스 (0) 2025.01.21 댓글