Eclipse #1 (코드 Style 설정)

 

팀 프로젝트를 진행할때 개발자별로 Coding Style이 달라서 고생하는 경우가 많습니다.
이를 위해 Eclipse는 코드 형식화를 지원하는데요,

아래와 같이 코딩 규칙을 위해바는 코드가 있다고 가정합시다.

 

해당 코드 위에서 [ Ctrl+Shift+F ] 키만 누르면 아래와 같이 코드가 이쁘게 정리됩니다.

 

이는 Eclipse에서 설정된 Code Formatter의 설정에 따른 것입니다.
프로젝트에서 개발된 모든 코드에 같은 코딩 규칙을 적용하고 싶다면
..
결정된 Coding Convention에 따라 Code Formatter의 설정을 바꾼 다음
,
그것을 XML 파일로 Export하고, 개발자에게 Import 시켜 적용하도록 하면 된답니다
.

아래 그림은 Windows - Preferences 에서 "Java - Code Style - Code Formatter"

선택했을 때 나오는 그림입니다
.
Eclipse 3.0
은 기본적으로 2가지 코드 형식을 기본적으로 내장하고 있습니다.

 

Java Conventions를 선택하고, Show.. 버튼을 누르면 해당 설정을 커스터마이징 할 수 있습니다.
탭 사이즈와 괄호의 위치 등 모든 것을 변경할 수 있습니다

Eclipse #2 (Import문 정리)

 

개발할 때 어떤 기능을 구현하기 위해 특정 라이브러리를 import 시켜놓고,
그 기능이 필요없어져서 삭제한 다음에도 import문은 그대로 두는 경우가 많습니다
.

그때 Eclipse가 제공하는 Organize import 기능은 아주 유용한데요
..
아래와 같이 사용되지 않는 라이브러리를 import한 경우 Eclipse는 앞에 전구를 키고 표시해줍니다
.
이때
[ Ctrl+Shift+O ] 버튼을 누르면 사용하지 않는 모든 import 문이 정리됩니다. 아래와 같이 깨끗하게 말이죠.

 

또 한가지 유용한 기능은 같은 패키지 내에서 여러 개의 클래스를 import할 경우입니다.
예를 들어 한 패키지 내에서 4개 이상의 클래스를 import 한다면
,
그것을 *로 합쳐서 표시하도록 하고 싶을 때가 있습니다
.
그럴 때는 window - preference 로 가서 java - code style - organize import에서

Number of imports needs for .*
의 수를 4로 해놓으면,
같은 패키지에서 4개이상의 클래스가 임포트되면 *로 합쳐서 표시해줍니다
.
(Apply
버튼 바로 위에 그 항목이 있습니다.)

 

Eclipse #3 (영역별 주석처리)

 

여러 줄에 걸쳐 있는 코드를 주석 처리하고 싶은데,
주석 처리하고자 하는 영역 내에 /* */가 있을 경우 참 곤란하시죠?

일일이 // 를 앞에 붙이려니 얼마나 손가락이 빠른지를 테스트하는거 같구.. ^^*
그럴 때 주석처리할 영역을 선택 한 다음
[ Ctrl+/ ] 를 눌러보세요.
아래와 같이 자동으로 해당 영역을 주석으로 만들어줍니다
.
주석을 해제하고 싶다면
다시 한번 더 [ Ctrl+/ ] 눌러주면 됩니다.

 

Eclipse #4 (에디터칸이동)

 

실제 프로젝트를 작업하다 보면 한번에 열어놓은 파일이 30개가 넘는 것은 기본이죠?
그때 해당 파일들 사이를 열려진 윈도우를 [ Alt+Tab ] 을 이용해서

이동하는 것 같은 기능이 있다면 편할겁니다.
그러한 단축키가
[ Ctrl+F6 ] 입니다.
그 키를 누르면 화면 중앙에 아래와 같은 에디터 이동 화면이 뜹니다

 

바로 이전으로 이동할 때는 [ Ctrl+F6 ]이 편하지만,
여러 개 중 하나를 이동할 때는 [ Ctrl+F6 ]을 누른 후,

[Ctrl+화살표] 를 이용해서 원하는 에디터로 이동하는 것이 편합니다.

Eclipse #6 (줄번호 표시 및 줄 이동하기)

 

Eclipse의 기본 설정에 라인 번호는 표시되지 않도록 되어 있습니다.
디버깅할 때 특정 라인에 에러가 있음을 확인했는데, 일일이 줄을 세어가면서 이동할 수도 없구
..
그때 해당 라인으로 이동하기 위한 단축키가
[ Ctrl+L ] 입니다.
윈도우와 같이 Ctrl+G 로 단축키를 변경해서 쓰시는 것도 좋을 듯 합니다
.

아예 줄번호가 항상 표시되도록 하고 싶다면 window - preference 에서
,
Java - Editor
로 이동한 다음
"Show line numbers"를 체크해두시면 됩니다.

Eclipse #7 (변경사항 추적하기)

 

변경 사항을 추적하고자 하는 파일을 PackageExplorer에서 선택 후,
오른쪽 버튼을 눌러 컨텍스트 메뉴에서
[ compare with Local History ] 선택합니다.

 

시간대 별로 이전의 작업 결과를 보실 수 있습니다.
만일 이전의 코드로 되돌아가고 싶다면, 같은 방법으로 파일의 컨텍스트 메뉴에서

[ Replace with ]
를 선택하고, [ Local History ]에서 변경하면 됩니다.

 

Eclipse #8 (Javadoc 문서생성 )

 

JavaDoc 형태의 주석으로 소스코드 문서화가 된 상태라고 가정하겠습니다.
Project
메뉴의
[ Generate Javadoc... ] 기능을 실행하면
간편한 마법사의 지원을 통해 Javadoc 문서를 생성할 수 있습니다.

일반적으로 프로젝트 루트 밑에 doc 이란 폴더 안에 JavaDoc으로 생성된 API 문서를 포함합니다.

 

생성될 API 문서에 포함시킬 정보를 선택하는 것이 마법사의 다음 단계입니다.
Finish
버튼을 누르면 Package Explorer에 아래와 같이 API 문서가 생성된 것을 확인할 수 있습니다.

Eclipse #9 (전체프로젝트 ZIP 백업)

 

전체 프로젝트를 백업하기 위해 압축을 해야 할때 유용한 기능입니다.
File
메뉴의 Export 기능을 실행하면 아래와 같은 윈도우가 뜹니다.

 

선택요소 중에서 ZIP 파일을 선택합니다.
다음 화면은 백업할 요소들을 선택하는 것입니다.
일반적으로 자동 생성되는 JavaDoc 문서나 Classes 파일들은 백업하지 않습니다.
적당한 백업 파일 이름과 위치를 결정하고 Finish 버튼을 누르면 백업이 완료됩니다.

 

이클립스에서 유용한 단축키

 

Ctrl + e : 한줄지움

Ctrl + w : 메뉴보여줌

Ctrl + space : 클래스등 코드 도움

Ctrl + / : 한줄 주석 반대는 Ctrl + \

Ctrl + , : 찾기나, TASK항목 이동

Ctrl + . : 이동

Ctrl + F6 : Editor 선택

Ctrl + F7 : View 선택

Ctrl + F8 : Perspectieve 선택

Ctrl + F11 : 디버깅

Ctrl + 1 : QuickFix 실행

Ctrl + Shift + b : 브레이크 포인트

Ctrl + Shift + e : 현재 캐럿에서 끝까지 삭제

Ctrl + Shift + f : 코드 포맷팅

Ctrl + Shift + m : 자동 임포트

Ctrl + Shift + o : 임포트 자동 정리

Ctrl + Shift + space : 입력 파라미터 정보 보여줌

 

'[JAVA]' 카테고리의 다른 글

시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
static 키워드 바로 알기  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
Overriding vs Overloading  (0) 2010.08.18
시스템의 밀리초 구하기.(국제표준시각(UTC, GMT) 1970/1/1/0/0/0 으로부터 경과한 시각)
------------------------------------------------------------------
// 밀리초 단위(*1000은 1초), 음수이면 이전 시각
long time = System.currentTimeMillis ( ); 
System.out.println ( time.toString ( ) ); 
------------------------------------------------------------------






