glenn-syj / more-effective-java

이펙티브 자바를 읽으며 자바를 더 효율적으로 공부합니다
4 stars 5 forks source link

[MEJ-006] SuppressWarning 애노테이션의 사용법에 관한 궁금증 #132

Closed ssh2957 closed 4 months ago

ssh2957 commented 5 months ago

Based on: #127 by @undeadtimo

노란색줄로 뜨는 경고창이 있어도 실행은 되기 때문에 크게 신경쓰지 않았는데 @SuppressWarnings로 그 경고가 뜨는것을 막을수 있다는 점과 어떻게 사용하는지 자세히 써주셔서 이해하는데 도움이 된것 같습니다. 감사합니다. 글을 읽으면서 궁금한점이 생겼는데요 undeadtimo님의 예시코드를 통해 실제로

    Type safety: The method add(Object) belongs to the raw type List. References to generic type List<E> should be parameterized

가 발생했는때 '@SuppressWarnings("unchecked")' 을 통해 경고가 뜨는것을 막을수 있었습니다. 하지만 저희가 코딩을 할때 다양한 경고들을 만날수 있고 실제로 undeadtimo님이 올려주신 예시코드에는

private static List versions; 

에서 List부분에도

List is a raw type. References to generic type List<E> should be parameterized

라는 경고가 떴지만 이는 '@SuppressWarnings("unchecked")' 을 통해 경고가 지워지지 않았습니다. 이말은 'unchecked' 말고 다른 단어로 경고를 막아야 한다는것 같은데 이런 경고를 막는 단어들도 상속을 받아 'unchecked' 보다 상위 개념의 단어를 쓰면 더욱더 다양한 경고들을 한번에 막을수 있는것인지 아니면 모든 경고들마다 각각의 단어들로(ex unchecked, deprecation 등) 막아야 하기 때문에 경고가 떴을때 마다 알맞는 단어들을 찾아서 써줘야 하는건지 궁금합니다.

undeadtimo commented 5 months ago

ssh2957님께서 좋은 질문을 해주셔서 감사드립니다.

우선 raw 타입에 대해 설명을 드리자면, raw 타입이란 제가 제시한 예시 코드에서처럼 타입 매개변수가 없는 것을 뜻합니다.

// raw type
private List versions;

// raw type이 아닌 것
private List<String> versions;

raw type인 List가 선언되었으므로 프로그램은 사용자에게 타입 매개변수를 지정하라고 경고를 띄웁니다.

List is a raw type. References to generic type List<E> should be parameterized

이 경고는 나중에 사용자로 하여금 에러를 방지할 수 있도록 해줍니다.

예를 들어, raw type에 직접적으로 요소를 넣게 되면 컴파일 에러가 발생하고

import java.util.ArrayList;
import java.util.List;

public class test {
    public static void main(String[] args) throws Exception {

        List srcList = new ArrayList();

        for(int i=0;i<1000;i++) {
            srcList.add(Integer.toString(i));
        }

        for (String str : srcList) {
            System.out.println(str);
        }

    }
}

raw 타입의 변수에 다른 리스트 또는 배열을 할당하였다가 올바르지 않은 타입의 변수를 넣어 '힙 오염'이 발생할 수 있게 됩니다.

public class test {

    public static void main(String args []) throws Exception {

        List<String> srcList = new ArrayList<String>();
        List copyList = srcList;

        for(int i=0;i<1000;i++) {
            copyList.add(i);
        }

        for (String str : srcList) {
            System.out.println(str);
        }

    }

}

이와 관련하여 '힙 오염'에 대해 제가 작성한 issue를 같이 보면 이해에 도움이 될 것 같습니다. #137

따라서, 가능하면 raw 타입을 사용하지 않는 것이 가장 좋지만, 부득이하게 사용해야 할 경우에는, raw 타입이 힙 오염을 발생시키지 않을 것을 확실하게 검증하여, @SuppressWarnings(“rawtypes”) 어노테이션을 통해 경고줄을 제거하면 됩니다.

단, rawtypes에 대한 경고만을 제거하는 것이 아니라 상위 경고를 바로 억제해버리면 다른 위험성을 알리는 경고까지 모두 억제될 가능성이 있기 때문에, 상위 경고를 바로 억제하는 것은 지양해야 하는 방식입니다.