Java 8 시리즈는 인프런 강의를 듣고 정리한 내용이다.
참고 : https://www.inflearn.com/course/the-java-java8/dashboard
더 자바, Java 8 - 인프런 | 강의
자바 8에 추가된 기능들은 자바가 제공하는 API는 물론이고 스프링 같은 제 3의 라이브러리 및 프레임워크에서도 널리 사용되고 있습니다. 이 시대의 자바 개발자라면 반드시 알아야 합니다. 이
www.inflearn.com
람다 표현식
public class Cal {
public static void main(String[] args) {
UnaryOperator<Integer> plus10 = (i) -> i+10;
UnaryOperator<Integer> multiply = (i) -> i*2;
UnaryOperator<Integer> plus5 = (i) -> {
return i+5;
};
System.out.println(plus10.andThen(multiply).apply(2));
}
}
위는 람다 표현식을 활용한 소스코드다.
i는 '매개변수'를 나타내고 매개변수의 타입으로는 UnaryOperator에 Integer로 정의되어 있어 생략이 가능하다.
매개변수가 있을 경우에는 위 i처럼 변수명을 넣어주면 되지만 만약 없을 경우 Supplier와 같이 ()만 표시하면 된다.
다음은 화살표 오른쪽 부분은 매개변수를 활용한 메소드의 동작을 정의하는 '바디'이다.
한 줄로 표현할 때는 괄호와 return을 생략해도 된다. 두 줄 이상일 경우 메소드 정의 방식처럼 화살표 다음으로 괄호를 열고 동작 방식을 정의해주고 괄호를 닫고 세미 콜론으로 마무리하면 된다.
변수 캡처
public class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
foo.run();
}
private void run() {
int baseNumber = 10;
// 람다
IntConsumer printInt = (i) -> {
System.out.println(i + baseNumber);
};
printInt.accept(10);
}
private void oudated_java_run() {
final int baseNumber = 10; //final 생략 가능 java8 부터
// 로컬 클래스
class LocalClass {
void printBaseNumber() {
System.out.println(baseNumber);
}
}
// 익명 클래스
Consumer<Integer> integerConsumer = new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(baseNumber);
}
}
}
}
위와 같이 지역변수(Local variable)로 baseNumber를 선언하면 변수 캡처가 된다. 이 기능은 기존에 내부 클래스와 익명 클래스에서도 쓰이던 기능이다. 캡처가 되면 람다 바디에서 해당 변수를 참조할 수 있게 된다.
java 8 이전에는 final과 함께 지역변수를 선언해야 했지만 java8부터는 final을 생략하더라도 final의 역할을 한다. 즉 변수의 값을 변경할 수 없다. 이를 effective final이라고 한다. 같은 스코프 내에서 변경하고 참조하려고 하면 인텔리제이에서 컴파일 에러로 빨간줄이 뜨는 것을 볼 수 있다.
여기서 중요한 점으로 람다와 나머지 둘의 차이점은 바로 쉐도잉이다.
쉐도잉이란 바깥 scope에서 선언한 변수를 좀 더 작은 scope에서 다시 선언하면 가려지는 것을 말한다.
이 쉐도잉이 람다에는 적용되지 않는다. 왜냐하면 람다의 바디의 scope는 바깥의 메소드 scope과 같은 것으로 취급하기 때문이다. 같은 scope에서 똑같은 변수를 두 개 선언하면 안 되는 원리와 같다.
쉽게 소스코드를 살펴보자.
public class Foo {
public static void main(String[] args) {
Foo foo = new Foo();
foo.run();
}
private void run() {
int baseNumber = 10;
// 람다
IntConsumer printInt = (i) -> {
// 여기서 아래와 같이 baseNumber를 또 선언하는 것이 불가능하다.
// int baseNumber = 5;
// i 대신 baseNumber로 선언하는 것도 불가능하다. 쉐도잉이 안 되기 때문
System.out.println(i + baseNumber);
};
printInt.accept(10);
}
private void oudated_java_run() {
final int baseNumber = 10; //final 생략 가능 java8 부터
// 로컬 클래스
class LocalClass {
void printBaseNumber() {
int baseNumber = 20;
System.out.println(baseNumber); //20이 출력되는 것이 바로 쉐도잉
}
}
// 익명 클래스
Consumer<Integer> integerConsumer = new Consumer<Integer>() {
// integer 변수명을 baseNumber로 바꿔도 동작하는 것이 바로 쉐도잉
@Override
public void accept(Integer integer) {
System.out.println(baseNumber);
}
}
}
}
'언어' 카테고리의 다른 글
[Java] static (0) | 2022.12.17 |
---|---|
[Java] Java8 - 함수형 프로그래밍(5) (0) | 2022.12.04 |
컴파일 언어 vs 인터프리터 언어 (0) | 2022.11.29 |
[Java] 다형성 Ploymorphism (0) | 2022.11.08 |
[Java] Java8 - 함수형 프로그래밍 (3) (0) | 2022.10.22 |