[JAVA] Generic
in JAVA
java에서 Generic이 무엇인지 알아보자.
Generic이란?
- 클래스나 메서드에서 사용할 데이터 타입을 지정하지 않고, 나중에 사용할 때 타입을 결정하는 기능
- 하나의 값이 여러 다른 데이터 타입들을 가질 수 있도록 하는 방법
- 클래스 내부에서 지정하는 것이 아닌, 외부에서 사용자에 의해 지정되는 것을 의미
- specific 타입을 미리 지정해주는 것이 아닌 필요에 의해 지정할 수 있도록 하는 generic 타입
- 제네릭을 사용하면 코드의 재사용성을 높이고, 타입 안정성을 보장할 수 있음
ArrayList<T>
,HashMap<K, V>
같은 자바 컬렉션 프레임워크에서 많이 사용됨
Generic의 장점
- 타입 안정성 (Type Safety) 보장
- 제네릭을 사용하면 컴파일 시점에 타입을 검사해서 타입 오류 방지 가능
- 예를 들어, ArrayList에 String만 저장하도록 지정하면 다른 타입을 추가하는 실수를 막을 수 있음
- 형변환(Casting) 불필요
- 제네릭을 사용하면 클래스 외부에서 타입을 지정해주기 때문에 따로 타입을 체크하고 변환할 필요 없음
- 관리하기 편함
- 코드의 재사용성 증가
- 같은 로직을 다양한 데이터 타입에 대해 사용할 수 있어 코드의 중복을 줄일 수 있음
Generic 사용법
import java.util.ArrayList; public class WithGenerics { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); //제네릭 사용 //ArrayList list = new ArrayList(); 제네릭 미사용 list.add("Hello"); //list.add(123); 오류 발생 (타입 안정성 보장) //제네릭을 사용하지 않으면 오류 발생 X -> 문제 발생 가능 String str = list.get(0); //형변환 없이 바로 사용 가능 System.out.println(str); } }
제네릭 클래스 만들기
// 제네릭 클래스 선언 (T는 타입 매개변수) class Box<T> { private T value; public void setValue(T value) { this.value = value; } public T getValue() { return value; } } public class GenericExample { public static void main(String[] args) { Box<String> stringBox = new Box<>(); //String으로 구체적인 타입 지정 stringBox.setValue("Hello"); System.out.println(stringBox.getValue()); Box<Integer> intBox = new Box<>(); intBox.setValue(100); System.out.println(intBox.getValue()); } }
제네릭 메서드 만들기
class Util { // 제네릭 메서드 선언 public static <T> void printData(T data) { System.out.println(data); } } public class GenericMethodExample { public static void main(String[] args) { Util.printData("Hello"); // String 타입 Util.printData(123); // Integer 타입 Util.printData(3.14); // Double 타입 } }
제네릭 타입 제한 (Bounded Type Parameter)
// Number를 상속받은 타입만 사용 가능 (Integer, Double 등) class NumberBox<T extends Number> { private T number; public void setNumber(T number) { this.number = number; } public T getNumber() { return number; } } public class BoundedGenericExample { public static void main(String[] args) { NumberBox<Integer> intBox = new NumberBox<>(); intBox.setNumber(100); System.out.println(intBox.getNumber()); NumberBox<Double> doubleBox = new NumberBox<>(); doubleBox.setNumber(3.14); System.out.println(doubleBox.getNumber()); // NumberBox<String> strBox = new NumberBox<>(); // 오류 발생 (String은 Number가 아님) } }
와일드카드 (
?
- 제네릭 타입 미지정)- 특정 타입을 제한하지 않고 유연하게 사용하고 싶은 경우
import java.util.ArrayList; import java.util.List; class WildcardExample { public static void printList(List<?> list) { // 와일드카드 사용 for (Object obj : list) { System.out.println(obj); } } public static void main(String[] args) { List<String> stringList = new ArrayList<>(); stringList.add("Apple"); stringList.add("Banana"); List<Integer> intList = new ArrayList<>(); intList.add(1); intList.add(2); printList(stringList); // 가능 printList(intList); // 가능 } }