현재 시각을 가져오기. ------------------------------------------------------------------ Date today = new Date (); System.out.println ( today ); 결과 : Sat Jul 12 16:03:00 GMT+01:00 2000 ------------------------------------------------------------------ 경과시간(초) 구하기 ------------------------------------------------------------------ long time1 = System.currentTimeMillis (); long time2 = System.currentTimeMillis (); system.out.println ( ( time2 - time1 ) / 1000.0 ); ------------------------------------------------------------------ Date를 Calendar로 맵핑시키기 ------------------------------------------------------------------ Date d = new Date ( ); Calendar c = Calendar.getInstance ( ); c.setTime ( d ); ------------------------------------------------------------------ 날짜(년/////초) 구하기 ------------------------------------------------------------------ import java.util.*; import java.text.*; SimpleDateFormat formatter = new SimpleDateFormat ( "yyyy.MM.dd HH:mm:ss", Locale.KOREA ); Date currentTime = new Date ( ); String dTime = formatter.format ( currentTime ); System.out.println ( dTime ); ------------------------------------------------------------------ 날짜(년/////초) 구하기2 ------------------------------------------------------------------ GregorianCalendar today = new GregorianCalendar ( ); int year = today.get ( today.YEAR ); int month = today.get ( today.MONTH ) + 1; int yoil = today.get ( today.DAY_OF_MONTH ); GregorianCalendar gc = new GregorianCalendar ( ); System.out.println ( gc.get ( Calendar.YEAR ) ); System.out.println ( String.valueOf ( gc.get ( Calendar.MONTH ) + 1 ) ); System.out.println ( gc.get ( Calendar.DATE ) ); System.out.println ( gc.get ( DAY_OF_MONTH ) ); ------------------------------------------------------------------ 날짜(년/////초) 구하기3 ------------------------------------------------------------------ DateFormat df = DateFormat.getDateInstance(DateFormat.LONG, Locale.KOREA); Calendar cal = Calendar.getInstance(Locale.KOREA); nal = df.format(cal.getTime()); ------------------------------------------------------------------ 표준시간대를 지정하고 날짜를 가져오기. ------------------------------------------------------------------ TimeZone jst = TimeZone.getTimeZone ("JST"); Calendar cal = Calendar.getInstance ( jst ); // 주어진 시간대에 맞게 현재 시각으로 초기화된 GregorianCalender 객체를 반환.// 또는 Calendar now = Calendar.getInstance(Locale.KOREA); System.out.println ( cal.get ( Calendar.YEAR ) + "년 " + ( cal.get ( Calendar.MONTH ) + 1 ) + "월 " + cal.get ( Calendar.DATE ) + "일 " + cal.get ( Calendar.HOUR_OF_DAY ) + "시 " +cal.get ( Calendar.MINUTE ) + "분 " + cal.get ( Calendar.SECOND ) + "초 " ); 결과 : 200085161647 ------------------------------------------------------------------ 영어로된 날짜를 숫자로 바꾸기 ------------------------------------------------------------------ Date myDate = new Date ( "Sun,5 Dec 1999 00:07:21" ); System.out.println ( myDate.getYear ( ) + "-" + myDate.getMonth ( ) + "-" + myDate.getDay ( ) ); ------------------------------------------------------------------ "Sun, 5 Dec 1999 00:07:21""1999-12-05"로 바꾸기 ------------------------------------------------------------------ SimpleDateFormat formatter_one = new SimpleDateFormat ( "EEE, dd MMM yyyy hh:mm:ss",Locale.ENGLISH ); SimpleDateFormat formatter_two = new SimpleDateFormat ( "yyyy-MM-dd" ); String inString = "Sun, 5 Dec 1999 00:07:21"; ParsePosition pos = new ParsePosition ( 0 ); Date frmTime = formatter_one.parse ( inString, pos ); String outString = formatter_two.format ( frmTime ); System.out.println ( outString ); ------------------------------------------------------------------ 숫자 12자리를, 다시 날짜로 변환하기 ------------------------------------------------------------------ Date conFromDate = new Date(); long ttl = conFromDate.parse ( "Dec 25, 1997 10:10:10" ); System.out.println ( ttl ); //예 938291839221 Date today = new Date ( ttl ); DateFormat format = DateFormat.getDateInstance ( DateFormat.FULL,Locale.US ); String formatted = format.format ( today ); System.out.println ( formatted ); ------------------------------------------------------------------ 특정일로부터 n일 만큼 이동한 날짜 구하기 ------------------------------------------------------------------ 특정일의 시간을 long형으로 읽어온다음.. 날짜*24*60*60*1000 을 계산하여, long형에 더해줍니다. 그리고 나서 Date클래스와 Calender클래스를 이용해서 날짜와 시간을 구하면 됩니다 ------------------------------------------------------------------ 특정일에서 일정 기간후의 날짜 구하기2 ------------------------------------------------------------------ //iDay 에 입력하신 만큼 빼거나 더한 날짜를 반환 합니다. import java.util.*; public String getDate ( int iDay ) { Calendar temp=Calendar.getInstance ( ); StringBuffer sbDate=new StringBuffer ( ); temp.add ( Calendar.DAY_OF_MONTH, iDay ); int nYear = temp.get ( Calendar.YEAR ); int nMonth = temp.get ( Calendar.MONTH ) + 1; int nDay = temp.get ( Calendar.DAY_OF_MONTH ); sbDate.append ( nYear ); if ( nMonth < 10 ) sbDate.append ( "0" ); sbDate.append ( nMonth ); if ( nDay < 10 ) sbDate.append ( "0" ); sbDate.append ( nDay ); return sbDate.toString ( ); } ------------------------------------------------------------------ 현재날짜에서 2달전의 날짜를 구하기 ------------------------------------------------------------------ Calendar cal = Calendar.getInstance ( );//오늘 날짜를 기준으루.. cal.add ( cal.MONTH, -2 ); //2개월 전.... System.out.println ( cal.get ( cal.YEAR ) ); System.out.println ( cal.get ( cal.MONTH ) + 1 ); System.out.println ( cal.get ( cal.DATE ) ); ------------------------------------------------------------------ 달에 마지막 날짜 구하기(말일) ------------------------------------------------------------------ for ( int month = 1; month <= 12; month++ ) { GregorianCalendar cld = new GregorianCalendar ( 2001, month - 1, 1 ); System.out.println ( month + "/" + cld.getActualMaximum ( Calendar.DAY_OF_MONTH ) ); } ------------------------------------------------------------------ 해당하는 달의 마지막 일 구하기(말일) ------------------------------------------------------------------ GregorianCalendar today = new GregorianCalendar ( ); int maxday = today.getActualMaximum ( ( today.DAY_OF_MONTH ) ); System.out.println ( maxday ); ------------------------------------------------------------------ 특정일을 입력받아 해당 월의 마지막 날짜를 구하는 간단한 예제.
(달은 -1 해준다.)...윤달 3031일 알아오기.
------------------------------------------------------------------ Calendar cal = Calendar.getInstance ( ); cal.set ( Integer.parseInt ( args[0] ), Integer.parseInt ( args [1] ) - 1, Integer.parseInt ( args [2] ) ); SimpleDateFormat dFormat = new SimpleDateFormat ( "yyyy-MM-dd" ); System.out.println ( "입력 날짜 " + dFormat.format ( cal.getTime ( ) ) ); System.out.println ( "해당 월의 마지막 일자 : " + cal.getActualMaximum ( Calendar.DATE ) ); ------------------------------------------------------------------ 해당월의 실제 날짜수 구하기 ( 19991월달의 실제 날짜수를 구하기 ) ------------------------------------------------------------------ Calendar calendar = Calendar.getInstance ( ); calendar.set ( 1999, 0, 1 ); int maxDays = calendar.getActualMaximum ( Calendar.DAY_OF_MONTH ); ------------------------------------------------------------------ 어제 날짜 구하기 ------------------------------------------------------------------ 오늘날짜를 초단위로 구해서 하루분을 빼주고 다시 셋팅해주면 쉽게 구할수 있죠.. setTime((기준일부터 오늘까지의 초를 구함) - 24*60*60)해주면 되겠죠.. ------------------------------------------------------------------ 어제 날짜 구하기2 ------------------------------------------------------------------ import java.util.*; public static Date getYesterday ( Date today ) { if ( today == null ) throw new IllegalStateException ( "today is null" ); Date yesterday = new Date ( ); yesterday.setTime ( today.getTime ( ) - ( (long) 1000 * 60 * 60 * 24 ) ); return yesterday; } ------------------------------------------------------------------ 내일 날짜 구하기 ------------------------------------------------------------------ Date today = new Date ( ); Date tomorrow = new Date ( today.getTime ( ) + (long) ( 1000 * 60 * 60 * 24 ) ); ------------------------------------------------------------------ 내일 날짜 구하기2 ------------------------------------------------------------------ Calendar today = Calendar.getInstance ( ); today.add ( Calendar.DATE, 1 ); Date tomorrow = today.getTime ( ); ------------------------------------------------------------------ 오늘날짜에서 5일 이후 날짜를 구하기 ------------------------------------------------------------------ Calendar cCal = Calendar.getInstance(); c.add(Calendar.DATE, 5); ------------------------------------------------------------------ 날짜에 해당하는 요일 구하기 ------------------------------------------------------------------ //DAY_OF_WEEK리턴값이 일요일(1), 월요일(2), 화요일(3) ~~ 토요일(7)을 반환합니다. //아래 소스는 JSP일부입니다. import java.util.*; Calendar cal= Calendar.getInstance ( ); int day_of_week = cal.get ( Calendar.DAY_OF_WEEK ); if ( day_of_week == 1 ) m_week="일요일"; else if ( day_of_week == 2 ) m_week="월요일"; else if ( day_of_week == 3 ) m_week="화요일"; else if ( day_of_week == 4 ) m_week="수요일"; else if ( day_of_week == 5 ) m_week="목요일"; else if ( day_of_week == 6 ) m_week="금요일"; else if ( day_of_week == 7 ) m_week="토요일"; 오늘은 : 입니다. ------------------------------------------------------------------ 콤보박스로 선택된 날짜(예:20001023)를 통해 요일을 영문으로 가져오기 ------------------------------------------------------------------ //gc.get(gc.DAY_OF_WEEK); 하면 일요일=1, 월요일=2, ..., 토요일=7이 나오니까, //요일을 배열로 만들어서 뽑아내면 되겠죠. GregorianCalendar gc=new GregorianCalendar ( 2000, 10 - 1 , 23 ); String [] dayOfWeek = { "", "Sun", "Mon", .... , "Sat" }; String yo_il = dayOfWeek ( gc.get ( gc.DAY_OF_WEEK ) ); ------------------------------------------------------------------ 두 날짜의 차이를 일수로 구하기 ------------------------------------------------------------------ 각각의 날짜를 Date형으로 만들어서 getTime()하면 long으로 값이 나오거든요(197011일 이후-맞던가?- 1/1000 초 단위로..) 그러면 이값의 차를 구해서요. (1000*60*60*24)로 나누어 보면 되겠죠. ------------------------------------------------------------------ 두 날짜의 차이를 일수로 구하기2 ------------------------------------------------------------------ import java.io.*; import java.util.*; Date today = new Date ( ); Calendar cal = Calendar.getInstance ( ); cal.setTime ( today );// 오늘로 설정. Calendar cal2 = Calendar.getInstance ( ); cal2.set ( 2000, 3, 12 ); // 기준일로 설정. month의 경우 해당월수-1을 해줍니다. int count = 0; while ( !cal2.after ( cal ) ) { count++; cal2.add ( Calendar.DATE, 1 ); // 다음날로 바뀜 System.out.println ( cal2.get ( Calendar.YEAR ) + "년 " + ( cal2.get ( Calendar.MONTH ) + 1 ) + "월 " + cal2.get ( Calendar.DATE ) + "일" ); } System.out.println ( "기준일로부터 " + count + "일이 지났습니다." ); ------------------------------------------------------------------ 두 날짜의 차이를 일수로 구하기3 ------------------------------------------------------------------ import java.io.*; import java.util.*; public class DateDiff { public static int GetDifferenceOfDate ( int nYear1, int nMonth1, int nDate1, int nYear2, int nMonth2, int nDate2 ) { Calendar cal = Calendar.getInstance ( ); int nTotalDate1 = 0, nTotalDate2 = 0, nDiffOfYear = 0, nDiffOfDay = 0; if ( nYear1 > nYear2 ) { for ( int i = nYear2; i < nYear1; i++ ) { cal.set ( i, 12, 0 ); nDiffOfYear += cal.get ( Calendar.DAY_OF_YEAR ); } nTotalDate1 += nDiffOfYear; } else if ( nYear1 < nYear2 ) { for ( int i = nYear1; i < nYear2; i++ ) { cal.set ( i, 12, 0 ); nDiffOfYear += cal.get ( Calendar.DAY_OF_YEAR ); } nTotalDate2 += nDiffOfYear; } cal.set ( nYear1, nMonth1-1, nDate1 ); nDiffOfDay = cal.get ( Calendar.DAY_OF_YEAR ); nTotalDate1 += nDiffOfDay; cal.set ( nYear2, nMonth2-1, nDate2 ); nDiffOfDay = cal.get ( Calendar.DAY_OF_YEAR ); nTotalDate2 += nDiffOfDay; return nTotalDate1-nTotalDate2; } public static void main ( String args[] ) { System.out.println ( "" + GetDifferenceOfDate (2000, 6, 15, 1999, 8, 23 ) ); } } ------------------------------------------------------------------ 파일에서 날짜정보를 가져오기 ------------------------------------------------------------------ File f = new File ( directory, file ); Date date = new Date ( f.lastModified ( ) ); Calendar cal = Calendar.getInstance ( ); cal.setTime ( date ); System.out.println("Year : " + cal.get(Calendar.YEAR)); System.out.println("Month : " + (cal.get(Calendar.MONTH) + 1)); System.out.println("Day : " + cal.get(Calendar.DAY_OF_MONTH)); System.out.println("Hours : " + cal.get(Calendar.HOUR_OF_DAY)); System.out.println("Minutes : " + cal.get(Calendar.MINUTE)); System.out.println("Second : " + cal.get(Calendar.SECOND)); ------------------------------------------------------------------ 날짜형식으로 2000-01-03으로 처음에 인식을 시킨후 7일씩 증가해서 1년정도의 날짜를 출력해 주고 싶은데요. ------------------------------------------------------------------ SimpleDateFormat sdf = new SimpleDateFormat ( "yyyy-mm-dd" ); Calendar c = Calendar.getInstance ( ); for ( int i = 0; i < 48; i++ ) { c.clear ( ); c.set ( 2000, 1, 3 - ( i * 7 ) ); java.util.Date d = c.getTime ( ); String thedate = sdf.format ( d ); System.out.println ( thedate ); } ------------------------------------------------------------------ 쓰레드에서 날짜 바꾸면 죽는 문제 ------------------------------------------------------------------ Main화면에 날짜와시간이Display되는 JPanel이 있습니다. date로 날짜와 시간을 변경하면 Main화면의 날짜와 시간이 Display되는 Panel에 변경된 날짜가 Display되지 않고 Main화면이 종료되어 버립니다. 문제소스: public void run ( ) { while ( true ) { try{ timer.sleep ( 60000 ); } catch ( InterruptedException ex ) { } lblTimeDate.setText ( fGetDateTime ( ) ); repaint ( ); } } public String fGetDateTime ( ) { final int millisPerHour = 60 * 60 * 1000; String DATE_FORMAT = "yyyy / MM / dd HH:mm"; SimpleDateFormat sdf = new SimpleDateFormat ( DATE_FORMAT ); SimpleTimeZone timeZone = new SimpleTimeZone ( 9 * millisPerHour, "KST" ); sdf.setTimeZone ( timeZone ); long time = System.currentTimeMillis ( ); Date date = new Date ( time ); return sdf.format ( date ); } 해답: // 날짜와 요일 구한다. timezone 으로 날짜를 다시 셋팅하시면 됨니다. public String getDate ( ) { Date now = new Date ( ); SimpleDateFormat sdf4 = new SimpleDateFormat ( "yyyy/MM/dd HH:mm EE" ); sdf4.setTimeZone ( TimeZone.getTimeZone ( "Asia/Seoul" ) ); return sdf4.format ( now ); } ------------------------------------------------------------------ 날짜와 시간이 유효한지 검사하려면...? ------------------------------------------------------------------ import java.util.*; import java.text.*; public class DateCheck { boolean dateValidity = true; DateCheck ( String dt ) { try { DateFormat df = DateFormat.getDateInstance ( DateFormat.SHORT ); df.setLenient ( false ); Date dt2 = df.parse ( dt ); } catch ( ParseException e ) { this.dateValidity = false; } catch ( IllegalArgumentException e ) { this.dateValidity = false; } } public boolean datevalid ( ) { return dateValidity; } public static void main ( String args [] ) { DateCheck dc = new DateCheck ( "2001-02-28" ); System.out.println ( " 유효한 날짜 : " + dc.datevalid ( ) ); } } ------------------------------------------------------------------ 두 날짜 비교하기(아래보다 정확) ------------------------------------------------------------------ 그냥 날짜 두개를 long(밀리 세컨드)형으로 비교하시면 됩니다... 이전의 데이타가 date형으로 되어 있다면, 이걸 long형으로 변환하고. 현재 날짜(시간)은 System.currentTimeMillis()메소드로 읽어들이고, 두수(long형)를 연산하여 그 결과 값으로 비교를 하시면 됩니다. 만약 그 결과값이 몇시간 혹은 며칠차이가 있는지를 계산할려면, 결과값을 Calender의 setTimeInMillis(long millis) 메소드를 이용해 설정한다음 각각의 날짜나 시간을 읽어오시면 됩니다 ------------------------------------------------------------------ 두 날짜 비교하기2 ------------------------------------------------------------------ //Calendar를 쓸 경우 데이타의 원본을 고치기 때문에 clone()을 사용하여 //복사한 후에 그 복사본을 가지고 비교한다 import java.util.*; import java.util.Calendar.*; import java.text.SimpleDateFormat; public class DayComparisonTest { public static void main(String args[]) { Calendar cal = Calendar.getInstance(); SimpleDateFormat dateForm = new SimpleDateFormat("yyyy-MM-dd"); Calendar aDate = Calendar.getInstance(); // 비교하고자 하는 임의의 날짜 aDate.set(2001, 0, 1); Calendar bDate = Calendar.getInstance(); // 이것이 시스템의 날짜 // 여기에 시,분,초를 0으로 세팅해야 before, after를 제대로 비교함 aDate.set( Calendar.HOUR_OF_DAY, 0 ); aDate.set( Calendar.MINUTE, 0 ); aDate.set( Calendar.SECOND, 0 ); aDate.set( Calendar.MILLISECOND, 0 ); bDate.set( Calendar.HOUR_OF_DAY, 0 ); bDate.set( Calendar.MINUTE, 0 ); bDate.set( Calendar.SECOND, 0 ); bDate.set( Calendar.MILLISECOND, 0 ); if (aDate.after(bDate)) // aDate가 bDate보다 클 경우 출력 System.out.println("시스템 날짜보다 뒤일 경우 aDate = " + dateForm.format(aDate.getTime())); else if (aDate.before(bDate)) // aDate가 bDate보다 작을 경우 출력 System.out.println("시스템 날짜보다 앞일 경우 aDate = " + dateForm.format(aDate.getTime())); else // aDate = bDate인 경우 System.out.println("같은 날이구만"); } }

'[JAVA]' 카테고리의 다른 글

Eclipse TIP  (0) 2010.08.26
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
static 키워드 바로 알기  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
Overriding vs Overloading  (0) 2010.08.18

오름차순 정렬
import java.util.Arrays;

public class Foo {
  public static void main(String args[]) {

    // 문자열 배열 정렬 (가나다 순으로 소팅)
    String s[] = {  "맹구",
                  "배용준",
                  "땡칠이",
                  "장동건",
                  "강수정",
                  "송창식",
                  "황당해",
                  "고은아"};

    Arrays.sort(s);
    System.out.println(Arrays.toString(s));
    // 결과: [강수정, 고은아, 땡칠이, 맹구, 배용준, 송창식, 장동건, 황당해]


    // 숫자 배열 정렬
    double num[] = {               -1000,
                     0.07890264912715708,
                                     0.2,
                    -0.18441624291164838,
                                       0,
                                     123,
                                    -0.1,
                                    -0.1,
                                    1000,
                                  0.4999};

    Arrays.sort(num);
    System.out.println(Arrays.toString(num));
    // 결과: [-1000.0, -0.18441624291164838, -0.1, -0.1, 0.0, 0.07890264912715708, 0.2, 0.4999, 123.0, 1000.0]
  }
}

=====================================================================================================

내림차순 정렬1
자바로 소팅을 할 때에는 역순 즉 내림차순(Descending Order)으로 소팅하는 간단한 방법이, 제가 알아본 바로는 없었습니다.

물론, 오름차순으로 소팅한 후, 그 배열의 순서를 뒤집어주면 역순 정렬이 됩니다. 이 방법의 속도가 느린 줄 알았는데, 비교 함수를 사용하는 것보다 빠르다고 하더군요. 각 요소를 소트할 때마다 비교 함수를 호출하는 데에 시간이 많이 걸리지만, 배열 요소 순서를 단순히 뒤집어 주는 것에는 시간이 거의 걸리지 않기 때문일 것입니다.

그래서 뒤집어 주는 방법으로 예제를 만들었습니다.

import java.util.*;

public class Foo {
  public static void main(String[] args) {


    String[] a = { "bbb", "AAA", "DDD", "똠방각하", "CCC", "aaa" };

    Arrays.sort(a, String.CASE_INSENSITIVE_ORDER);


//////////////////////////////////////////////////
    // 배열을 리스트로 변환
    List<String> list = Arrays.asList(a);

    // 리스트 뒤집어 주기
    Collections.reverse(list);
//////////////////////////////////////////////////


    // 리스트를 배열로 다시 변환
    a = list.toArray(new String[list.size()]);


    // 순서 뒤집어진 배열을 문자열로 변환 후 출력
    String s = Arrays.toString(a);
    System.out.println(s);
    // 출력 결과: [똠방각하, DDD, CCC, bbb, aaa, AAA]

  }
}
===================================================================================

내림차순 정렬2
import java.util.*;

public class Foo {
  public static void main(String[] args) {

    String[] a = { "bbb", "AAA", "DDD", "똠방각하", "CCC", "aaa" };


    // 정렬
    Arrays.sort(a, String.CASE_INSENSITIVE_ORDER);


    // 배열 순서 거꾸로
    reverseArrayString(a);


    // 순서 뒤집어진 "문자열 배열"을 "문자열"로 변환 후 출력
    System.out.println(Arrays.toString(a));
    // 출력 결과: [똠방각하, DDD, CCC, bbb, aaa, AAA]
  }

 


  public static void reverseArrayString(String[] array) {
    String temp;

    for (int i = 0; i < array.length / 2; i++) {
      temp = array[i];
      array[i] = array[(array.length - 1) - i];
      array[(array.length - 1) - i] = temp;
    }
  }


}

'[JAVA]' 카테고리의 다른 글

Eclipse TIP  (0) 2010.08.26
시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
static 키워드 바로 알기  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
Overriding vs Overloading  (0) 2010.08.18

자바를 한번쯤 공부해본사람이라면 static키워드를 모르지는 않을 것입니다.

하지만, 바르게 알고 있는 사람들은 그리 많지 않습니다.


자바경력자를 면접볼 때 static키워드에 대해서 질문하곤 합니다.


면접관 : static키워드에 대해서 설명해보세요.
응시자 : static키워드를 쓰면, 객체를 생성하지 않고도 변수나 함수를 사용할 수 있습니다.


면접관 : 왜 static키워드를 쓰나요?
응시자 : 객체를 생성하지 않아도 되니까 편리하고 속도도 빠릅니다.


면접관 : 그렇다면 모든 변수와 함수에 static을 붙이는 것이 좋겠네요?
응시자 : 가능한한 static을 붙이는 것이 좋다고 생각합니다.


면접관 : 어떤 경우에 static을 붙일 수 있고, 어떤 경우에 static을 붙일 수 없습니까?
응시자 : ...


면접관 : 만일 당신이 새로운 클래스를 작성한다고 할 때, 어떤 경우에 static키워드를
             사용해야한다고 생각합니까?

응시자 : ...


대부분의 경우 위와 같은 내용으로 문답이 진행됩니다.

사실 응시자의 대답은 다 맞는 얘기입니다. 하지만, static의 핵심적인 개념을 모르기 때문에
어떤 경우에 왜 static을 사용해야하는지는 잘모르는 것 같습니다.


먼저 결론부터 간단히 정리하면 다음과 같습니다.


1.클래스를 설계할 때, 멤버변수 중 모든 인스턴스에 공통적으로 사용해야하는 것에 static을 붙인다.
 - 인스턴스를 생성하면, 각 인스턴스들은 서로 독립적기 때문에 서로 다른 값을 유지한다.
    경우에 따라서는 각 인스턴스들이 공통적으로 같은 값이 유지되어야 하는 경우 static을
    붙인다.


2. static이 붙은 멤버변수는 인스턴스를 생성하지 않아도 사용할 수 있다.
 - static이 붙은 멤버변수(클래스변수)는 클래스가 메모리에 올라갈때 이미 자동적으로
   생성되기 때문이다.


3. static이 붙은 메서드(함수)에서는 인스턴스 변수를 사용할 수 없다.
 - static이 메서드는 인스턴스 생성 없이 호출가능한 반면, 인스턴스 변수는 인스턴스를
    생성해야만 존재하기 때문에... static이 붙은 메서드(클래스메서드)를 호출할 때
    인스턴스가 생성되어있을수도 그렇지 않을 수도 있어서 static이 붙은 메서드에서
    인스턴스변수의 사용을 허용하지 않는다.
    (반대로, 인스턴스변수나 인스턴스메서드에서는 static이 붙은 멤버들을 사용하는 것이
     언제나 가능하다. 인스턴스변수가 존재한다는 것은 static이 붙은 변수가 이미 메모리에
     존재한다는 것을 의미하기 때문이다.)


4. 메서드 내에서 인스턴스 변수를 사용하지 않는다면, static을 붙이는 것을 고려한다.
 - 메서드의 작업내용중에서 인스턴스 변수를 필요로 한다면, static을 붙일 수 없다.
    반대로 인스턴스변수를 필요로 하지 않는다면, 가능하면 static을 붙이는 것이 좋다.
    메서드 호출시간이 짧아지기 때문에 효율이 높아진다.
    (static을 안붙인 메서드는 실행시 호출되어야할 메서드를 찾는 과정이 추가적으로
    필요하기 때문에 시간이 더 걸린다.)


5. 클래스 설계시 static의 사용지침
 - 먼저 클래스의 멤버변수중 모든 인스턴스에 공통된 값을 유지해야하는 것이 있는지
    살펴보고 있으면, static을 붙여준다.
 - 작성한 메서드 중에서 인스턴스 변수를 사용하지 않는 메서드에 대해서 static을
    붙일 것을 고려한다.
 
일반적으로 인스턴스변수와 관련된 작업을 하는 메서드는 인스턴스메서드(static이 안붙은
메서드)이고 static변수(클래스변수)와 관련된 작업을 하는 메서드는 클래스메서드(static이 붙은 메서드)라고 보면 된다.


다음은 static에 대한 자세한 설명과 예제입니다.


static은 객체지향개념을 이해하는 가장 중요한 첫걸음이니 확실히 알아두셔야합니다.


==================================================================
   


 

3.2 클래스변수와 인스턴스변수


클래스변수와 인스턴스변수의 차이를 이해하기 위한 예로 카드 게임에 사용되는 카드를 클래스로 정의해보자.

카드 클래스를 작성하기 위해서는 먼저 카드를 분석해서 속성과 기능을 알아 내야한다. 속성으로는 카드의 무늬, 숫자, 폭, 높이 정도를 생각할 수 있을 것이다.
이 중에서 어떤 속성을 클래스 변수로 선언할 것이며, 또 어떤 속성들을 인스턴스 변수로 선언할 것인지 생각해보자.


class Card {
     String kind ;                         // 카드의 무늬 - 인스턴스 변수
     int number;                         // 카드의 숫자 - 인스턴스 변수
     static int width = 100 ;             // 카드의 폭 - 클래스 변수
     static int height = 250 ;            // 카드의 높이 - 클래스 변수
}


각 Card인스턴스는 자신만의 무늬(kind)와 숫자(number)를 유지하고 있어야 하므로 이들을 인스턴스변수로 선언하였고, 각 카드들의 폭(width)과 높이(height)는 모든 인스턴스가 공통적으로 같은 값을 유지해야하므로 클래스변수로 선언하였다.

만일 카드의 폭을 변경해야할 필요가 있을 때는 모든 카드의 width값을 변경하지 않고, 한 카드의 width값만 변경해도 모든 카드의 width값이 변경되는 셈이다.

[예제6-4] CardTest.java

class CardTest{
      public static void main(String args[]) {
            // 클래스변수(static 변수)는 객체생성없이 '클래스이름.클래스변수'로 직접 사용 가능하다.
            System.out.println("Card.width = " + Card.width);
            System.out.println("Card.height = " + Card.height);

            Card c1 = new Card();
            c1.kind = "Heart";
            c1.number = 7;

            Card c2 = new Card();
            c2.kind = "Spade";
            c2.number = 4;

            System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
            System.out.println("c2는 " + c2.kind + ", " + c2.number + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );             System.out.println("이제 c1의 width와 height를 각각 50, 80으로 변경합니다.");
            c1.width = 50;
            c1.height = 80;

            System.out.println("c1은 " + c1.kind + ", " + c1.number + "이며, 크기는 (" + c1.width + ", " + c1.height + ")" );
            System.out.println("c2는 " + c2.kind + ", " + c2.number + "이며, 크기는 (" + c2.width + ", " + c2.height + ")" );
      }
}

class Card {
     String kind ;                         // 카드의 무늬 - 인스턴스 변수
     int number;                         // 카드의 숫자 - 인스턴스 변수
     static int width = 100;             // 카드의 폭 - 클래스 변수
     static int height = 250;             // 카드의 높이 - 클래스 변수
}

[실행결과]
Card.width = 100
Card.height = 250
c1은 Heart, 7이며, 크기는 (100, 250)
c2는 Spade, 4이며, 크기는 (100, 250)
이제 c1의 width와 height를 각각 50, 80으로 변경합니다.
c1은 Heart, 7이며, 크기는 (50, 80)
c2는 Spade, 4이며, 크기는 (50, 80)


Card클래스의 클래스변수(static변수)인 width, height 그리고 color는 Card클래스의 인스턴스를 생성하지 않고도 '클래스이름.클래스변수'와 같은 방식으로 사용할 수 있다.
Card인스턴스인 c1과 c2는 클래스 변수인 width와 height를 공유하기 때문에, c1의 width와 height를 변경하면 c2의 width와 height값도 바뀐 것과 같은 결과를 얻는다.
Card.width, c1.width, c2.width는 모두 같은 저장공간을 참조하므로 항상 같은 값을 갖게 된다.
인스턴스 변수는 인스턴스가 생성될 때 마다 생성되므로 인스턴스마다 각기 다른 값을 유지할 수 있지만, 클래스 변수는 모든 인스턴스가 하나의 저장공간을 공유하므로, 항상 공통된 값을 갖는다.

3.9 클래스메서드(static메서드)와 인스턴스메서드


변수에서 그랬던 것과 같이, 메서드 앞에 static이 붙어 있으면 클래스메서드이고 붙어 있지 않으면 인스턴스메서드이다.
클래스 메서드는 호출방법 역시 클래스변수처럼, 객체를 생성하지 않고도 '클래스이름.메서드이름(매개변수)'와 같은 식으로 호출이 가능하다.
그렇다면 어느 경우에 static을 사용해서 클래스메서드로 정의해야하는 것일까?

클래스는 '데이터(변수)와 데이터에 관련된 메서드의 집합'이라고 할 수 있다. 같은 클래스 내에 있는 메서드와 멤버변수는 아주 밀접한 관계가 있다. 인스턴스메서드는 인스턴스변수와 관련된 작업을 하는, 즉 메서드의 작업을 수행하는데 인스턴스변수를 필요로 하는 메서드이다.
그래서 인스턴스변수와 관계없거나(메서드 내에서 인스턴스변수를 사용하지 않거나), 클래스변수만을 사용하는 메서드들은 클래스메서드로 정의한다.

물론 인스턴스변수를 사용하지 않는다고 해서 반드시 클래스 메서드로 정의해야하는 것은 아니지만, 그렇게 하는 것이 일반적이다.
참고로 Math클래스의 모든 메서드는 클래스메서드임을 알 수 있다. Math클래스에는 인스턴스변수가 하나도 없거니와 Math클래스의 함수들은 작업을 수행하는데 필요한 값들을 모두 매개변수로 받아서 처리 하기 때문이다. 이처럼, 단순히 함수들만의 집합인 경우에는 클래스메서드로 선언한다.

[참고]인스턴스 변수 뿐만 아니라 인스턴스 메서드를 호출하는 경우에도 인스턴스 메서드로 선언되어야 한다. 인스턴스 메서드를 호출하는 것 역시 인스턴스 변수를 간접적으로 사용하는 것이기 때문이다.

[예제6-12] MyMathTest2.java

class MyMath2 {
      long a, b;
     
      // 인스턴스변수 a, b를 이용한 작업을 하므로 매개변수가 필요없다.
      long add() {       return a + b; }
      long subtract() {       return a - b; }
      long multiply() {       return a * b; }
      double divide() {       return a / b; }

      // 인스턴스변수와 관계없이 매개변수만으로 작업이 가능하다.
      static long add(long a, long b) {       return a + b; }
      static long subtract(long a, long b) {       return a - b; }
      static long multiply(long a, long b) {       return a * b; }
      static double divide(double a, double b) {       return a / b; }
}

class MyMathTest2 {
      public static void main(String args[]) {
            // 클래스메서드 호출
            System.out.println(MyMath2.add(200L, 100L));
            System.out.println(MyMath2.subtract(200L, 100L));
            System.out.println(MyMath2.multiply(200L, 100L));
            System.out.println(MyMath2.divide(200.0, 100.0));

            MyMath2 mm = new MyMath2();
            mm.a = 200L;
            mm.b = 100L;
            // 인스턴스메서드는 객체생성 후에만 호출이 가능함.
            System.out.println(mm.add());
            System.out.println(mm.subtract());
            System.out.println(mm.multiply());
            System.out.println(mm.divide());

}
[실행결과]
300
100
20000
2.0
300
100
20000
2.0

인스턴스메서드인 add(), subtract(), multiply(), divide()는 인스턴스변수인 a와 b만으로도 충분히 원하는 작업이 가능하기 때문에, 매개변수를 필요로 하지 않으므로 괄호()에 매개변수를 선언하지 않았다.
반면에 add(long a, long b), subtract(long a, long b) 등은 인스턴스변수 없이 매개변수만으로 작업을 수행하기 때문에 static을 붙여서 클래스메서드로 선언하였다. MyMathTest2의 main메서드에서 보면, 클래스메서드는 객체생성없이 바로 호출이 가능했고, 인스턴스메서드는 MyMath2클래스의 인스턴스를 생성한 후에야 호출이 가능했다.
이 예제를 통해서 어떤 경우 인스턴스메서드로, 또는 클래스메서드로 선언해야하는지, 그리고 그 차이를 이해하는 것은 매우 중요하다.



3.10 클래스멤버와 인스턴스멤버간의 참조와 호출.


같은 클래스에 속한 멤버들간에는 별도의 인스턴스를 생성하지 않고도 서로 참조 또는 호출이 가능하다. 단, 클래스멤버가 인스턴스멤버를 참조 또는 호출하고자 하는 경우에는 인스턴스를 생성해야 한다.
그 이유는 인스턴스멤버가 존재하는 시점에 클래스멤버는 항상 존재하지만, 클래스멤버가 존재하는 시점에 인스턴스멤버가 항상 존재한다는 것을 보장할 수 없기 때문이다.

[예제6-] ArrayEx.java

class MemberCall {
      int iv = 10;
      static int cv = 20;

      int iv2 = cv;
//   static int cv2 = iv;                   에러. 클래스변수는 인스턴스 변수를 사용할 수 없음.
      static int cv2 = new MemberCall().iv;   // 굳이 사용하려면 이처럼 객체를 생성해야함.

      static void classMethod1() {
            System.out.println(cv);
//         System.out.println(iv);       에러. 클래스메서드에서 인스턴스변수를 바로 사용할 수 없음.
            MemberCall c = new MemberCall();      
            System.out.println(c.iv);   // 객체를 생성한 후에야 인스턴스변수의 참조가 가능함.
     }

      void instanceMethod1() {
            System.out.println(cv);            
            System.out.println(iv);  // 인스턴스메서드에서는 인스턴스변수를 바로 사용가능.
     }

      static void classMethod2() {
            classMethod1();
//         instanceMethod1(); 에러. 클래스메서드에서는 인스턴스메서드를 바로 호출할 수 없음.
            MemberCall c = new MemberCall();
            c.instanceMethod1(); // 인스턴스를 생성한 후에야 인스턴스메서드를 호출할 수 있음.
      }
     
      void instanceMethod2() { // 인스턴스메서드에서는 인스턴스메서드와 클래스메서드
            classMethod1();         // 모두 인스턴스생성없이 바로 호출이 가능하다.
            instanceMethod1();
     }
}

클래스멤버(클래스변수와 클래스메서드)는 언제나 참조 또는 호출이 가능하다.
그렇기 때문에 인스턴스멤버가 클래스멤버를 참조, 호출하는 것은 아무런 문제가 안 된다.
클래스멤버간의 참조 또는 호출 역시 아무런 문제가 없다.

그러나, 인스턴스멤버(인스턴스변수와 인스턴스메서드)는 반드시 객체를 생성한 후에만 참조 또는 호출이 가능하기 때문에 클래스멤버가 인스턴스멤버를 참조, 호출하기 위해서는 객체를 생성하여야 한다.

하지만, 인스턴스멤버간의 호출에는 아무런 문제가 없다. 하나의 인스턴스멤버가 존재한다는 것은 인스턴스가 이미 생성되어있다는 것을 의미하며, 즉 다른 인스턴스멤버들도 모두 존재하기 때문이다.

실제로는 같은 클래스 내에서 클래스멤버가 인스턴스멤버를 참조 또는 호출해야하는 경우는 드물다. 만일 그런 경우가 발생한다면, 인스턴스메서드로 작성해야할 메서드를 클래스메서드로 한 것은 아닌지 한번 더 생각해봐야 한다.

[알아두면 좋아요]

수학에서의 대입법처럼, c = new MemberCall()이므로 c.instanceMethod1();에서 c대신 new MemberCall()을 대입하여 사용할 수 있다.

      MemberCall c = new MemberCall();
      int result = c.instanceMethod1();

위의 두 줄을 다음과 같이 한 줄로 할 수 있다.

      int result = new MemberCall().instanceMethod1();

대신 참조변수를 사용하지 않았기 때문에 생성된 MemeberCall인스턴스는 더 이상 사용할 수 없다

'[JAVA]' 카테고리의 다른 글

시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
Overriding vs Overloading  (0) 2010.08.18
JAVA  (0) 2010.02.09

J2SE 5.0이전에는 간단한 JTable을 출력하는 것도 어려운 일이었다. J2SE 5.0에는 API에 print() 메소드가 추가되어 테이블 출력, 결과물에 머리글/바닥글 삽입, 출력 페이지에 테이블크기 맞추기 등의 설정이 가능해졌다. 이번 테크팁에서는 이런 새로운 기능들을 사용하여 간단한 JTable을 출력하는 법에 대해 알아본다. 또한 한 줄 걸러 음영 넣기, 그림자 유무에 따라 테이블 출력하기 등의 사용자 정의에 대해서도 설명한다.

Swing 튜토리얼에 나와있는 SimpleTableDemo program을 리팩토링하는 것부터 시작하자. 리팩토링은 이번 테크팁 내 모든 예제의 공통 코드를 취합하고 있다. 테이블에 대한 데이터는 private static final variables형의 columnNames와 code>data(각 코드 리스팅의 마지막 부분에 나타남)에 포함되어 있다. 다른 공통 코드는 setUpJFrame()getTablePanel()에 포함되어 있다. 이 메소드들은 JTable을 보여주는 데 사용하는 JFrameJPanel을 설정하는 데 사용된다.(공통 코드는 다음의 예제에 나타나지만, 그 후의 예제에는 포함되지 않는다.)

다음은 BaseTable 클래스이다.

   import javax.swing.JTable;
   import javax.swing.SwingUtilities;
   import javax.swing.JFrame;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
   import java.awt.Dimension;
   import java.awt.GridLayout;
   
   public class BaseTable extends JTable {
   
         public BaseTable() {
           super(data, columnNames);
           setUpJFrame();
         }
   
         public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
             public void run() {
               new BaseTable();
             }
           });
         }
   
         // Table Frame common to all examples in this tip
   
          private void setUpJFrame() {
          JFrame frame = new JFrame();
           frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
           frame.add( getTablePanel());
           frame.pack();
           frame.setVisible(true);
         }
   
        private JPanel getTablePanel(){
           JPanel jPanel = new JPanel(new GridLayout(1,0));
           jPanel.setOpaque(true);
          setPreferredScrollableViewportSize(
                                 new Dimension(500, 70));
           jPanel.add(new JScrollPane(this));
           return jPanel;
         }
   
         // Table Data common to all examples in this tip
   
         private static final String[] columnNames =
           {"First Name", "Last Name", "Sport",
            "# of Years", "Vegetarian"};
   
         private static final Object[][] data = {
           {"Mary", "Campione", "Snowboarding",
            new Integer(5), new Boolean(false)},
           {"Alison", "Huml", "Rowing",
            new Integer(3), new Boolean(true)},
           {"Kathy", "Walrath", "Knitting",
            new Integer(2), new Boolean(false)},
           {"Sharon", "Zakhour", "Speed reading",
            new Integer(20), new Boolean(true)},
           {"Philip", "Milne", "Pool",
            new Integer(10), new Boolean(false)}
         };
       }

