기맹기 개발 블로그

[Java] 제네릭 (Generic) 본문

Java

[Java] 제네릭 (Generic)

기맹기 2023. 1. 12. 01:50

제네릭

Java 5부터 추가된 Generic을 사용하여 다음의 장점을 얻을 수 있다.

  1. 컴파일 시간에 강한 타입 체크가 가능하다.
  2. 불필요한 타입 캐스팅을 제거하여 성능을 향상시킨다.

 

제네릭 타입: class<T>, interface<T>

public class 클래스명<T> { ... }
public interface 인터페이스명<T> { ... }

타입을 파라미터로 가지는 클래스와 인터페이스를 제네릭 타입이라고 한다.

타입 파라미터는 변수명과 동일한 규칙으로 작성할 수는 있지만, T 처럼 대문자 한글자로 표현하는 것이 관례이다.

자바 7부터 <> 연산자를 사용하면 컴파일러가 타입 파라미터를 자동 추론한다.

List<String> myList = new ArrayList<String>();  // 타입 파라미터 명시
List<String> myList = new ArrayList<>();        // 자동 추론

 

멀티 타입 파라미터: class<K, V, …>, interface<K, V, …>

타입 파라미터가 여러 개인 경우 콤마로 구분하여 사용할 수 있다.

 

제네릭 메소드: <T, R> R method(T t)

리턴 타입과 매개변수 타입에 사용되는 타입 파라미터들을 메소드 선언 가장 앞에 적는다.

public static <K, V> boolean compare(Pair<K, V> p1, Pair<K, V> p2);

위의 예시처럼 두 개의 타입 파라미터를 사용하는 Pair 클래스를 비교하는 제네릭 메소드를 선언할 수 있다.

 

제한된 타입 파라미터: <T extends 최상위타입>

타입 파라미터의 타입을 제한할 필요가 있을 때 사용한다.

public static <T extends Number> int compare(T t1, T t2);

위의 예시처럼 타입 파라미터 T를 Number 클래스의 하위 클래스 타입으로 제한할 수 있다.

 

와일드카드 타입: <?>, <? extends …>, <? super …>

제네릭 타입을 매개변수나 리턴 타입으로 사용할 때 와일드카드 타입을 활용할 수 있다.

? 를 와일드카드라고 하며 모든 클래스나 인터페이스 타입이 될 수 있다.

  • <?> : unbounded wildcards
    • 모든 타입이 가능하다.
  • <? extends 타입> : upper bounded wildcards
    • 타입과 타입의 하위 타입만 가능하다.
  • <? super 타입> : lower bounded wildcards
    • 타입과 타입의 상위 타입만 가능하다.

예를 들어 과정을 나타내는 제네릭 타입 Course가 있다고 하자. 이 때 수강생의 타입은 타입 파라미터로 적용된다.

public class Course<T> {
	private String name;
	private List<T> students;

	...
}

수강생이 될 수 있는 사람을 나타내는 Person 클래스는 여러 하위 클래스를 가진다고 하자.

public class Person { ... }
public class Worker extends Person { ... }
public class Student extends Person { ... }
public class HighStudent extends Student { ... }

이 때 각 타입별로 등록 메소드의 로직을 다르게 하고 싶을 때 메소드의 매개변수에 와일드카드를 활용할 수 있다.

// 모든 과정을 지원
public static void registerCourse(Course<?> course) { ... }

// Student와 Student의 하위 타입을 지원
public static void registerCourseStudent(Course<? extends Student> course) { ... }

// Worker와 Worker의 상위 타입을 지원
public static void registerCourseWorker(Course<? super Worker> course) { ... }
  • registerCourse : Person, Worker, Student, HighStudent 모두 가능
  • registerCourseStudent : Student, HighStudent 가능
  • registerCourseWorker : Worker, Person 가능

 


출처 : 이것이 자바다

'Java' 카테고리의 다른 글

[Java] JVM 구조  (0) 2023.03.05
[Java] JIT 메소드 인라인  (0) 2023.03.02
[Java] Java의 멀티스레드  (0) 2023.02.18