자바 람다(Labmda) - 1 (람다식, 타겟타입, Functional Interface, 익명 객체)

dykwon·2024년 1월 16일

람다식이란 ?

  1. 함수적 프로그래밍이 부각되고 있는데, 이는 병렬 처리와 이벤트 지향 프로그래밍에 적합하기 때문임
  2. 람다식은 익명 함수를 생성하기 위한 식으로 명령형과 함수지향 언어에 가깝다
// 객체 생성을 통한 구현
Runnable runnable = new Runnable() {
	@Override
    public void run(){
    	// Task
    }
}

// 함수형 인터페이스가 선언된 경우 아래와 같이 람다식으로 호출이 가능
Runnable runnable = () -> {
		// Task
}

람다식 기본 문법

(타입 매개변수 , ...) -> {
		// Task; ....;
}

(int a) -> {System.out.println(a);}
// 타입 없이 사용 가능
(a) -> {System.out.println(a);}
// 매개 변수가 하나인 경우 소괄호 생략
a -> {System.out.println(a);}
// 매개 변수가 없는 경우
() -> { //실행문; }

타겟 타입과 Functional Interface

  1. 람다식은 인터페이스 변수에 대입된다. 즉 람다식은 인터페이스의 익명 구현 객체를 생성한다.
  2. 인터페이스는 직접 인스턴스화 할 수 없기때문에, 구현 클래스가 필요한데, 람다식은 익명 구현 클래스를 생성하고 객체화한다.
  3. 람다식은 대입될 인터페이스 종류에 따라 작성 방법이 달라지기 때문에, 대입될 인터페이스를 람다식의 타겟 타입이라고 한다.

Functional Interface

  1. 람다식이 하나의 메소드를 정의하기 떄문에 두 개 이상의 추상 메소드가 선언된 인터페이스는 람다식을 이용해서 구현 객체를 생성할 수 없다.
  2. 즉 Functional interface에는 하나의 추상 메소드 선언만이 가능하다.
  3. @FunctionalInterface 어노테이션은 함수적 인터페이스를 작성할때 두개 이상의 추상메소드가 선언되지 않도록 컴파일러가 체킹하는 기능
@FunctionalInterface
public interface Interfaze{
	public int method(int x);
}

public class clazz {
	public static void main(String[] args){
    	Interfaze fi;
        fi = (x) -> {return x * 5};
        int i = fi.method(5);
    }
}

클래스의 멤버와 로컬 변수 사용

람다식의 실행 블록에서는 클래스의 멤버(필드 및 메소드)와 로컬 변수를 사용할 수 있다.
여기서, 로컬 변수 사용에는 약간의 주의사항이 따른다. (람다가 익명 객체를 생성하기 때문에, 특성을 똑같이 갖는다.)

  1. 클래스의 멤버 사용
  • 람다식에서 this 키워드를 사용할때는 주의가 필요하다.
  • 일반적으로 익명 객체 내부에서 this는 익명 객체의 참조이지만 람다에서는 람다식을 실행한 객체의 참조이다.
public class UsingThis {
    public int outterField = 10;

    class Inner{
        int innerField = 20; //Inner 클래스 멤버변수.

        void method(){
            //람다식
            MyFunctionalInterface fi = () -> {
                System.out.println("outterField : "+outterField); //10
                System.out.println("outterField : "+UsingThis.this.outterField); //10

                System.out.println("innerField : "+innerField); //20
                System.out.println("innerField : "+this.innerField); //20
            };
            fi.method();
        }

    }
}
  1. 로컬 변수 사용
  • 람다식은 메소드 내부에서 주로 작성되기 때문에 로컬 익명 구현 객체를 생성시킨다.

  • 익명 구현 객체 특성에 따라, 람다식에서 메소드의 매개변수나 로컬 변수를 사용한다면 이 변수는 수정이 불가한 final 특성을 갖는다.

    • 익명 객체는 객체의 사용이 일회성인 경우, 사용하는 객체 생성 방식이다.
    • extends 키워드를 사용하지 않고, 부모 클래스를 new를 통해 생성함으로써 자식 클래스를 구현하거나
    • interface의 내용을 클래스 생성을 통해 코드상에서 바로 구현하는 경우를 말한다.
    // 부모 클래스 (익명 객체 예시)
    class Animal {
        public String bark() {
            return "동물이 웁니다";
        }
    }
    
    public class Main {
        public static void main(String[] args) {
            // 익명 클래스 : 클래스 정의와 객체화를 동시에. 일회성으로 사용
            Animal dog = new Animal() {
                @Override
                public String bark() {
                    return "개가 짖습니다";
                }
            }; // 단 익명 클래스는 끝에 세미콜론을 반드시 붙여 주어야 한다.
    
            // 익명 클래스 객체 사용
            dog.bark();
        }
    }
    // 인터페이스 (익명 구현 객체 예시)
    public interface TactSwitch {
        void onClick();
    }
    
    //인터페이스 SwitchEvent의 익명 구현 객체 
    TactSwitch tactSwitch = new TactSwitch() {
        boolean check = false;
    
        @Override
        public void onClick() {
            if (check) {
                check = false;
                System.out.println("OFF");
            } else {
                check = true;
                System.out.println("ON");
            }
        }
    };
profile
Programmer, who turns ideas into value

0개의 댓글