Notice
Recent Posts
Recent Comments
Link
«   2025/10   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

내로그

람다식(Lambda) 본문

WEB/Java

람다식(Lambda)

Kotato 2022. 8. 23. 14:36

람다식이란?

람다식
함수(메소드)를 간단한 식으로 표현하는 방법

(타입 매개변수,...) -> { 실행문 }

 

표현방법
1. 메서드의 이름과 반환타입을 제거하고 -> 를 블록 {} 앞에 추가한다.
2. 반환값이 있는 경우 , 식이나 값만 적고 return 문 생략 가능 (끝에 ; 안 붙임)
3. 매개변수의 타입이 추론 가능하면 생략가능(대부분의 경우 생략가능)
4. 매개변수가 하나인 경우, 괄호() 생략 가능(타입이 없을때만)
5. 블록 안의 문장이 하나 뿐 일때, 괄호{} 생략가능(끝에 ; 안붙임)
   단, 하나뿐인 문장이 return 문이면 괄호{} 생략뷸가

*람다식은 익명객체

자바는 람다식을 함수적 인터페이스(메소드를 1개만 가지고있는)의 익명 구현 객체로 취급

 

Runnable runnable = new Runnable(){
	public void run(){...}
}

// 람다식
Runnable runnable = () -> {...}

타겟타입

-람다식이 대입되는 인터페이스

-익명 구현 객체를 만들 때 사용할 인터페이스

인터페이스(타겟타입) 변수 = 람다식;

 

함수적 인터페이스( functional interface )

- 하나의 추상 메소드만 선언된 인터페이스

@FunctionalInterface 어노테이션

-하나의 추상메소드만 가지는 컴파일러가 체크함

-두개 이상의 추상 메소드가 선언되어 있으면 컴파일 오류

@FunctionalInterface
public interface MyFunctionalInterface {
    public void method();
}
public class MyFunctionalInterfaceTest {
    public static void main(String[] args){

        MyFunctionalInterface fi = () -> System.out.println("Hello");
        fi.method();
    }
}

 

클래스의 멤버 사용

-람다식 실행 블록에는 클래스의 멤버인 필드와 메소드를 제약 없이 사용할 수 있다.

-람다식 실행 블록내에서 this는 람다식을 실행한 객체의 참조이다.

public class ExampleTest {
    public int outerField = 10;

    class Inner {
        int innerField =20;

        void method(){
            //람다식
            MyFunctionalInterface fi = () -> {
                // 바깥 객체 참조 클래스명.this
                System.out.println("outerField: "+ ExampleTest.this.outerField);
                // 람다식 내부 this 는 Inner 객체 참조
                System.out.println("innerField: "+ this.innerField); 
            };
            fi.method();
        }
    }

 

*로컬 변수의 사용

-람다식은 함수적 인터페이스의 익명 구현 객체를 생성한다.

-람다식에서 사용하는 외부 로컬 변수는 final 특성을 갖는다.

public class UsingLocalVariable {
    void method(int arg){
        int localVar = 40;
        
        // arg , localVar 은 람다식에서 사용하고 있기 때문에 final 특성을 가짐
        // 수정 불가

        MyFunctionalInterface fi = () -> {
          System.out.println("arg: "+ arg);
          System.out.println("localVar: "+ localVar);
        };
        
        fi.method();
    }
}

 

*한 개의 추상 메소드를 가지는 인터페이스들은 모두 람다식 사용 가능

public class LambdaExample {
    
    public static void main(String[] args){
        
        Runnable runnable = ()->{
            for(int i=0; i<10; i++){
                System.out.println(i);
            }
        };
        
        // 1
        Thread thread = new Thread(runnable);
        thread.start();
        
        //2
        Thread thread2 = new Thread(()->{
           for(int i=0;i<10;i++){
               System.out.println(i);
           }
        });
    }
}

Runnable 은 run() 이라는 하나의 추상메소드를 가지므로 람다식 사용 가능

 

*자바 8부터 표준 API로 제공되는 함수적 인터페이스

- Consumer : 매개값만 있고 리턴값이 없는 추상 메소드( accept() )를 가지고 있다.

- Supplier : 매개값은 없고 리턴값만 있는 추상 메소드( get() )를 가지고 있다.

- Function : 매개값과 리턴 값이 모두 있는 추상 메소드( apply() )를 가지고 있다.

                     주로 매개값을 리턴값으로 매핑(타입변환)할 경우에 사용

- Operator : 매개값과 리턴 값이 모두 있는 추상 메소드( apply() )를 가지고 있다.

                     주로 매개값을 연산하고 그 결과를 리턴할 경우 사용

- Predicate : 매개값을 조사해서 true 또는 false를 리턴할 때 사용( test() )

 

andThen() 과 compose() 디폴트 메소드

- 함수적 인터페이스가 가지고 있는 디폴트 메소드이다.

- 두개의 함수적 인터페이스를 순차적으로 연결해서 실행한다.

- 첫번째 리턴값을 두번째 매개값으로 제공해서 최종 결과값을 리턴한다.

- andThen() 과 compose()의 차이점은 어떤 함수적 인터페이스부터 처리하냐이다.

 

메소드 참조

- 메소드를 참조해서 매개변수의 정보 및 리턴타입을 알아내어

  람다식에서 불필요한 매개변수를 제거하는 것이 목적이다.

 

- 기존 메소드를 단순하게 호출만 하는경우

( string ) -> System.out.println( string );

System.out :: println ----- 이렇게 표현하는게 메소드 참조다.

 

-메소드 참조도 람다식과 마찬가지로 인터페이스의 익명 구현 객체로 생성됨

타겟 타입에서 추상 메소드의 매개변수 및 리턴 타입에 따라 메소드 참조도 달라진다.

 

public class Calculator {
    String name;
    public static int staticAdd(int num1, int num2){
        return num1+num2;
    };

    public int instanceAdd(int num1, int num2){
        return num1 + num2;
    };

    public Calculator(String name){
        this.name = name;
    }

    public static void main(String[] args){
        IntBinaryOperator operator;

        Function<String,Calculator> function = Calculator::new; // 생성자 참조
        Calculator calculator = function.apply("참조");

        operator = (num1,num2)->Calculator.staticAdd(num1,num2);
        operator = Calculator::staticAdd; // static 메소드 참조

        operator = (num1,num2)->calculator.instanceAdd(num1,num2);
        operator = calculator::instanceAdd; // instance 메소드 참조
    }
}

 

'WEB > Java' 카테고리의 다른 글

Java Stream(스트림) 중간처리, 최종처리 메소드  (0) 2022.08.25
Java Stream(스트림) 파이프라인  (0) 2022.08.24
Java Stream(스트림)  (0) 2022.08.24