Java 5 부터 제네릭 (Generic) 타입이 새로 추가되었다.
제네릭을 사용해서 잘못된 타입이 사용될 수 있는 문제를 컴파일 과정에서 제거할 수 있다.
제네릭은 클래스, 인터페이스, 메소드를 정의할 때 타입(type) 을 파라미터로 사용할 수 있도록 한다.
타입 파라미터는 코드 작성 시 구체적인 타입으로 대체되어서 다양한 코드를 생성하도록 해준다.
1. 제네릭의 장점
- 컴파일 시 강한 타입 체크를 할 수 있다.
컴파일러는 코드에서 잘못 사용된 타입 때문에 발생하는 문제점을 제거하기 위해
제네릭 코드에 대해 강한 타입 체크를 한다.
실행 시 타입 에러가 나는 것보다 컴파일 시에 미리 타입을 강하게 체크해서 에러를 사전에 방지한다.
- 타입 변환(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); // 타입 변환을 하지 않는다. (필요X)
2. 제네릭 타입 Class<T>, interface<T>
타입을 파라미터로 가지는 클래스와 인터페이스를 말한다.
제네릭 타입은 클래스, 인터페이스 이름 뒤에 "< >" 부호가 붙고, 사이에 타입 파라미터 T 가 위치한다.
public class 클래스명<T> { . . . }
public interface 인터페이스명<T> { . . . }
- 타입 파라미터는 변수명과 동일한 규칙에 따라 작성한다.
(일반적으로 대소문자 알파벳 한 글자로 표현)
① Object 클래스를 사용하는 경우
예) Box 클래스
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
Object 타입 선언 : 필드에 모든 종류의 객체를 저장하려는 의도.
Object 클래스는 모든 자바 클래스의 최상위 클래스이다.
따라서 자식 객체는 부모 타입에 대입할 수 있다는 성질을 통해 모든 자바 객체는
Object 타입으로 자동 타입 변환되어 저장된다.
Object object = 자바 모든 객체;
set() 메소드는 매개 변수 타입으로 Object 를 사용함으로써 자바의 모든 객체를 받을 수 있고,
받은 매개값을 Object 필드에 저장시킨다.
get() 메소드는 Object 필드에 저장된 객체를 Object 타입으로 리턴한다.
만약 필드에 저장된 원래 타입의 객체를 얻으려면,
아래와 같이 강제 타입 변환을 해야 한다.
Box box = new Box();
box.set("hello"); // String 타입을 Object 타입으로 자동 타입 변환해서 저장
String str = (String) box.get(); // Object 타입을 String 타입으로 강제 타입 변환해서 얻음
Object 타입을 String 타입으로 강제 타입 변환을 해서 얻어야 한다.
예) Box.java : Box 클래스
public class Box {
private Object object;
public void set(Object object) { this.object = object; }
public Object get() { return object; }
}
Apple.java : Apple 클래스
public class Apple {
}
BoxExample.java : 비 제네릭 타입 이용 실행 클래스
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 강제 타입 변환
}
}
Object 타입을 사용하면 모든 종류의 자바 객체를 저장할 수 있는 장점이 있지만,
저장할 때 타입 변환이 발생, 읽어올 때도 타입 변환이 발생한다.
이러한 타입 변환이 빈번해지면 전체 프로그램 성능에 악영향을 미치게된다.
② 제네릭 사용
Box.java
public class Box<T> {
private T t;
public T get() { return t; }
public void set(T t) { this.t = t; }
}
타입 파라미터를 사용해서 Object 타입을 모두 T 로 대체했다.
T 는 Box 클래스로 객체를 생성할 때 구체적인 타입으로 변경된다.
Box<String> box = new Box<String>(); // Box 객체 생성
타입 파라미터 T 는 String 타입으로 변경되어 Box 클래스의 내부는 아래와 같이 자동으로 재구성된다.
public class Box<String> {
private String t;
public void set(String t) { this.t = t; }
public String get() { return t; }
}
필드 타입이 String 으로 변경되었고, set() 메소드도 String 타입만 매개값으로 받을 수 있게 변경되었다.
get() 메소드 역시 String 타입으로 리턴하도록 변경된다.
따라서 아래 코드를 실행하면 타입 변환이 전혀 발생하지 않는다.
Box<String> box = new Box<String>();
box.set("hello");
String str = box.get();
만약 아래와 같이 Box 객체를 생성한다면??
Integer 는 int 값에 대한 객체 타입으로 자바에서 제공하는 표준 API 이다. (래퍼 객체)
Box<Integer> box = new Box<Integer>();
타입 파라미터 T 는 Integer 타입으로 변경되어 Box 클래스는 내부적으로 아래와 같이 자동으로 재구성된다.
public class Box<Integer> {
private Integer t;
public void set(Integer t) { this.t = t; }
public Integer get() { return t; }
}
필드 타입 : Integer 로 변경
set() 메소드의 매개값 타입 : Integer 로 변경
get() 메소드의 리턴 타입 : Integer 로 변경
따라서 아래 코드를 실행하면 타입 변환이 전혀 발생하지 않는다.
Box<Integer> box = new Box<Integer> {
private Integer t;
public void set(Integer t) { this.t = t; }
public Integer get() { return t; }
}
제네릭은 클래스를 설계할 때 구체적인 타입을 명시하지 않고, 타입 파라미터로 대체했다가,
실제 클래스가 사용될 때 (객체 생성 시) 구체적인 타입을 지정함으로써 타입 변환을 최소화한다.
예)
Box.java : 제네릭 타입
public class Box<T> {
private T t;
public T get() { return t; }
public void set(T t) { this.t = t }
}
BoxExample.java : 제네릭 타입 이용 실행 클래스
public class BoxExample {
public static void main(String[] args) {
Box<String> box1 = new Box<String>();
box1.set("hello");
String str = box1.get();
Box<String> box2 = new Box<Integer>();
box2.set(6);
int value = box2.get();
}
}
'Java 심화 > 2. 제네릭 < >' 카테고리의 다른 글
2. Java 자바 제네릭 - 멀티 타입 파라미터( class<K, V . . . >, interface<K, V, . . .> ) (0) | 2020.11.06 |
---|