kkkkkkkkkkkk
kkkkk
kkkkkkkkkkkk
전체 방문자
오늘
어제
  • 분류 전체보기
    • CS & OS
    • Algorithms
    • Laguage
    • Book
      • 객체지향의 사실과 오해
      • Effective Java
      • Spring boot 와 AWS로 혼자 구현하는 ..
      • 도메인 주도 계발 시작하기
    • DB
    • Spring
    • Spring Boot
    • JPA
    • Git
    • Clean Code
    • HTTP

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 책임
  • 역할
  • 설계 원칙
  • 객체지향 프로그래밍
  • 응집도
  • 결합도

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
kkkkkkkkkkkk

kkkkk

Book/Effective Java

[Item 29] 이왕이면 제네릭 타입으로 만들라

2022. 8. 18. 17:32

책에는 Stack 클래스를 예로 들었는데 이 글은 stack클래스를 모방한 Cage 클래스로 예를 들겠습니다.

 

 

public class Cage {
    private Object[] cages;
    private int size;
    private static intDEFAULT_SIZE= 10;

    public Cage() {
        this.cages = new Object[DEFAULT_SIZE];
    }

    public void push(Object o) {
        checkCapacity();
        this.cages[size++] = o;
    }

    public Object pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        Object result = cages[--size];
        cages[size] = null;
        return result;
    }

    private void checkCapacity() {
        if (cages.length == size) {
            this.cages = Arrays.copyOf(this.cages, 2 * size + 1);
        }
    }
}

Object 타입의 원소들을 저장하려는 Cage 클래스다. 이 클래스는 제네릭 타입이여야 마땅한 클래스다.

 

오히려 cage 안에서 객체를 꺼내 형변환 과정에서 런타임 에러가 날 위험이 있다.

 

 

제네릭 타입으로 수정해보자.

public class GenericCage<E> {
    private E[] cages;
    private int size;
    private static intDEFAULT_SIZE= 10;

    public GenericCage() {
        this.cages = new E[DEFAULT_SIZE];
    }

    public void push(E o) {
        checkCapacity();
        this.cages[size++] = o;
    }

    public E pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        E result = cages[--size];
        cages[size] = null;
        return result;
    }

    private void checkCapacity() {
        if (cages.length == size) {
            this.cages = Arrays.copyOf(this.cages, 2 * size + 1);
        }
    }
}

 

Object 타입을 E 타입으로 수정하였다.

 

컴파일에서 this.cages = new E[DEFAULT_SIZE]; 이부분이 에러가 난다. 앞서 말했듯이 제네릭으로 만들려할 때의 실체화가 문제가 된다.

 

 

해결책을 해결책은 두 가지다.

  • 첫 번째.

 

제네릭 배열 생성을 금지하는 제약을 대놓고 우회하는 방법

public GenericCage() {
    this.cages = (E[]) new Object[DEFAULT_SIZE]; // 컴파일 경고
}

 

컴파일 경고가 발생하며 이는 타입 안정을 보장하지 않는다는 메시지다.

 

하지만 push() 메서드를 보면 항상 E 타입의 원소만 E타입의 배열에 저장하게 된다. 이러한 경우는 타입이 안전하다고 판단할 수 있어 @SuppressWarnings 애너테이션으로 범위를 최소화하여 경고를 숨긴다.

 

@SuppressWarnings("unchecked")
public GenericCage() {
    this.cages = (E[]) new Object[DEFAULT_SIZE];
}

 

cages 필드의 타입이 E[] 타입으로 받는 것으로 가독성이 좋아지며 코드도 간결하다.

 

하지만 E 가 Object 가 아니면 런타임 타입이 컴파일타임 타입과 달라 힙 오염이 발생한다.

 

  • 두 번째

cages 타입을 E[] 에서 Object[] 로 바꾸는 것이다.

private Object[] cages;

public E pop() {
        if (size == 0) {
            throw new EmptyStackException();
        }
        E result =  cages[--size]; // 컴파일 에러
        cages[size] = null;
        return result;
    }

 

Object 타입으로 변경하면 pop() 메서드에서 원소를 꺼내오는 부분에서 컴파일 에러가 발생한다.

 

이는 Object 타입에서 원소를 형변환하는데 문제가 되어서 나오는 에러인데 받는 타입이 E 타입이므로 E 타입으로 형변환을 해준다.

 

E result = (E) cages[--size]; // 컴파일 경고

 

변경 후 코드를 보면 컴파일 경고가 발생한다. 이 부분을 @SuppressWarnings 애노테이션으로 경고를 숨겨주자.

 

@SuppressWarnings("unchecked") E result = (E) cages[--size];

 

이 방식은 꺼내올 때 마다 E 타입으로 형변환을 해야하는 단점이 존재한다.

 

 

제네릭 타입 매개변수 제약

List<String> -> o
List<List<String>> -> o
List<int> - x

 

래퍼 타입은 가능하나 프리미티브 타입으로 제네릭을 만들 수 없다.

 

 

한정적 타입 매개변수

List<E extends Person>

 

Person 타입과 Person 타입의 하위 타입만 받는 다는 뜻이다.

'Book > Effective Java' 카테고리의 다른 글

[Item 33] 타입 안전 이종 컨테이너를 고려하라  (0) 2022.09.02
[Item 32] 제네릭과 가변인수를 함께 쓸 때는 신중하라  (0) 2022.08.31
[Item 31] 한정적 와일드카드를 사용해 API 유연성을 높이라  (0) 2022.08.31
[Item 30] 이왕이면 제네릭 메서드로 만들라  (0) 2022.08.30
[Item 28] 배열보다는 리스트를 사용하라  (0) 2022.08.18
[Item 27] 비검사 경고를 제거하라  (0) 2022.08.06
[Item 26] 로 타입(Raw Type)은 사용하지 말라  (0) 2022.08.05
[Item 25] 톱레벨 클래스는 한 파일에 하나만 담으라  (0) 2022.08.05
    'Book/Effective Java' 카테고리의 다른 글
    • [Item 31] 한정적 와일드카드를 사용해 API 유연성을 높이라
    • [Item 30] 이왕이면 제네릭 메서드로 만들라
    • [Item 28] 배열보다는 리스트를 사용하라
    • [Item 27] 비검사 경고를 제거하라
    kkkkkkkkkkkk
    kkkkkkkkkkkk

    티스토리툴바