함수형 프로그래밍을 하기 위해선 람다 표현식을 알아야 좋다. 람다 함수가 뭔지 알아보자
람다함수란 프로그래밍 언어에서 사용되는 개념으로 익명 함수(Anonymous functions)를 지칭하는 용어이다.
현재 사용되고 있는 람다의 근간은 수학과 기초 컴퓨터과학 분야에서의 람다 대수이고 람다 대수는 간단히 말하자면 수학에서 사용하는 함수를 보다 단순하게 표현하는 방법이다.
람다 함수는 프로그래밍 언어에서 사용되는 개념으로 익명 함수(Anonymous functions)를 지칭하는 용어이다.
장점
- 숙련만 된다면 코드를 간결하게 줄일 수 있다.
- 멀티스레드를 활용하여 병렬처리를 할 수 있다.
- 사이드 이팩트가 없다. → 함수 밖에 있는 값을 변경할 수 없다.
단점
- 너무 많은 코드를 생략하다보니 가독성이 떨어질 수 있다.
1) 내부/로컬클래스
class TestClass {
class LocalClass {
public String hello(String name) {
return name + "님";
}
}
}
2) 익명클래스
public static void main(String[] args) {
WelcomeSomething welcomeSomething = new WelcomeSomething() {
@Override
public String hello(String name) {
return name + "님";
}
};
System.out.println(welcomeSomething.hello("GRYOH") + " Welcome");
}
람다식은 매개변수 + 실행문으로 구성되어 있다
모양은 () -> {} //매개변수 : () , 실행문 : {}
첫 괄호에 인터페이스의 매개변수()를 입력하고 -> 를 입력하고 {}안에 실행할 코드를 작성하면 된다.
@FunctionalInterface
public interface WelcomeSomething {
public String hello(String name);
}
@FunctionalInterface
public interface WelcomeDefaultSomething {
public void hello(String name);
}
WelcomeSomething welcomeSomething = (String name) -> { return name + "님"; };
System.out.println(welcomeSomething.printName("GRY") + " Welcome");
WelcomeSomething welcomeSomething = (name) -> { return name + "님"; };
System.out.println(welcomeSomething.printName("GRY") + " Welcome");
WelcomeDefaultSomething welcomeDefaultSomething = () -> {
System.out.println("임시회원님 Welcome");
};
welcomeDefaultSomething.hello();
WelcomeDefaultSomething welcomeDefaultSomething = () -> System.out.println("임시회원님 Welcome");
welcomeDefaultSomething.hello();
WelcomeSomething welcomeSomething = name -> name + "님";
System.out.println(welcomeSomething.hello("GRYOH") + " Welcome");
익명 내부 클래스로 작성했던 코드보다 훨씬 간결해졌다
공통점
바깥 클래스의 변수나 메서드에 접근할 수 있다.
차이점
1.내부클래스와 람다에서의 this는 다른 의미이다.
int num1 = 1;
// 변수값 변경이 없기 때문에 사실상 final이고 final키워드 생략이 가능하다. (컴파일러가 추론가능)
// 내부클래스(로컬클래스)
class TestClass {
class InnerClass {
int num2 = 2;
public int printNum(int number) {
this.num1 = 3; // 컴파일 에러 - 현재 this는 InnerClass임
this.num2 = 3;
return number;
}
}
}
// 익명클래스
NumberClass nc = new NumberClass() {
int num2 = 2;
@Override
public int printNum(int number) {
this.num1 = 3; // 컴파일 에러-현재 this는 NumberClass임
this.num2 = 3;
return number;
}
};
//람다 표현식
NumberClass nc2 = number -> {
int num1 = 3; // 컴파일 에러 - shadowing 불가
int num2 = 2;
return number;
};
2.람다는 은닉변수(Shadow Variable)를 허용하지 않는다.(shadowing 불가)
int baseNumber = 10; // 사실상 final 변수 (effective final)
class InnerClass {
class LocalClass {
int baseNumber = 20; // shadowing 된 변수
public int printNum(int number) {
return number + baseNumber; // baseNumber => 20
}
}
}
NumberClass ncAnonymousClass = new NumberClass() {
int baseNumber = 20; // shadowing 된 변수
@Override
public int printNum(int number) {
return number + baseNumber; // baseNumber => 20
}
};
NumberClass ncLambda = n -> {
return n + baseNumber; // baseNumber => 10 (1)
};
baseNumber++; // 사실상 final 이기 때문에 값을 변경하면 (1)람다표현식에서 컴파일 에러가 발생한다
// variable used in lambda expression should be final or effectively final 에러 발생
3.람다는 단일 추상함수 인터페이스만 사용할 수 있다.
public interface Greeting {
void hello();
void hi();
}
public static void main(String[] args) {
//multiple non-overriding abstract methods found in interface 에러발생
Greeting greeting = () -> System.out.println("안녕"); //컴파일 에러발생
}