BaseTableinvokeLater()를 통해 이벤트 디스패치 쓰레드(event dispatch thread)에 GUI를 생성하고 보여주는 방법을 권장한다. BaseTable을 컴파일하고 구동하자. data에서 공급한 데이터들이 나타나는 5행 테이블이 나타난다.


한 줄 걸러 음영을 넣는 것은 의외로 어렵지 않다. 이는 javax.swing.JTable prepareRenderer() 메소드를 오버라이딩하여 만들 수 있다. 먼저, 사용자가 오버라이딩하는 prepareRenderer() 메소드로부터 현재 셀이 렌더링되도록 한다. 다음으로, rowIndex가 짝수인지 홀수인지 결정한다. 홀수행은 배경색을 변경하고 짝수행은 현재색이 배경색이 되도록 한다. 이는 다음 ColorTable 클래스에 나와있다.

   import javax.swing.JTable;
   import javax.swing.SwingUtilities;
   import javax.swing.JFrame;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
   import javax.swing.table.TableCellRenderer;
   import java.awt.Dimension;
   import java.awt.GridLayout;
   import java.awt.Component;
   import java.awt.Color;
   
   public class ColorTable extends JTable {
   
         public ColorTable() {
           super(data, columnNames);
           setUpJFrame();
         }
   
      public Component prepareRenderer(
                                TableCellRenderer renderer,
                                int row, int col) {
           Component c = super.prepareRenderer(renderer,
                                      row, col);
           if (row % 2 == 0 && !isCellSelected(row,col)) {
             c.setBackground(Color.LIGHT_GRAY);
           } else {
             c.setBackground(getBackground());
           }
           return c;
         }
   
         public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
             public void run() {
               new ColorTable();
             }
           });
         }
         // put common code here . . .
     }

