람다식

jaegeunsong97·2023년 1월 21일
0
post-thumbnail

2023_1_21_TIL

객체지향 구조 내에서 람다식 적용 과정

  • 함수 -> 기능 또는 동작을 정의
  • 메소드 -> 클래스 또는 인터페이스내에 정의된 함수
  • 하나의 추상 메소드만 포함하는 인터페이스 -> 함수형 인터페이스
    • 함수형 인터페이스의 호출 및 기능을 구현하는 방법을 새롭게 정의한 것 '람다식'
    • 람다식을 사용하면 독립적으로 정의한 함수를 호출만 하면 공통기능 사용
    • 람다식은 기존의 OPP안에서 함수형 FP를 가능하게 하는 기법
interface A {
	void abc();
}
class B implements A {
	@Override
    public void abc() {System.out.println("메소드 내용 1");}
}
public class RefOfClassConstructor_2 {
    public static void main(String[] args) {
    	// 방법 1
    	A a1 = new B();
        a1.abc();
        
        // 방법 2 -> 익명 이너클래스 사용
        A a2 = new A() {
        	@Override
            public void abc() {System.out.println("메소드 내용 2");}
        }
        a2.abc();
        
        // 방법 3 -> 람다식 사용(함수형 프로그래밍 FP)
        A a3 = () -> {System.out.println("메소드 내용 3");
        a3.abc();
  • 람다식은 익명 이너클래스의 축약된 형태
    • 하나의 추상 메소드만을 가진 FP만 람다식으로 구현
      • 이유는 익명 이너클래스의 축약된 형태이기 때문에(2개이상 이면 어떤 메소드를 구현하는 것인지 구분을 못함)

람다식의 기본 문법 및 약식 표현

  • 람다식의 기본 문법
    • (소괄호) -> {중괄호}
  • 람다식의 약식 표현
    • {실행문1개} = 실행문1개(2개이상은 X)
    • 입력매개변수 자료형은 생략 가능 -> FP에 포함된 추상 메소드의 입력매개변수 타입으로 유추 가능
      • (입력매개변수1개) = 입력매개변수1개(소괄호 생략시 매개변수의 자료형 생략)
    • return문 1개 return 생략(중괄호도 생략)

구현 메소드의 약식표현

  • 람다식의 사용
    • 익명 이녀 클래스 내부 구현 매소드의 약식 표현
    • 참조의 의미 -> 함수형 인터페이스의 메소드를 구현하는 데 있어 구현대신, 이미 있는 기능을 가져다 사용하겠다는 것
    • 메소드 참조
      • 즉, 구현 메소드의 약식표현은 함수형 인터페이스의 추상메소드를 직접 구현했을 때, 메소드 참조는 이미 있는 메소드로 대체했을 때인 것.
    • 생성자 참조
      • 구현 메소드의 내용이 객체 생성 코드만으로 고정되어 있을 때
  • 구현 메소드의 약식표현
      1. 람다식의 활용
      • 함수형 인터페이스의 객체 생성과정에서 익명이너 클래스를 이용해서 객체 생성한 것
        • 직접 추상 메소드를 구현하는 형태 -> return 타입으로 4가지 존재
interface A {void method1();}
interface B {void method2(int a);}
interface C {int method3();}
interface D {double method4(int a, double b);}

public class FunctionToLambdaExpression {
    public static void main(String[] args) {
    	// 익명 이너 클래스 방법, 람다식 방법, 입력X 리턴X
        A a1 = new A() {
            @Override
            public void method1() {
                System.out.println("입력X 리턴X 함수");
            }
        };
        A a2 = () -> {System.out.println("입력X 리턴X 함수");};
        A a3 = () -> System.out.println("입력X 리턴X 함수");
		
        // 익명 이너 클래스 방법, 람다식 방법, 입력O 리턴X
        B b1 = new B() {
            @Override
            public void method2(int a) {
                System.out.println("입력O 리턴X 함수");
            }
        };
        B b2 = (int a) -> {System.out.println("입력O 리턴X 함수");};
        B b3 = (a) -> {System.out.println("입력O 리턴X 함수");};
        B b4 = (a) -> System.out.println("입력O 리턴X 함수");
        B b5 = a -> System.out.println("입력O 리턴X 함수");
		
        // 익명 이너 클래스 방법, 람다식 방법, 입력X 리턴O
        C c1 = new C() {
            @Override
            public int method3() {
                return 4;
            }
        };
        C c2 = () -> {return 4;};
        C c3 = () -> 4;
		
        // 익명 이너 클래스 방법, 람다식 방법, 입력O 리턴O
        D d1 = new D() {
            @Override
            public double method4(int a, double b) {
                return a + b;
            }
        };
        D d2 = (int a, double b) -> {return a + b;};
        D d3 = (a, b) -> {return a + b;};
        D d4 = (a, b) -> a + b;
    }
}

메소드 참조

    1. 람다식의 활용
    • 추상메소드를 직접 구현 대신, 구현되어있는 것 참조
      • 참조 방식 -> 인스턴스 메소드 참조(방법 2가지) | 정적 메소드 참조
  • 참조 방식 1. 정의되어 있는 인스턴스 메소드 참조(인스턴스 메소드 참조)
    • 이미 정의되어 있는 인스턴스 메소드를 참조하는 것
    • 인스턴스 메소드 참조할려면 객체먼저 생성 필요
    • 형태 -> 클래스객체 참조변수::인스턴스메소드
interface A {void abc();}
class B {
	void bcd() {System.out.println("메소드");}
}

public class RefOfInstanceMethod_Type1_1 {
    public static void main(String[] args) {
    	// 1. 익명 이너 클래스
        A a1 = new A() {
        	@Override
            public void bcd() {
            	B b = new B();
                b.bcd();
            }
        };
     	
        // 2. 람다식으로 표현
        A a2 = () -> {
        	B b = new B();
            b.bcd();
        };
        
        // 3. 정의된 인스턴스 매소드 참조
        B b = new B();
        A a3 = b::bcd;
    }
}
interface A {void abc(int k);};

public class RefOfInstanceMethod_Type1_2 {
    public static void main(String[] args) {
    	// 1. 익명 이너 클래스
        A a1 = new A() {
        	@Override
            public void abc(int k) {System.out.println(k);}
        };
        
        // 2. 람다식으로 표현
        A a2 = (int k) -> {
        	System.out.println(k);
        };
        
        // 3. 인스턴스 메소드 참조
        // 의미 : 인터페이스 A의 추상 메소드인 abc()는 System.out.println()와 동일하게 하라
        A a3 = System.out::println;
            	
  • 참조방식 2. 정의되어 있는 정적 메소드 참조
    • 클래스명::정적메소드
      • 객체 생성없이 클래스명으로 바로 사용 가능
interface A {void abc();}
class B {
	static void bcd() {System.out.println("메소드");}
}

public class RefOfStaticMethod {
    public static void main(String[] args) {
    	// 1. 익명 이너클래스
        A a1 = new A() {
        	@Override
            B.bcd();
        };
        
        // 2. 람다식으로 표현
        A a2 = () -> {
        	B.bcd();
        };
        
        // 3. 정적 메소드 참조
        // 의미 : 인터페이스A의 객체를 생성할 때 구현하야 하는 ab()메소드를 B.bcd()와 동일
        A a3 = B::bcd;
  • 첫 번째 매개변수로 전달된 객체의 인스턴스 메소드 참조(인스턴스 메소드 참조)
    • 첫 번째 인스턴스 메소드 참조방법 변형 형태
    • 첫 번쨰 매개변수 = 인스턴스메소드 포함하는 객체 넘기기
      • 전달된 객체의 인스턴스 메소드 참조!!
    • 클래스명::인스턴스 메소드
      • 클래스명이 나온다? -> 정적메소드 or 매개변수로 전달된 인스턴스 메소드 참조
      • 메소드의 구분 -> static 여부만으로도 바로 알수 있음
    • 인터페이스 매개변수 개수 = 매개변수에 있는 객체 매개변수 + 1;
interface A {void abc(B b, int k);}
class B {
	void bcd(int k) {System.out.println(k);}
}

public class RefOfInstanceMethod_Type2_1 {
    public static void main(String[] args) {
    	// 1. 익명 이너 클래스
        A a1 = new A() {
        	@Override
            public void abc(B b, int k) {b.bcd(k);}
        };
        
        // 2. 람다식
        A a2 = (b, k) -> {b.bcd(k);};
        
        // 3. 직접 정의한 인스턴스 메소드 참조
        // 의미 : abc(B b, int k)호출 시, 첫 번째 매개변수 b내부의 bcd(int k)메소드를 호출
        A a3 = B::bcd;


// 자바가 제공하는 인스턴스 메소드 참조
interface A {int abc(String str);}

public class RefOfInstanceMethod_Type2_2 {
    public static void main(String[] args) {
    	// 1. 익명 내부 클래스
        A a1 = new A() {
        	@Override
            public int abc(String str) {return str.length();}
        };
        
        // 2. 람다식
        A a2 = (String str) -> str.length();
        
        // 3. 자바가 제공하는 인스턴스 메소드 참조
        A a3 = String::length;

생성자 참조

    1. 람다식의 활용
  • 배열 생성자 참조
    • 배열타입::new
interface A {int[] abc(int len);}

public class RefOfArrayConstructor {
    public static void main(String[] args) {
    	// 1. 익명 이너 클래스
        A a1 = new A() {
        	@Override
            public int[] abc(int len) {return new int[len];}
        };
        
        // 2. 람다식
        A a2 = (int len) -> new int[len];
        
        // 3. 배열의 생성자 참조
        // 의미 : abc(len) 호출시 new int[len]을 실행한 후 객체를 리턴
        A a3 = int[]::new;
        
        int[] array1 = a1.abc(3);
        int[] array2 = a2.abc(3);
        int[] array3 = a3.abc(3);
  • 클래스 생성자 참조
    • 클래스::new
/// 기본 생성자 참조
interface A {B abc();}// 추상 메소드 abc() 매개변수 없음
class B {
    B() {
        System.out.println("첫 번째 생성자");
    }
    B(int k) {
        System.out.println("두 번째 생성자");
    }
}

public class RefOfClassConstructor_1 {
    public static void main(String[] args) {
    	// 1. 내부 익명 클래스
        A a1 = new A() {
            @Override
            public B abc() {
                return new B();
            }
        };
		
        // 2. 람다식
        A a2 = () -> new B();
		
        // 3. 클래스 생성자 참조
        // 의미 : a.abc()호출시, new B() 실행 후 객체 생성
        A a3 = B::new;
      
      
/// 매개변수를 가진 생성자 참조
interface A {B abc(int k);}// 추상 메소드 abc() 매개변수 있음
class B {
    B() {
        System.out.println("첫 번째 생성자");
    }
    B(int k) {// 요놈 출력
        System.out.println("두 번째 생성자");
    }
}

public class RefOfClassConstructor_2 {
    public static void main(String[] args) {
    	// 1. 익명 이너 클래스
        A a1 = new A() {
            @Override
            public B abc(int k) {
                return new B(3);
            }
        };
		
        // 2. 람다식
        A a2 = (int k) -> new B(3);
		
        // 3. 배열의 생성자 참조
        // 의미 : abc(k) 호출시, new B(k) 실행
        A a3 = B::new;
profile
현재 블로그 : https://jasonsong97.tistory.com/

0개의 댓글