본문 바로가기

프로그래밍 언어 기초/JAVA

Chapter 12. 제네릭(Generic)

12. 1. 제네릭(Generic)이란?

 제네릭은 데이터의 타입 즉 자료형(Data Type)과 관련이 있습니다. Chapter 1.에서 자료형은 데이터(자료, Data)를 식별하기 위한 분류라고 했습니다. 그런데, 자료형은 변수라는 상자에 어떤 데이터를 담을 것인지 미리 선언하는 것인데, 앞으로 담을 데이터의 자료형을 알 수 없다면 어떨까요? 혹은 대응해야 할 자료형이 여러 가지라서 어디서나 보편적으로 쓸 수 있는 코드를 작성하고 싶다면 어떨까요? 이럴 때 사용할 수 있는 것이 바로 제네릭(Generic)입니다.

 

https://1-hee.tistory.com/2

 

chapter 1. 자바 변수와 연산자 그리고 메서드

1.1. 변수(Variable)이란? 컴퓨터 메모리에 자료(Data)를 저장하기 위한 공간으로 자료형(Type, 形)에 따라 그 크기가 다릅니다. 우리가 사용하는 컴퓨터는 기술의 발전으로 커다란 양의 데이터도 거뜬

1-hee.tistory.com

 

 제네릭은 다양한 타입의 객체를 다루는 메소드나 ArrayList와 같은 컬렉션 클래스에서 컴파일 시 타입을 체크합니다. 미리 사용할 타입을 명시하여 형 변환을 하지 않아도 되게 하는 역할을 하며 객체의 타입에 대한 안정성의 향상 및 형 변환의 번거로움을 감소시켜 줍니다.

 

 제네릭의 사용은 <>를 통해 할 수 있습니다. 클래스, 인터페이스, 메소드 등에서 사용할 수 있으며 <> 안에 작성되는 약어나 문자들은 타입 파라미터가 되어 의미상으로 타입을 지정하고 나중에 인스턴스를 생성할 때 지정하게 됩니다. 즉 <> 안에 Integer라고 작성한다고 해도, <> 안에서의 Integer는 자료형 Integer와 다른의미라는 것이지요.

 

타입 파라미터의 종류 (대체로 이런 의미로 사용한다는 뜻!)

T : reference Type

E : Element

K : Key

V : Value

 

제네릭의 선언

public class GenericClass1<T> { 
	// 제네릭에 <> 안에 <Integer>와 같이 직접 선언해 주더라도  
	// 이것은 타입 파라미터로 인식되어 자료형 Integer와 의미가 같지 않음.
	
	private T something;
	
	public T getSomething() {
		return something;
	}
}

 

제네릭의 사용

public class GenericTest {
	
	public static void main(String[] args) {
				
		GenericClass1<String> gc2 = new GenericClass1<>(); 
        // 제네릭은 객체 생성시 왼쪽에 반드시 자료형을  명시해주어야 한다.
		gc2.getSomething();
		
	}
	
}

 

 

 제네릭은 타입 파라미터에 제한을 둘 수도 있습니다. 필요에 따라 구체적인 타입 제한이 필요한 경우 extends 키워드를 사용해 타입을 제한할 수 있습니다. 가령 계산기를 만드는 프로그램에서 숫자와 관련된 자료형을 갖는 데이터를 사용하게 하고자 한다면, <T extends Number>와 같이 사용하여 제한 가능합니다. 만약 이 제약 조건을 여러 개 설정하고 싶다면 & 키워드를 사용해 추가할 수도 있습니다.

 

public class GenericRestrictClass1<T extends Number> {

	public T something;
	
	public T getSomething() {
		return something;
	}

}

 

제네릭 제약사항 테스트

public class GenericTest {
	
	public static void main(String[] args) {
						
		// 제약사항이 extends Number 였기에 Integer, Long, float, double 등이 사용 가능하다.
		GenericRestrictClass1<Integer> grc1 = new GenericRestrictClass1<>();
		grc1.getSomething();
		
		// 숫자형만 가능하므로 컴파일 오류!
		// GenericRestrictClass1<Character> grc2 = new GenericRestrictClass1<>();
		
	}	
}

 

또 다른 제약사항으로는 super가 있습니다. 이 제약 조건은 해당 자료형의 조상 타입만 가능하게 합니다.

 

public class GenericRestrictClass2<T super Parent> {

	public T something;
	
	public T getSomething() {
		return something;
	}

}

 

마지막으로 모든 자료형을 허용할 때에는 ? 라는 와일드 카드를 사용할 수 있습니다

 

public class GenericRestrictClass3 {

	boolean addAll(int idx, Collection<? extends Object> c) {
		return false;
	}
}

 

 

제네릭의 제약사항

제네릭 설명
<?> 모든 자료형(Object)
<? extends T> T 또는 T를 상속받은 타입들만 사용 가능
<? super T> T 또는 T 의 조상 타입만 사용 가능