ColorTable을 컴파일하고 구동한다. 다음과 같이 홀수행에 음영이 생기게 될 것이다.


이제 BaseTable에 의해 보여지는 꾸며지지 않은 테이블을 출력하자. 이를 위해서는 JTable에 추가된 출력 메소드를 호출해야한다. 이번 예제에서는 print()가 컨스트럭터로부터 호출된다. 독립변수가 없는 print() 메소드는 JTable을 머리글이나 바닥글 없이 출력하고, FIT_WIDTH 출력 모드(NORMAL의 반대)를 선택한다. 나타날 수 있는 PrinterException을 핸들링해야하는데, 샘플에서는 스택 트래이스(stack trace)를 이용하여 나타날 수 있는 예외상황을 핸들링한다.

   import javax.swing.JTable;
   import javax.swing.SwingUtilities;
   import javax.swing.JFrame;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
   import java.awt.Dimension;
   import java.awt.GridLayout;
   import java.awt.print.PrinterException;
   
   public class BasePrintableTable extends JTable {
   
         public BasePrintableTable() {
           super(data, columnNames);
           setUpJFrame();
           try {
             print();
           } catch (PrinterException e) {
             e.printStackTrace();
           }
         }
   
         public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
             public void run() {
               new BasePrintableTable();
             }
           });
         }
         // put common code here . . .
  } 

