본문 바로가기
프로그래밍 언어

람다식

by do_ng 2021. 3. 7.

메서드를 간단하게 표현한 식 

 

자바에서 함수적 프로그래밍을 위해 자바8부터 람다식을 지원하면서 기존의 자바 코드가 간결해지게 되었다. 

 

예시) 

 

1.일반 메서드 

public int max(int a,int b){
        return a < b ? a : b;
    }

 

2.람다식 사용 메서드 

(int a,int b) -> a < b ? a : b;

 

일반적으로 메서드를 호출하기 위해서는 메서드가 클래스에 포함되어 있어야 하므로 클래스로부터 객체를 생성함으로써 메서드를 호출할 수 있다. 그러나 람다식을 사용하면 클래스를 생성하지 않고도 간단하게 호출할 수 있다. 

 

람다식의 경우 런타임시 인터페이스의 익명 객체로 생성되므로 단순히 메서드가 생성되는 것이 아니라 메서드를 포함하고 있는 익명객체를 생성한다. 

 

 

익명 객체 생성시 문제점)

 Object obj1 = new Object() {
                int max(int a,int b){
                    return a > b ? a:b;
                }
            };

            int value_1 = obj1.max(3,5);

-> 위와 같이 익명 객체안에 새로운 메서드를 추가한 다음 Object 타입으로 익명 객체를 다룰 참조변수를 생성하고 

해당 참조변수로 새롭게 만든 메서드를 호출 할 수 없다. 왜냐하면 Object 클래스에는 'max' 라는 메서드가 없기 때문이다. (자식 객체를 생성 했어도 부모타입으로 받으면 부모 클래스에 있는 메서드만 사용가능 만약에 부모에 있는 메서드를 자식 클래스에서 오버라이딩 했다면 자식 메서드를 호출함) 

 

 Object obj = new Object() {
                public String toString() {
                    return super.toString();
                }
            };

            String value = obj.toString();

-> Object 클래스에는 toString() 메서드가 있기 때문에 호출 하는 것이 가능하다. 

 

함수적 인터페이스)

인터페이스 변수 = 람다식; 

-> 인터페이스 자체로는 객체화가 불가능하기 때문에 인터페이스를 구현한 클래스가 필요한데, 람다식은 익명 구현 클래스를 생성하고 객체화를 한다. 

 

모든 인터페이스를 람다식의 타겟 타입(람다식이 대입될 인터페이스) 으로 사용할 수 없다. 

람다식이 하나의 메서드를 정의하기 때문에 두개 이상의 추상 메서드가 선언된 인터페이스는 람다식을 이용해서 객체를 생성할 수 없다. 즉, 함수형 인터페이스에는 오직 하나의 추상 메서드만 정의되어 있어야지 람다식과 인터페이스의 메서드가 1:1로 연결이 될 수 있다. 

 

함수적 인터페이스를 작성할 때 두 개 이상의 추상 메서드가 선언되지 않도록 컴파일러가 체킹해주는 기능이 있는데, 인터페이스 선언시 @FunctionalInterface 어노테이션을 붙여주면 된다.

(두개 이상의 추상 메서드가 선언되면 컴파일 오류를 발생시킨다.) 

 

@FunctionalInterface 예시) 

@FunctionalInterface
interface MyFunction{
   // public abstract 생략 가능 
    int max(int a,int b);
    int plus(int a,int b);
}

두 개 이상의 추상 메서드가 선언이 되었으므로 @FunctionalInterface 의해 컴파일 오류가 발생한다. 

@FunctionalInterface 를 붙이는 것은 선택사항이다. 이 어노테이션을 붙이지 않더라도 하나의 추상 메서드만 있다면 함수적 인터페이스로 사용할 수 있다. 

 

 

매개 변수와 리턴값이 없는 람다식) 

 

1. 매개 변수와 리턴값이 없는 추상 메서드를 가진 함수적 인터페이스 만들기 

@FunctionalInterface
interface MyFunction_1 {
    public void method();
}

 

2. 람다식으로 메서드 호출하기 

 // 방법1 
 MyFunction_1 mf = () -> {
                System.out.print("Method call 방법 1");
            };
          
// 방법2 
// 실행문이 하나일 경우 {}(중괄호) 생략 가능             
MyFunction_1 mf2 = () -> System.out.print("Method call 방법 1");
mf.method();

-> 아래 3번과 같이 람다식은 메서드를 생성하기 위해서 내부적으로 익명 객체를 만들게 된다.  

 

3. 직접 익명 객체를 만든후 메서드 호출하기 

 MyFunction_1 mf1 = new MyFunction_1() {
                @Override
                public void method() {
                    System.out.print("Method call 방법 2");
                }
            };

            mf1.method();

 

매개 변수가 있고 리턴값이 없는 람다식)

 

1. 매개 변수만 있고 리턴값이 없는 추상 메서드를 가진 함수적 인터페이스 

@FunctionalInterface
interface MyFunction_1 {
    public void method(int x);
}

 

2. 람다식으로 메서드 호출하기 

 MyFunction_1 mf;

// 방법 1
mf = (x) -> {
    int result = x * 5;
    System.out.print(result);
};
mf.method(3);

// 방법 2 (매개 변수가 하나일 경우에는 괄호 생략이 가능) 
mf = x -> System.out.println(x*5);
mf.method(3);

-> 내부적으로 함수적 인터페이스를 implements 해서 익명 객체를 만들게 되므로 메서드를 호출할 수 있다. 

 

매개변수와 리턴값이 있는 람다식)

 

1. 매개 변수와 리턴값이 있는 추상 메서드를 가진 함수적 인터페이스 

@FunctionalInterface
interface MyFunction_1 {
    public int method(int x,int y);
}

 

2. 람다식으로 메서드 호출하기 

MyFunction_1 mf;

// 방법 1
mf = (x,y) -> {
    return x + y;
};
System.out.println(mf.method(3,5));

// 방법 2 (return만 있을 경우 중괄호와 return문 생략가능)
mf = (x,y) -> x + y;
System.out.println(mf.method(3,5));

 

Predicate 함수적 인터페이스 ) 

 

- 매개 변수와 Boolean 리턴값이 있는 test(T t) 메서드를 가지고 있음 

- Predicate<T> 인터페이스를 타겟 타입을 하는 람다식 작성 방법 ) 

1. test() 메서드는 매개값으로 T 객체 하나를 가지므로 람다식도 한 개의 매개 변수를 사용함 

2. test() 메서드의 리턴 타입이 Boolean이므로 람다식 중괄호의 리턴값은 Boolean이 된다. 

 

'프로그래밍 언어' 카테고리의 다른 글

자바스크립트 입문 1 (async,defer)  (0) 2021.05.20
websocket  (0) 2021.03.16
쓰레드  (0) 2021.03.04
타입 지정시 연산 속도  (0) 2021.02.26
자바 스터디(예외)  (0) 2021.02.24