Chapter12 지네릭스, 열거헝, 애너테이션 generics, enumeration, annotation

cookienc·2021년 7월 14일
0

Java 기본 개념

목록 보기
11/13
post-thumbnail

1. 지네릭스(Generics)

1.1 지네릭스란?

  • 컴파일시 타입을 체크해 주는 기능(런타임 에러↓)

지네릭스의 장점
1. 타입 안정성을 제공한다.
2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다.

1.2 지네릭 클래스의 선언

class Box<T> { // 지네릭 타입 T를 선언
 T item;
 void setItem(T item) { this.item = item; }
 T getItem() { return item; }
}

<지네릭스 용어>

  • Box < T > : 지네릭 클래스. 'T의 Box' 또는 'T Box'라고 읽는다.
  • T : 타입변수 또는 타입 매개변수
  • Box : 원시 타입(raw type)
  • 객체 생성시, 타입 변수(E) 대신 실제 타입을 지정(대입)

Iterator

  • 클래스를 작성할 때, Object타입 대신 T와 같은 타입 변수를 사용

HashMap<K,V>

  • 여러 개의 타입 변수가 필요한 경우, 콤마(,)를 구분자로 선언

1.3 지네릭 클래스의 객체 생성과 사용

  • 참조 변수와 생성자에 같은 타입을 써준다. → 지네릭 클래스간의 다형성과 매개변수의 다형성도 성립.
    → 코드가 간결해 진다.
  • JDK 1.7부터 생성자의 타입변수는 생략이 가능하다.

1.4 제한된 지네릭 클래스

  • extends로 대입할 수 있는 타입을 제한
    class FruitBox<T extends Fruit> { // Fruit의 자손만 타입으로 지정가능
    ArrayList<T> list = new ArrayList<T>();
    ...
    }
    Fruitbox<Apple> appleBox = new FruitBox<Apple>(); // OK
    Fruitbox<Toy> toyBox = new FruitBox<Tody>(); // 에러, Toy는 Fruit의 자손이 아님
    • 인터페이스인 경우도 extends를 사용(두개 이상을 사용하려면 &기호를 사용)

<지네릭스 제약>

  • 지네릭 클래스 객체를 생성할 때, 객체별로 다른 타입을 지정하는 것은 가능하다
  • static멤버에 타입 변수 T를 사용할 수 없다. 왜냐하면 타입 변수는 인스턴스변수로 간주되기 때문이다.
  • 지네릭 배열 타입의 참조변수는 가능하지만 지네릭 배열 생성은 불가능 → 객체 생성, 배열 생성 둘다 x

1.5 와일드 카드

  • 하나의 참조 변수로 대입된 타입이 다른 객체를 참조 가능
    • <? extends T> : 와일드 카드의 상한 제한. T와 그 자손들만 가능
    • <? super T> : 와일드 카드의 하한 제한. T와 그 조상들만 가능
    • <?> : 제한 없음. 모든 타입이 가능. <? extends Object>와 동일
  • 메서드의 매개변수에 와일드 카드를 사용할 수 있다.

1.6 지네릭 메서드

  • 지네릭 타입이 선언된 메서드(타입 변수는 메서드내에서만 유효)
  • 클래스의 타입 매개변수와 메서드의 타입 매개변수 는 별개
  • 메서드를 호출할 때마다 타입을 대입해야 함(대부분 생략 가능).

지네릭 메서드는 메서드를 호출할 때마다 다른 지네릭 타입을 대입할 수 있게 한 것
와일드 카드는 하나의 참조변수로 서로 다른 타입이 대입된 여러 지네릭 객체를 다루기 위한 것

1.7 지네릭 타입의 형변환

  • 지네릭 타입과 원시 타입 간의 형변환은 바람직 하지 않다.(경고 발생)
  • 서로 다른 지네릭 타입이 대입된 지네릭 타입들은 형변환이 안된다.
  • 와일드 카드가 사용된 지네릭 타입으로는 형변환 가능

1.8 지네릭 타입의 제거

  • 컴파일러는 지네릭 타입을 제거하고, 필요한 곳에 형변환을 넣는다.
    1. 컴파일 시에 지네릭 타입의 경계(bound)를 제거 → 하위호환성(안정성)을 위해서
    2. 지네릭 타입 제거 후에 타입이 불일치하면, 형변환을 추가
    3. 와일드 카드가 포함된 경우, 적절한 타입으로 형변환 추가


2. 열거형(enums)

2.1 열거형이란?

  • 관련된 상수들을 같이 묶어 놓은 것. 타입에 안전한 열거형을 제공(값과 타입을 모두 체크)

2.2 열거형의 정의와 사용

  • 열거형을 정의하는 방법
    • enum 열거형이름 { 상수명1, 상수명2, .. }
  • 열거형 상수의 비교에 ==와 compareTo() 사용가능

<모든 열거형의 조상 - java.lang.Enum>

  • 모든 열거형은 Enum의 자손이며, 아래의 메서드를 상속받는다.
  • values(), valueOf()는 컴파일러가 자동으로 추가

