제네릭 이해하기
제네릭이란?
자료형을 파라미터화 하여 컴파일시에 구체적인 타입이 결정되도록 하는 기능입니다. 제네릭을 사용하면 컴파일시 타입체크가 가능하여 실행시 자료형 에러가 발생하는 상황을 사전에 방지하고 컴파일시에 미리 타입을 확인할 수 있습니다.
public class Car<T> {
private T t;
public void setter(T t){
this.t=t;
}
public T getter(){
return t;
}
}
위의 예시에서 Car라는 클래스를 만드는 경우 클래스 내에서 어떠한 자료형을 사용할지 설정하지 않고 Car옆에 <T>를 적어주게 되는데 이러한 표현이 제네릭입니다. T는 자료형을 아직 결정하지 않은 상태이고 개발코드를 작성시 T대신에 들어가는 자료형이 T를 대신하게 됩니다. 꼭 T가 될 필요는 없습니다.
public static void main(String[] args){
Car<String> car = new Car<>(); // Car<String>();으로 작성하여도 무관합니다.
car.setter("myCar");
System.out.println(car.getter()); // myCar출력
Car<Integer> carPrice = new Car<>();
carPrice.setter(1000);
System.out.println(carPrice.getter()); // 1000 출력
}
Car<T>클래스를 만들어 두었고 클래스를 이용할 때는 Car<String>으로 불러와서 사용하였습니다. 이러한 경우 Car<T>에서 T가 String으로 입력 받았기 때문에 String으로 활용됩니다. Car<Integer>로 T를 Integer로 사용한 경우 Integer를 받게 되고 getter를 통하여 Integer값이 반환됩니다. 이러한 식으로 사용할 타입을 T와 같이 임의의 값으로 작성해두고 사용시 결정을 할 수 있습니다.
멀티 타입 파라미터
제네릭을 사용시 두 개 이상의 자료형을 사용할 수 있습니다.
public class Phone<B,M>{
prviate B b;
private M m;
public void setB(B b){
this.b=b;
}
public B getB(){
return b;
}
public void setM(M m){
this.m=m;
}
public M getM(){
return m;
}
}
위의 예시와 같이 B와 M을 넣어주게되면 두개의 자료형을 제네릭으로 사용할 수 있습니다. Phone이라는 클래스를 사용시 B와 M을 정해주게 되면 예시의 B와 M이 정해지게 됩니다.
public static void main(String[] args){
Phone<String, String> phone = new Phone<>();
phone.setB("Samsung");
phone.setM("galaxy");
System.out.println(phone.getB());//Samsung 출력
System.out.println(phone.setM());//galaxy 출력
}
위의 예시에서는 B와 M을 String으로 설정하였지만 다른 자료형도 가능하며 직접 만든 자료형도 올 수 있습니다. 따라서 여러자료형을 사용하는 경우 이와 같이 멀티 타입 파라미터도 가능합니다.
제네릭 메서드란?
일반적인 메서드와 비슷하지만 입력받는 매개변수의 자료형이 제네릭인 경우를 제네릭 메서드라고 합니다.
public class Test {
public static void main(String[] args) {
Integer num1 = 1;
Integer num2 = 2;
String name1 = "홍길동";
String name2 = "이순신";
Test.<Integer,String>print(num1,name1); //Test는 현재 클래스
}
public static <T,M> void print(T t,M m){
String type1 = t.getClass().getSimpleName();
String type2 = m.getClass().getSimpleName();
switch(type1) {
case "String":
System.out.println((String)t);
break;
case "Integer":
System.out.println((int)t);
break;
default :
System.out.println("자료형을 알 수 없습니다.");
break;
}
switch(type2) {
case "String":
System.out.println((String)m);
break;
case "Integer":
System.out.println((int)m);
break;
default :
System.out.println("자료형을 알 수 없습니다.");
break;
}
}
}
위와 같이 print라는 메서드를 만들면 매개변수의 자료형을 제네릭을 사용하였습니다. 메서드 내에서 t와 m의 자료형을 구해서 switch를 통하여 각 타입마다 어떠한 문장을 출력할 것인지 설정을 하였습니다. 메서드를 사용할 때는 메서드 이름 앞에<>를 통하여 자료형을 지정해 주고 ()안에 들어갈 변수를 작성해주시면 됩니다. 위의 예시의 경우 출력은 1과 홍길동이 출력됩니다.