간결하고 효율적인 함수 정의를 위해 만들어졌다.
익명 구현 객체 (인터페이스 구현 객체) 로 변환
인터페이스가 단 하나의 추상 메소드만 가져야 한다. -> 함수형 인터페이스라고 부르는데, 인터페이스에 @FunctionalInterface라는 어노테이션을 붙이는 경우가 있다. 이 어노테이션은 해당 인터페이스가 함수형 인터페이스 조건에 맞는지 검사해준다. 안 붙여도 상관없으나 유지보수를 위해 붙여주는게 좋다!!
매개변수의 타입을 생략하고 작성할 수 있다.
리턴값이 있는 경우 return을 생략하고 작성할 수 있다.



위 코드의 myfunctionInterface01,02,03의 기능은 같다.
람다식을 활용하면 효율적으로 코드를 작성할 수 있으며,
mymath(참조변수)::print(메소드) 처럼 표현할 수 있다.
이해하기 쉽게 한 줄을 뜯어 살펴보자면,
MyfunctionInterface myfunctionInterface03 = mymath::print;
->
myfunctionInterface03은 MyfunctionInterface라는 인터페이스 타입을 가지고
mymath는 'Mymath' 클래스의 인스턴스를 참조하여 method04를 Mymath의 print 메서드로 오버라이드한다는 뜻이다.
위 예시는 인스턴스 메소드이기 때문에 객체를 생성하고 참조 변수 뒤에 ::기호를 붙이고 메서드 이름을 기술하였지만, 정적 메소드인 경우 참조변수가 아니라 클래스가 들어갈 수 있다.

람다식을 객체를 생성하고 리턴하는 기능으로만 구성된다면 생성자 참조로 대치할 수 있다.
() -> { return new MyMath(); }
위 코드를 생성자 참조로 표현해보면,
MyMath :: new
아까 메서드할 때 했던거랑 비슷한 흐름이다~~
근데 여기서 생성자에 파라미터가 추가 된다면?
(num) -> { return new MyMath(num); }
이런 식으로 만들고 싶지만 불가능 하다....
왜냐면 MyMath를 직접적으로 만들어서 바로 리턴하는 게 아니라
interface의 method()를 통해서 리턴하는 것이기 때문이다.
그니까 위에 코드로 실행하기 위해서는 interface를
interface MyFunctionInterface{
MyMath method(int num);
}
이런 식으로 바꿔주던가 해야한다.
근데 이렇게 수정하는건 OCP에 어긋나 보인다....(개인적인 의견)
고로 이런 상황을 대비해 자바에서는 미리 함수형 인터페이스들을 정의해두었다.
Function<Integer,MyMath> myMathFunction = MyMath::new;
MyMath myMath = myMathFunction.apply(100);
myMath.print(10,20);
위의 코드는 MyMath 클래스 생성자에 100이라는 파라미터를 넣고 print를 한 것이다.
위 코드의 출력값은 다음과 같다.
MyMath 매개변수 하나 생성자
30
대조적으로 다음 두개의 코드는 클래스 생성자에 파라미터를 안넣는 (기존 방법으로 만든) 일반 식과 람다식이다.
MyFunctionInterface myFunctionInterface01 = new MyFunctionInterface() {
@Override
public MyMath method() {
return new MyMath();
}
};
MyMath myMath = myFunctionInterface01.method();
myMath.print(10,20);
MyFunctionInterface myFunctionInterface02 = MyMath::new;
MyMath myMath02 = myFunctionInterface02.method();
myMath02.print(10,20);
다음 코드의 출력값은 다음과 같다.
MyMath 기본생성자
30
MyMath 기본생성자
30