JAVA/지네릭스
지네릭스(Generics)
chanhee01
2023. 8. 6. 15:39
지네릭스란 다양한 타입의 겍체들을 다루는 메서드나 컬렉션 클래스에 컴파일 시의 타입 체크를 해주는 기능이다.
class Box {
Object item;
void setItem(Object item) {
this.item = item;
}
Object getItem() {
return item;
}
}
지네릭스를 사용하기 전에는 이렇게 Object로 변수들을 선언했다.
ArrayList와 같은 컬렉션 클래스에서 다양한 종류의 객체를 담을 수 있긴 하지만 꺼낼 때마다 타입체크를 하고 형변환을 하는 것에 불편함이 있을 수 있다.
지네릭 클래스로 변경
class Box<T> {
T item;
void setItem(T item) {
this.item = item;
}
T getItem() {
return item;
}
}
클래스 옆에 <T>를 붙이고 Object 타입을 모두 T로 바꿔주면 된다.
public static void main(String[] args) {
Box<String> b = new Box<String>();
// Box<String> b = new Box<>(); 위의 코드와 동일 new Box<String>의 String은 생략 가능
b.setItem("ABC");
b.setItem(new Object()); // String 이외의 다른 타입은 에러
String item = b.getItem();
}
생성자를 만들 때 Box<T>의 T 부분에 변수 타입을 지정해준다. 그러면 setItem에 변수를 넣을 때 지정한 변수 타입이 아니면 에러가 발생한다. 위의 예제에서는 String을 넣었기 때문에 b.setItem(new Object()) 부분에서 에러가 발생하게 된다.
그리고 지네릭스를 사용하지 않았을 때에는 String item = (String) b.getItem(); 이라는 형변환이 필요했는데, 지네릭스를 사용할 때에는 별도의 형변환은 필요하지 않다.
중요한 것은 Box<String>가 Box<Integer>는 같은 클래스를 다른 타입으로 호출한 것이므로 서로 다른 클래스를 호출한 것은 아니다. 마치 매개변수의 값이 다른 같은 클래스를 호출한 것과 비슷하다 볼 수 있다.
public class Main {
public static void main(String[] args) {
Box<Food> foodBox = new Box<>();
Box<Cake> cakeBox = new Box<>();
// Box<Chicken> chickenBox = new Box<Cake>(); 같은 타입이 아니어서 에러
foodBox.add(new Food());
foodBox.add(new Chicken()); // Chicken이 food의 자손이라 가능
cakeBox.add(new Cake());
// cakeBox.add(new Food()); 자손 타입에 부모는 못 넣음
// cakeBox.add(new Water()); 타입 불일치
System.out.println(foodBox);
System.out.println(cakeBox);
}
}
class Food { public String toString() {return "Food";} }
class Cake extends Food { public String toString() {return "Cake";} }
class Chicken extends Food { public String toString() {return "Chicken";} }
class Water { public String toString() {return "Water";} }
class Box<T> {
ArrayList<T> list = new ArrayList<>();
void add (T item) {list.add(item);}
T get (int i) {return list.get(i);}
int size() {return list.size();}
public String toString() {return list.toString();}
}
위와 같이 상속받는 경우에도 사용할 수 있고, 타입으로 ArrayList를 선언한 경우에는 그 타입이나 자손 타입만 들어올 수 있다.