함수형 프로그래밍 기법을 지원하는 자바의 문법요소이다.
메서드를 하나의 '식(Expression)'으로 표현한 것으로, 코드를 매우 간결하면서 명확하게 표현할 수 있다는 큰 장점이 있다.
익명의 객체이다. 때문에 기존 자바의 문법 요소를 해치지 않으면서 함수형 프로그래밍 기법을 사용할 수 있는 장치가 필요했다. 이에 따라 함수형 인터페이스(Functional Interface)가 만들어지게 되었다.
// 기존 방식
void example1() {
System.out.println(5);
}
// 람다식
() -> {System.out.println(5);}
// 기존 방식
int example2() {
return 10;
}
// 람다식
() -> {return 10;}
// 기존 방식
void example3(String str) {
System.out.println(str);
}
// 람다식
(String str) -> { System.out.println(str);}
// 기존 방식
int sum(int num1, int num2) {
return num1 + num2;
}
// 람다식
(int num1, int num2) -> {
num1 + num2
}
// 실행문이 하나만 존재할 때
(int num1, int num2) -> num1 + num2
// 매개변수 타입을 쉽게 유추할 수 있는 경우
(num1, num2) -> num1 + num2
// sum 메서드 람다식
(num1, num2) -> num1 + num2
// 람다식을 객체로 표현
new Object() {
int sum(int num1, int num2) {
return num1 + num1;
}
}
Object클래스에는 sum이라는 메서드가 없기때문에, object타입의 참조변수에 담아도 sum메서드를 사용할 수 없다. 이 문제를 해결하기 위해 '함수형 인터페이스'를 사용한다.public class LamdaExample1 {
public static void main(String[] args) {
Object obj = new Object() {
int sum(int num1, int num2) {
return num1 + num1;
}
};
// 람다식 Object obj = (num1, num2) -> num1 + num2 로 대체 가능
}
public class LamdaExample1 {
public static void main(String[] args) {
/* Object obj = new Object() {
int sum(int num1, int num2) {
return num1 + num1;
}
};
*/
ExampleFunction exampleFunction = (num1, num2) -> num1 + num2;
System.out.println(exampleFunction.sum(10,15));
}
@FunctionalInterface // 컴파일러가 인터페이스가 바르게 정의되었는 지 확인할 수 있도록
interface ExampleFunction {
public abstract int sum(int num1, int num2);
}
// 출력값
25
@FunctionalInterface
public interface MyFunctionalInterface {
public void accept();
}
public class MyFunctionalInterfaceExample {
public static void main(String[] args) throws Exception {
MyFunctionalInterface example;
example = () -> {
String str = "첫 번째 메서드 호출!";
System.out.println(str);
};
example.accept();
example = () -> System.out.println("두 번째 메서드 호출!");
//실행문이 하나라면 중괄호 { }는 생략 가능
example.accept();
}
}
// 출력값
첫 번째 메서드 호출!
두 번째 메서드 호출!
@FunctionalInterface
public interface MyFunctionalInterface {
public void accept(int x);
}
public class MyFunctionalInterfaceExample {
public static void main(String[] args) throws Exception {
MyFunctionalInterface example;
example = (x) -> {
int result = x * 5;
System.out.println(result);
};
example.accept(2);
example = (x) -> System.out.println(x * 5);
example.accept(2);
}
}
// 출력값
10
10
@FunctionalInterface
public interface MyFunctionalInterface {
public int accept(int x, int y);
}
public class MyFunctionalInterfaceExample {
public static void main(String[] args) throws Exception {
MyFunctionalInterface example;
example = (x, y) -> {
int result = x + y;
return result;
};
int result1 = example.accept(2, 5);
System.out.println(result1);
example = (x, y) -> { return x + y; };
int result2 = example.accept(2, 5);
System.out.println(result2);
example = (x, y) -> x + y;
// 실행문이 한 줄인 경우, 중괄호 {}와 return문 생략가능
int result3 = example.accept(2, 5);
System.out.println(result3);
example = (x, y) -> sum(x, y);
// 실행문이 한 줄인 경우, 중괄호 {}와 return문 생략가능
int result4 = example.accept(2, 5);
System.out.println(result4);
}
public static int sum(int x, int y){
return x + y;
}
}
//출력값
7
7
7
7
https://docs.oracle.com/javase/8/docs/api/java/util/function/package-summary.html
기본적으로 내장된 함수형 인터페이스를 사용하여 매번 같은 기능을 수행하는 함수형 인터페이스를 사용하면 매번 같은 기능을 수행하는 함수형 인터페이스를 직접 만드는 번거로움을 줄여준다.
공식 문서를 읽고 공부하는 습관은 효과적인 학습 결과를 준다. 따라서, 습관화 하자.
클래스 :: 메서드참조 변수 :: 메서드//Calculator.java
public class Calculator {
public static int staticMethod(int x, int y) {
return x + y;
}
public int instanceMethod(int x, int y) {
return x * y;
}
}
import java.util.function.IntBinaryOperator;
public class MethodReferences {
public static void main(String[] args) throws Exception {
IntBinaryOperator operator;
/*정적 메서드
클래스이름::메서드이름
*/
operator = Calculator::staticMethod;
System.out.println("정적메서드 결과 : " + operator.applyAsInt(3, 5));
/*인스턴스 메서드
인스턴스명::메서드명
*/
Calculator calculator = new Calculator();
operator = calculator::instanceMethod;
System.out.println("인스턴스 메서드 결과 : "+ operator.applyAsInt(3, 5));
}
}
/*
정적메서드 결과 : 8
인스턴스 메서드 결과 : 15
*/
(a,b) -> {return new 클래스(a,b);};
//생성자 참조 문법
클래스 :: new
//Member.java
public class Member {
private String name;
private String id;
public Member() {
System.out.println("Member() 실행");
}
public Member(String id) {
System.out.println("Member(String id) 실행");
this.id = id;
}
public Member(String name, String id) {
System.out.println("Member(String name, String id) 실행");
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
import java.util.function.BiFunction;
import java.util.function.Function;
public class ConstructorRef {
public static void main(String[] args) throws Exception {
Function<String, Member> function1 = Member::new;
Member member1 = function1.apply("kimcoding");
BiFunction<String, String, Member> function2 = Member::new;
Member member2 = function2.apply("kimcoding", "김코딩");
}
}
/*
Member(String id) 실행
Member(String name, String id) 실행
*/