람다식을 처음봤을 때, 뭐 이렇게 멋지고 간단한 표현이 있어..? 했던 기억이 난다.
하지만 사용을 경계하고, 가능하면 지양해야하는 이유를 짚고 가야할 것 같다. (포프TV에서 람다식이라고 검색해서 들어보는 것 추천)
- 람다식은 함수명이 없어서 무명함수라고 하기도하는데, 익명함수(anonymous function)라고 대부분 말함. 일단 여러 인원이 개발하는 환경에서 특정 함수를 찾다가 없으면 새로 만들곤 하는데 람다식을 사용하면 검색도 어렵고, 존재하는지 실제로 코드를 들여다보지 않는 이상 쉽지 않다.
- 디버깅이나 추적에 어려움이 있다.
- 마찬가지로 테스트, 유지보수 어려움..
- 보통 한번만 쓸 것 같을 때 사용하는데, 나중에 쓰게되는 케이스가 발생할 수 있다. 이 때 재사용성을 고려해서 함수를 만들어야 하는 상황이 발생하면 일단 다른 사람이 남의 코드를 다 알고있지는 못하기 때문에 리펙토링 작업에서 빠질수도 있는 것.
추상메소드 1개만을 갖는 인터페이스에 적용이 가능하다! 그 이유는 아래에서!
보통의 경우 다음과 같이 인터페이스를 선언하고 implements 해서 메소드를 구현하고 객체를 선언한다.
public interface A{
void m();
}
public calss AA implements A {
public void m(){
System.out.println("AA");
}
}
public class Test{
public static void main(String[] args){
A a1 = new AA();
}
}
그런데 여기서 아래와 같이 익명 내부 클래스로 표현 가능하다.
public class Test{
public static void main(String[] args){
A a1 = new AA();
A a2 = new A() {
public void m(){
System.out.println("익명 내부 클래스");
}
};
}
}
이걸 한 단계 더 나아가서 람다식으로 바꾸면 다음과 같다.
객체를 선언하는 new A() 부분과 메소드가 하나만 있다는 것을 이미 알기 때문에, public void m까지 생략하고
다음과 같이 표현해준다.
public class Test{
public static void main(String[] args){
A a1 = new AA();
A a2 = new A() {
public void m(){
System.out.println("익명 내부 클래스");
}
};
A a3 = () -> {
System.out.println("람다식");
}
//호출
a1.m();
a2.m();
a3.m();
}
}
public interface A{
void m();
}
public interface B{
void m(String str);
}
public interface C{
String m();
}
public interface D{
int m(int x, int y);
}
람다식을 표현하면 다음과 같다.
public class Test{
public static void main(String[] args){
A a = () -> {
System.out.println("A");
}
B b = (str) -> {
System.out.println(str);
}
C c = () -> {
return "C";
}
D d = (x, y) -> {
return x+y;
}
}
}
+ 추가로 단축이 가능하다
public class Test{
public static void main(String[] args){
A a = () ->
System.out.println("A"); //1줄이면 중괄호는 생략할 수 있다.
B b = str ->
System.out.println(str); //파라미터가 1개면 괄호를 생략할 수 있다.
C c = () -> "C"; // return도 생략가능.
D d = (x, y) -> x+y; //파라미터 2개이상이면 괄호 생략 불가능.
}
}
마지막으로 내가 람다식으로 사용할 인터페이스라면 @FunctionalInterface 라고 어노테이션을 붙여주는게 좋다.
이걸 붙이면 더이상 추상 메소드를 추가할 수 없기 때문!
@FunctionalInterface
public interface A{
void m();
}
java.util.function 패키지에 이미 인터페이스들이 대부분 정의가 되어있으니 참고~
https://docs.oracle.com/javase/9/docs/api/java/util/function/package-summary.html