BasePrintableTable을 컴파일하고 구동하자. 테이블이 나타난다(이전의 예제보다는 나타나는 데 조금 더 오래 걸릴 것이다). 그 후 출력 다이얼로그가 나타난다.


프린터를 선택하고 Print 버튼을 누른다. 사용자가 선택한 프린터에 테이블이 보내질 것이다.

테이블의 질을 높이는 방법 중 하나는 출력물에 머리글과 바닥글을 추가하는 것이다. 이를 위해서는 MessageFormat오브젝트 같이 머릿글과 바닥글을 입력하는 매개변수를 받는 print() 버전의 사용이 필요하다. 이 오브젝트들은 페이지의 윗부분과 아랫 부분에 가운데 정렬 텍스트들을 생성하도록 만들어졌으며, 첫번째 포지션에 제공된 데이터를 참고하여 페이지 숫자를 삽입할 수도 있다. 다음은 JTable을 출력하는데 머리글과 바닥글을 추가하기 위해 필요한 컨스트럭터의 변경사항들이다.

   public BasePrintableTable() {
     super(data, columnNames);
     setUpJFrame();
     try {
           print(PrintMode.NORMAL, new MessageFormat(
             "Personal Info"),
           new MessageFormat("Page {0,number}"));
         } catch (PrinterException e) {
           e.printStackTrace();
         }
    } 

