제네릭이란
프로그램에서 변수와, 메소드를 선언할 때 자료형을 선언해줍니다.
대부분 하나의 자료형으로 구현되지만, 변수나 메소드의 자료형을 필요에 따라
여러 자료형으로 사용할 수 있다면 프로그램을 유연하게 사용할 수 있을 겁니다.
이와 같이 어떤 값이 하나의 참조 자료형이 아닌
여러 참조형을 사용할 수 있도록 프로그래밍하는 것을 제네릭(generic)이라고 합니다.
제네릭은 클래스나 메소드에서 사용할 내부 데이터 타입을 컴파일 시, 미리 지정하는 방법입니다.
제네릭을 사용하면 참조 자료형이 변환될 때 이에 대한 검증을 컴파일러가 하므로 아래와 같은 장점이 있습니다.
- 클래스와 메소드 내부 객체의 타입 안정성을 높임
- 반환 값에 대한 타입 변환 및 타입 검사에 들어가는 노력이 줄어듦
그럼 코드를 통해 자세한 사용법을 알아보겠습니다.
제네릭 정의와 선언
일반적인 클래스와 같이 정의하지만 클래스명 뒤에 <>(다이아몬드 연산자)가 있는 것을 확인할 수 있습니다.
class 클래스명<T>{ ... }
// T는 자료형의 타입
이는 자료형의 타입을 나타내는 타입 파라미터로 아래와 같이 다양한 파라미터를 사용할 수 있습니다.
타입 파라미터 | 설명 |
<T> | Type |
<E> | Element |
<K> | Key |
<N> | Number |
<V> | Value |
<R> | Result |
그러면 클래스를 더 구체화해보겠습니다.
class GenericClass<T>{ // T는 자료형의 타입
private T var;
public void set(T t) {
var = t;
}
public T get() {
return var;
}
}
set은 타입별로 파라미터를 받아 변수에 저장해주고 get은 변수를 리턴해주는 메소드입니다.
그러면 아래 코드에서 선언과 동시에 어떻게 사용하는지 확인해보겠습니다.
public class GenericEx {
public static void main(String[] args) {
GenericClass<String> genStr = new GenericClass<>(); // String으로 선언
genStr.set("hello world");
System.out.println("String 타입의 변수 : "+ genStr.get());
GenericClass<Integer> genInt = new GenericClass<>(); // Integer로 선언
genInt.set(100);
System.out.println("Integer 타입의 변수 : "+genInt.get());
}
}
매개변수의 타입에 String과 Integer를 넣어도 둘 다 실행이 잘 되는 것을 볼 수 있습니다.
왜 타입에 string과 int를 넣지 않았을까요?
그 이유는 제네릭에서는 선언할 수 있는 타입이 객체 타입이기 때문입니다.
int나 string은 기본자료형이기 때문에 제네릭의 타입으로 사용할 수 없습니다.
그럼 제네릭을 사용하지 않았을 때 어떤 불편함이 있는지 아래 코드로 알아보겠습니다.
class NonGenericClass{
private Object var;
public void set(Object o) {
var = o;
}
public Object get() {
return var;
}
}
클래스의 구성은 제네릭을 사용했을 때와 같지만 타입 파라미터를 받는 대신
최상위 클래스인 Object로 변수를 지정해주고 리턴하는 것을 볼 수 있습니다.
선언부에서 제네릭 없이 선언하게 되면 아래와 같이 데이터를 주고받음에 있어 형 변환이 필요하게 됩니다.
public class NonGeneric {
public static void main(String[] args) {
NonGenericClass ng = new NonGenericClass();
String str = "hello world";
ng.set(str); // 서브 클래스(String) -> 슈퍼 클래스(Object) = 자동 형변환
// 슈퍼 클래스(Object) -> 서브 클래스(String) = 직접 형변환을 해주어야 함
String str2 = (String)ng.get();
}
}
이와 같이 자식 클래스에서 데이터를 꺼내올 때는 원래의 타입으로 형 변환이 필요하게 되지만
제네릭 같은 경우 선언할 때 타입을 지정해주면 그 타입의 객체만 사용할 수 있음으로 별도의 형 변환이 필요 없게 됩니다.
이로써 타입 체크와 형 변환을 생략할 수 있으므로 코드가 간결해지고 성능의 향상을 기대할 수 있습니다.
'Java, JSP' 카테고리의 다른 글
[Java/자바] 해시맵, HashMap 사용법과 EntrySet, Iterator (0) | 2022.01.11 |
---|---|
[Java/자바] 객체 비교, equals()와 hashCode() (0) | 2022.01.10 |
[Java/자바] StringBuffer와 StringBuilder의 차이, 사용법 (0) | 2022.01.07 |
[Java/자바] 예외처리 (try - catch - finally), 사용자 정의 예외 (0) | 2022.01.04 |
[Java/자바] 내부클래스(Inner Class) - 인스턴스 클래스, 정적 클래스, 지역 클래스, 익명 클래스 (2) | 2022.01.04 |
댓글