JAVA

[Java.5-1] 제네릭 클래스

식빵민 2022. 5. 20. 14:29

제네릭(Generic) : 데이터의 타입을 일반화 하는것

  • 매개변수를 표시할 때 다양한 타입 지원을 위한 일반화된 매개변수 <>(타입 매개변수)로 표현
  • 여러 타입으로 구체화 가능
  • 제네릭 클래스 : 원시 타입을 타입 매개변수로 정의한 클래스

 

제네릭이 필요한 이유

  • 어떤 클래스를 구현할때, 여러 데이터 타입에 대해 각각 구현해야 함
  • 혹은 Object 클래스로 업캐스팅을 활용해서 Object 객체로 일반화시켜야 함
    • int, double --(wrapper)-> Integer, Double 사용할때마다 downcasting 해줘야 됨
    • int -> Double 인 경우 컴파일 단계에서는 멀쩡해도, 실행단계에서 Runtime 오류가 발생할 수 있음.
//여러 타입에 대해 각각 구현
class IntStack{
    ...
    void push(int n){}
    int pop(){}
    ...
}

class DoubleStack{
    ...
    void push(double d){}
    int pop(){}
    ...
}
  • 제네릭으로 해결 가능 : 타입 매개변수를 활용, 실제 타입은 객체생성시에 결정
//제네릭 사용방법
class Stack <T>{//T는 나중에 객체 생성시에 정해짐
    ...
    void push(T t){}
    T pop(){}
    ...
}

타입 매개변수

  • '<'와 '>'사이에 하나의 대문자를 임의로 지정, 타입매개변수로 사용
  • 제네릭 타입 매개변수는 객체 , 나중에 실제 타입으로 구체화
//객체 타입 지정
Stack <Integer> si = new Stack<Integer>();//T를 Integer로 지정
//자동 타입 추론
Stack <Integer> si = new Stack<>();//T를 Integer로 추론

 * 명확한 프로그래밍을 위해 타입 지정을 추천합니다!

  • 자주 사용되는 문자
    E : element
    T : type
    K : key
    V : value
  • 실제 타입으로 구체화할때, 기본 타입 사용 불가
Stack<int> si = new Stack <int>();//!!컴파일 오류!!
//->Wrapper 클래스 사용
Stack<Integer> si = new Stack <Integer>();

 

제네릭 클래스 구현

public class MyClass<T>{
    T val;
    void set(T val){
    	this.val = val;
    }
    T get(){
    	return val;
    }
}

제네릭 클래스로 객체 생성

//객체 생성
MyClass<String> s = new MyClass<String>();

//T가 String으로 구체화
public class MyClass<String>{
	String val;
    void set(String val){
    	this.val = val;//String 타입의 값 val을 this.val에 지정
    }
    String get(){
    	return val;//String 타입의 값 val을 반환
    }
}

제네릭의 강점

  • 컴파일 시 타입이 결정되어 보다 안전한 프로그래밍을 할 수 있다.
  • 런타임 타입 충돌 문제를 방지할 수 있다