머리글은 굵은 글자로 가운데 정렬되며, "Personal Info" 텍스트로 구성될 것이다. 바닥글은 가운데 정렬된 "Page 1" 텍스트로 되어있으며, 여러 페이지의 문서에서는 {0, number}이 현재 페이지의 숫자 형식으로 바뀔 것이다.


좀 더 고난도의 출력물을 원한다면, print() 서명을 이용하여 프린트 다이얼로그의 표시 유무, 프린트가 되는 동안의 형식 다이얼로그 표시 유무 등을 지정할 수 있다. 또한 이 서명으로 PrintRequestAttributeSet를 전달하여 프린트하는데 사용하는 속성들을 지정할 수도 있다.

프린트 기능들과 JTable에서 한 줄 걸러 음영이 들어가는 ColorTable 버전을 어떻게 결합시킬 것인지 고려해보자. 간단한 방법으로는 다음과 같이 BasePrintableTableColorTablePrintableColorTable로 동시에 포함시키는 것이다.

   import javax.swing.JTable;
   import javax.swing.SwingUtilities;
   import javax.swing.JFrame;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
   import javax.swing.table.TableCellRenderer;
   import java.awt.Dimension;
   import java.awt.GridLayout;
   import java.awt.Component;
   import java.awt.Color;
   import java.awt.print.PrinterException;
   
   public class PrintableColorTable extends JTable {
   
         public PrintableColorTable() {
           super(data, columnNames);
           setUpJFrame();
           try {
             print();
           } catch (PrinterException e) {
             e.printStackTrace();
           }
         }
   
      public Component prepareRenderer(
                                TableCellRenderer renderer,
                                int row, int col) {
           Component c = super.prepareRenderer(renderer,
                                      row, col);
           if (row % 2 == 0 && !isCellSelected(row,col)) {
             c.setBackground(Color.LIGHT_GRAY);
           } else {
             c.setBackground(getBackground());
           }
           return c;
         }
   
         public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
             public void run() {
               new PrintableColorTable();
             }
           });
         }
         // common code here . . .
  } 

