손영배 블로그 누구나 쉽게 이해하고 습득하기

제네릭이 무엇인가? 본문

Interview

제네릭이 무엇인가?

손영배 2019. 8. 30. 12:15

왜 제네릭을 사용해야 하는가?

-  제네릭은 클래스, 인터페이스, 메소드를 정의할 때 타입(Type)을 파라미터(parameter)로 사용할 수 있도록 한다.

- 타입 파라미터는 코드 작성 시 구체적인 타입으로 대체되어 다양한 코드를 생성하도록 해준다.

 

장점

- 제네릭 타입을 이용함으로써 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다.

- 컴파일 시 강한 타입 체크를 할 수 있다.

 

- 타입 변환(casting)을 제거한다.

비제네릭 코드는 불필요한 타입 변환 하기 때문에 프로그램 성능에 악영향을 미친다.

List list = new ArrayList();
list.add("hello");
String str = (String) list.get(0); //

List에 저장되는 요소를 String 타입으로 국한하기 때문에 요소를 찾아올 때 타입 변환을  할 필요가 없어 프로그램 성능이 향상된다.

List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0); //타입 변환을 하지 않는다.

 

제네릭 타입(class<T>, interface<T>)

- 제네릭 타입은 타입을 파라미터로 가지는 클래스와 인터페이스를 말한다. 

public class 클래스명<T> {...}
public interface 인터페이스명<T> {...}

 

- 타입 변환이 빈번해지면 전체 프로그램 성능에 좋지 못한 결과를 가져올 수 있다. 성능저하

//문제점을 야기하는 코드
public class Box{
	private Object object;
    public void set(Object object) { this.object = object; }
    public Object get() { return object; }
 }
 
 public class Apple { }
 
 public class BoxExample {
 	public static void main(String[] args){
    	Box box = new Box();
        box.set("홍길동");					 // String -> Object (자동 타입 변환)	
        String name = (String) box.get();	// Object -> String (강제 타입 변환)
 		
        box.set(new Apple());				//Apple  -> object(자동 타입 변환)
        Apple apple = (Apple) box.get();    //Object -> Apple (강제 타입 변환)
 	}
 }
//제네릭으로 해결
public class Box<T> {
	private T t;
    public T get() { return t };
    public void set(T t) { this.t = t; }
}

public class BoxExample {
	public static void main(String[] args) {
    	Box<String> box1 = new Box<String> ();	
		box1.set("hello");
		String str = box1.get();
        
        Box<Integer> box2 = new Box<Integer>();
        box2.set(6);
        int value = box2.get();
	}
}

//제네릭은 클래스를 설계할 때 구체적인 타입을 명시하지 않고, 타입 파라미터로 대체했다가
//실제 클래스가 사용될 때 구체적인 타입을 지정함으로써 타입 변환을 최소화 시킨다.

 

멀티 타입 파라미터( class<K,V,.....>, interface<K, V, .......> )

public class Product <T, M>{
	private T kind;
	private M model;
	
	public T getKind() { return this.kind; }
	public M getModel() { return this.model; }
	
	public void setKind(T kind) { this.kind = kind; }
	public void setModel(M model) { this.model = model; }
	
	public static void main(String[] args) {
		Product<Tv, String> product1 = new Product<Tv, String>();
		product1.set(new Tv());
		product1.setModel("스마트Tv");
		Tv tv = product1.getKind();
		String tvModel = product1.getModel();
	}
}

제네릭 메소드( <T, R> R method(T t) )

- 제네릭 메소드는 매개타입과 리턴 타입으로 타입 파라미터를 갖는 메소드를 말한다.

public <타입파라미터...> 리턴타입 메소드명(매개변수, , ,..) { ... }
public <T> Box<T> boxing(T t ) { ... }

public class Util {

	public static <T> Box<T> boxing(T t) {
    	Box<T> box = new Box<T>();
        box.set(t);
        return box;
    }
    
    public static void main(String[] args) {
    	Box<Integer> box1 = Util.boxing(100);
        int intValue = box1.get();
        
        Box<String> box2 = Util.boxing("홍길동");
       	String strValue = box2.get();
    }
}