열거형은 서로 연관된 상수들의 집합을 말한다.
//예시
enum Seasons { SPRING, SUMMER, FALL, WINTER }
enum Frameworks { DJANGO, SPRING, NEST, EXPRESS }
열거형에서 사용할 수 있는 메서드는 맨 아래 공식 문서 링크에서 확인할 수 있다.
(object에 정의된 메서드를 사용할 수 있었던것과 동일하다.)
제네릭을 배우기 전에 사용했던 방법은 a클래스가 int로 지정되어 있으면 a클래스를 통해 만들어진 인스턴스는 int타입의 데이터로만 저장할 수 있었다.
또, a클래스와 같은 기능인데 다른 타입의 데이터를 저장하게 하려면 각 타입별로 같은 내용의 클래스를 만들어줘야했다.
근데 제네릭을 사용하면 이런 수고를 하지 않아도 된다...
정리하면, 제네릭을 사용하면 한개의 클래스로 모든 타입의 데이터를 저장할 수 있는 인스턴스를 만들 수 있다.
클래스 또는 메서드의 코드가 특정 데이터 타입에 한정되지 않게 해둔것이다.
class Basket<T> {
private T item;
public Basket(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public void setItem(T item) {
this.item = item;
}
}
//이런식으로 클래스를 만들고
Basket<String> basket1 = new Basket<String>("기타 줄");
//이렇게 인스턴스화 해서 사용한다.
주의할 점
class Basket<T> {
private T item1; // O
static T item2; // X
}
클래스 변수에 타입 매개변수를 사용하게되면, 위 클래스로 만든 인스턴스들이 공유하는 클래스 변수의 타입이 서로 달라지게 되어서, 클래스 변수를 통해 같은 변수를 공유하는 것이 아니게 된다.
그래서 Static이 붙은 변수 또는 메서드에는 타입 매개변수를 사용할 수 없다.
특정 클래스를 상속받은 클래스만 타입으로 지정할 수 있도록 제한할 수 있다.
class Rose extends Flower { ... }
//이렇게 작성해서 사용한다.
class Basket<T extends Flower> {
private T item;
특정 인터페이스를 구현한 클래스만 타입으로 지정할 수 있도록 제한하는 것도 가능하다.
이때도 extends를 사용한다.
위 예제들처럼 클래스 전체를 제네릭으로 선언할 수도 있고, 특정 메서드만 제네릭으로 선언하는 것도 가능하다.
이것을 제네릭 메서드라고한다.
제네릭 메서드의 타입 매개 변수 선언은 반환타입 앞에서 이루어지며, 해당 메서드 내에서만 선언한 타입 매개 변수를 사용할 수 있다.
class Basket {
...
public <T> void add(T element) {
...
}
}
제네릭 메서드의 타입 매개 변수는 제네릭 클래스의 타입 매개 변수와 변개이다.
아래와 같이 T라는 타입 매개 변수명을 사용한다 해도, 같은 알파벳을 이름으로 사용하는거고 서로 다은 타입 매개변수로 간주된다.
class Basket<T> { // 1 : 여기에서 선언한 타입 매개 변수 T와
...
public <T> void add(T element) { // 2 : 여기에서 선언한 타입 매개 변수 T는 서로 다른 것입니다.
...
}
}
제네릭 메서드의 타입 지정은 메서드가 호출될 때 이루어지기 때문이다.
또한 메서드 타입 매개 변수는 static 메서드에서도 사용 가능하다.
class Basket {
...
static <T> int setPrice(T element) {
...
}
}
제네릭 와일드카드
자바의 제네릭에서 와일드 카드는 어떠한 타입으로든 대체될 수 있는 타입 파라미터를 의미하며, 기호 ? 를 사용한다.
일반적으로 와일드카드는 extends와 super 키워드를 조합하여 사용한다.
<? extends T> //상한 제한 - T와 T를 상속받는 하위 클래스 타입만 타입 파라미터로 받을 수 있도록 지정한다.
<? super T> //하한 제한 - T와 T의 상위 클래스만 타입 파라미터로 받도록 한다.