일반 클래스를 제네릭 클래스로 변경

eomprgrm·2023년 4월 12일
0

이펙티브자바

목록 보기
1/3

이펙티브자바를 읽고 작성하는 글이다.

1. 기존 클래스의 문제

기존 Stack 클래스는 Object[]을 사용하고 있는데, 이는 타입 안정성에 위배된다.
Stack 클래스에서 꺼낸 객체의 형변환 시 런타임 에러가 발생할 위험이 있다.

public class Stack {
	priavte Object[] elements; // Object 형태의 배열, 런타임 에러 발생 가능성
    private int size = 0;
    private static final int DEFAULT_INITIAL_CAPACITY = 16;

2. 제네릭 클래스로 변경 1

다음은 제네릭 클래스로 변경하는 과정이다.

Object 타입을 선언하는 대신, 제네릭 클래스로 선언하였다.
생성자 선언부에 컴파일 에러가 발생한다. 해당 에러는 E와 같은 실체화 불가 타입으로는 배열을 만들 수 없다는 것이다. (배열을 사용하는 코드를 제네릭으로 변경하려 할 때 항상 문제가 되는 부분일 것이다.)

이를 해결하기 위해 Object 배열을 제네릭 배열로 형변환 하는 방법이 있다. 이 때, 컴파일러에서 경고를 내보내는데 일반적으로 타입 안전하지 않다는 것이다.

지금 변경한 코드가 타입 안전한 이유

배열 elements는 private 필드에 저장되고, 클라이언트로 반환되거나 다른 메서드에 전달될 일이 전혀 없다. 따라서 이 비검사 형변환은 확실히 안전하다고 말할 수 있다.

3. 제네릭 클래스로 변경 2

다음은 elements 필드의 타입을 E[]에서 Object[]로 바꾸는 것이다.

private Object[] elements; // E[] 제네릭 타입의 배열에서 Object[] 배열로 변경

제네릭 타입을 반환하는 pop() 메서드에서 다음과 같은 컴파일 에러가 발생한다.
이 경우 E 타입으로 형변환하여 에러를 해결할 수 있다. (타입 안전한지에 대한 의문이 생길 수 있다)

지금 변경한 코드가 타입 안전한 이유

elements 필드에 객체를 집어넣는 push() 메서드의 파라미터 타입이 제네릭으로 선언한 E 타입이기 때문에 오직 E 타입의 인스턴스만을 받을 수 있다. 따라서 타입 안전한 코드라고 말할 수 있다.

4. 결론

클라이언트에서 직접 형변환을 해야 하는 타입보다 제네릭이 더 안전하고 쓰기 편하다. 그러니 새로운 타입을 설게할 때는 제네릭 클래스를 통해 형변환 없이도 사용할 수 있도록 하라. 기존 타입 중 제네릭이 있어야 하는 게 있다면 변경하도록 하자. 기존 클라이언트에는 아무런 영향을 주지 않으면서, 새로운 사용자를 훨씬 편하게 해주는 길이다.

profile
오늘의 학습을 기록하는 공간

0개의 댓글