Java에서 제네릭(Generic)은 클래스, 인터페이스, 메서드 등에 사용할 수 있는 타입 매개변수화 기법을 말한다.
제네릭을 사용하면 컴파일 시 타입을 체크할 수 있으며, 코드의 재사용성을 높이고, 타입 안정성을 보장할 수 있다.
제네릭은 자바 5에서 도입되었으며, 주로 컬렉션 프레임워크에서 많이 사용된다.
제네릭의 주요 특징
타입 안전성(Type Safety) 보장
컴파일 시점에 타입을 체크하여 런타임 에러를 줄일 수 있다
타입 캐스팅 제거
제네릭을 사용하면 불필요한 타입 캐스팅을 제거할 수 있다
코드 재사용성 증가
다양한 타입에 대해 동일한 코드를 사용할 수 있다
제네릭의 기본 사용법
제네릭 클래스
제네릭 클래스는 클래스 선언 시 타입 매개변수를 사용하여 정의할 수 있다
다음은 제네릭 클래스를 사용하는 예제이다
public class Box<T> {
private T item;
public void setItem(T item) {
this.item = item;
}
public T getItem() {
return item;
}
public static void main(String[] args) {
Box<String> stringBox = new Box<>();
stringBox.setItem("Hello");
System.out.println(stringBox.getItem());
Box<Integer> integerBox = new Box<>();
integerBox.setItem(123);
System.out.println(integerBox.getItem());
}
}
위의 예제에서 Box<T>는 제네릭 클래스이다
T는 타입 매개변수로, Box 클래스 내부에서 실제 타입으로 대체된다
제네릭 메서드
제네릭 메서드는 메서드 선언에 타입 매개변수를 사용할 수 있다
public class GenericMethodExample {
public static <T> void printArray(T[] array) {
for (T element : array) {
System.out.print(element + " ");
}
System.out.println();
}
public static void main(String[] args) {
Integer[] intArray = {1, 2, 3, 4, 5};
String[] stringArray = {"A", "B", "C", "D", "E"};
printArray(intArray);
printArray(stringArray);
}
}
위의 예제에서 printArray 메서드는 제네릭 메서드이다
T는 메서드의 타입 매개변수이다
제네릭 인터페이스
제네릭 인터페이스는 인터페이스 선언 시 타입 매개변수를 사용할 수 있다
public interface Pair<K, V> {
public K getKey();
public V getValue();
}
class OrderedPair<K, V> implements Pair<K, V> {
private K key;
private V value;
public OrderedPair(K key, V value) {
this.key = key;
this.value = value;
}
@Override
public K getKey() { return key; }
@Override
public V getValue() { return value; }
public static void main(String[] args) {
Pair<String, Integer> p1 = new OrderedPair<>("One", 1);
Pair<String, String> p2 = new OrderedPair<>("Hello", "World");
System.out.println("Pair 1: " + p1.getKey() + " = " + p1.getValue());
System.out.println("Pair 2: " + p2.getKey() + " = " + p2.getValue());
}
}
위의 예제에서 Pair<K, V>는 제네릭 인터페이스이며, OrderedPair<K, V>는 이를 구현한 제네릭 클래스이다
제네릭 타입 제한 (Bounded Type Parameters)
제네릭 타입에 특정 타입만 허용하도록 제한할 수 있다
이는 extends 키워드를 사용하여 구현할 수 있다
public class BoundedTypeParameterExample {
public static <T extends Number> void printNumber(T number) {
System.out.println("Number: " + number);
}
public static void main(String[] args) {
printNumber(123); // Integer
printNumber(45.67); // Double
// printNumber("123"); // 컴파일 오류
}
}
위의 예제에서 T extends Number는 T가 Number 클래스 또는 그 하위 클래스여야 함을 의미한다
와일드카드(Generic Wildcards)
와일드카드는 제네릭 타입을 보다 유연하게 사용할 수 있도록 도와준다
무제한 와일드카드 <?>
상한 경계 와일드카드 <? extends Type>
하한 경계 와일드카드 <? super Type>
와일드카드 예제
import java.util.List;
import java.util.ArrayList;
public class WildcardExample {
public static void printList(List<?> list) {
for (Object elem : list) {
System.out.print(elem + " ");
}
System.out.println();
}
public static void main(String[] args) {
List<Integer> intList = new ArrayList<>();
intList.add(1);
intList.add(2);
intList.add(3);
List<String> stringList = new ArrayList<>();
stringList.add("A");
stringList.add("B");
stringList.add("C");
printList(intList);
printList(stringList);
}
}
위의 예제에서 printList 메서드는 무제한 와일드카드를 사용하여 모든 타입의 리스트를 인자로 받을 수 있다
요약
제네릭은 자바에서 타입을 매개변수화하여 코드의 재사용성을 높이고, 컴파일 시 타입 체크를 통해 타입 안전성을 보장하는 강력한 기법이다
제네릭 클래스, 제네릭 메서드, 제네릭 인터페이스, 와일드카드 등 다양한 기능을 통해 복잡한 타입 관계를 표현할 수 있다
이를 적절히 사용하면 더 안전하고 유지보수하기 쉬운 코드를 작성할 수 있다
'Job Interview Prep' 카테고리의 다른 글
ktlint 자동적용 안 되는 경우 해결법 (0) | 2024.06.02 |
---|---|
String과 StringBuilder, StringBuffer의 차이 (0) | 2024.05.31 |
Java volatile / synchronized (0) | 2024.05.31 |
JavaBean (1) | 2024.05.31 |
Java의 다형성(Polymorphism) (0) | 2024.05.31 |