반응형

본 글은 책 자바의 정석을 ref 하여 요약한 글입니다.


 

제네릭스

컴파일 타임 시 타입 체크를 해주는 기능

다룰 객체의 타입을 미리 명시하여 형변환을 제거

추가적인 형변환을 하지 않아 성능이 향상된다.

컴파일 이후부터는 지정된 타입으로 바뀐다.

클래스와 메서드에 선언할 수 있다.

 

 

제한

static 에는 사용 불가능 (클래스 변수는 공유가 되는데, 인스턴스마다 제네릭 타입이 달라지므로)

new 배열 생성 코드 불가능 (new 연산자는 컴파일 타임 때 타입을 정확히 알아야 함)

 

 

형변환

지정된 제네릭 타입의 자손을 사용하면 형변환이 된다.

void add(T t)

*T가 부모일 경우 T의 자손도 인수로 사용할 수 있다.

 

 

제한된 지네릭 

<T extends 부모 클래스>

부모 클래스와 자손 클래스들만 사용 가능

불필요한 다른 타입의 사용을 막는다.

사용할 수 있는 필드, 메서드는 부모 클래스의 것으로 제한된다.

 

 

✔ 제네릭 메서드

메서드의 리턴 타입 앞에 제네릭 타입을 지정하며 지역변수와 비슷하게 사용된다.

클래스의 제네릭 타입과는 관련이 없다. 메서드 내부에서만 사용된다.

<사용할 제네릭 타입> 리턴타입 메서드명(매개인자)

 

 

 

 

✔ 와일드카드

메서드의 리턴 타입, 매개 인자에 사용된다.

제네릭 타입이 불공변이기 때문에 사용한다.

 * 불공변: 변하지 않는다.

 * List<Object> list = new ArrayList<Integer>()

 * 컴파일 안된다. 제네릭은 형변환 개념이 없다 <Object> 와 <Integer>는 아무 상관이 없다.

 

제네릭 형 변환

Clazz<String>  <==>  Clazz<Object>   형변환 // 불가능 (불공변)

Clazz<?>   <==>   Clazz<Object>   형변환  //  가능 (와일드 카드 사용 이유)

논제네릭과 제네릭   형변환  //  가능

 

 

메서드 인자 제네릭 타입

메서드는 타입이 달라야 오버 로딩이 가능한데, 지네릭 타입이 불공변이라 오버로딩이 되지 않는다.

 

void add(FruitBox<Fruit> f)   // FruitBox<Fruit> 만 인수로 들어올 수 있다.
void add(FruitBox<Apple> f)    // FruitBox<Apple> 만 인수로 들어올 수 있다.
오버로딩 불가능

어떤 제네릭 클래스가 들어올지 몰라서,
void add(FruitBox<?> f)

 

 

와일드카드는 메서드의 인수가 제네릭 타입만 다를 때 여러 제네릭 타입이 사용될 수 있도록 한다.

와일드카드를 사용하면 제네릭 타입이 무엇인지 알 수 없다.

정확한 제네릭 타입을 몰라서 확실하게 사용할 수 있는 기능만 사용한다.

 

메서드 인자로 와일드 카드를 사용할 때 메서드 구현부에서의 제한

 

(1)  <?> 제한 없음

 

(2)  <? extends T> T와 그 자손들만 가능

상한 제한으로 하게 되면 출력은 할 수 있고, 입력이 불가능하다.

출력: T의 출력 메서드를 자손 클래스들이 모두 상속했거나, 오버라이딩하여 가능하다.

입력: 제네릭 클래스가가 T의 하위 타입을 사용할 경우 T를 입력할 수 없다.

 

(3)   <? super T> T와 그 조상들만 가능

하한 제한으로 하게 되면 반대로 출력을 할 수 없고, 입력만 할 수 있다.

입력: T와 그 조상들을 타입 변수로 제한하므로 T 타입은 무조건 입력이 될 수 있다.

출력: 상위 타입이 T타입의 메서드를 갖고 있지 않을 수 있다.

 

(가능한 경우에도 자바에서는 상한 제한에서 입력, 하한 제한에서의 출력을 불가능하게 막아둠)

 

 

 

 

✔ 제네릭 타입의 제거

하위 자바 버전과의 호환성을 유지하기위해 컴파일때 제거

 


 

열거형 (Enum)

 

서로 관련있는 상수를 편하게 관리하기 위해 등장

사용할 도메인 범위를 지정할 수 있다는 장점을 갖는다.

값뿐만 아니라 타입까지 사용하기 때문에 정확한 비교가 가능하다.

 

메서드

ordinal() 열거형 상수의 순서를 반환

name() 열거형 상수의 이름을 반환

values() 열거형 상수들을 배열에 담아서 반환

 

지정된 멤버 추가

enum Direction { EAST(-1), SOUTH(5), WEST(100), NORTH(10);

private final int value;

Direction(int value){

     this.value = value;

}

불연속 열거형 값을 사용하기 위해선 생성자와 인스턴스 변수가 필요하다. (생성자는 private가 생략됨)

상수에 두가지 값을 사용하려면 두가지의 인스턴스 변수가 필요하다.

 

열거형 상수의 이해

열거형 상수 하나하나가 객체다.

객체의 주소가 바뀌지 않으므로 == 비교가 가능하다.

 

 

 


 

어노테이션

주석처럼 프로그램에 영향을 미치지 않으면서, 다른 프로그램에게 유용한 정보를 제공

 

 

메타 어노테이션 - 어노테이션을 위한 어노테이션

 

@Target

적용 가능한 대상을 지정

 

@Retention

어노테이션이 유지되는 기간

Runtime으로 지정시 Reflection을 통해 정보를 읽어서 처리할 수 있다.

 

@Inherited

자손 클래스에 상속되도록 한다.

 

@Repeatable

해당 어노테이션을 여러번 지정 가능

 

 

 

 

어노테이션 타입 지정

어노테이션에 선언된 메서드를 요소라고 한다.

요소들의 값을 빠짐없이 적어주어야 한다. (default가 지정되어 있으면 적어주지 않아도 된다.)

요소가 하나일 경우 이름 생략 가능

 

[규칙]

메서드 선언에는 매개변수를 사용할 수 없다.

예외를 선언할 수 없다.

메서드의 반환형에는 기본 타입, 문자열, 배열, 열거형, Class<> 클래스, 어노테이션 

상수를 선언할 수도 있다.

 

 

 

 

반응형

+ Recent posts