2022-02-15(화) 14주차 2일

Jeongyun Heo·2022년 2월 15일
0

com.eomcs.oop.ex12.Exam0510.java

기존에 있는 메서드를 사용할 수 있다.
인터페이스를 구현할 때 기존의 메서드를 사용하고 싶

익명 클래스로 만들 수도 있음

더하기든 빼기든 앞으로는 compute를 호출하자
인터페이스를 구현해야 됨
그렇다고 처음부터 작성하기는

새 사용법에 맞춰서 새로 만들어야 한다
기존에 작성된 코드를 복붙할 것인가
경력 있는 개발자는 그러진 않을 것이다

메서드를 처음부터 다시 구현하는 게 아니라
기존에 작성한 코드를

처음부터 작성하면 시간도 걸리고.. 버그 검사해야 되고
코드가 중복되면 위험하다는 건 몇 번이나 강조했었음

    class CalculatorImpl implements Calculator {
      @Override
      public int compute(int x, int y) {
        return x + y;
      }
    }
    class CalculatorImpl implements Calculator {
      @Override
      public int compute(int x, int y) {
        return MyCalculator.plus(x,  y);
      }
    }
    
    Calculator calc1 = new CalculatorImpl();
    Calculator calc2 = new Calculator() {
      @Override
      public int compute(int x, int y) {
        return MyCalculator.plus(x, y);
      }
    };

인스턴스를 생성하는 문장은 항상 세미콜론으로 끝나야 한다.

람다 문법

Calculator calc3 = (x, y) -> MyCalculator.plus(x, y);

return 지우기

컴파일러 너가 해
inner class에서 컴파일러가 자동으로 만들어 주는 거랑 똑같음

네 번째,
껍데기 너가 만들어

    Calculator calc4 = MyCalculator::plus;
    System.out.println(calc4.compute(100, 200));

컴파일러가 나 대신 클래스 만들라는 거
Calculator 인터페이스 구현체를 만들라는 거
MyCalculator::plus 이 문장이
익명 클래스 문장으로 바뀐다는 거

독립적인 문법이라기 보다 기존에 있는 문법을 간략하게 표현할 수 있는 일종의 단축 문법

단축 문법이 존재하는데도 불구하고 저렇게 짜면
메서드 레퍼런스라는 껍데기를 자동으로 씌워주는 문법이 존재하는데도 안 쓰면 무식하다는 소리 들음

// 메서드 레퍼런스 - 스태틱 메서드 레퍼런스
package com.eomcs.oop.ex12;


public class Exam0510xx {

  static class MyCalculator {
    public static int plus(int a, int b) {return a + b;}
    public static int minus(int a, int b) {return a - b;}
    public static int multiple(int a, int b) {return a * b;}
    public static int divide(int a, int b) {return a / b;}
  }

  interface Calculator {
    int compute(int x, int y);
  }

  public static void main(String[] args) {

    // 1) 로컬 클래스
    class CalculatorImpl implements Calculator {
      @Override
      public int compute(int x, int y) {
        return MyCalculator.plus(x, y);
      }
    }

    Calculator c1 = new CalculatorImpl();

    System.out.println(c1.compute(200, 17));

    // 1) 익명 클래스
    Calculator c2 = new Calculator() {
      @Override
      public int compute(int x, int y) {
        return MyCalculator.plus(x, y);
      }
    };

    System.out.println(c2.compute(200, 17));

    // 3) 람다
    Calculator c3 = (x, y) -> MyCalculator.plus(x, y);

    System.out.println(c3.compute(200, 17));

    // 4) 메서드 레퍼런스
    Calculator c4 = MyCalculator::plus;

    System.out.println(c4.compute(200, 17));
  }
}

com.eomcs.oop.ex12.Exam0520.java
메서드 레퍼런스 - 스태틱 메서드 레퍼런스 구현 원리

Calculator c1 = MyCalculator::plus;

컴파일러에게 기존 메서드를 사용하여
인터페이스 구현체를 만들라는 명령

직접 코딩하지 말고
컴파일러가 대신해서 이런 코드를 작성해준다

new Calculator() {
  @Override
  public int compute(int x, int y) {
    return MyCalculator.plus(x, y);
  }
};

단축 문법일 뿐이다

com.eomcs.oop.ex12.Exam0530.java

Calculator c01 = MyCalculator::plus;
Calculator c01 = MyCalculator::minus;
Calculator c01 = MyCalculator::multiple;
Calculator c01 = MyCalculator::divide;

단, 못 만드는 게 있을 거임

해당 메서드를 가지고 구현체를 만들 수 없다.

메서드 레퍼런스가 가능한지 불가능한지

double compute(int a, int b)
            ↓ call
  int plus(int a, int b)

plus에 껍데기를 씌울 수 있는가
파라미터 값이 그대로 전달될 수 있는가 따진다
리턴한 int값을 double로 리턴할 수 있는가

short compute(int a, int b)
            ↓ call
  int plus(int a, int b)

파라미터 받을 수 있는가? O
short로 던질 수 있는가? X. 자동 형변환이 안 된다.

byte, short, char > int > long > float > double
거꾸로는 자동 형변환 안 됨!

