자바는 객체지향 프로그래밍으로써 특정 기능을 수행하기 위해서는 객체를 만들고 객체 내부에 멤버 변수를 선언하고 기능을 수행하는 메서드를 구현하였다.
하지만 Java8부터 자바는 함수형 프로그래밍 방식을 지원하였으며 우리는 이것을 람다식이라고 부른다.
함수형 프로그래밍(Functional Programming: FP)
자바는 Class가 있고 class의 instance변수가 있고, 그 instance 변수를 활용한 method를 만들며 구현을 하지만 람다식은 함수가 있고 함수의 매개변수를 이용한 시행문으로 구성된다.
(매개변수) -> {실행문;}
매개변수를 받아서 실행을 하라는 의미
Example
int add(int x, int y){
return x+y;
}
(int x, int y) -> {return x+y;}
// 매개 변수가 하나인 경우 자료형과 괄호 생략가능
str->{System.out.println(str);}
// 매개변수가 두 개이상인 경우 괄호를 생략할 수 없음
x, y -> {System.out.println(x+y);} //오류
// 실행문이 한 문장인 경우 중괄호 생략 가능
str-> System.out.println(str);
// 실행문이 한 문장이라도 return문(반환문)은 중괄호를 생략할 수 없음
str-> return str.length(); //오류
// 실행문이 한 문장의 반환문인 경우엔 return과 중괄호를 모두 생략
(x, y) -> x+y;
str -> str.length;
함수형 인터페이스는 람다식을 선언하기 위한 인터페이스로 익명 함수와 매개변수만으로 구현되므로 인터페이스는 단 하나의 메서드만을 선언해야한다.
@FunctionalInterface 애노테이션(annotation)을 interface에 추가하여 컴파일러에게 함수형 인터페이스라는 정보를 줘서 2개 이상의 메서드가 선언되는 것을 방지해야한다.
Example
@FunctionalInterface
public interface Add {
int add(int a, int y);
}
MyNumber.java (interface)
package ch03;
@FunctionalInterface
public interface MyNumber {
int getMax(int num1, int num2);
}
MyNumberTest.java
package ch03;
public class MyNumberTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
MyNumber myNumber = (x, y) -> x > y? x : y;
/* 아래와 같이 표현도 가능하다.
MyNumber myNumber = (x, y) -> {
if (x > y)
return x;
else return y;
};
*/
System.out.println(myNumber.getMax(10, 20));
}
}
객체지향 프로그래밍의 프로그래밍 순서는 Interface생성, interface를 구현하는 class생성, 해당 클래스로 instance를 생성하고 사용하는 순서로 진행된다.
반대로 람다식은 객체지향 프로그래밍의 class를 생성하는 과정이 생략되었다. 람다식의 class생성과정이 없어 class가 생성되지 않는다고 생각할 수 있지만 내부적으로는 익명의 class가 생성되어져 프로그램이 돌아가게 된다.
StringConcat.java
package ch04;
@FunctionalInterface
public interface StringConcat {
public void makeString(String s1, String s2);
}
StringConcat.java
package ch04;
public class StringConcatImpl implements StringConcat{
@Override
public void makeString(String s1, String s2) {
// TODO Auto-generated method stub
System.out.println(s1 + ", " + s2);
}
}
StringConcat.java
package ch04;
public class StringConcatTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
String s1 = "Hello";
String s2 = "World";
// 람다식을 사용하지 않은 일반적인 객체지향 프로그래밍 방법!!
// Interface생성, interface를 구현하는 class생성, 해당 클래스로 instance를 생성하고 사용
StringConcatImpl strImpl = new StringConcatImpl();
strImpl.makeString(s1, s2);
// 람다식을 사용한 프로그래밍!!!
StringConcat concat = (s, v)-> System.out.println(s + ", " + v);
concat.makeString(s1, s2);
// 객체지향과 비교했을때 class를 생성하는 과정이 생략되었다.
// class가 생성안된다고 생각을 하겠지만 내부적으로 익명 class가 생성되어지게 된다.
// class생성은 개발자가 직접 프로그래을 하는 과정만 생략된 것이다.
// *람다식 함수형 인터페이스에는 하나의 메서드만 가능!!
}
}
람다식 사용 예시
StringConcat concat2 = (s, v)->System.out.println(s + "," + v ); //System.out.println(i);
concat2.makeString(s1, s2);
람다식을 컴파일할 때 내부적으로 돌아가는 구조
StringConcat concat3 = new StringConcat() {
@Override
public void makeString(String s1, String s2) {
System.out.println( s1 + "," + s2 );
};
concat3.makeString(s1, s2);