Part 14. 제네릭스

Hyunsu·2023년 2월 27일
0

국비 교육

목록 보기
19/36
post-thumbnail

📝 목차

  1. 제네릭스 (Generics)
  2. 제네릭스 타입과 표현식
  3. 제네릭스 사용법

1. 제네릭스 (Generics)

제네릭스란 클래스나 메서드 내부에서 다룰 데이터의 클래스 타입을 지정하거나
컬렉션이 다룰 클래스 타입을 제한하여 한 가지 종류의 클래스만 저장할 수 있게 한 기능이다.

제네릭스를 사용하는 이유

  • 컴파일 단계에서 잘못된 타입을 사용할 수 있는 문제 제거
  • 컬렉션에 저장된 여러 종류의 객체를 꺼내서 사용할 때 객체의 종류에 따라 매번 형변환을 해야하기 때문에 코드가 복잡해짐
  • 컬렉션과 람다식 및 스트림과 NIO 에서 널리 사용
  • API Document 해석에 어려움을 겪어 학습에 제한

제네릭스 이점

  • 컴파일 시 강한 타입 체크 가능하므로 실행 및 컴파일 시 에러 방지
  • 타입 변환 제거 가능
// 제네릭스 사용 X
List list = new ArrayList();
list.add("hello");
String str = (String)list.get(0);

// 제네릭스 사용 O
List<String> list = new ArrayList<String>();
list.add("hello");
String str = list.get(0);

2. 제네릭스 타입과 표현식

타입을 파라미터 즉 매개변수로 가지는 클래스와 인터페이스 선언 시 클래스 또는 인터페이스 이름 뒤에 < > 를 붙이고 사이에는 타입 파라미터를 넣는다.

// 표현식
클래스명<클래스타입> 레퍼런스 = new 생성자<클래스타입>();
클래스명<클래스타입> 레퍼런스 = new 생성자<>();

// 사용 예시
ArrayList<Book> list1 = new ArrayList<Book>();
ArrayList<Book> list2 = new ArrayList<>();

인자로 넘기는 경우

ArrayList<Book> list = new ArrayList<Book>();
BookManager bm = new BookManager();
bm.printlnformation(list);

// BookManagaer Class
public void printformation(ArrayList<Book> list) {

}

메서드 쪽에서 받아주는 매개 변수도 제네릭스가 적용되어야 한다.

리턴하는 경우

public ArrayList<Book> getInformation() {
	ArrayList<Book> list = new ArrayList<Book>();
    return list;
}

메서드의 반환형에도 제네릭스가 적용되어야 한다.


3. 제네릭스 사용법

📌 제네릭스 클래스

컴파일 시 타입 파라미터가 구체적인 클래스로 변경된다.

// 제네릭스 사용 클래스
public class Box<T> {
	private T t;
    public void set(T t) { this.t = t; }
    public T get() { return t; }
}

// 구체적인 클래스로 변환
Box<Integer> box = new Box<Integer>();
box.set(6);
Integer i = box.get();

public class Box<Integer> {
	private Integer t;
    public void set(Integer t) { this.t = t; }
    public Integer get() { return t; }
}

📌 멀티 타입 파라미터

제네릭스 타입은 두 개 이상의 타입 파라미터 사용이 가능하며 콤마로 구분한다.

Employee<Dept, Person> = new Employee<Dept, Person>();
Employee<Dept, Person> = new Employee<>();

public class Employee<D, P> {
	private D dept;
    private D person;
    
    public D getDept() { return this.dept; }
    public P getPerson() { return this.person; } 
    
    public void setDept(D dept) { this.kind = kind; }
    public void setPerson(P person) { this.person = person; }
}

📌 상속과 구현

제네릭스 타입을 부모 클래스로 사용해야 할 경우 타입 파라미터는 자식 클래스에도 기술한다.

public class ChildProduct<T, M> extends Product<T, M> { ... }

📌 구체적 타입 제한

상속 및 구현 관계를 이용해 타입 제한이 가능하며 상위 타입은 클래스 뿐만 아니라 인터페이스도 가능하다.

  • extends 키워드
<K extends T>

extends 를 사용하면 특정 타입의 자손 타입만 제네릭 타입으로 들어올 수 있다.
즉 T 와 T 의 자손 타입만 들어올 수 있다.
제네릭 타입에서는 클래스 뿐만 아니라 인터페이스도 extends 키워드를 사용한다.

  • super 키워드
<K super T>

super 을 사용하면 특정 타입의 부모 타입만 제네릭 타입으로 들어올 수 있다. 즉 T 와 T 의 부모 타입만 들어올 수 있다.

  • ? 키워드
// 기본 사용
<?>

// 조합 사용
<? extends T>
<? super T>

물음표는 와일드 카드를 의미한다. 모든 타입이 제네릭 타입으로 들어올 수 있다.

profile
현수의 개발 저장소

0개의 댓글