void compute(int a, int b)
            ↓ call
  int plus(int a, int b)

안 받고 안 던지는 건 OK

Object compute(int a, int b)
            ↓ call
  int plus(int a, int b)

인터페이스를 자동으로 구현할 수 있는가

int ------> Object (자동 형변환 됨)

오토 박싱

int a = 100;
Integer obj = new Integer(100);

Object obj2 = a; // Integer.valueOf(a);

Object 타입이면 오토 박싱이 일어난다.

String compute(int a, int b)
            ↓ call
  int plus(int a, int b)

com.eomcs.oop.ex12.Exam0540.java

구현체를 만들 수 있냐고
리턴 값을 double로 만들 수 있냐고

인터페이스에 있는 메서드가 byte를 받아서 int에 전달할 수 있는가? O

 int compute(long a, long b)
            ↓ call
  int plus(int a, int b)

외부에서 compute를 호출할 때 long 값을 받을 건데
plus 호출해줘 라고 했을 때
자기가 받은 long 값을 전달할 수 있는가? X

Calculator1 c1 = MyCalculator::plus;
내가 준 메서드 가지고 Calculator 구현체 만들어봐
Calculator 구현. 메서드까지 구현.
이게 가능하면 OK
이게 불가능하면 OK가 안 되는 거

메서드 레퍼런스는 여기서 끝내겠다
나중에 익숙해지면 생성자에서 쓰는

com.eomcs.algorithm.data_structure.array2.step1

이걸 지원하는 문법이 바로 제네릭이라는 문법

ArrayList로 받을 항목의 타입

  @SuppressWarnings("unchecked")
  public itemType get(int index) {
    if (index < 0 || index >= size) {
      throw new ArrayIndexOutOfBoundsException("인덱스가 유효하지 않습니다.");
    }
    return (itemType) elementData[index];
  }

안 넣어주면 기본이 Object

가능하면 알파벳 대문자 한 개로

https://docs.oracle.com/javase/tutorial/

https://docs.oracle.com/javase/tutorial/java/generics/index.html

E - Element (used extensively by the Java Collections Framework)
K - Key
N - Number
T - Type
V - Value
S,U,V etc. - 2nd, 3rd, 4th types

제네릭 문법 사용 전

① 특정 타입으로 사용을 제한할 수 없다.
② 값을 꺼낼 때마다 형변환 해야 한다.

개선

IntArrayList
StringArrayList
ScoreArrayList

① 특정 타입을 다루는 클래스 별도 정의
② 형변환이 필요 없다

문제점
타입별로 ArrayList 정의해야 한다

제네릭(generic) 문법 사용 후

특정 타입을 다루는 클래스

한 개의 클래스로 다양한 타입을 다룰 수 있다.

Object로 하면 특정 타입으로 사용을 제한할 수 없다.
꺼낼 때마다 형변환 해야 된다.

제네릭(generic) 클래스 사용

표준 클래스 정의
ArrayList<E>

사용할 때 타입을 지정한다.

ArrayList<integer>
ArrayList<String>
ArrayList<Score>
ArrayList<Member>

한 개의 클래스를 가지고 다양한 타입에 사용할 수 있다.

com.eomcs.generic.ex01

클래스 전체에도 적용할 수 있지만 메서드에 한정해서 적용할 수도 있다.

잘못된 형변환은 컴파일러는 속일 수 있을 지라도, runtime 에서는 오류를 발생시킨다.
JVM이 잡아 낸다

제네릭 문법을 떠나서 알고 있기

  // 제네릭 적용 전
  static Object[] reverse(Object[] arr) {
    for (int i = 0; i < arr.length / 2; i++) {
      Object temp = arr[i];
      int targetIndex = arr.length - 1 - i;
      arr[i] = arr[targetIndex];
      arr[targetIndex] = temp;
    }
    return arr;
  }

제네릭 배열

제네릭의 타입 파라미터로 레퍼런스 배열을 생성할 수 없다.

arr = new T[10]; // 컴파일 오류! new 명령어를 사용할 때 제네릭의 타입 파라미터를 사용할 수 없다.

문법적으로 안 된다

타입별로 클래스를 만들 필요가 없다

어떤 타입의 목록을 다루는 ArrayList 타입을 지정하지 않으면 아무거나 다 됨

    // => 레퍼런스를 선언할 때 제네릭 타입을 지정하지 않으면
    // ArrayList 객체를 생성할 때 지정한 제네릭 타입은 무시된다.

컴파일러도 검사 못 함

파라미터 타입이 정해지지 않았기 때문에

제네릭: 레퍼런스와 인스턴스

다형적 변수에 입각해서

여기서는 다형적 변수 그런 거 안 따짐.

사용하는 문법을 검사할 때는 다형적 문법을 따진다.

레퍼런스에서 지정한 타입과 인스턴스에서 지정합 타입이 다르다면 모순 발생!

224, 225는 나중에

com.eomcs.generic.ex02.Exam0230.java

https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/HashMap.html

com.eomcs.generic.ex03

com.eomcs.oop.ex12.Exam0630.java

generic.ex01 ~ ex03

com.eomcs.basic.ex03 혼자 공부하기 (반드시 하기)

0개의 댓글

관련 채용 정보