2012년 9월 19일 수요일

자바의 열거형(enum)


오늘부터 새로운 기분으로 시작한다는 의미에서 JDK 1.5버젼 이상, 즉 자바 5부터 새롭게 등장한 기능인 enum이란 타입에 대해서 알아보도록 하겠다. 자바 5 이상의 버젼이 아닐경우 enum이란 키워드를 이용해 클래스나 변수 혹은 메소드를 그 이전에 만든 프로그램에 쓰려면 여러분은 안타깝지만 새로운 버젼에서는 그 소스들을 다 수정해야한다. 물론 강이의 자바강좌로 자바의 시작을 함께한 이들은 필요가 없겠지만 말이다.^^

enum이란 키워드를 처음본 이들도 있을테고 아니면 자바나 그외 언어를 공부해온 이들은 enum 이놈(?)에 대해서 들어는 보았겠지만 아직도 생소하거나 자유자재로 이용을 못하는 이들이 생각보다 많을 것이다. 그 이유는 단 하나! 이제서야 강이의 자바강좌에서 다루기로 했기 때문이다.ㅎㅎ

농담이고 아직까지 enum에 대해서 익숙하지 않은 이들은 이번 필자의 강의를 집중한다면 여러분이 프로그래머로서 배열을 굳이 만들지 않고서도 간단하게 코드를 작성할수 있는 새로운 자바병기(?)를 하나 가지게 될것이다.^^

enum은 그럼 어떨때 쓰는 것이 효과적일까?
일단 enum은 enumeration이라는 영어단어를 짧게 쓴것이라 보인다. 필자의 영어실력을 믿으므로 확인해본바 없으나 아마 그럴것이다.ㅎㅎ 우리말로 뜻이 "열거" 즉 길게 늘어뜨려놓은 형태를 뜻하는데 자바에서는 쉽게 그런 형태의 예로 배열을 떠올릴수 있을 것이다.

enum을 쓰지않아도 코드 짜는것이 불가능한 것은 아니다. 그런데 이게 왜 등장했냐면 이유는 당연지사 더 편하게 코딩하라고 나온것이다. 프로그램을 만들다보면 배열은 배열인데 이게 우리가 임의로 만들 필요가 없는 아주 당연한 배열의 형태들이 있다. 그 예를 들어보자면, 월요일부터 일요일까지 요일을 쓴다던가, 아니면 위의 그림처럼 화폐의 동전들을 나열한다던가, 그것도 아니면 수금지화목토천해명 같이 행성들을 태양에서부터 차례로 놓기위함이라던지, 이런 식으로 아주 일상적으로 쓰이는 배열 형태들이 있는데 이것을 굳이 배열로 다 정의하려면 시간도 오래걸리고 코드도 상당히 복잡해 보일 것인데 이런 상황에 enum이란 키워드를 쓰면 시간도 시간이지만 그 효율성과 강력한 기능의 이놈(?)을 굳이 두고 어려운 길을 갈 필요는 없을 것이다.ㅎㅎ

그럼 본격적으로 enum을 어떻게 쓰는지 공부해 보기로 하겠다. 그전에 한마디 덧붙이자면, enum을 공부하다가 지친 이들은 용어의 생소함과 더불어 복잡한 이론에 공부하다 지친 이들이 의외로 많을 것인데 그런 이들은 오늘 이 강의로 말미암아 어려운 설명없이도 그동안의 궁금증을 말끔히 씻어주도록 필자가 핵심중의 핵심만 찌르고 나머지는 모두 짤라버리는 초특급 핵심강의를 펼치려하니 이제부터 정신을 한곳에 모아주기 바란다.^^

뭐 대단한 걸 기대하고 있을지 모르는 이들에게는 김이 빠질지 모르겠지만 오늘도 아니나 다를까 딴거 다 필요없고 필자의 예제 하나만 보면 그동안 이해안되었던 모든 의문들이 눈녹듯이 사라질 것이고 새로 배우는 이들은 별거없어 손가락만 빠는 사태가 즐비할지 모르는 황당한 사태가 벌어질 것을 알면서도 필자의 공력을 아낌없이 쏟아부은 예제를 아래에 공개하노니 모두 눈깔빠지도록 쳐다보면서 직접 타이핑해 보기 바란다.ㅎㅎ


강이의 자바강좌 본 예제의 결과값은 아래와 같다.

Today is Monday.
Today is not Monday.
Weekday is Monday to Friday.
NICKLE
5
5

enum을 조금 공부해본 이들이라면 예제를 보면 필자의 설명없이도 저절로 이해가 될정도로 소스를 아주 쉽게 구성하였으나 처음 본 이들은 조금 주춤할지 모르나 필자가 여기에 조금만 강의양념을 쳐주면 역시 별거없다는 것을 깨닫게 될것이다. 그럼 지금부터 예제 설명에 들어가보기로 하겠다.

