👉🏻 이 글은 자바의 정석(3판) Chapter.12을 공부하고 적은 내용입니다.
👉🏻 제네릭스(Generics)란?
다양한 타입의 객체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다. 컴파일 시에 타입을 체크하기 때문에
1. 객체의 타입 안정성을 높이고
2. 형변환의 번거로움이 줄어든다. (코드가 간결해 진다.)
👉🏻 다룰 객체의 타입을 미리 멸시해 줌으로써 번거로운 형변환을 줄여준다.
제네릭 타입은 클래스와 메서드에 선언할 수 있다.
class Box<T> { // 제네릭 타입 T 선언
T item;
void setItem(T item) { this.item = item; }
T getItem() { return item; }
}
Box<String> b = new Box<String>(); // 제네릭 타입 호출
b.setItem("ABC");
위에서 T는 타입 변수 (타입변수는 T가 아닌 다른 것도 사용 가능)
Ex. ArrayList<E>, Map<K, V>
이들은 기호만 다를 뿐 '임의의 참조형 타입'을 의미한다는 것은 모두 같다.
Box<T> : 제네릭 클래스T : 타입 변수, 타입 매개변수 (T는 타입 문자)Box : 원시 타입 (raw type)String : 대입된 타입 (매개변수화된 타입)static멤버에 타입변수 T를 사용할 수 없다. static T item; // Error!
static int compare(T t1, T t2) { ... } // Error!
new연산자 때문. 컴파일 시점에 T가 어떤 타입이 될지 전혀 알 수 없기 때문이다. instanceof도 마찬가지이다. T[] itemArr; // OK. T타입의 배열을 위한 참조변수
T[] toArray(){
T[] tmpArr = new T[itemArr.length]; // Error! 생성불가
...
return tmpArr;
}
--> newInstance()와 같이 동적 객체 생성 메서드 이용, Object배열을 생성해서 복사한 다음 T[]로 형변환 하는 방법 사용
class Box<T> {
ArrayList<T> list = new ArrayList<T>();
void add(T item) { list.add(item); }
T get(int i) { return list.get(i); }
ArrayList<T> getList { return list; }
int size() { return list.size(); }
public String toString() { return list.toString(); }
👉🏻 자손타입으로 제한 가능
class Fruit<T extends Fruit> {
ArrayList<T> list = new ArrayList<T>;
...
}
⚠️ 인터페이스를 구현할 때 또한 implements가 아닌 extends를 사용한다.
여러 개를 구현할 때는 &기호로 연결.
static Jucie makeJucie(FruitBox<Fruit> box) {
...
}
static Jucie makeJucie(FruitBox<Apple> box) {
...
}
⚠️ 위와 같이 오버로딩 하면 컴파일 에러가 발생한다. 제네릭 타입이 다른 것만으로는 오버로딩(new)이 성립하지 않는다. 위는 '메서드 중복 정의'이다.
----> "와일드 카드(?)" 고안
<? extends T> : 와일드카드 상한 제한 (T와 그 자손들)
<? super T> : 와일드카드 하한 제한 (T와 그 조상들)
<?> : 제한 없음. 모든 타입 가능 ( = <? extends Object> )
메서드의 선언부에 제네릭 타입이 선언된 메서드를 제네릭 메서드라 한다.
static <T> void sort (List<T> list, Comparator<? super T> c)
클래스의 타입변수와 메서드의 타입변수는 완전히 별개의 것이다.
static 멤버에는 타입 매개변수를 사용할 수 없지만, 메서드에 제네릭 타입을 선언하고 사용하는 것은 가능하다.
public static <T extends Comparable<? super T>> void sort (List<T> list)
// ⬇️ List <T>의 요소가 Comparable인터페이스를 구현한 것이어야 한다.
public static <T extends Comparable<T>> void sort (List<T> list)
👉🏻 열거형(enums)이란?
JDK1.5부터 새로 추가되었다.
열거형이 갖는 값뿐만 아니라 타입까지 관리. (타입에 안전한 열거형)
: 실제 값이 같아도 타입이 다르면 조건식의 결과가 false가 된다.
모든 열거형의 조상은 java.lang.Enum 이다.
class Card{
static final int CLOVER = 0;
static final int HEART= 1;
static final int DIAMOND = 2;
static final int SPADE = 3;
static final int TWO = 0;
static final int THREE = 1;
static final int FOUR = 2;
final int kind;
final int num;
}
⬇️ 열거형으로
class Card{
// 정의 : enum 열거형이름 { 상수명1, 상수명2, ... }
enum Kind { COLVER, HEART, DIAMOND, SPADE }
enum Value { TWO, THREE, FOUR }
final Kind kind; // type이 int가 아님에 유의
final Value value;
}
if(Card.Kind.CLOVER == Card.Value.TWO) // false. 타입이 다르기 때문.
== 사용 가능 (static 상수의 값이 객체의 주소이고 이 값은 바뀌지 않기 때문)compareTo() 사용 )enum Direction {
EAST(1), SOUTH(5), WEST(-1), NORTH(10);
private final int value; // 정수를 저장할 필드(인스턴스 변수) 추가
Direction(int value) { this.value = value; } // 생성자
public int getValue() { return value; } // 외부 접근을 가능하게 한다.
}
열거형의 생성자는 묵시적으로 private이다.
👉🏻 애너테이션(annotation)이란?
애너테이션의 뜻은 주석, 주해, 메모이다.
미리 정의된@태그들을 이용해서 주석 안에 정보를 저장하고, javadoc.exe라는 프로그램이 이를 읽어서 문서를 작성하는데 사용한다.
👉🏻 이를 이용하여 소스코드 안에 다른 프로그램을 위한 정보를 미리 약속된 형식으로 포함시킨 것이 애너테이션이다.
JDK에서 제공하는 애너테이션은 java.lang.annotation 패키지에 포함되어 있다.
자바에서 기본적으로 제공하는 애너테이션은 몇 개 없다. 그나마 이들의 일부는 메타 애너테이션으로, 애너테이션을 정의하는데 사용되는 애너테이션의 애너테이션이다.
| 애너테이션 | 설명 |
|---|---|
| @Override | 컴파일러에게 오버라이딩하는 대상이라는 것을 알린다. |
| @Deprecated | 앞으로 사용할 것을 권장하는 대상에 붙인다. |
| @SuppressWarning | 컴파일러의 특정 경고가 나타나지 않게 해준다. |
| @FunctionalInterface | 함수형 인터페이스라는 것을 알린다. |
| @SafeVarargs | 제네릭스 타입의 가변인자에 사용. |
| @Native | native메서드에서 참조되는 상수 앞에 붙인다. |
컴파일러가 같은 이름의 메서드가 조상에 있는지 확인하고 없으면 에러 메세지를 출력한다. 이는 알아내기 어려운 실수를 미연에 방지해주므로 반드시 붙이는 것이 좋다.
애너테이션을 위한 애너테이션으로, 애너테이션을 정의할 때 애너테이션 적용대상(target)이나, 유지기간(retention)을 지정하는데 사용된다.
| 애너테이션 | 설명 |
|---|---|
| @Target | 애너테이션이 적용가능한 대상을 지정하는데 사용 |
| @Documented | 애너테이션 정보가 작성된 문서에 포함되게 한다. |
| @Inherited | 애너테이션이 자손 클래스에 상속되도록 한다. |
| @Retention | 애너테이션이 유지되는 범위를 지정하는데 사용. |
| @Repeatable | 애너테이션을 반복해서 적용 가능하게 한다. |