농부와 컴퓨터/PROGRAMMING

[2006.10.16 (월) 맑음] JDK 1.5 에서의 Generic ( 쌍, 또는 집합형 데이터 변수의 내장 데이터타입 )

금오귤림원 2006. 10. 16. 02:19

컴파일 에러 : (컴파일 옵션 -Xlint)

warning: [unchecked] unchecked call to put(K,V) as a member of the raw type java.util.HashMap

---------------

JDK 5를 쓰고 계시나 보네요.

위에 저 경고 메시지는 Java 5 (Java 1.5를 그냥 5라고 부르더군요) 부터 추가된 Generic 이라는 기능때문에 표시된겁니다.

기존 JDK 1.4.x까지는 java.util 패키지에 있는 컬렉션 패키지를 포함해서 객체를 보관하는 자료 구조들이 모두 Object 타입으로 처리하게 되어 있었지요. 그런데 이렇게 되면, 실제 그 보관된 자료들이 어떤 클래스(또는 인터페이스) 타입인지 알아보기가 어렵습니다. 코드를 작성하면서 하나의 타입으로 통일해서 넣는다고 해도 꺼내 올 때는 강제로 형 변환을 해주어야만 하지요. 바로 아래와 같은 형식이 될겁니다.

Integer iObj = new Integer(10);
ArrayList arr = new ArrayList();
arr.add(iObj);

Integer iObj2 = (Integer) arr.get(0);
 
다시 정리하면, 저장된 데이터가 어떤 타입인지 알기가 어렵기 때문에 프로그램 실행시 예기치 못한 오류가 발생할 가능성이 커지고, 불필요하게 형변환을 계속 해줘야 하기 때문에 불편하지요.

그런데 저런 것들이 Java 5로 오면서 이렇게 바뀝니다.

Integer iObj = new Integer(10);

ArrayList<Integer> arr = new ArrayList<Integer>(); // Generic을 이용하여 보관할 타입을 지정합니다.

arr.add(iObj);

Integer iObj2 = arr.get(0); // 보관된 데이터의 타입이 확실하므로 형변환이 필요없습니다.

즉, 기존에 Object 타입을 사용함으로 인해 발생했던 모호함이 Generic을 사용함으로 인해서 실제 보관될 데이터의 형식이 어떤 것인지 확실히 알 수 있게 되었고 불필요한 형변환이 없어졌지요.

그럼 이제 님의 문제점으로 돌아가 보지요. HashMap 클래스도 ArrayList와 마찬가지로 기존에는 보관되는 타입이 키와 값 모두 Object 타입이였습니다. 하지만 Generic을 쓰면 키와 값에 Object가 아닌 실제 저장될 데이터의 타입을 직접 명시할 수 있지요.

HashMap map = new HashMap();
map.put("a", new Integer(10));
map.put("b", new Integer(20));

Integer iObj = (Integer) map.get("a");

위와 같은 JDK 1.4.x 버전 코드를 Java 5의 Generic을 적용해서 고치면 아래와 같습니다.

HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("a", new Integer(10));
map.put("b", new Integer(20));

Integer iObj = map.get("a");
 
이렇게 되면서 ArrayList에서 보신 예와 마찬가지로 map이라는 참조 변수 선언시에 HashMap 클래스에 실제로 담을 객체의 타입을 명시해주고, get() 메소드를 이용하여 데이터를 꺼내올 때에도 형변환을 하지 않습니다.

이런 특징들은 맨 처음 말씀드린것 처럼, Java 5의 API에 전반적으로 적용이 되어 있습니다.

해결책은 두가지가 있겠지요. (너무 뻔한가요? ^^;;)

첫 번째는 기존 코드 스타일을 그대로 쓸 경우, Java 5를 지우고 JDK 1.4로 돌아갑니다.
이 경우는 기존 코드의 부피가 너무 커서 도저히 한번에 Java 5에 맞는 형식으로 모두 바꾸기 어려울 때에 적당하겠지요. 코드 호환성은 1.4가 되겠지만, JRE 5에서 동작하는데에는 아무런 문제가 없습니다.

두번째는 Generic을 전체 코드에 적용해서 Java 5에 맞게 고치는 것이지요. 앞으로 Generic이 계속 사용될 추세이고, Sun에서도 권장하는 것을 보면, 이것이 대세인것 같습니다. 코딩할 때 길이는 좀 길어지지만, 아무래도 안정성은 더 좋아지겠지요. 예전처럼 터무니없는 ClassCastException은 별로 일어나지 않게 될겁니다. ^^;

설명이 도움이 됐다면 좋겠습니다. ^^