Java 8 Lambda 람다 #2
Intro
Java 8에 새로 도입된 Lambda에 대해서 알아보자.
Java 8 Lambda 강좌 - Java Brains
연습예제 github
람다와 함께 지원되는 functional interfaces
별도의 인터페이스 생성없이 람다표현식을 쉽고 편리하게 사용가능하도록
Java 8 에서 여러 케이스의 functional interface들을 기본 지원해주는데요.
이와 관련해 내용이 잘 정리된 사이트가 있어 link를 아래 첨부합니다.
람다식에서의 Exception 처리
람다식에서 Exception 처리는 어떻게 할까요?
ExeptionExample.java 에서 람다식 호출부분에 Exception을 발생하는 코드를 작성합니다.
Exception 발생 코드
ExeptionExample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
public static void main(String[] args) {
int[] sumeNumbers = { 1, 2, 3, 4, 5 };
int key = 2;
process(sumeNumbers, key, (v, k) -> System.out.println(v / k));
}
private static void process(int[] sumeNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : sumeNumbers) {
consumer.accept(i, key);
}
}
- 결과값
Exception in thread "main" java.lang.ArithmeticException: / by zero
at com.github.moregorenine.lambda.unit2.ExeptionExample.lambda$0(ExeptionExample.java:11)
at com.github.moregorenine.lambda.unit2.ExeptionExample.process(ExeptionExample.java:16)
at com.github.moregorenine.lambda.unit2.ExeptionExample.main(ExeptionExample.java:11)
위와 같이 5line 람다식 실행 중 Exception이 발생했을 때 람다에서는 어떻게 처리해야 할까요?
강의자는 Wrapper로 감싸는 #3 처리방식을 추천합니다. 왜일까요?
개인적인 견해로는 ExeptionExample.java의 코드와 처리 #1, #2, #3을 비교해보면 #3방식은 기존 코드를 수정하지 않았습니다.
람다식 부분을 수정한 것도 아니고, 람다식을 수행하는 interface를 수정한 것도 아닙니다.
그래서 #3방식이 #1, #2 방식에 비해 조금 더 유연한 처리가 가능한 방식이란 생각이 드네요.
시간을 가지고 조금더 곰곰히 생각 해봐야겠네요. 다른 의견이나 보충하고 싶은 내용이 있으시면 댓글 부탁드려요.
Exception 처리 #1 - ExeptionHandlingExample1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
int[] sumeNumbers = { 1, 2, 3, 4, 5 };
int key = 0;
process(sumeNumbers, key, (v, k) -> System.out.println(v / k));
}
private static void process(int[] sumeNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : sumeNumbers) {
try {
consumer.accept(i, key);
} catch (ArithmeticException e) {
System.out.println("ArithmeticException 발생...");
}
}
}
- 결과값
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
Exception 처리 #2 - ExeptionHandlingExample2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static void main(String[] args) {
int[] sumeNumbers = { 1, 2, 3, 4, 5 };
int key = 0;
process(sumeNumbers, key, (v, k) -> {
try {
System.out.println(v / k);
} catch (ArithmeticException e) {
System.out.println("ArithmeticException 발생...");
}
});
}
private static void process(int[] sumeNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : sumeNumbers) {
consumer.accept(i, key);
}
}
- 결과값
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
Exception 처리 #3 - ExeptionHandlingExample3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static void main(String[] args) {
int[] sumeNumbers = { 1, 2, 3, 4, 5 };
int key = 0;
process(sumeNumbers, key, wrapperLambda((v, k) -> System.out.println(v / k)));
}
private static BiConsumer<Integer, Integer> wrapperLambda(BiConsumer<Integer, Integer> consumer) {
return (v, k) -> {
try {
consumer.accept(v, k);
} catch (ArithmeticException e) {
System.out.println("ArithmeticException 발생...");
}
};
}
private static void process(int[] sumeNumbers, int key, BiConsumer<Integer, Integer> consumer) {
for (int i : sumeNumbers) {
consumer.accept(i, key);
}
}
- 결과값
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
ArithmeticException 발생...
Closures 람다식
ClosuresExample.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class ClosuresExample {
public static void main(String[] args) {
int a = 10;
int b = 20;
doProcess(a, new Process() {
@Override
public void process(int i) {
System.out.println(i + b);
b++;
}
});
}
private static void doProcess(int i, Process p) {
p.process(i);
}
}
interface Process {
void process(int i);
}
위의 코드는 오류가 발생한다. 어느 부분에서 왜 날까?
11line 부분에서 아래와 같은 오류가 난다.
Exception in thread "main" java.lang.Error: Unresolved compilation problem:
Local variable b defined in an enclosing scope must be final or effectively final
그 이유는 java의 anonymous class나 람다는 final 이어야만 접근이 가능하다. effectively final은 final 선언이 되어있진 않지만 생략만 됐지 실지적으로 final이란 말이다. 이에 대해 참조로 아래 링크를 추가한다.
java anonymous class 의 final
람다식의 ‘this’ 참조
ThisReferenceExample1.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static void main(String[] args) {
ThisReferenceExample1 thisReferenceExample = new ThisReferenceExample1();
thisReferenceExample.doProcess(10, new Process() {
@Override
public void process(int i) {
System.out.println("value of i is " + i);
System.out.println(this);
}
});
}
private void doProcess(int i, Process p) {
p.process(i);
}
- 결과값
value of i is 10
com.github.moregorenine.lambda.unit2.ThisReferenceExample1$1@7852e922
8line에 this는 누굴 가르키는 것일까? 4line의 Process interface의 인스턴스를 가르킨다.
ThisReferenceExample2.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class ThisReferenceExample2 {
public static void main(String[] args) {
ThisReferenceExample2 thisReferenceExample = new ThisReferenceExample2();
thisReferenceExample.doProcess(10, i -> {
System.out.println("value of i is " + i);
System.out.println(this);
});
}
private void doProcess(int i, Process p) {
p.process(i);
}
}
ThisReferenceExample1의 4line을 람다식으로 변경해보았다.
그러자 this 참조를 사용할 수 없는 컴파일오류가 발생한다.
ThisReferenceExample3.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class ThisReferenceExample3 {
public static void main(String[] args) {
ThisReferenceExample3 thisReferenceExample = new ThisReferenceExample3();
thisReferenceExample.doProcess(10, i -> {
System.out.println("value of i is " + i);
// System.out.println(this); this will not work
});
thisReferenceExample.execute();
}
private void doProcess(int i, Process p) {
p.process(i);
}
private void execute() {
doProcess(10, i -> {
System.out.println("value of i is " + i);
System.out.println(this);
});
}
}
ThisReferenceExample2.java의 람다식을 execute 함수를 생성해서 호출할 경우
1
2
3
4
5
/** Static wrapper for DirectMethodHandle.internalMemberName. */
@ForceInline
/*non-public*/ static Object internalMemberName(Object mh) {
return ((DirectMethodHandle)mh).member;
}
위 함수가 실행되며 ‘this’ 객체 참조가 가능했다.
Related Posts
Java 8 Lambda 람다 #1 link
댓글남기기