개몽가

[Java, Spring]제네릭과 @SuppressWarnings 본문

Skill/Java

[Java, Spring]제네릭과 @SuppressWarnings

개몽가 2020. 4. 11. 16:21

"제네릭과 @SuppressWarnings"

웹 프로젝트를 진행하던 중 DAO와 DAO가 상속받는 부모 클래스에 @SuppressWarnings("unchecked"), @SuppressWarnings("rawtypes") 가 모든 메소드 위에 선언된 것을 봤다.
왜 해줘야하는지 궁금해서 찾아보고 정리를 하게 되었다.

DB에서 select한 여러 row의 데이터를 Temp라는 bean에 담아서 List형태로 서버(*impl)단계까지 가져오는 코드다.


[VO 클래스 : Temp.java]

[JdbcTemplate 구현 클래스 : JdbcTemp.java]

    public class JdbcTemp {
       @SuppressWarnings("rawtypes");
       public List list(String queryId, Object obj) { //queryId는 쿼리 id, obj는 쿼리에 매핑되는 파라미터 들어있는 VO 또는 Map 객체
             return getSqlMapClientTemplate().queryForList(queryId, obj);
       }
    }

[DAO클래스 : TempDAO.java]

    public class TempDAO extends JdbcTemp{
      @SuppressWarnings("unchecked");
      public List tempList(String id, TempObj temp obj) throws Exception{
            return list(id, obj); //JdbcTemp에서 정의한 list호출
      }
    }
    
  
  
  두 개의 @SuppressWarnings가 쓰였다.
  이 두개를 지우게 되면 오류가 나진 않지만 이클립스에서 경고 메세지인 노란색 줄이 그어지게 된다.
  왜 그럴까? 이클립스에서 노란줄에 마우스를 가져다 대면 밑에와 같은 메세지가 뜬다
  
  
   *@SuppressWarnings("rawtypes") 제거 시, "List is a raw type : References to generic type List should be parameterized"
      raw type은 타입 매개변수를 쓰지 않은 제네릭 클래스 또는 인터페이스를 말하는데, JdbcTemp.java의 메소드 반환타입으로 선언된 List를 뜻한다. 
      인터페이스인 List를 제네릭형식으로 사용하지 않고 그냥 사용했기 때문에 경고메세지를 띄어준다.
      그렇기 때문에  "rawtypes" -> 원시 유형 사용법과 관련된 경고 억제
    
    
   *@SuppressWarnings("unchecked") 제거 시, "type safety : the expression of type List needs unchecked converion to conform to List"
      부모클래스에서 타입을 지정하지 않고 raw type(원천타입)이기 때문에 "코드의 형 안정성" 경고 메세지를 띄어준다.
      그렇기 때문에  "unchecked" -> 미확인 오퍼레이션과 관련된 경고 억제
    
    
  @SuppressWarnings 는 컴파일러가 정적분석 진행 시 오류 아니라고 마킹해주는 역할을 한다. 간단히 말해서, 노란줄을 없애주는 역할!
  
  위와 같은 형식은 @SuppressWarnings이 너무 많이 들어가게된다. 줄여주는 작업을 진행하면
  
  
  
[JdbcTemplate 구현 클래스 : JdbcTemp.java]

    public class JdbcTemp {
       public List<?> list(String queryId, Object obj) { //queryId는 쿼리 id, obj는 쿼리에 매핑되는 파라미터 들어있는 VO 또는 Map 객체
             return getSqlMapClientTemplate().queryForList(queryId, obj);
       }
    }

[DAO클래스 : TempDAO.java]

    public class TempDAO extends JdbcTemp{
      public List<?> tempList(String id, TempObj temp obj) throws Exception{
            return list(id, obj); //JdbcTemp에서 정의한 list호출
      }
    }
 
 
[impl클래스 : TempServiceImpl.java]

    @SuppressWarnings("unchecked");
    List = (List)tempDAO.list(~,~);
    
    
JdbcTemplate, DAO에서 제네릭 타입<?>  "언바운드 와일드 카드 타입"으로 선언 또는 받고 Impl에서 형변환을 해주는 작업을 진행한다.
형변환을 해주지 않으면 작업에서 제네릭 타입이 Temp 타입이 아닌 것이 들어오면 ClassCastException이 날 수 있기 때문에 빨간줄이 가게된다. (List)로 형변환 해주고, 노란색의 경고메세지가 뜨기 때문에 메소드 리턴 데이터를 받을 수 있는 지역변수에 @SuppressWarnings("unchecked"); 를 써주면 된다.
    
(제네릭 타입 

 써도 무방!), DAO의 메소드에서 리턴타입을 정확히 알 수 있다면(ex. temp) 쓰고 여기서  @SuppressWarnings 가능)
    

왜? raw type(원천타입)은 경고메세지를 날릴까? (출처 : https://ojava.tistory.com/27)
>> 잘못된 타입의 데이터가 들어갈 경우, 컴파일 시 에러를 잡지 못하고 런타임 때 에러가 뜬다고 함. 제네릭 형태로 진행하게 되면 컴파일 시 타입이 맞지 않는 데이터가 추가될 시 에러를 잡을 수 있게 되어 "안정성인 측면"에서 좋다고함!
>> 원천타입을 남겨두는 이유는 제네릭(Generic)과 @SuppressWarnings가 java5부터 지원을 하기 시작했는데 없애버리면 5 이전 버전과 호환이 안되게 때문이라고 한다.


[@SuppressWarnings 종류] (출처 : https://yangyag.tistory.com/152 [Hello Brother!] )

    all : 모든 경고를 표시 안함
    cast : 캐스트 연산자 관련 경고를 표시 안함
    dep-ann : 사용하지 말아야 할 주석 관련 경고를 표시 안함
    deprecation : 사용하지 말아야 할 메소드 관련 경고를 표시 안함
    fallthrough : switch문에서의 break 누락 관련 경고를 표시 안함
    finally : 반환하지 않는 finally 블럭 관련 경고를 표시 안함
    null : null 분석 관련 경고를 표시 안함
    rawtypes : 제네릭을 사용하는 클래스 매개 변수가 불특정일 때의 경고를 표시 안함
    unchecked : 검증되지 않은 연산자 관련 경고를 표시 안함
    unused : 사용하지 않는 코드 관련 경고를 표시 안함