Coding/언어-JAVA

JAVA 익명클래스, 람다 #Day8

꿀딴지- 2023. 8. 16. 16:34

익명클래스(inner클래스 중 하나)

  • 객체의 선언과 생성을 동시에 하여 오직 하나의 객체를 생성하고, 단 한 번만 사용되는 일회용 클래스
  • 익명 객체 : 자기 자신을 만드는 클래스의 이름이 없는 객체(클래스 없이 만들어지는 객체) → 1회용 객체(클래스는 여러개의 객체)
  • 익명 자식 객체, 익명 구현 객체(인터페이스를 구현해서 만드는 객체, 인터페이스 타입의 참조변수에 할당할 수 있다.)

 

1. 기존에 정의된 클래스를 활용하여 이름없이 객체 생성 시 오버라이딩하여 사용

  • 객체를 상속해서 다른 클래스로 정의한게 아니고, 그때그때 새로운 익명클래스 객체를 만들어 반환함
public class _01_AnonymousClass1 {
    public static void main(String[] args) {

        Coffee specialCoffee = new Coffee() {
            @Override
            public void order(String coffee) {
                super.order(coffee);
                System.out.println("(귓속말) 딸기 케이크는 서비스예요.");
            }

            @Override
            public void returnTray() {
                System.out.println("(귓속말) 자리에 두시면 제가 치울게요.");
            }
        };
        specialCoffee.order("바닐라 라떼");
        specialCoffee.returnTray();
    }
}

class Coffee {
    public void order(String coffee) {
        System.out.println("주문하신 " + coffee + " 나왔습니다.");
    }

    public void returnTray() {
        System.out.println("커피 반납이 완료되었습니다.");
    }
}

2. 추상클래스를 직접 구현하면서 해당 객체를 바로 전달(return)함

public class _02_AnonymousClass2 {
    public static void main(String[] args) {
        HomeMadeBurger momMadeBurger = getMomMadeBurger();
        momMadeBurger.cook();
        System.out.println("----------------------------");
    }

    public static HomeMadeBurger getMomMadeBurger() {
        return new HomeMadeBurger() {
            @Override
            public void cook() {
                System.out.println("집에서 만드는 엄마표 수제 버거");
                System.out.println("재료 : 빵, 소고기패티, 해시브라운, 양상추, 마요네즈, 피클");
            }
        };
    }
}

abstract class HomeMadeBurger {
    public abstract void cook();
}

3. 함수형인터페이스 사용(익명 구현 객체) @FunctionalInterface

  • 단 하나의 추상 메서드만 선언(람다식과 인터페이스의 메서드가 1:1로 매칭)
  • 메서드를 클래스 내에서 선언하는게 아닌, 클래스 밖에서 선언하여 사용함 (자바는 객체지향이라 무조건 클래스 내에 위치해야 하는데, 함수형인터페이스를 통해 익명 구현 객체의 메서드로 우회해서 처리하는 것임)
public class LamdaExample1 {
    public static void main(String[] args) {
        
        Object obj = new Object() { //람다식을 객체로 표현 // 람다식 Object obj = (num1, num2) -> num1 + num2; 로 대체 가능
            int sum(int num1, int num2) { return num1 + num1;} 
        };

        obj.sum(1, 2); //Error
        //Object 클래스에는 sum이라는 메서드가 없으므로, 
        //Object 타입의 참조변수에 담는다고 하더라도 sum 메서드를 사용할 수 없음 
        //-> 함수형 인터페이스 필요
        
        
        //함수형인터페이스를 사용하여 내부 메서드를 사용하게끔 함
        MyFunctionalInterface example = (x) -> System.out.println(x * 5);
        example.accept(2);
    }
}

@FunctionalInterface
interface MyFunctionalInterface {
    void accept(int x);
}

 

람다식(=익명함수) JDK 1.8이후 사용가능

  • 익명클래스를 함수식으로 표현하는 방식으로 간결한 형태의 코드 뭉치 : 1회성, 리스트에서 많이 사용됨
  • 메서드를 하나의 식으로 표현 → 변수에 할당할 수 있다.
  • 함수형인터페이스만 람다식의 타입으로 사용될 수 있음

반환타입 제거, 메서드명 없음, 중괄호 생략가능(1줄일경우)

(전달값1, 전달값2, …) →{ 코드 }

pubic void print(String s){
	System.out.println(s);
}

s -> System.out.println(s)
//접근제어자, 반환타입, 메서드명 생략, 전달값 타입 생략
//한줄이면 중괄호(세미콜론) 생략

public int add(int x, int y){
	return x+y;
}
(x,y)-> {return x+y} //전달값2개 이상이면 소괄소 생략 불가, 반환값 이으면 중괄호 생략 불가 
(x,y)-> x+y //리턴 생략해도 결과 반환해줌

<함수형 인터페이스와 람다 사용예제>

public class LamdoCalculator {
    public static void main(String[] args) {
        Calculable add = (a,b) -> a + b; //함수형 인터페이스 내 메서드 정의
        Calculable sub = (a,b) -> a - b;

        add.calculate(1,2);     
        operate(add, 10,2); // add를 정의해서 operate 호출(add가 재사용가능함)
        operate((a,b) -> a+b, 2,3); // 이게 최종 형상 (1회성으로 사용할 때 유리)

    }
    //람다식과 값 두개를 받아와서 람다식에 해당하는 연산을 수행 후 출력
    private static void operate(Calculable cal, int a, int b){
        System.out.println(cal.calculate(a,b));
    }

}
@FunctionalInterface
interface Calculable{
    int calculate(int a, int b);
}

'Coding > 언어-JAVA' 카테고리의 다른 글

JAVA 사용자 입출력(Scanner, Printf)  (0) 2023.08.17
JAVA 스트림(Stream) #Day8  (0) 2023.08.16
JAVA 에너테이션 #Day7  (0) 2023.08.12
JAVA 열거형(Enum) #Day7  (0) 2023.08.11
JAVA 예외(try-catch) #Day7  (0) 2023.08.11