티스토리 뷰
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
개발자의 성향에 따라 경고 메시지에 대처하는 태도에도 차이가 있습니다. 어떤 개발자의 경우에는 경고 메시지가 수두룩하게 쏟아져도 프로그램만 정상적으로 빌드 된다면 별로 개의치 않고 개발을 진행하기도 합니다. 많은 경우 그냥 두어도 별 문제가 되지 않는 경우도 있지만 어떤 경우에는 문법 오류로 걸러지지 않았지만 프로그램 로직에 치명적인 영향을 주는 요소가 되기도 합니다. 그래서 왠만하면 하나의 경고 메시지도 없도록 개발자가 명시적인 처리를 해주는 좋지 않은가! 하는 것이 필자의 생각입니다. 어떤분은 컴파일 옵션을 통해서 경고 메시지가나오지 않도록 하는 경우도 있지만......
위의 경고 메시지의 경우에도 빌드에는 문제가 없지만 어떤 부분에 문제가 잠복하고 있을지 모르는 일입니다. 그렇지만, 별도의 컴파일을 옵션을 지정하지 않으면 어떤 부분에 문제가 있는지 확인할 수가 없습니다.
프로젝트의 컨텍스트 메뉴>properties를 선택하고 Build>Compiling에서 "Additional Compiler Options" 항목에 "-Xlint" 옵션을 추가한 다음 코드를 다시 컴파일하면 문제가 있는 부분들을 자세하게 확인할 수 있습니다. "Clean & Build" 추천. 필자가 처리한 여러 경고 메시지의 내용과 처리 방법입니다.
- warning: [path] bad path element <jar명> : no such file or directory
라이브러리에 포함된 *.jar 파일 속에 있는 META-INF 폴더의 MANIFEST.MF 파일에서 위의 그림과 같이 "Class-Path:"로 또다른 *.jar를 참조하고 있는데 해당 파일이 없는 경우입니다. 이런 경우 지정 경로에 해당 파일들을 찾아서 복사해주거나 *.jar 파일의 MANIFEST.MF 파일을 수정해서 찾지 못하는 jar 파일에 대한 "Class-Path:"를 지우는 방법이 있습니다.
*.jar 파일 속에 있는 MANIFEST.MF 파일을 수정하려면 jar 압축 해제 > MANIFEST.MF 파일 수정 > jar 재압축의 과정을 밟아야 합니다. 해당 jar 파일이 있는 경로에서 작업을 합니다.
mkdir tmp
cd tmp
jar xvf ../derby.jar
위의 예제 처럼 내용이 없는 임시 폴더를 만들어서 jar 파일의 압축을 해제한 다음 MANIFEST.MF 파일을 수정합니다.
jar cvfM derby.jar ./*
move derby.jar ..
파일 수정이 끝나면 다시 jar 파일을 생성해서 원래 폴더에 업데이트하면 됩니다. jar 파일을 재생성할 때 M 옵션을 지정해야만 원래의 MANIFEST.MF 파일이 복원됩니다.
어떤 jar 파일에 "Class-Path:" 구문이 있는지 찾기 어렵다면 다음과 같은 쉘 명령을 사용하는 것도 좋습니다.
for i in *.jar; do echo $i; jar xf $i; grep -i 'class-path' ./META-INF/MANIFEST.MF; done
필자의 경우에는 mingw를 설치해 놓아서("MSys-MinGW 개발 환경 설치하기" 참조) 윈도우에서도 리눅스의 쉘을 사용할 수 있었습니다.
위의 그림처럼 "Class-Path:" 구문을 가지고 있는 jar 파일을 찾아서 처리할 수 있습니다.
- warning: [serial] serializable class <클래스명> has no definition of serialVersionUID
각 클래스내에 "private static final long serialVersionUID = -5235346466744331791L;"와 같이 serialVersionUID를 명시하라는 권고입니다. 경고 메시지가 나오지 않도록 제한해도 되지만 각 클래스에 serialVersionUID를 명시하라는 권고를 따르는 것도 좋습니다.
코드에 간편하게 serialVersionUID를 추가하는 방법은 "넷빈즈에 Serial version UID 생성기 플러그인 설치 및 사용하기"를 참고하세요.
- warning: [rawtypes] found raw type: Vector
- warning: [unchecked] unchecked call to add(E) as a member of the raw type Vector
- warning: [rawtypes] found raw type: Enumeration
이 경고 메시지는 벡터(Vector)나 리스트(List)와 같은 클래스를 사용할 때 그 내용물의 타입이 무엇인지를 지정하라는 메시지입니다.
private Vector m_Listeners = new Vector(); //.... public void addJNumberEventListener(JNumberEventListener listener) { m_Listeners.add(listener); } //.... for (Enumeration e = m_Listeners.elements(); e.hasMoreElements();) { oListener = (JNumberEventListener) e.nextElement(); oListener.keyPerformed(oEv); }
위의 코드는 경고가 발생하고 있는 것으로 Vector 클래스로 선언한 m_Listeners의 사용 내역을 보면 그 내용물의 타입은 JNumberEventListener임을 알수 있는데 m_Listeners의 타입을 <JNumberEventListener>와 같이 지정해야 합니다. 이런 권고는 Enumeration에 대해서도 마찬가지 입니다. Enumeration의 경우에도 <JNumberEventListener>와 같이 타입을 지정하면 (JNumberEventListener) e.nextElement()문장에서 지정한 캐스팅이 필요없게 됩니다. 내용의 타입을 알기 때문입니다.
private Vector<JNumberEventListener> m_Listeners = new Vector<JNumberEventListener>(); //.... public void addJNumberEventListener(JNumberEventListener listener) { m_Listeners.add(listener); } //.... for (Enumeration<JNumberEventListener> e = m_Listeners.elements(); e.hasMoreElements();) { oListener = e.nextElement(); oListener.keyPerformed(oEv); }
위의 코드는 집합 오브젝트의 내용에 대한 타입을 지정한 결과입니다. 이러한 권고는 위에서 언급한 Vector, Enumeration 외에도 List, ArrayList, JList 등에도 적용해야 합니다.
경고 메시지들의 원인을 찾아서 모두 수정하면 좋겠지만 수정이 여의치 않은 경우에는 위의 그림처럼 특정한 경고를 대상으로 메시지를 출력하지 않도록 제한할 수 있습니다. "@SuppressWarnings({"rawtypes", "unchecked"})" 문장을 클래스 직전에 기술하면 됩니다. 대상이 되는 경고들은 경고 메시지 앞에 [rawtypes]처럼 표시하므로 참고합니다.
경고를 제한하는 기능이 동작하려면 위의 그림처럼 프로젝트의 컴파일 옵션주에 "Enable Annotation Processing"를 체크해야 합니다.
- warning: [cast] redundant cast to
private final Map<String, PrinterWritter> m_apool = new HashMap<>(); public PrinterWritter getPrinterWritter(String con, String port) throws TicketPrinterException { String skey = con + "-->" + port; PrinterWritter pw = (PrinterWritter) m_apool.get(skey);
이 경고 메시지는 굳이 타입 캐스팅을 하지 않아도 되는 곳에 캐스팅을 했다는 의미입니다. 정수 변수인데 (정수) 캐스팅을 수행한 것과 같은 경우입니다. 위의 예제를 보면 m_apool.get()을 통해서 리턴되는 데이터의 타입은 (PrinterWritter)임을 확인할 수 있습니다. 다른 타입이면 몰라도 같은 타입에 캐스팅을 하는 것은 의미없는 코딩입니다. 불필요한 캐스팅을 없애주면 해결되는 간단한 경고입니다.
'프로그래밍' 카테고리의 다른 글
실습으로 배우는 C언어 4 - 디렉토리 분석기 (0) | 2017.02.28 |
---|---|
C++ 라이브러리를 Java에서 사용하기. JNI와 JNA (0) | 2017.02.16 |
넷빈즈에 Serial version UID 생성기 플러그인 설치 및 사용하기 (0) | 2017.02.07 |
Note: Recompile with -Xlint:deprecation for details. 경고 처리 요령 (0) | 2017.02.06 |
C# 닷넷으로 구글/네이버 메일(SMTP) 보내기 (0) | 2017.01.19 |