2.3 열거형에 멤버 추가하기

  • 불연속적인 열거형 상수의 경우, 원하는 값을 괄호()안에 적는다.
    enum Direction { EAST(1), SOUTH(5), WEST(-1), NORTH(10) } → 콤마(,)로 여러개 가능
  • 괄호()를 사용하려면, 인스턴스 변수와 생성자를 새로 추가해 줘야 한다.
  • 열거형의 생성자는 암묵적으로 private이므로, 외부에서 객체생성 불가
    `Direction d = new Direction(1); // 에러

<열거형에 추상 메서드 추가하기>

enum Transportation {
    BUS(100)  { int fare(int distance) { return distance*BASIC_FARE; } }, // 추상 메서드 구현
    TRAIN(150) { int fare(int distance) { return distance*BASIC_FARE; } },
    SHIP(100) { int fare(int distance) { return distance*BASIC_FARE; } },
    AIRPLANE(300) { int fare(int distance) { return distance*BASIC_FARE; } };

    protected final int BASIC_FARE; // 각 상수에서 접근 가능하게 하기 위해서 protected를 쓴다.

    Transportation(int basicFare) {
        BASIC_FARE = basicFare;
    }

    public int getBasicFare() { return BASIC_FARE; }

    abstract int fare(int distance); // 열거형의 추상 메서드
}

2.4 열거형의 이해

  • 열거형 상수 하나하나가 객체이다.
    • enum Directoin { EAST, SOUTH, WEST, NORTH } 이면 각각의 방위는 Direction의 객체이다.


3. 애너테이션(annotation)

3.1 애너테이션이란?

  • 주석처럼 프로그래밍 언어에 영향을 미치지 않으며, 유용한 정보를 제공

3.2 표준 애너테이션

@Override

  • 오버라이딩을 올바르게 했는지 컴파일러가 체크하게 한다.
  • 메서드이름을 잘못적는 실수를 하는 경우 방지.

@Deprecated

  • 앞으로 사용하지 않을 것을 권장하는 필드나 메서드에 붙인다.

@FunctionalInterface

  • 함수형 인터페이스에 붙이면, 컴파일러가 올바르게 작성했는지 체크
  • 함수형 인터페이스에는 하나의 추상메서드만 가져야 한다는 제약이 있음.

@SuppressWarnings

  • 컴파일러의 경고메시지가 나타나지 않게 억제한다.
  • 둘 이상의 경고를 사용하려면 대괄호({})를 사용해야한다.
    • @SuppressWarnings({"deprecation", "unchecked"})

3.3 메타 애너테이션

  • 애너테이션을 만들 때 사용.

@Target

  • 애너테이션을 정의할 때, 적용대상 지정에 사용

@Retention

  • 애너테이션이 유지되는 기간을 지정하는데 사용
  • 컴파일러에 의해 사용되는 애너테이션의 유지 정책은 SOURCE이다.
  • 실행시에 사용 가능한 애너테이션의 정책은 RUNTIME이다.

@Documented, @Inherited

  • javadoc으로 작성한 문선에 포함시키면 @Documented를 붙인다.
  • 애너테이션을 자손 클래스에 상속하고자 할 때, @Inherited를 붙인다.

@Repeatable

  • 반복해서 붙일 수 있는 애너테이션을 정의할 때 사용.
  • @Repeatable이 붙은 애너테이션은 반복해서 붙이 ㄹ수 잇다.

3.4 애너테이션 타입 정의하기

  • 애너테이션을 직접 만들어 쓸 수 있다.
@interface 애너테이션이름 {
	타입 요소이름(); // 애너테이션의 요소를 선언한다.
	...
}
  • 애너테이션의 메서드는 추상 메서드이며, 애너테이션을 적용할 때 지정(순서x)
  • 자신이 아닌 다른 애너테이션을 포함할 수 있다.

<애너테이션의 요소>

  • 적용시 값을 지정하지 않으면, 사용될 수 있는 기본값 지정 가능(NULL 제외)
  • 요소가 하나이고 이름이 value일 때는 요소의 이름 생략가능
  • 요소의 타입이 배열인 경우, 괄호{}를 사용해야 한다.(값이 없을 때도 반드시 써야함)

<모든 애너테이션의 조상 - java.lang.annotation.Annotation>

  • Annotation은 모든 애너테이션의 조상이지만 상속 불가(허용되지 않는 표현)
  • Annotation은 인터페이스이다. → 추상메서드를 구현 안해도 사용 가능

<마커 애너테이션 - Marker Annoation>

  • 요소가 하나도 정의되지 않은 애너테이션

<애너테이션 요소의 규칙>

  • 애너테이션의 요소를 선언할 때 아래의 규칙을 반드시 지켜야 한다.
    • 요소의 타입은 기본형, String, enum, 애너테이션, Class만 허용됨
    • 괄호()안에 매개변수를 선언할 수 없다.
    • 예외를 선언할 수 없다.
    • 요소를 타입 매개변수로 정의할 수 없다.

0개의 댓글