자바로 개인 프로젝트를 하다 보면, 인터페이스에 제너릭을 사용해야하는 경우가 있다. 그런데 사실 제너릭은 컬렉션에서만 사용해보고 제너릭을 사용해서 인터페이스나 클래스를 만들어 본 적은 없었다. 그래서 제너릭을 복습하는 차원에서 포스팅을 해보려고 한다.
이번 포스팅은 제너릭을 사용하는 이유
에 대해서 이다.
우선, 공식 문서에서 제너릭을 사용하는 이유는 다음과같다.
1. 컴파일 타임에 타입을 검사할 수 있다.
2. 캐스트를 사용하지 않아도 된다.
첫 번째 이유에 대해 생각을 해보자.
보통 자바의 컬렉션에서 제너릭을 사용한다. 그렇다면 제너릭을 컬렉션에서 왜 사용하는 걸까?
컴파일 시점에 타입을 체크할 수 있게 해준다.
//제너릭을 사용함으로써 컴파일 시점에 타입을 체크할 수 있다.
List < String > lists = new ArrayList<>();
lists.add("문자열 타입");
lists.add(123); //컴파일 에러
// 제너릭을 사용하지 않는다면 한 컬렉션에 다른 타입의 요소가 들어가는 것을 컴파일 에러가 아닌 런타임에 발견한다.
List lists = new ArrayList();
lists.add("문자열 타입");
lists.add(123);
두 번째 이유를 이해하기 위해서 제너릭을 사용하지 않는 경우를 먼저 살펴보자.
public class NoGeneric {
private Object object;
public void setObject(Object object) {
this.object = object;
}
public Object getObject() {
return object;
}
}
NoGeneric noGeneric1 = new NoGeneric();
noGeneric1.setObject("문자열");
String a = (String) noGeneric1.getObject(); //String 타입으로 캐스팅
NoGeneric noGeneric2 = new NoGeneric();
noGeneric2.setObject(123);
Integer b = (Integer) noGeneric2.getObject(); //Integer 타입으로 캐스팅
NoGeneric noGeneric3 = new NoGeneric();
noGeneric3.setObject(1.1);
Double c = (Double) noGeneric3.getObject(); //Double 타입으로 캐스팅
위 코드를 보면 그냥 캐스팅 하면 안되나??
라고 생각할 수 도 있지만, 이렇게 다운 캐스팅하는 것 또한 런타임에 오류가 발생할 가능성이 있기 때문에 지양하는 것이 좋다.
NoGeneric noGeneric1 = new NoGeneric();
noGeneric1.setObject("문자열");
//실제로 문자열 타입이어야 하지만 Intger 타입으로 해도 컴파일 오류가 나지 않고 런 타임에 오류를 발견한다.
Integer a = (Integer) noGeneric1.getObject();
String a = (String) noGeneric1.getObject();
제너릭을 사용하는 경우를 살펴 보면, 아래 코드와 같이 표현할 수 있다. Object가 들어갔던 타입에 T라는 알파벳을 적었다.
public class YesGeneric<T> {
private T object;
public void setObject(T object) {
this.object = object;
}
public T getObject() {
return object;
}
}
이렇게 제너릭 타입으로 작성을 하게 되면 캐스팅을 하지 않아도 되고, 컴파일에 오류를 발견할 수 있다.
YesGeneric < String > yesGeneric1 = new YesGeneric<>();
yesGeneric1.setObject("문자열");
String a = yesGeneric1.getObject();
YesGeneric < Integer > yesGeneric2 = new YesGeneric<>();
yesGeneric2.setObject(1);
Integer b = yesGeneric2.getObject();
YesGeneric < Double > yesGeneric3 = new YesGeneric<>();
yesGeneric3.setObject(1.1);
Double c = yesGeneric3.getObject();
Reference