지금 프로그램을 보면 enum을 이용해서 만든 것이 크게 2가지가 있다. 하나는 Day 열거형이고 또 다른 하나는 Currency 열거형이다. 내용은 안에 보다시피 하나는 일요일~토요일에 관한 요일을 열거한 것이고 또 다른 하나는 화폐통화중 동전들 페니부터~쿼터까지 모아놓은 것이다. 우리나라의 동전 10원, 50원, 100원, 500원처럼 외국에서는 동전이 1센트(페니), 5센트(니컬), 10센트(다임), 25센트(쿼터)라 하는데 그걸 쓴것이다. 우리나라 동전으로 예제를 만들까 하다가 이럴때라도 외국물(?) 먹어보자고 필자가 특별히 외국화폐를 가져왔다.ㅎㅎ

자 일단,
enum Day {SUNDAY,MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY}
를 열거하였는데 이렇게 static final 상수처럼 enum '이름'을 넣어 관련항목을 위처럼 열거해서 써먹을수가 있다. 그밑에 있는 check 메소드는 필자가 그냥 간단히 오늘이 월요일인지 아닌지를 확인하는 간단한 예를 if~else 구문을 활용해 돌려본 것뿐이다.

그럼 다음으로,
enum Currency를 들수 있는데 enum 이넘이 매력적인 이유중 하나가 위처럼 단순 열거에 그치지 않고 이렇게 이놈안에 메소드나 필드를 정의해서 쓸수가 있는데 이넘이 클래스나 객체로서도 강력한 성능을 발휘하는 것과 동전에서 보듯이 이처럼 물건의 의미가 바로 수치랑 연결되는 것들이 있을때 바로 예제처럼 수치까지 적용해서 써먹을수 있는 기능이 또한 매력적이다.

지금 enum Currency에서는 value 변수를 이용한 생성자가 들어가 있는데 동전이 어떤 것이냐에 따라 그 값어치 즉 화폐단위를 바로 인식하도록 만든 것이다. 만약 PENNY(1) 이런식으로 쓰지 못하였다면 이것을 일일히 변수를 만들어 값을 하나하나 대입해야하는 번거로운 소스를 만들어야할 것이나 이넘(?) 덕분에 그 수고를 한번에 덜수 있었다 하겠다^^

여러분이 지금 필자가 무슨 말하는지 이해가 잘 안되고 있을텐데 그건 당연한 것이다. 지금 필자는 이미 메인메소드의 내용을 알면서 설명을 하는 것이고 여러분은 아직 메인메소드 내용을 잘 모르는 상태로 설명을 듣고 있으니 이해가 잘 안되는 것은 당연하다. 그런데 왜 이렇게 먼저 설명부터 하냐고? 메인메소드를 지금부터 필자의 설명과 함께 보다보면 그 이유를 끝에 알게 될것이다.ㅎㅎ

자 그럼 무엇을 테스트해 보려하는지 메인메소드의 내용을 보기로 하자.
일단 첫째줄에
Day today=Day.MONDAY;
라고 썼는데 말그대로 오늘이 월요일이라고 알려준 것이다.
여기서 알수 있는 것은 enum은 굳이 new라는 키워드를 이용해 레퍼런스로 접근하지 않고 바로 써먹을수 있다는 것이다. 그런 까닭에 check 메소드에 static을 쓴것인데 이 부분에 대해서는 그냥 넘겨도되고 궁금해서 못참겠거든 필자의 예전 static에 관련된 강의를 검색해서 찾아보기 바란다. 그럼 다시 돌아와서 다음줄을 보자
check(today);
오늘이 무슨 요일인지 체크해보라는 명령이다.
아까 오늘이 월요일이라고 알려줬으니 당연히
Today is Monday. 라는 값이 나와야 할것이다.
그 다음에는 토요일이냐고 물어봤으니
월요일이 아니라는 답이 나온 것이고
그 밑에 스위치문에는 오늘이 월요일이니
월요일은 case에 해당이 없으므로 default 구문의 값이 찍히는 것이다.

자 그럼 이제 Currency에 관련된 enum 구문을 테스트해 보기로 하자.
Currency coin=Currency.NICKLE;
즉 coin이 5센트짜리 니컬이라고 정의해 주었다.
그럼 다음줄에 무슨 동전 들고있는지 찍어보라고 아래 명령을 줬더니
System.out.println(coin);
NICKLE이라고 찍힌 것이고
다음줄에 coin.value를 찍으라고 했는데
이게 생성자를 이용해 동전에 따라 수치를 나타내라고 한것이니
결과값에 보는 것처럼 숫자 5가 찍혔으니 enum의 강력한 힘(?)이
제대로 발휘하고 있다고 느낄수 있다.
그 다음줄은 똑같은 명령인데
그렇게 바로 지정해서 쓸수 있다는 것도 보여줄겸 적었을 뿐이다.