PrintableColorTable은 홀수행의 배경색을 옅은 회색으로 설정하여 JTable을 화면에 나타내고 출력한다. 그러나 출력 테이블의 형식이 표시된 테이블과 다르도록 하고싶다면 다른 방법이 필요하다. 예를 들어, 표시되는 테이블에서는 줄무늬(한 줄 걸러 음영)를 유지하고 싶지만, 출력되는 테이블에서는 보이지 않도록 하고싶다고 가정하자. Swing 엔지니어인 Shannon Hickey는 다른 형식을 사용하여 JTable을 화면에 나타내고 출력하는 데 다음의 방법을 제안한다. JavaDesktop 포럼 JTable.print() - different TableCellRenderer을 참고하기 바란다.

Shannon의 방법에서는 현재 출력 중인지 트래킹하는 boolean을 도입한다. 그 후 JTable.print(Graphics g) 메소드를 오버라이딩하여 boolean을 움직인다. 이는 다음과 같다.

   public void print(Graphics g) {
     printing = true;
     try {
       super.print(g);
     }  finally {
       printing = false;
     }
   }

다음으로, 셀의 배경색을 설정할 때 boolean을 테스트한다.

   if (row % 2 == 0 && !isCellSelected(row,col)) {
       c.setBackground(Color.LIGHT_GRAY);
   // cell is selected, use the highlight color
   } else if (isCellSelected(row, col)) {
       c.setBackground(getSelectionBackground());
   } else {
       c.setBackground(getBackground());
   } 

