반응형
Java 8의 특징
- Interface에 default 메서드, static 메서드 사용 가능
- 자바 8 이전까지 Interface의 abstract 메서드는 반드시 클래스에서 구현했어야 함.
- 인터페이스에 absrtact 메서드를 추가했다면, 그 인터페이스를 사용한 모든 클래스에서 그 메서드를 구현했어야 함 (바이너리 호환성 이슈)
- 자바 8이후로 default, static 메서드 사용이 가능
- 자바 8 이전까지 Interface의 abstract 메서드는 반드시 클래스에서 구현했어야 함.
- 람다식 사용 가능, 람다를 이용해서 스트림API 사용 가능(람다는 Java8 기능 중 큰 변화)
- Time, Date 관련한 API 추가
함수형 프로그래밍(Functional Programming)
- 계산을 수학적 함수의 평가로 취급하고, 변경 불가능한 값을 이용
- 함수형 프로그래밍은 순수 함수들로만 작성된다.
- 순수함수 : 입력이 같으면 출력이 항상 같다.
- 함수가 1등 시민
- 1등 시민 : 함수를 변수나 자료구조 안에 담을 수 있고, 함수를 인자로 전달할 수도 있으며, 반환 값으로도 사용할 수 있다.
- 람다와 클로저를 사용할 수 있다. (Stream도 가능)
- 람다 : 익명함수를 의미, 클로저 : 자신이 생성될 때의 scope에서 알 수 있었던 변수를 기억하는 함수
- 즉, 부수 효과가 없는 함수들로만 구축
함수형 프로그래밍의 목적
- 불변 상태 변수를 이용해 부수 효과를 제거
- 모든 것을 객체 취급
- 코드를 간결하게 하여, 가독성을 높임
- 동시성 작업을 보다 쉽고 안전하게 구현
부수 효과?
- 변수를 수정하거나 객체 필드를 설정
- 예외를 던지거나 오류를 내면서 실행을 중단
- 콘솔에 입출력 / 파일 입출력
람다(Lambda)
- 익명 : 함수에 이름이 없다.
- 함수 : 메서드 처럼 특정 클래스에 종속되지 않는다. 파라미터 리스트, 바디, 리턴값을 포함 한다.
- 전달 : 람다 표현식을 메서드의 인자로 전달하거나 변수 값으로 저장할 수 있다.
- 간결성 : 익명 클래스를 처럼 부가 코드를 구현할 필요가 없다
ex 1-1) 일반적인 Java 표현식
Comparator<Integer> comparator = new Comparator<Integer>(){
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
};
ex 1-2) Lambda 표현식
Comparator<Integer> comparator = (o1, o2) -> o2 - o1;
ex 2-1) Runnable 예(일반적인 Java)
public class AsyncHelloWorld {
public static void main(String[] args){
new Thread(new Runnable(){
@Override
public void run() {
System.out.println(“Hello World”);
}
}).start();
}
}
ex 2-2) Runnable 예(Lambda 표현식)
public class AsyncHelloWorld {
public static void main(String[] args){
new Thread(() -> {
System.out.println(“Hello World”);
}).start();
}
}
람다 vs 익명클래스
익명 클래스는 컴파일 시, 서브클래스로 별도의 파일로 컴파일되고, 람다는 기존 클래스에 포함
람다 표현식의 예
- 파라미터 타입지정 Comparator<Long> longComparator = (Long first, Long second) -> Long.compare(first,second);
- 파라미터 타입지정, 문맥에서 유추 Comparator<Long> longComparator = (first, second) -> Long.compare(first,second);
- 파라미터가 한 개인 경우, 파라미터 목록에 괄호 생략 Predicate<String> predicate = t -> t.length() > 10;
- 파라미터가 없는 경우 Callable<String> callable = () -> “noparam”;
- 결과 값이 없는 경우 Runnable runnable = () -> System.out.println(“no return”);
- 코드 블록을 사용할 경우, return을 이용해서 결과 값을 리턴 Operator<Integer> plusOp = (op1,op2) -> { int result = op1 + op2; return result * resutl; }
함수형 인터페이스의 종류
함수형 인터페이스의 Default Method
- negate() : 뒤집기(반대)
- and()
- or()
Predicate<Apple> redApple = a -> a.getColor().equals("red");
// negate() : Predicate 뒤집기
Predicate<Apple> notRedApple = redApple.negate();
// and() : red & weight > 150
Predicate<Apple> redHeavyApple = redApple.and(a -> a.getWeight() > 150);
andThen()과 compose() Default Method
- consumer, Function, Operator 함수형 인터페이스는 andThen()과 compose() 디폴트 메서드를 가진다.
- 두 개의 함수형 인터페이스를 순차적으로 연결하여 실행.
- andThen()은 앞에 있는 함수형 인터페이스를 먼저 실행하며, compose()는 뒤에 있는 함수형 인터페이스를 먼저 실행한다.
Method Reference 종류
- 메서드 참조의 목적 : 메서드를 참조해서 매개변수의 정보 및 리턴 타입을 알아내, 람다식에 불필요한 매개변수를 제거(간결하게)
정적 메서드 참조 | 클래스명::정적메서드명 |
객체 메서드 참조 | 객체변수::메서드명 |
람다인자 객체 메서드 참조 | 클래스명::메서드명 |
생성자 참조 | 클래스명::new |
함수형 인터페이스 요약
- 람다 표현식은 익명클래스를 간결하게 표현할 수 있다. (약간은 다르다)
- 함수형 인터페이스는 추상 메서드 하나만 정의된 인터페이스이다.
- Java에서는 자주 사용되는 기본적인 형태의 함수형 인터페이스를 제공한다.
- 기본 제공되는 함수형 인터페이스는 Boxing을 피할 수 있도록 IntPredicate, IntToLongFunction과 같은 primitive 타입의 인터페이스를 제공한다.
- 메서드 레퍼런스를 이용하면 기존의 메서드 구현을 재사용 및 전달 가능하다.
- Comparator, Predicate, Function 같은 함수형 인터페이스는 람다 표현식을 조합 할 수 있는 다양한 디폴트 메서드를 제공한다
반응형
'BE > Java' 카테고리의 다른 글
[JMeter] JMeter 사용 및 설치 방법 (0) | 2024.05.06 |
---|---|
[Java 8] Stream, 데이터 리듀싱 (1) | 2024.03.24 |
[Java] Reflection? (0) | 2023.12.25 |
[Java] Jacoco 간단하게 사용해보기 (Maven) (0) | 2023.07.08 |
[Mockito] ArgumentCaptor (0) | 2023.05.29 |