Generic(제네릭)
Generic(제네릭)을 사용해야 하는 이유
제네릭 타입을 사용함으로써 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 미리 제거할 수 있기 때문이다. 자바 컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해 제네릭 코드에 대해 강한 타입 체크를 한다. 실행 시 타입 에러가 나는 것보다는 컴파일 시에 미리 타입을 강하게 체크해서 에러를 사전에 방지하는 것이 좋다. 또 부가적인 효과로 제네릭 코드를 사용하면 타입을 국한하기 때문에 요소를 찾아올 때 타입 변환을 할 필요가 없어 프로그램 성능이 향상되는 효과를 얻을 수 있다.
Box클래스
public class Box {
private Object obj;
public void setObj(Object obj){
this.obj = obj;
}
public Object getObj(){
return obj;
}
}
BoxExam클래스
public class BoxExam {
public static void main(String[] args) {
Box box = new Box();
box.setObj(new Object());
Object obj = box.getObj();
box.setObj("hello");
String str = (String)box.getObj(); //형변환
System.out.println(str);
box.setObj(1);
int value = (int)box.getObj(); //형변환
System.out.println(value);
}
}
이 코드도 잘못된 코드는 아니다. getObj() 메소드는 파라미터로 Object를 받기 때문에 어떤 데이터 타입도 모두 받을 수 있다. 그러므로 box.getObj부분에 형변환만 잘 시켜주면 어떤 데이터 타입이든 저장할 수 있다.
하지만 만약 다른 데이터 타입을 setObj() 메소드 부분에 넣어준다면 컴파일은 되지만 실행하면 런타임에 오류가 나는 것을 확인할 수 있다.
Generic이라는 사용됨으로써 인스턴스를 만들때 사용하는 타입을 지정
Generic을 이용하여 Box 클래스 수정
public class Box<E> {
private E obj;
public void setObj(E obj){
this.obj = obj;
}
public E getObj(){
return obj;
}
}
- 클래스 이름 뒤에 <E>가 제네릭을 적용한 것이다. Box는 가상의 클래스 E를 사용한다는 의미.
- Object를 받아들이고, 리턴하던 부분이 E로 변경. E는 실제로 존재하는 클래스는 아니다.
Generic을 이용하여 수정한 Box를 이용하는 BoxExam클래스
public class BoxExam {
public static void main(String[] args) {
Box<Object> box = new Box<>();
box.setObj(new Object());
Object obj = box.getObj();
Box<String> box2 = new Box<>();
box2.setObj("hello"); //만약 다른 데이터타입을 넣으면 오류
String str = box2.getObj();
System.out.println(str);
Box<Integer> box3 = new Box<>();
box3.setObj(1); //만약 다른 데이터타입을 넣으면 오류
int value = (int)box3.getObj();
System.out.println(value);
}
}
- 참조 타입에<Object> , <String>, <Integer>가 있는 것을 볼 수 있다.
- 첫 번째는 Object를 사용하는 Box를 인스턴스로 만들겠다는 의미
- 두 번째는 String을 사용하는 Box인스턴스를 만들겠다는 의미
- 세 번째는 Integer를 사용하는 Box인스턴스를 만든다는 의미
* 자바에서 타입 변수 자리에 사용할 실제 타입을 명시할 때 기본 타입을 바로 사용할 수는 없다.
이때는 위 예제의 Integer와 같이 래퍼(wrapper) 클래스를 사용해야만 한다.
또한, Java SE 7부터 인스턴스 생성 시 타입을 추정할 수 있는 경우에는 타입을 생략할 수 있다.
MyArray<Integer> myArr = new MyArray<>(); // Java SE 7부터 가능함.