전체 보기

[백기선 자바] 제네릭

작성일자
2023/08/20
태그
SUB PAGE
프로젝트
백기선 자바
책 종류
1 more property

[자바 라이브 스터디] 12주차 - 제네릭

목표) 자바의 제네릭에 대해 학습하세요.
12
issues

1. 제네릭 사용법

정의) 컴파일 시의 타입 체크를 해줘서 메서드나 클래스가 다양한 타입의 객체 다룰 수 있게 해주는 기능
특징)
타입 안정성을 제공함
타입체크와 형변환 생략 가능해져 코드 간결해짐
static 멤버에 T 사용 불가(T가 인스턴스 변수로 간주되기 때문)
instanceof 연산자와 new 연산자의 피연산자로 T 사용 불가(컴파일 시점에 T가 뭔지 정확히 알아야 하기 때문)
사용) UserUtils<T> 와 같이 선언해 제네릭 클래스를 만들어두고, UserUtils<User> 와 같이 제네릭 타입을 호출해 사용함
예시)
1.
제네릭 타입을 클래스에 선언
클래스 옆에 <T>를 붙이고 Object 타입들을 T 타입으로 변경
적용 전
class UserUtils; { Object user; void setUser(Object user) { this.user = user; } Object getUser() { return user; } }
Java
복사
적용 후 → 제네릭 클래스 UserUtils<T>
class UserUtils<T>; { T user; void setUser(T user) { this.user = user; } T getUser() { return user; } }
Java
복사
2.
제네릭 클래스의 객체 생성
참조변수와 생성자에 T 타입 대신에 사용할 실제 타입을 지정
Teacher teacher = new Teacher(); UserUtils<Teacher> userUtils= new UserUtils<Teacher>(); userUtils.setUser(new Object()); //에러 userUtils.setUser(teacher); Teacher newTeacher = (Teacher)userUtils.getUser();
Java
복사
JDK 1.7부터 UserUtils<Teacher> userUtils= new UserUtils<>();도 가능
제네릭 도입 전 코드와의 호환 위해 아래도 허용은 하지만 경고 발생함 (지양하자)
Teacher teacher = new Teacher(); UserUtils userUtils = new UserUtils(); userUtils.setUser(new Object()); // 경고 userUtils.setUser(teacher); // 경고
Java
복사
만일 경고 안 뜨게 하고 싶다면, Object 타입으로라도 지정해주면 됨
Teacher teacher = new Teacher(); UserUtils<Object> userUtils = new UserUtils<Object>(); userUtils.setUser(new Object()); userUtils.setUser(teacher);
Java
복사

2. 제네릭 주요 개념 (바운디드 타입, 와일드 카드)

바운디드 타입
정의) 제네릭 타입에서 타입 인자로 사용할 수 있는 타입을 제한하려는 경우 바운디드 타입 매개변수를 선언해 사용
사용) 타입 매개변수 이름(T), extends 키워드, 상위 바운드를 나열
UserUtils<T extends User> 와 같이 사용하면 User의 자손들만 담을 수 있게 제한 가능
UserUtils<T extends Speakable>Speakable가 인터페이스여도 마찬가지로 extends를 사용함
UserUtils<T extends User & Speakable>과 같이 사용하면 User의 자손이면서 Speakable을 구현한 클래스만 타입 매개변수 T에 대입할 수 있음 (순서는 인터페이스보다 클래스가 먼저 와야 함)
와일드 카드
정의) 제네릭 타입이 달라도 오버로딩 성립하게 하려는 경우, 모든 타입을 대신할 수 있는 와일드카드 타입 사용
사용)
UserUtils<? extends User> 와 같이 사용하면 User의 자손들만 담을 수 있게 제한 가능
UserUtils<? super User>와 같이 사용하면 User의 조상들만 담을 수 있게 제한 가능
UserUtils<?>와 같이 사용하면 모든 타입이 가능. UserUtils<? extends Object>와 동일

3. 제네릭 메소드 만들기

정의) 메서드 선언부에 제네릭 타입이 선언된 메서드
특징)
제네릭 타입의 선언 위치는 반환 타입 바로 앞임
제네릭 메서드는 제네릭 클래스가 아닌 클래스에도 정의 가능
사용)
적용 전)
static Lecture makeLecture(UserUtils<? extends User> userUtils) { return new Lecture(); }
Java
복사
적용 후)
static <T extends User> Lecture makeLecture(UserUtils<T> userUtils) { return new Lecture(); }
Java
복사

4. Erasure

정의) 컴파일러가 제네릭 타입 이용해서 소스파일 체크하고 필요한 곳에 형변환 넣어주어 결국 컴파일 후 원시 타입으로 바뀜
과정)
제네릭 타입의 경계 제거
적용 전)
class UserUtils<T extends User> { void add(T t) { ... } }
Java
복사
적용 후)
class UserUtils { void add(User user) { ... } }
Java
복사
제네릭 타입 제거한 후 타입 일치하지 않으면 형변환 추가
적용 전)
T get (int i) { return list.get(i); }
Java
복사
적용 후)
User get (int i) { return (User)list.get(i); }
Java
복사