뭐 거창한 프로그램 같은데 벌써 끝나버렸다.ㅎㅎ 예제에서 스위치 구문을 메인메소드 안에 바로 썼는데 사실 이건 좋은 예가 아니나 바로 이해가능하도록 핵심사항을 여러분께 바로 전달하기 위해 긴급조치한 부분이니 이점 양해하기 바란다.^ 아까 초반에 필자의 설명이 잘 이해되지 않은 이들도 지금 다시 보면 술술 모든 의문이 다 풀릴 것이다. 필자가 이 한 예제에 두개의 enum 구문을 넣어 이렇게도 저렇게도 쓸수 있다는 것을 보여준 이곳에선 아주 귀한 일석이조(一石二鳥) 자바공법(?)을 불어넣은 예제이니 확실히 복습해서 몽땅 자기걸로 만들기 바란다.^^

2012년 9월 9일 일요일

스윙으로 원본창 만들기(JRootPane)



JRootContainer 클래스를 공부해 보도록 하겠다. 모든 스윙 컨테이너들은 JRootPane을 가지는데 JRootPane이라는 객체는 layeredpane과 glassPane으로 구성되어 있다. 그 중에서도 layeredpane은 contentPane과 optional menu bar를 가지고 있고 JRootPane의 틀안에서 보자면 JLayeredPane의 인스턴스인 layeredpane은 모든 컨테이너 자식들의 부모격 콤포넌트로 다층레이어로 이루어져 있어 여러 콤포넌트들이 내용을 담을수 있는 contentPane 위에 올수 있도록 만들어준다. JRootPane 틀안에서 JPanel의 인스턴스인 glassPane은 모든 콤포넌트들의 최상위에 위치하며 이것은 마우스의 이벤트나 콤포넌트 사이에서 dragging이나 drawing을 가능하게 만들어준다. 즉 마우스 동작의 반응여부를 컨트롤하거나 어떤 콤포넌트들의 위에서 그림을 그릴수 있다는 것이다. 기본적으로 glassPane은 보이지 않게 되어있다.


컨테이너들의 컨텐츠들은 사실 그것들과 관계된 content pane에 저장되는데 스윙 컨테이너에 바로 add( ) 메소드를 이용하지 않고 대신에 컨테이너의 content pane을 거쳐서 add하게 된다. 다시 말해, content pane을 거친다는 의미는 코드상으로 getContentPane( ) 메소드를 이용한 중간단계가 있다는 것을 의미한다.

이렇게 쓰면 컨테이너는 도대체 뭐냐고 하는 이들이 있을 것이다.^^ Root 한마디로 최상위 컨테이너들은 총 다섯가지가 있다. 나열해보면 JFrame, JDialog, JApplet, JWindow, JInternalFrame이 있는데 자바 애플리케이션 만들때 사용하는거라는건 다 알테고 JInternalFrame은 자바 애플리케이션 안에 여러개의 프레임을 만들때 필요하다. 다른 컨테이너들이야 이름지어진 뜻데로 생각하면 될테고 그전 강의들에서 필자가 다루어왔으니 다 알것이라 믿겠다.ㅎㅎ

컨테이너들은 JFrame, JDialog, JApplet, 별로 쓰이지 않아서 빼고 싶은 JWindow가 대표적인 컨테이너들이다. 그리고 light-weight 경량 컨테이너인 JInternalFrame이 있겠으나 이건 AWT 클래스를 계승하고 있지 않으므로 약간 동떨어진 삘을 받는다. 이해가 되지 않으면 그림을 살짝 들여다보면 이해가 될것이라 생각한다. 어차피 이번 강좌의 내용은 스윙의 구조도에 대한 기본적인 체계에 대한 설명이니 설령 어렵게 느껴지더라도 스윙을 많이 접하게 되면 이래서 되고 저래서 안되는구나하는 이치를 저절로 깨닫게된다. 한마디로 시간이 약이다.ㅎㅎ


하지만 필자가 누구더냐? 그런 이들을 위해 그냥 간단하고 심플한 예제 하나로 본 내용의 이치와 정석을 깨우치도록 해보겠다. 실행할 예제의 결과는 다음과 같다.


사실 말로만 끝내도 상관없으나 프레임처럼 최상위 컨테이너에 해당하는 contentPane은 JRootPane의 인스턴스 객체안에서 생성되므로 사실 정의할 필요가 없으나 JRootpane의 클래스 인스턴스를 직접적으로 정의하고 쓴다면 그에 필요한 컨테이너를 정의하여야 한다. 바로 그것이 아까 초반부에 얘기한 중간단계라는 것이다. 사실 자바의 JRootPane을 공부하면서 가장 어렵게 느껴지는 부분이 이것이므로 이에 대한 예제를 핵심코드라인 2줄로서 그 차이점을 명쾌하게 파헤쳐본 것이 아래의 예제라 하겠다.


예제를 보고 직접 해보면 무엇을 설명하고자 하는지 알게되리라 본다. 그럼 이로서 그동안 진행해온 스윙을 간략하게나마 이렇게 마무리하고 다음 시간부터는 새로운 주제와 내용으로 무장해서 여러분의 기대와 성원에 성심성의껏 부응해 보도록 하겠다. 그럼 좋은 하루~^^