다음의 FancyPrintableColor 클래스에서는 이 단계들을 모두 포함한다. JTable의 음영 버전을 화면에 나타내지만, 출력물에는 음영이 포함되어 있지 않다.

   import javax.swing.JTable;
   import javax.swing.SwingUtilities;
   import javax.swing.JFrame;
   import javax.swing.JPanel;
   import javax.swing.JScrollPane;
   import javax.swing.table.TableCellRenderer;
   import java.awt.Dimension;
   import java.awt.GridLayout;
   import java.awt.Component;
   import java.awt.Color;
   import java.awt.Graphics;
   import java.awt.print.PrinterException;
   
   public class FancyPrintableColorTable extends JTable {
       private boolean printing = false;
   
         public FancyPrintableColorTable() {
           super(data, columnNames);
           setUpJFrame();
           try {
             print();
           } catch (PrinterException e) {
             e.printStackTrace();
           }
         }
      public void print(Graphics g) {
         printing = true;
         try {
           super.print(g);
         }  finally {
           printing = false;
         }
       }
   
      public Component prepareRenderer(
                                TableCellRenderer renderer,
                                int row, int col) {
           Component c = super.prepareRenderer(renderer,
                                      row, col);
           // if printing, only use plain background
           if (printing) {
              c.setBackground(getBackground());
           } else {
               if (row % 2 == 0 && !isCellSelected(row,col)) {
                   c.setBackground(Color.LIGHT_GRAY);
           // cell is selected, use the highlight color
           } else if (isCellSelected(row, col)) {
               c.setBackground(getSelectionBackground());
           } else {
               c.setBackground(getBackground());
           }
         }    
           return c;
        }
   
         public static void main(String[] args) {
           SwingUtilities.invokeLater(new Runnable() {
             public void run() {
               new FancyPrintableColorTable();
             }
           });
         }
       // common code here . . .
   } 

테이블을 출력하는 새로운 기능들에 대해 좀 더 알고싶다면, Swing API changes in JDK 5.0JTable needs printing support를 참고하기 바란다.

'[JAVA]' 카테고리의 다른 글

시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
static 키워드 바로 알기  (0) 2010.08.24
Overriding vs Overloading  (0) 2010.08.18
JAVA  (0) 2010.02.09

우선 오버로딩과 오버라이딩은 용어는 비슷하나 그 차이는 명백합니다.


-오버로딩은 기존에 메소드의 인자를 이용하여서 하나의 함수에 여라가지 기능을 만드는것 입니다.

기존에 int a(int a);라는 함수와

또다른 int a(int a, char b)가 존재한다고 가정합니다.

main()에서 호출시 a(10); 이라고 호출하게 되면 첫번째 int a(int a)라는 함수가 호출됩니다.  만약 a(10,'x'); 을 호출했다면 후자인 int a(int a, char b)가 호출되게 되는겁니다.

주로 생성자메소드를 정의할때 많이 사용합니다.

한마디로 같은 함수의 이름을 가지지만 인자 갯수나 타입로 구분해서 사용하는 것이죠.


-객체지향 개념에서 오버로딩(Overloading)만큼이나 중요하면서 상속 개념에서 빼놓을 수 없는 것이 바로 오버라이딩(Overriding)입니다. 오버라이딩이란 상위 클래스에 있는 메서드와 똑같은 메서드를 하위 클래스에서 다시 만드는 행위를 말합니다. 즉 하위 클래스에서 메서드를 재정의하는 것을 말합니다. 메서드 재정의(Overriding)를 개인적으로 '아버지 무시하기'로 부르고 있는데, 그 이유는 아들이 아버지의 메서드를 재정의했을 때 아버지의 메서드를 완전히 무시하는 경향이 있기 때문입니다. 메서드 재정의에 대해서 자세하게 알아보도록 하겠습니다.
-상속 개념에서의 오버라이딩(Overriding)
아버지 클래스를 상속받아 아들 클래스를 만들었을 때, 아버지가 가지고 있던 메서드를 아들 클래스가 다시 만들었다고 가정해 보십시오. 아버지 것은 내 것이고 내 것도 내 것이니, 완벽하게 똑같은 이름의 메서드가 두 개 존재합니다. 아들 클래스의 객체변수를 만들고, 이 객체를 이용해서 메서드를 호출한다면 아들 클래스는 순간 당황하게 될 것입니다. 아버지 것을 사용할까? 내 것을 사용할까? 하지만 아들 클래스의 객체는 유유히 아버지의 것을 무시하고 자신의 것을 사용합니다. 왜냐하면, 자신의 것이 더 소중하니까요! 아버지의 메서드는 완전히 무시당하는 것이죠. 이것을 우리는 오버라이딩(Overriding)이라고 부르고 있습니다.


여기서 virtual 키워드를 왜 사용하는지에 대한 해답이 나오는 겁니다.
virtual키워드를 사용함으로서 나는 부모 메소드를 사용하는것이 아니고 새로 정의한 메소드를 사용하겠다고 선언하는 것 입니다.

궂이 virtual 키워드를 붙이지 않아도 컴파일되는 과정에서 자동으로 분류(물론 순수 가상 함수(=0)일 경우는 제외한 경우입니다.) 해주기는하나 명확히 구분하기 위해서 virtual 키워드를 붙이는 것입니다.


*  오버로딩 : 새로만든다는 개념
1.메서드 이름이 같아야 함. 

2.리턴형이 같아도 되고 달라고 된다.  
3.파라미터의 개수가 달라야함.
4.파라미터의 개수 가 같을 경우 자료형이 달라야한다.
5.같은 클래스의 볼록안에 지원된다.

*  오버라이딩 : 기존에 있는 메소드를 재정의 한다는 개념
1. 오버라이드하고자 하는 메소드가 상위 클래스에 존재해야 한다.

2. 메소드의 이름이 같아야 한다. 
3. 메소드의 파라미터 개수, 데이터형이 같아야 한다.
4. 메소드의 리턴형이 같아야 한다.
5. 상위 메소드와 동일하거나 더 구체적인 Exception을 발생시켜야 한다.
6. 상위 메소드와 동일하거나 접근 범위가 넓은 접근 제한자를 사용해야 한다.

'[JAVA]' 카테고리의 다른 글

시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
static 키워드 바로 알기  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
JAVA  (0) 2010.02.09




첨부파일 설명:
--------------
j2se 도움말에는 Sun Microsystems에서 제공하는 jdk-1_5_0-doc.zip 파일이 존재합니다.
하지만, 압축해제하더라도 html 형식으로 된 파일이기에 api를 검색하는데 색인 기능이 없어서
불편합니다.
이에 대해, 첨부한 파일을 압축해제하면 chm 파일 형태로 검색을 지원합니다.

'[JAVA]' 카테고리의 다른 글

시간/날짜 관련 TIP 소스 모음  (0) 2010.08.25
문자열 배열 정렬(오름차순, 내림차순)  (0) 2010.08.24
static 키워드 바로 알기  (0) 2010.08.24
JTABLE 출력하기  (0) 2010.08.20
Overriding vs Overloading  (0) 2010.08.18

+ Recent posts