Continuous Challenge

[이것이 자바다] 제네릭이란? 본문

Study/이것이 자바다

[이것이 자바다] 제네릭이란?

응굥 2023. 3. 15. 21:26
728x90
728x90

Box 클래스를 선언하려고 한다. Box의 내용물 content 필드를 선언하려고 할 때, 타입을 무엇으로 해야 할까?

Box 는 다양한 내용물을 저장해야 하므로 특정 클래스 타입으로 선언할 수 없다. 그래서 Object 타입으로 선언한다.

public class Box {
	public Object content;
}

Object 타입은 모든 클래스의 최상위 부모 클래스이다. 그렇기 때문에 content 필드에는 어떤 객체든 대입이 가능하다.

 

문제는 Box 안의 내용물을 얻을 때이다. content 는 Object 타입이므로 어떤 객체가 대입되어 있는지 알 수 없다. 

이 때 대입된 내용물의 타입을 안다면 강제 타입 변환을 거쳐 얻을 수 있다.

String content = (String) box.content;

어떤 내용물이 저장되어 있는지 모른다면 instanceof 연산자로 타입을 조사할 수는 있지만 모든 종류의 클래스를 대상으로 조사할 수는 없다. 따라서 Object 타입으로 content 필드를 선언하는 것은 좋은 방법이 아니다.

 

JDK 1.5 이전에서는 여러 타입을 사용하는 대부분의 클래스나 메소드에서 인수나 반환값으로 Object 타입을 사용했다.
하지만 JDK 1.5부터 도입된 제네릭을 사용하면 컴파일 시에 미리 타입이 정해지므로, 타입 검사나 타입 변환과 같은 번거로운 작업을 생략할 수 있다.

 

Box를 생성하기 전에 우리는 어떤 내용물을 넣을지 이미 알고 있다. 따라서 Box를 생성할 때 저장할 내용물의 타입을 미리 알려주면 Box는 content에 무엇이 대입되고, 읽을 때 어떤 타입으로 제공할지를 알게 된다. 이것이 제네릭이다.

 

제네릭(Generic)이란 결정되지 않은 타입을 파라미터로 처리하고
실제 사용할 때 파라미터를 구체적인 타입으로 대체시키는 기능


제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시에 미리 지정하는 방법이다.


컴파일 시에 미리 타입 검사(type check)를 수행할 때의 장점

1. 클래스나 메소드 내부에서 사용되는 객체의 타입 안정성을 높일 수 있다.
2. 반환값에 대한 타입 변환 및 타입 검사에 들어가는 노력을 줄일 수 있다.

 

제네릭의 제거 시기

자바 코드에서 선언되고 사용된 제네릭 타입은 컴파일 시 컴파일러에 의해 자동으로 검사되어 타입 변환된다.
그리고 코드 내의 모든 제네릭 타입은 제거되어, 컴파일된 class 파일에는 어떠한 제네릭 타입도 포함되지 않게 된다.
이런 식으로 동작하는 이유는 제네릭을 사용하지 않는 코드와의 호환성을 유지하기 위해서이다.


public class Box<T> {
	public T content;
}

Box 클래스에서 결정되지 않은 content의 타입을 T라는 타입 파라미터로 정의한 것이다.

<T>는 T가 타입 파라미터임을 뜻하는 기호로, 타입이 필요한 자리에 T를 사용할 수 있음을 알려주는 역할을 한다.

Box<String> box1 = new Box<String>();
box1.content = "안녕하세요.";
String str = box1.content;

Box의 내용물로 String을 저장하고 싶다면 타입 파라미터 T 대신 String으로 대체하면 된다. 

//Box<String> box1 = new Box<String>();
Box<String> box1 = new Box<>();

변수를 선언할 때와 동일한 타입으로 호출하고 싶다면 생성자 호출 시 생성자에는 타입을 명시하지 않고 <>만 붙일 수 있다.

 


예제

public class Box<T> {
	public T content;
}
public class GenericExample {
	public static void main(String[] args) {
		Box<String> box1 = new Box<>(); 
		box1.content = "안녕하세요.";
		String str = box1.content;
		System.out.println(str);

		/* Box의 내용물로 100을 저장하고 싶다면 타입 파라미터 T 대신 Integer로 대체하면 된다. */
		//Box<Integer> box2 = new Box<Integer>();
		Box<Integer> box2 = new Box<>();
		box2.content = 100;
		int value = box2.content;
		System.out.println(value);
	}
}

실행결과

안녕하세요
100

참고

http://www.tcpschool.com/java/java_generic_concept

728x90
728x90
Comments