1.
find -iname '*.java' | xargs vim
이런 식으로 편집할 모든 파일을 vim 으로 엽니다.
(파일명/디렉토리명에 공백이 있다면 find -iname '*.java' -print0 | xargs -0 vim)
2.
qq (매크로 시작)
:%s/\v\/\/.*$|\/\*[^\n]*\*\///g | w | n (주석 없애고 다음 파일로 이동)
q (매크로 끝)
3.
파일 갯수만큼 매크로를 호출하기 위하여,
넉넉하게 1000@q 정도로 입력합니다.
ㅇ putty 설정값 백업
http://kldp.org/node/42609 에서 인용
regedit을 실행하신 다음에
내 컴퓨터\HKEY_CURRENT_USER\Softeare\Simon Tatham\PuTTY 에 있습니다.
호스트키까지 똥째로 저장하시려면 이 뿌띠 키(디렉토리처럼 생긴거)를 통째로 저장하거나 아니면 이아래에 있는 Session키를 저장하시면 됩니다. (한번 저장해놓고 여러 컴퓨터에서 활용하시려면 Session 만 저장하세요)
왼쪽트리에서 키를 선택하고 나서 메뉴에서 레지스트리->레지스트리 파일 내보내기->선택한 분기 에서 "PuTTYHosts.reg" 처럼 원하시는 이름으로 저장하세요.
이 파일을 더블클릭하시면 설정값들을 다시 입력하실수 있습니다. 자신이 쓰는 깨끗하게 호스트들을 깨끗하게 정리해서 만들어놓고 웹에 올려놓으면, 어디서든지 뿌띠하고 이 파일을만 받아서(뿌띠도 설치할 필요 없으니) 바로 사용할수 있어서 편합니다.
ㅇ putty private key 파일을 openssh 키파일로 변환할려면
http://kldp.org/node/74183 참고
public key는 Putty Key Generator의 상단에 보면 복사할수 있고요,
private key는 메뉴에서 Conversions->"Export OpenSSH key"로 pem 파일로 저장할수 있습니다.
public key는 authorized_keys 파일에 추가하고, id_rsa.pub나 id_dsa.pub 등으로 저장하면 되고,
private key는 id_rsa나 id_dsa로 저장하면 됩니다.
ㅇ openssh 에서 만든 private 키를 putty로 옮기기
키를 윈도우로 가지고와서 프로그램에서 Conversions -> Import key 를 이용하면 된다.
여기서 주의할점. 아래와 같이 KEY 내용이 끝나고 엔터키가 있어야한다.
-----BEGIN RSA PRIVATE KEY-----
MIICWgIBAAKBgQCvxDhf4cFa8vUSLi1EZDSYFyzChwZ41Tfdv92ma/sN8RTQ4rKJ
iK2xQSjvKUIA0RC/ieWy70PfPvSNtsJIXw2xyGJ1YtvvY4Gjy+KYj+kwkMzXR0yU
+/UJF75G5k1M5BMV4BgLyr+5BkmFv/Vub8To6OTLeLp4AGL6QOKKm3vNiQIBIwKB
..... 중략
-----END RSA PRIVATE KEY-----
-->> 여기 빈칸 하나!!!
* / 는 최상위 디렉터리를 뜻함. 만약 찾고자 하는 디렉터리가 있다면 그걸로 대체
- 파일 이름에 foobar 가 들어간 파일 찾기
find / -name "foobar" -print
- 특정 사용자(foobar) 소유의 파일을 찾기
find / -user foobar -print | more
- 최근 하루동안에 변경된 파일을 찾기
find / -ctime -1 -a -type f | xargs ls -l | more
- 오래된 파일(30일 이상 수정되지 않은 파일) 찾기
find / -mtime +30 -print | more
- 최근 30일안에 접근하지 않은 파일과 디렉터리를 별도의 파일로 만들기
find / ! ( -atime -30 -a ( -type d -o -type f ) ) | xargs ls -l > not_access.txt
- 하위 디렉터리로 내려가지 않고 현재 디렉터리에서만 검색하기
find . -prune ...
- 퍼미션이 777 인 파일 찾기
find / -perm 777 -print | xargs ls -l | more
- others 에게 쓰기(write) 권한이 있는 파일을 찾기
find / -perm -2 -print | xargs ls -l | more
- others 에게 쓰기(write) 권한이 있는 파일을 찾아 쓰기 권한을 없애기
find / -perm -2 -print | xargs chmod o-w
또는
find / -perm -2 -exec chmod o-w {} ; -print | xargs ls -l | more
- 사용자이름과 그룹이름이 없는 파일 찾기
find / ( -nouser -o -nogroup ) -print | more
- 빈 파일(크기가 0 인 파일) 찾기
find / -empty -print | more
또는
find / -size 0 -print | more
- 파일 크기가 100M 이상인 파일을 찾기
find / -size +102400k -print | xargs ls -hl
- 디렉터리만 찾기?
find . -type d ...
- root 권한으로 실행되는 파일 찾기
find / ( -user root -a -perm +4000 ) -print | xargs ls -l | more
- 다른 파일시스템은 검색하지 않기
find / -xdev ...
- 파일 이름에 공백이 들어간 파일 찾기
find / -name "* *" -print
- 숨겨진(hidden) 파일을 찾기
find / -name ".*" -print | more
- *.bak 파일을 찾아 지우기
find / -name "*.bak" -exec rm -rf {} ;
- *.bak 파일을 찾아 특정 디렉터리로 옮기기
mv `find . -name "*.bak"` /home/bak/
- 여러개의 파일에서 특정 문자열을 바꾸기
find / -name "*.txt" -exec perl -pi -e 's/찾을문자열/바꿀문자열/g' {} ;
from: http://www.raibledesigns.com/page/rd/20030312
I changed my shorcut icon (Win2K) to have the following as it's target:
eclipse.exe -vmargs -Xverify:none -XX:+UseParallelGC -XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M -Xmx256m -Xms256m
Eclipse now starts in a mere 6 seconds (2 GHz Dell, 512 MB RAM). Without these extra settings, it takes 11 seconds to start. That's what I call a performance increase! (2003-03-12 09:32:04.0)
from: http://www.raibledesigns.com/comment.do?method=edit&entryid=065039163189104748672473500018
I tried this out, but the memory settings don't seem to have anything to do with startup time.
18 seconds - "eclipse.exe"
13 seconds - "eclipse.exe -vmargs -Xverify:none"
12 seconds - "eclipse.exe -vmargs -Xverify:none -XX:+UseParallelGC -XX:PermSize=20M -XX:MaxNewSize=32M -XX:NewSize=32M -Xmx96m -Xms96m"
It's only the Xverify:none parameter which has a noticeable effect on reducing startup time. On the java website I found that this parameter turns off bytecode verification ( http://developer.java.sun.com/developer/onlineTraining/Security/Fundamentals/Security.html ), although the default is supposedly "only verify classes loaded over the network".
vi를 즐겨쓰는 사람들을 위한 이클립스를 위한 플러그인 - 나는 대만족^^ㅋ
등록하면 viplugin.license 가 생길텐데..아직 등록을 안해서..ㅡㅡ;
그래도 만족^^ㅋ
http://www.satokar.com/viplugin/
여기도 가볼 것. - http://mm.sookmyung.ac.kr/~sblim/lec/xml-int02/javascript/js02-02.htm |
|
blur |
포커스를 다른곳으로 옮길 경우 |
click | 링크나 폼의 구성원을 클릭할 때 |
change | 선택값을 바꿀 경우 |
focus | 포커스가 위치할 경우 |
mouseover | 마우스가 올라올 경우 |
mouseout | 마우스가 떠날 경우 |
mousedown | 마우스를 누를 경우 |
mousemove | 마우스를 움직일 경우 |
mouseup | 마우스를 눌렀다 놓을 경우 |
select | 입력양식의 하나가 선택될 때 |
submit | 폼을 전송하는 경우 |
load | 페이지,윈도우가 브라우져로 읽혀질 때 |
unload | 현재의 브라우저,윈도우를 떠날 때 |
error | 문서나 이미지에서 에러를 만났을 때 |
reset | 리셋 버튼이 눌렸을 때 |
dbclick | 더블클릭시 |
dragdrop | 마우스 누르고 움직일 경우 |
keydown | 키 입력시 |
keypress | 키 누를 때 |
keyup | 키를 누르고 놓았을 때 |
move | 윈도우나 프레임을 움직일 때 |
resize | 윈도우나 프레임 사이즈를 움직일 때 |
|
blur() |
입력 포커스를 다른 곳으로 이동시킴 |
click() | 마우스 버튼이 눌러진 것처럼 해줌 |
focus() | 입력 포커스를 준 것처럼 해줌 |
submit() | 폼의 submit 버튼을 누른 것처럼 해줌 |
select() | 메소드 폼의 특정 입력 필드를 선택함 |
|
event.keyCode | 누른 키의 ASCII 정수 값 |
event.x |
문서 기준 누른 좌표의 left |
event.y | 문서 기준 누른 좌표의 top |
event.clientX | 문서 기준 누른 좌표의 left |
event.clientY | 문서 기준 누른 좌표의 top |
event.screenX | 콘테이너 기준 누른 좌표의 left |
event.screenY | 콘테이너 기준 누른 좌표의 top |
|
선택 목록(SELECT) |
onBlur, onChange, onFocus |
문자 필드(TEXT) | onBlur, onChange, onFocus, onSelect |
문자 영역(TEXTAREA) | onBlur, onChange, onFocus, onSelect |
버튼(BUTTON) | onClick |
체크박스(CHECKBOX) | onClick |
라디오 버튼(RADID) | onClick |
링크 | onClick, onMouseover |
RESET 버튼(RESET) | onClick |
SUBMIT 버튼(BUTTON) | onClick |
DOCUMENT | onLoad, onUnload |
WINDOW | onLoad, onUnload |
폼(FORM) | onSubmit |
- onload = script [CT]
- The onload event occurs when the user agent finishes loading a window or all frames within a FRAMESET. This attribute may be used with BODY and FRAMESET elements.
- onunload = script [CT]
- The onunload event occurs when the user agent removes a document from a window or frame. This attribute may be used with BODY and FRAMESET elements.
- onclick = script [CT]
- The onclick event occurs when the pointing device button is clicked over an element. This attribute may be used with most elements.
- ondblclick = script [CT]
- The ondblclick event occurs when the pointing device button is double clicked over an element. This attribute may be used with most elements.
- onmousedown = script [CT]
- The onmousedown event occurs when the pointing device button is pressed over an element. This attribute may be used with most elements.
- onmouseup = script [CT]
- The onmouseup event occurs when the pointing device button is released over an element. This attribute may be used with most elements.
- onmouseover = script [CT]
- The onmouseover event occurs when the pointing device is moved onto an element. This attribute may be used with most elements.
- onmousemove = script [CT]
- The onmousemove event occurs when the pointing device is moved while it is over an element. This attribute may be used with most elements.
- onmouseout = script [CT]
- The onmouseout event occurs when the pointing device is moved away from an element. This attribute may be used with most elements.
- onfocus = script [CT]
- The onfocus event occurs when an element receives focus either by the pointing device or by tabbing navigation. This attribute may be used with the following elements: A, AREA, LABEL, INPUT, SELECT, TEXTAREA, and BUTTON.
- onblur = script [CT]
- The onblur event occurs when an element loses focus either by the pointing device or by tabbing navigation. It may be used with the same elements as onfocus.
- onkeypress = script [CT]
- The onkeypress event occurs when a key is pressed and released over an element. This attribute may be used with most elements.
- onkeydown = script [CT]
- The onkeydown event occurs when a key is pressed down over an element. This attribute may be used with most elements.
- onkeyup = script [CT]
- The onkeyup event occurs when a key is released over an element. This attribute may be used with most elements.
- onsubmit = script [CT]
- The onsubmit event occurs when a form is submitted. It only applies to the FORM element.
- onreset = script [CT]
- The onreset event occurs when a form is reset. It only applies to the FORM element.
- onselect = script [CT]
- The onselect event occurs when a user selects some text in a text field. This attribute may be used with the INPUT and TEXTAREA elements.
- onchange = script [CT]
- The onchange event occurs when a control loses the input focus and its value has been modified since gaining focus. This attribute applies to the following elements: INPUT, SELECT, and TEXTAREA.
자동 로그아웃 등에 사용되는 onUnload 이벤트는 창을 닫는 것만이 아니라 새로고침에서도 발생한다.
이것을 구분하는 스크립트
if( self.screenTop > 9000 ) {
// 브라우저 닫힘
} else {
if( document.readyState == "complete" ) {
// 새로고침
} else if( document.readyState == "loading" ) {
// 다른 사이트로 이동
}
}
}
<body onUnload="javascript:unload();">
</body>
window.onload 이벤트를 등록하면 이미지나 css 파일이 다 로드된 후에 이벤트가 발생한다.
가끔 웹 서버 문제로 이미지 하나가 로딩이 늦어 질 경우 이벤트 발생 시점이 의도한 바와 차이가 생기게 된다.
이를 해결하기 위한 방법이 아래의 URL 에서 확인 가능하다.
The window.onload Problem - Solved!
* http://dean.edwards.name/weblog/2005/09/busted
window.onload (again)
* http://dean.edwards.name/weblog/2006/06/again/
위의 방법에 따라 onload 이벤트를 등록하게 될 경우 내부적으로 이벤트를 Push 하는 방법을 적용하고,
onunload 이벤트에 하나가 아닌 다수의 이벤트를 등록할 때 이를 관리하기 위한 부분도 추가하여
기존에 사용하던 이벤트 관리 스크립트를 업데이트 했다.
아래는 이벤트 관리 스크립트 소스.
/**
* Class :: Event add, remove, registed event unload
* File :: Event.js
*
* @classDescription 브라우저에 따른 이벤트 등록, 해제, 등록된 이벤트 모두 해제
*/
var EventManager = function() {
constructor = this.__construct();
}
/**
* window 객체에 load 이벤트 등록시 펑션 리스트를 등록
*/
var _OnLoadList = [];
/**
* window 객체에 unload 이벤트 등록시 펑션 리스트를 등록
*/
var _UnLoadList = [];
/**
* prototype of EventHandler class
* __construct
*
* _EventList
*
* add
* remove
* unload
*/
EventManager.prototype = {
/**
* window의 unload 이벤트에 EventHandler.unload 메소드를 등록
*
* @see #unload
* @constructor
*/
__construct: function() {
var oThisObject = this;
/* for Mozilla */
if (window.addEventListener) {
window.addEventListener("DOMContentLoaded", oThisObject.baseRun, false);
/* for Safari */
} else if (/WebKit/i.test(navigator.userAgent)) { // sniff
var _timer = setInterval(function() {
if (/loaded|complete/.test(document.readyState)) {
oThisObject.baseRun();
}
}, 10);
/* for Internet Explorer */
} else {
var bInit = false;
/*@cc_on @*/
/*@if (@_win32)
document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
var oScriptLoad = document.getElementById("__ie_onload");
oScriptLoad.onreadystatechange = function() {
if (this.readyState == "complete") {
oThisObject.baseRun();
}
};
bInit = true;
/*@end @*/
/* for Other */
if (bInit == false) {
window.onload = oThisObject.baseRun;
}
}
this.add( window, 'unload_event', EventManager.prototype.unload );
},
/**
* 페이지 종료시 등록된 이벤트를 해제하기 위하여 추가된 Event 목록
*
* @type {Array} add 에서 데이터 추가
*/
_EventList: [],
/**
* event 를 addEventListener 와 attachEvent 를 사용하여 등록 <br />
* _EventList 에 등록된 이벤트를 배열로 저장
*
* @param {Object} setElement HTML Object
* @param {String} eventName event name - on 을 접두어로 붙이지 않음
* @param {Function} funcName Exist function name
*/
add: function( setElement, eventName, funcName ) {
if ((setElement == window) && (eventName == 'load')) {
_OnLoadList.push(funcName);
} else if ((setElement == window) && (eventName == 'unload')) {
_UnLoadList.push(funcName);
} else {
if ((setElement == window) && (eventName == 'unload_event')) {
eventName = 'unload';
}
if ( window.addEventListener ) {
setElement.addEventListener( eventName, funcName, false );
} else {
setElement.attachEvent( 'on' + eventName, funcName );
}
this._EventList.push({
object: setElement,
event: eventName,
func: funcName
})
}
},
/**
* event 를 removeEventListener 와 detachEvent 를 사용하여 해제
*
* @param {Object} setElement HTML Object
* @param {String} eventName event name - on 을 접두어로 붙이지 않음
* @param {String} funcName Exist function name
*/
remove: function( setElement, eventName, funcName ) {
if ( window.removeEventListener ) {
setElement.removeEventListener( eventName, funcName, false );
} else {
setElement.detachEvent( 'on' + eventName, funcName );
}
},
/**
* window.unload 이벤트시 _EventList 에 등록된 모든 이벤트를 해제
*/
unload: function() {
var sFunction = '';
for ( var oEventData in _UnLoadList ) {
sFunction = _UnLoadList[oEventData];
if (sFunction == '______array') {
continue;
}
sFunction.call();
}
_UnLoadList = []
for ( var oEventData in this._EventList ) {
this.remove( oEventData.object, oEventData.event, oEventData.func );
}
},
/**
* window.onload 에 등록한 function 을 모두 실행시킨다.
*/
baseRun: function() {
var sFunction = '';
for ( var oEventData in _OnLoadList ) {
sFunction = _OnLoadList[oEventData];
if (sFunction == '______array') {
continue;
}
sFunction.call();
}
}
}
var oEvent = new EventManager();
var Event = function() {
return oEvent;
}
Dependency Walker is a free utility that scans any 32-bit or 64-bit Windows module (exe, dll, ocx, sys, etc.) and builds a hierarchical tree diagram of all dependent modules. For each module found, it lists all the functions that are exported by that module, and which of those functions are actually being called by other modules. Another view displays the minimum set of required files, along with detailed information about each file including a full path to the file, base address, version numbers, machine type, debug information, and more.
![사용자 삽입 이미지](https://t1.daumcdn.net/tistoryfile/fs7/26_18_26_18_blog98621_attach_0_17.png?original)
vim 으로 파일 한꺼번에 고치기
vi 에는 파일을 오픈한 뒤 특정한 명령을 실행 할 수있는 -c 옵션이 있다.
예를 들어 vi -c 15 foo.c 이렇게 하면 foo.c 를 오픈한 뒤 ':15' 명령을 실행해 15번째 줄로 이동을 한다.
vim 에서는 이 기능을 확장하여 -c 옵션을 여러개 사용할 수 있다.
예를 들어 vim -c '11' -c 'd' foo.c 하면 foo.c 를 열고, 11번째 줄로 이동(-c '11')을 한 다음 현재 라인 지움(-c 'd') 동작을 한다.
여기에 -c 'wq' 를 추가하면 수정후 저장/종료까지 한꺼번에 되므로 command line 명령 처럼 사용할 수 있게 되고, shell script 를 이용해 여러 파일에 적용하면 된다.
예를 들어 현재 디렉토리의 모든 c 소스 에서 'foo' 라는 문자열을 'bar' 로 바꾸고 싶다면
#!/bin/csh -f
foreach fn (*.c)
vim -c '%s/foo/bar/g' -c 'wq' $fn
end
처럼 script를 만들면 된다.
물론 단순 패턴 치환이라면
#!/bin/csh -f
foreach fn (*.c)
sed $fn 's/foo/bar/g' > tmpfile
mv tmpfile $fn
end
와같이 해도 되지만 vim이 할 수 있는 일은 단순 패턴 치환 이상이기 때문에 훨씬 더 다양한 용도로 사용할 수 있다.
아래는 현재 디렉토리와 바로 아래 서브디렉토리의 모든 *.txt 파일을 dos 형식(cr-lf 가 붙는)으로 바꾸는 script 이다.
#!/bin/csh -f
foreach fn ( *.txt */*.txt )
vim -c 'set fileformat=dos' -c 'wq' $fn
end
현재 디렉토리의 모든 *.c *.h 파일로 부터 syntax highlighting 된 html 파일을 만들어 보자.
#!/bin/csh -f
foreach fn ( *.[ch] )
vim -c 'call Convert2HTML(0,0)' -c wq -c q $fn
end
.vimrc 에
set termencoding=euc-kr
set fileencodings=euc-kr,utf-8
.cshrc 에
alias kvi '/usr/bin/vim --cmd "set fileencoding=euc-kr" --cmd "set encoding=euc-kr" \!*'
alias uvi '/usr/bin/vim --cmd "set fileencoding=utf-8" --cmd "set encoding=utf-8" \!*'
이렇게 해두고.. utf-8 파일을 편집 할 때는 uvi를, euc-kr 파일을 편집할 때는 kvi 를 사용하면 된다.
UTF-8 로 저장된 파일을 편집시 : e ++enc=utf-8
euc-kr로 파일을 저장할 때 : w ++enc=euc-kr
<IfModule mod_setenvif.c>
SetEnvIfNoCase Request_URI "\$.(gif)|(jpg)|(css)|(png)" do_not_log
</IfModule>
CustomLog "logs/access_log" common env=!do_not_log
이제는 VIM 을 기본 문서 편집기로 연결해놓고 있다.
C/C++ 의 소스편집과 분석은 물론이고, 일반 문서 편집에도 최고이다.
거기다가 OS 를 가리지 않는 범용성.
사용하는 동안 써본 최고의 플러그인들을 모아봤다.
사실 이미 오래전부터 올리려고 했던 파일 모음인데,
이제야 올리게 되었다. 거의 1년 가까운 시간이 지난 지금.
그래서 현재 최신버전은 VIM6.4 이지만 설명이 6.3을 기준으로 되어있다.
모든 플러그인들은 물론 6.4에서도 잘 동작한다.
하지만 오래전 작성된 관계로 플러그인들이 최신으로 갱신되었을 가능성이 있다.
플러그인 모음 파일의 구성은 다음과 같다.
1. 설치
- 설명 파일 및 다큐멘트
Readme1st.txt
그외 rtf 파일은 짬짬이 기록해놓은 VIM 툴 팁이다.
(rtf 파일은 기본적으로는 워드에 연결되어 있지만, 워드패드에서 열수 있고,
훈민메모패드에서도 불러들일 수 있다. 훈민메모패드 최고 ! )
- vimrc 초기화 파일 :
gvimrc_silver.com
$VIM (vim을 설치한 루트 디렉토리)/_vimrc 에서 "gvimrc-silver.vim" 을 부르도록 수정 필요.
- tools for vim
다음의 툴들을 %PATH%
ec55w32 : Exuberant Ctags 5.5
태그 파일을 만들어 주는 프로그램. "taglist.vim" 플러그인에서 사용한다.
gvimrc_silver.com 의 키맵 <F7> , <F8>, <F9> 를 사용해서 작업한다.
cscope : 태그에서 한발 나아간 관계형 DB작성 프로그램,
소스인사이트 처럼 심볼 찾기, 함수 Caller/Callee 를 찾을 수 있다.
자세한 사용법은 나중에 다시 설명 예정.
참조 Vim Cscope Tutorial (http://wiki.kldp.org/wiki.php/VimCscopeTutorial)
- Plugin FIles
$VIMRUNTIME (vim 실행 파일이 위치한 디렉토리) [ = $VIM (vim을 설치한 루트 디렉토리)/vim버전]
필요한 경우 해당 폴더의 백업을 해도 좋다.
해당 위치에 파일을 풀어주면 된다.
즉 Tools\Vim Essential Addon 을 $VIMRUNTIME 에다가 덮어주면 된다.
- Plugin help file add
설치한 플러그인 파일의 도움말에 대한 태그를 생성한다.
:helptags $VIMRUNTIME/doc
( 설치후 ":help winmanager" 혹은 ":help tag" 입력후 CTRL-D를 입력해본다.)
2. 사용법
먼저 VIM 에서 멀티 윈도우기능을 사용하기 위해서는
":help windows" 를 실행하여 "window.txt" 의 키 이해필요.
멀티 윈도우에서의 기본기능은 하나의 윈도우에서 의 전후좌우 (h, j, k, l)에
CTRL_W 를 앞에 먼저 입력하면 윈도우 간의 이동이 가능하다.
예 ::: CTRL-W ( <C-W> ) + h : 좌 윈도우
그외 자세하고 세부적인 사항은 역시 써봐야 한다.
VIM은 쓰면 쓸 수록 그 놀라운 기능과 다양한 지원에 놀라게 된다.
- <F6>
토글 키 ,
윈도우매니저 기능 On/Off
파일을 연상태에서 <F6> 을 누르면 왼쪽 상단 에 [File List] 하단에 [Buf List] 가 생성됨.
[File List] 를 이용해서 특정 폴더로 이동 , 파일을 열수 있음.
*** 이때 현재 디렉토리 위치는 변경되지 않음. (":pwd" 로 확인)
디렉토리 위치의 이동을 위해서는 명령창에서 cd 실행.
[Buf List] VIM 버퍼에 있는 파일의 리스트를 보여줌, 선택하여 열기 가능.
- <F7>,<F8>,<F9>
토글 키
<F8> : 태그리스트 On/Off
<F7> : 태그 갱신 (즉 파일내용이 바뀌었을 때 사용)
<F9> : 태그 리스트의 싱크 (코드와 태그의 상태를 맞춰줌)
[Tag List] 가 좌측에 새김 ( 매크로, 변수, 함수 등이 표시됨.)
[출처] http://blog.naver.com/agfe2/90002349695
java를 처음 공부하면서 초반에 컴파일 및 실행을 시키기해서 cmd창을 자주 쓰게 된다
탐색기에 익숙한 우리들에게 cmd창에서 폴더 이동은 어지간 짜증나는 일이 아닐수 없다.
간단한 레지스트리 추가로 원하는 폴더에서 바로 cmd창을 열어보자...
============================================================
실행 ==> regedit
레스지트 창을 연다
HKEY_CLASSESS_ROOT
|
+-- directory
|
+-- shell
로 이동한다
새로만들기 => key를 실행하다
임의의 폴더이름을 만들고, 폴더안에 기본값에 데이터를 "도스창 바로가기" 등의 메뉴 이름을 정한다
만든 폴더안에 다시 한번
새로만들기 => key를 실행한다
폴더이름은 command로 하고 기본키의 데이터값을
C:\WINDOWS\system32\cmd.exe /k cd "%1"
이제부터 탐색기에서 원하는 폴더에 우측 버튼을 열리면 "도스창 바로가기" 가 생겨 바로 선택한 폴더에서 cmd창이 열리는 것을 볼수 있다
개발자가 놓치기 쉬운 자바의 기본원리
- 전성호(커뮤니티본부 커뮤니티개발1팀), 2006년 10월
목차
-
- 1 객체지향의 구멍 static
- 2 Java는 Pointer언어이다? (Java에는 Pointer밖에 없다?)
- 3 상속과 interface의 문제점
- 4 package와 access 제어에 관한 이해
- 5 기타 Java 기능
- 6 이래도 Java가 간단한가?
- 7 Java 기능 적용 몇가지
- 8 Java 5.0 Tiger 에 대하여
-
- 8.1 Working with java.util.Arrays
- 8.2 Using java.util.Queue interface
- 8.3 java.lang.StringBuilder 사용하기
- 8.4 Using Type-Safe Lists
- 8.5 Writing Generic Types
- 8.6 새로운 static final enum
- 8.7 Using java.util.EnumMap
- 8.8 Using java.util.EnumSet
- 8.9 Convert Primitives to Wrapper Types
- 8.10 Method Overload resolution in AutoBoxing
- 8.11 가변적인 argument 개수 ...
- 8.12 The Three Standard Annotation
- 8.13 Creating Custom Annotation Types
- 8.2 Using java.util.Queue interface
- 8.1 Working with java.util.Arrays
- 9 The for/in Statement
-
- 9.1 for/in 의 자주 사용되는 형태
- 10 Static Import
-
- 10.1 static member/method import
- 11 References
1.1 Java는 객체지향 언어이다? #
- 오해1. "객체지향에서는 객체끼리 서로 메세지를 주고 받으며 동작한다." 라는 말을 듣고 다음과 같이 생각할 수 있다. "객체지향에서는 객체가 각각 독립하여 움직인다는 것인가, 그러면 각 객체에 독립된 thread가 할당되어 있단 말인가?" 그렇지 않다. "메세지를 보낸다"라는 것은 단순히 각 객체의 함수 호출에 불과하다.
- 오해2. "객체지향에서는 method가 class에 부속되어 있다"는 말을 듣고 다음과 같이 생각할 수 있다. "그러면 instance별로 method의 실행코드가 복제되고 있는 것이 아닌가?" 물론 이것도 오해다. method의 실행코드는 종래의 함수와 동일한 어딘가 다른곳(JVM의 class area)에 존재하며 그 첫번째 파라미터로 객체의 포인터 this가 건네질 뿐이다.
- 오해3. "그렇다면 각 instance가 method의 실행코드를 통째로 갖고 있지 않는 것은 확실하지만, method의 실행 코드의 포인터는 각 instance별로 보관하고 있는것이 아닌가?" 이것은 약가 애매한 오해이긴 하다. JVM 스펙에서는 class영역에 실행코드를 갖고 있으며, method 호출시 별도의 stack frame이 생성되어 실행되고 실행 완료시 복귀 주소를 전달한다.
1.2 전역변수 #
- (참고) final 초기화에서의 주의점. 예를 들어 다음과 같은 코드를 보았을때 우려되는 점은 무엇인가?
public final static Color WHITE = new Color(255, 255, 255);
- static field는 final의 경우와 달리 정말 "하나여도 되는지" 여부를 잘 생각해야 한다.
- static method는 주저하지 말고 쓰되 다음 두가지의 경우 매우 활용적이다.
- 다른 많은 클래스에서 사용하는 Utility Method 군을 만드는 경우. (주로 Utility Class의 method)
- 클래스 안에서만 사용하는 "하청 메소드(private method)". 이유를 예를 들어 설명하면, 아래와 같은 조금은 과장된 클래스가 있다고 하자.
public class T .. private int a; private int b; private int c; private int calc(){ c = a + b; return c * c; } ....other method or getter/setter...
private static int calc(int a, int b){ int c = a + b; return c * c; }
2.1 Java는 primitive형을 제외하곤 모두 Pointer이다 #
2.2 null은 객체인가? #
- null object의 instance method 호출
- null object의 field(member variables)에 대한 액세스 또는 그 값의 변경
- null의 길이를 배열처럼 취득할 경우
- null의 slot을 배열처럼 액세스 또는 수정
- null을 Throwable처럼 throw 할 경우
2.3 String에 대하여 #
String str = "111222"; String a = "111"; String b = "222"; String c = "111"; String d = b; String t = str.substring(0,3); //111
- str == (a + b) ==> 이것은 두개의 참조와 하나의 참조를 비교했으므로 당연히 false이다.
- a == b ==> 이것은 당연히 false
- d == b ==> 이것은 동일한 reference이므로 true
- a == t ==> a 와 t 는 둘다 값이 "111"이다. 하지만 이것은 서로 다른 참조를 가져 false이다. 그렇다면 다음 5번도 false일까?
- a == c ==> 이것은 true이다. 아.. 4번과 혼란스럽다. 이것이 참인 이유는? ==> 이것의 해답은 JSR 3.10.5에 다음과 같이 나와 있기 때문이다.
2.4 객체지향의 캡슐화 파괴 주의 #
//(참고)Member에는 두개의 field(Identity Class 형의 ID와 Family Class 형의 family)가 있다. /** shallow copy */ Member shallowCopy(){ Member newer = new Member(); newer.id = this.id; newer.family = this.family; return newer; } /** deep copy */ Member deepCopy(){ Member newer = new Member(); newer.id = new Idetity(this.id.getId(), this.id.getName()); newer.family = new Family(this.family.getFamilyName(), this.family.getFamilyInfo()); return newer; }
- 모든 field(member variable)를 생성자(constructor)를 이용하여 초기화 한다.
- 모든 field는 private으로 선언하고, getter method는 만들되 setter는 기술하지 않는다.
2.5.1 배열은 object 인가? #
2.5.2 배열의 length는 왜 field(member variable)인가? #
2.5.3 final과 배열에 대하여... #
2.5.4 "Java에서의 다차원 배열은 존재하지 않는다." #
2.6.1 "Java에서 parameter(argument) 전달은 무조건 'call by value' 이다" #
2.6.2 "C와 같은 언어는 static linking이지만, Java는 dynamic linking이다." #
2.7.1 "Garbage Collection은 만능이 아니다." #
2.8.1 "결국 Java에는 pointer가 있는 것인가, 없는 것인가?" #
// 이부분에 대해 Object를 이해하시면 족히 이런 문제는 사라질것으로 봅니다.
// 클래스에 대한 인스턴스(object)들은 reference로 밖에 가질(참조될)수 없기 때문입니다.
// 컴파일러 입장이 아닌 언어 자체의 사상을 가지고 쉽게 이해시키는 것이 좋을것 같습니다.
3.1.1 상속에 있어서의 생성자(constructor) #
3.1.2 "down cast는 본질적으로 매우 위험하다" #
3.1.3 "추상클래스에 final이 있으면 compile error이다" #
3.2.1 "interface는 interface일뿐 다중 상속의 대용품이 아니다." #
3.3 상속 제대로 사용하기 #
- 상속에서는 슈퍼클래스가 허용하고 있는 조작을 서브클래스에서 모두 허용해야 하지만, composition과 delegation에서는 조작을 제한할 수 있다.
- 클래스는 결코 변경할 수 없지만, composition하고 있는 객체는 자유롭게 변경할 수 있다. 예를 들면 학생 클래스가 영원이 학생이 아니라 나중에 취직을 하여 직장인 클래스가 될수 있다.
- Shape(부모)의 공통된 내용을 구현한 구현 클래스(ShapeImpl)를 만든다.
- Polyline과 Circle 클래스에서 ShapeImpl을 composition하고 부모와 공통되지 않는 method를 각각 위임 받는다.
- ShapeImpl 클래스의 method를 추출한 ShapeIF interface를 작성하고 Polyline과 Circle에서는 implements 한다.
4.1.1 "package는 '계층구조' 인가?" #
4.1.2 "compiler 가 인식하는 class검색 순서(소스코드내 클래스가 발견될 경우 그 클래스의 위치를 찾는 순서)" #
- 그 class자신
- 단일형식으로 임포트된 class
- 동일한 패키지에 존재하는 다른 class
- 온디멘드 형식(..* 형태) 임포트 선언된 class
4.2.1 "interfacde member의 access 제어" #
4.2.2 그렇다면 interface를 다른 package에 대하여 숨기고 싶으면 어떻게 하는가? #
5.1.1 "Multi Thread에서는 흐름은 복수이지만 data는 공유될 수 있다." #
5.1.2 "Thread는 객체와 직교하는 개념이다." #
- Multi Thread에서는 Thread라는 처리 흐름이 2개 이상 존재할 수 있다.
- 어떤 Thread에서 움직이기 시작한 method가 다른 method를 호출 했을때 호출된 측의 method는 호출한 측의 method와 동일한 Thread에서 동작한다.
- Thread의 경계와 객체의 경계는 전혀 관계가 없다. 즉, Thread와 객체는 직교하고 있다.
5.1.3 "Synchronized 의 이해" #
synchronized void method1(){ ... } void method2(){ synchronized(this){ ... } }
5.1.4 "Thread 사용법의 정석은?" #
- Runnable을 implements하고 Thread의 참조를 보유(composition) 하는 방법. 이경우는 단지 Runnable만 implement함으로서 해결되는 경우가 대부분이긴 하지만, 그 class 내에서 해당 class의 Thread를 조작하게 된다면 composition한 Thread 객체에 delegation하면 된기 때문이다.
- Thread class를 상속하는 방법. JDK의 소스를 보면 Thread class에는 Runnable을 implements 하고 있다. 그리고 run method는 native method이다. 따라서 Thread를 상속한 모든 클래스는 사실 Runnable을 implements하고 있는 것이다. run method는 abstract가 아니므로 구현되어 있고 우리는 이를 오버라이드하여 사용하고 있다. 이 방식을 사용하면 Thread의 method를 안팍으로 자유롭게 호출할 수 이지만, 이미 다른 class를 상속하고 있다면 이 방식을 사용할 수는 없다.
5.2.1 "finally 절은 반드시 어떠한 경우에도 실행되는가?" #
try{ ... System.exit(1); }catch(...){ }finally{ ... //이 부분은 실행되지 않는다. }
5.2.2.1 Error #
5.2.2.2 RuntimeException #
5.2.2.3 그밖의 Exception #
5.2.3 "OutOfMemoryError는 어떻게 처리해야 하는가?" #
5.3 Object Serialize #
5.3.1 "Serialize를 위해서는 marker interface인 java.io.Serializable interface를 implements해야한다." #
5.3.2 "super class는 Serializable이 아닌데 sub class만 Serializable인 경우의 문제점" #
5.3.3 "transient field의 복원(?)관련" #
private void writeObject(java.io.ObjectOutputStream out) throws IOException; private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
5.3.4 "Stack Overflow에 주의하라!" #
private synchronized void writeObject(java.io.ObjectOutputStream s) throws IOException { s.defaultWrtieObject(); //이 코드는 무조건 들어가게 되는데 이곳 소스의 System.arraycopy()에서 overflow발생한다. s.writeInt(size); //이부분이 실제 추가되어 Stack Overflow를 예방한다. for(Entry e = ...) s.writeObject(e.element); } ... } //readObject()도 이와 같은 개념으로 변경되어 있다.
5.4.1 "중첩클래스의 개념" #
5.4.2 "내부클래스는 부모의 참조를 몰래 보유하고 있다." #
class Test{ class InnerClass { int i; ... } public static void main(String[] args){ InnerClass icls = new InnerClass(); ... } }
5.4.3 "local inner class에 대하여" #
public class OuterClass { public int get(){ int i = 9; int id = 99; int id2 = 99; final int id3 = 100000; class LocalInnerClass { int id = 100; LocalInnerClass(){ System.out.println("LocalInnerClass"); } int getId(){ return id3 + id; } } LocalInnerClass lic = new LocalInnerClass(); return id + lic.getId(); } public static void main(String[] args){ OuterClass outer = new OuterClass(); System.out.println("id = " + outer.get()); //결과 값은 "100000(id3) + 100(LocalInnerClass.id) + 99(OuterClass.get())" 인 100199가 나온다. } }
5.4.4 "anonymous class(무명클래스)에 대하여" #
class AnonymousTest { private interface Printable { void print(); } static void doPrint(Printable p){ p.print(); } public static void main(String[] args){ doPrint( new Printable(){ public void print(){ System.out.println("this is new Printable print()"); } }); } }
6.1.1 "overload란 이름이 가고 인수가 다른 method에 compiler가 다른 이름을 붙이는 기능" #
//IFS.java interface IFS { public String getName(); } //Impl1.java class Impl1 implements IFS { public String getName(){ return "Impl1"; } } //Impl2.java class Impl2 implements IFS { public String getName(){ return "Impl2"; } } //main이 있는 OverloadTest.java public class OverloadTest { static void pr(int i){ System.out.println("pr_int : " + i); } static void pr(String s){ System.out.println("pr_string : " + s); } static void pr(IFS ifs){ System.out.println("pr_string : " + ifs.getName()); } static void pr_run(Impl1 i1){ System.out.println("pr_run : " + i1.getName()); } static void pr_run(Impl2 i2){ System.out.println("pr_run : " + i2.getName()); } public static void main(String[] args){ OverloadTest test = new OverloadTest(); test.pr(10); test.pr("Jeid"); IFS ifs1 = new Impl1(); test.pr(ifs1); IFS ifs2 = new Impl2(); test.pr(ifs2); //pr_run(ifs1); //pr_run(ifs2); } }
OverloadTest.java:36: cannot resolve symbol symbol : method pr_run (IFS) location: class OverloadTest pr_run(ifs1); ^ OverloadTest.java:37: cannot resolve symbol symbol : method pr_run (IFS) location: class OverloadTest pr_run(ifs2); ^ 2 errors
6.1.2 "그렇다면 overload에서 실제로 혼동되는 부분은 무엇인가?" #
class OverloadTest2 { static int base(double a, double b){ ... } //method A static int count(int a, int b){ ... } //method B static int count(double a, double b){ ... } //method C static int sum(int a, double b){ ... } //method D static int sum(double a, int b){ ... } //method E }
- base(3,4) 를 호출했을때 수행되는 method는? => 당연히 method A (3과 4는 정수라도 double이 되므로 정상적으로 수행됨)
- count(3,4) 를 호출했을때 수행되는 method는? => B와 C중 갈등이 생긴다. 이럴경우 JVM은 가장 한정적(more specific)한 method를 찾는다. 여기서 3과 4는 정수형에 가까우므로 method B 가 호출된다.
- count(3, 4.0) 을 호출했을때 수행되는 method는? => 이것은 4.0 이 double이므로 method C 가 더 한정적이므로 method C 가 호출된다.
- sum(3,4.0) 을 호출했을때 수행되는 method는? => 이것은 당연히 type이 일치하는 method D.
- sum(3,4) 를 호출했을때 수행되는 method는?? => 이런 코드가 소스내에 있으면 다음과 같은 compile 오류를 표출한다.
OverloadTest.java:48: reference to sum is ambiguous, both method sum(int,double) in OverloadTest and method sum(double,int) in OverloadTest match System.out.println("sum(3,4) = " + sum(3,4)); ^ 1 error
6.1.3 (참고) 또다른 혼동, overload한 method를 override 하면? #
6.2.1 "Java class의 member 4 종류" #
- instance field
- instance method
- static field
- static method
6.2.2 "override시 method 이름에 대한 함정" #
6.2.3 "또다른 나의(?) 실수 - 말도 안되는 오타" #
public class Member { private int memberNo; public int getMemberNo(){ return this.memberNo; } public void setMemberNo(int menberNo){ this.memberNo = memberNo; } ...... }
6.2.4 "static member를 instance를 경유하여 참조해서는 안 된다." #
ClassA a = new ClassA(); int i = a.AA; //instance를 경유하여 접근 int j = ClassA.AA; //올바르게 접근
6.2.5 "super keyword는 부모의 this" #
6.4.1 "생성자에 void 를 붙인다면?" #
public class ConstructorTest{ void ConstructorTest(){ System.out.println("Constuctor"); } ..... }
6.4.2 "if / switch 의 함정" #
.... if( a < 5 ) b = 3; c = 10; //이부분은 나중에 추가된 라인이다. if( isStudent ) if( isFemale ) sayHello("Hi~~"); else sayHello("Hello Professor~");
7.1.1 "interface 분리의 필요성" #
7.2 Java에서의 열거형 #
public static final int LEFT = 0; public static final int CENTER = 1; public static final int RIGHT = 2; ... label.setAlignment(Label.CENTER); ...
//LabelAlignment.java public class LabelAlignment { private LabelAlignment() {} //이는 생성자를 private으로 하여 다른데서는 만들지 못하도록 하기위함이다. public static final LabelAlignment LEFT = new LabelAlignment(): public static final LabelAlignment CENTER = new LabelAlignment(): public static final LabelAlignment RIGHT = new LabelAlignment(): } //변형된 Label.java 의 일부.. public synchronized void setAlignment(LabelAlignment alignment){ if( alignment == LabelAlignment.LEFT ){ ...//왼쪽으로 맞추기.. }else if( ... ... } } ...
//LabelAlignment.java public class LabelAlignment { private int flag; private LabelAlignment(int flag){ this.flag = flag; } public static final LabelAlignment LEFT = new LabelAlignment(0): public static final LabelAlignment CENTER = new LabelAlignment(1): public static final LabelAlignment RIGHT = new LabelAlignment(2): public boolean equals(Object obj){ return ((LabelAlignment)obj).flag == this.flag; } } //변형된 Label.java 의 일부.. public synchronized void setAlignment(LabelAlignment alignment){ if( LabelAlignment.LEFT.equals(alignment) ){ ...//왼쪽으로 맞추기.. }else if( ... ... } } ...
7.3 Debug write #
#ifdef DEBUG fprintf(stderr, "error...%d\n", error); #endif /* DEBUG */
if( Debug.isDebug ){ System.out.println("error..." + error); }
// 1. GetCallerSecurityManager.java public final class GetCallerSecurityManager extends SecurityManager { public Class[] getStackTrace(){ return this.getClassContext(); } } // 2. GetCallerClass.java public final class GetCallerClass { private static GetCallerSecurityManager mgr; static{ mgr = new GetCallerSecurityManager(); System.setSecurityManager(mgr); } public static void writeCaller(String str){ Class[] stk = mgr.getStackTrace(); int size = stk.length; for(int i = 0; i < size; i++){ System.out.println("stk[" + i + "] = " + stk[i]); } String className = stk[2].getName(); System.out.println("className is " + className + " : " + str); } } // 3. GetCallerClassMain1 : 호출하는 클래스 예제 1 public class GetCallerClassMain1 { public static void main(String[] args){ GetCallerClass.writeCaller(", real is 1."); } } // 4. GetCallerClassMain1 : 호출하는 클래스 예제 2 public class GetCallerClassMain2 { public static void main(String[] args){ GetCallerClass.writeCaller(", real is 2."); } }
className is GetCallerClassMain1 : , real is 1. className is GetCallerClassMain2 : , real is 2.
8.1 Working with java.util.Arrays #
package com.jeid.tiger; import java.util.Arrays; import java.util.Comparator; import java.util.List; public class ArraysTester { private int[] arr; private String[] strs; public ArraysTester(int size) { arr = new int[size]; strs = new String[size]; for (int i = 0; i < size; i++) { if (i < 10) { arr[i] = 100 + i; } else if (i < 20) { arr[i] = 1000 - i; } else { arr[i] = i; } strs[i] = "str" + arr[i]; } } public int[] getArr() { return this.arr; } public String[] getStrs() { return this.strs; } public static void main(String[] args) { int size = 50; ArraysTester tester = new ArraysTester(size); int[] testerArr = tester.getArr(); int[] cloneArr = tester.getArr().clone(); String[] testerStrs = tester.getStrs(); String[] cloneStrs = tester.getStrs().clone(); // clone test if (Arrays.equals(cloneArr, testerArr)) { System.out.println("clonse int array is same."); } else { System.out.println("clonse int array is NOT same."); } if (Arrays.equals(cloneStrs, testerStrs)) { System.out.println("clonse String array is same."); } else { System.out.println("clonse String array is NOT same."); } // 2부터 10까지 값 셋팅 Arrays.fill(cloneArr, 2, 10, new Double(Math.PI).intValue()); testerArr[10] = 98; testerStrs[10] = "corea"; testerStrs[11] = null; List<String> listTest = Arrays.asList(testerStrs); System.out.println("listTest[10] = " + listTest.get(10)); System.out.println("------- unsorted arr -------"); System.out.println("Arrays.toString(int[]) = " + Arrays.toString(testerArr)); System.out.println("Arrays.toString(String[]) = " + Arrays.toString(testerStrs)); Arrays.sort(testerArr); // Arrays.sort(testerStrs); //NullPointerException in sort method..(null이 없더라도 길이에 대한 크기 체크는 못함) Arrays.sort(testerStrs, new Comparator<String>() { public int compare(String s1, String s2) { if (s1 == null && s2 == null) { return 0; } else if (s1 == null && s2 != null) { return -1; } else if (s1 != null && s2 == null) { return 1; } else if (s1.length() < s2.length()) { return -1; } else if (s1.length() > s2.length()) { return 1; } else if (s1.length() == s2.length()) { return 0; } else { return s1.compareTo(s2); } } }); System.out.println("------- sorted arr -------"); System.out.println("Arrays.toString(int[]) = " + Arrays.toString(testerArr)); System.out.println("Arrays.toString(String[]) = " + Arrays.toString(testerStrs)); System.out.println("------------------------------------------------"); String[][] mstrs1 = { { "A", "B" }, { "C", "D" } }; String[][] mstrs2 = { { "a", "b" }, { "c", "d" } }; String[][] mstrs3 = { { "A", "B" }, { "C", "D" } }; System.out.println("Arrays.deepToString(mstrs1) = " + Arrays.deepToString(mstrs1)); System.out.println("Arrays.deepToString(mstrs2) = " + Arrays.deepToString(mstrs2)); System.out.println("Arrays.deepToString(mstrs3) = " + Arrays.deepToString(mstrs3)); if( Arrays.deepEquals(mstrs1, mstrs2)) { System.out.println("mstrs1 is same the mstrs2."); }else { System.out.println("mstrs1 is NOT same the mstrs2."); } if( Arrays.deepEquals(mstrs1, mstrs3)) { System.out.println("mstrs1 is same the mstrs3."); }else { System.out.println("mstrs1 is NOT same the mstrs3."); } System.out.println("mstrs1's hashCode = " + Arrays.deepHashCode(mstrs1)); System.out.println("mstrs2's hashCode = " + Arrays.deepHashCode(mstrs2)); System.out.println("mstrs3's hashCode = " + Arrays.deepHashCode(mstrs3)); } }
8.2 Using java.util.Queue interface #
package com.jeid.tiger; import java.util.LinkedList; import java.util.PriorityQueue; import java.util.Queue; public class QueueTester { public static void main(String[] args) { System.out.println("---------- testFIFO ----------"); testFIFO(); System.out.println("---------- testOrdering ----------"); testOrdering(); } private static void testFIFO() { Queue<String> q = new LinkedList<String>(); q.add("First"); q.add("Second"); q.add("Third"); String str; while ((str = q.poll()) != null) { System.out.println(str); } } private static void testOrdering() { int size = 10; Queue<Integer> qi = new PriorityQueue<Integer>(size); Queue<String> qs = new PriorityQueue<String>(size); for (int i = 0; i < size; i++) { qi.offer(10 - i); qs.offer("str" + (10 - i)); } for (int i = 0; i < size; i++) { System.out.println("qi[" + i + "] = " + qi.poll() + ", qs[" + i + "] = " + qs.poll()); } } }
8.3 java.lang.StringBuilder 사용하기 #
package com.jeid.tiger; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class StringBuilderTester { public static void main(String[] args) { List<String> list = new ArrayList<String>(); list.add("str1"); list.add("str2"); list.add("str3"); String ret = appendItems(list); System.out.println("ret = " + ret); } private static String appendItems(List<String> list) { StringBuilder sb = new StringBuilder(); for (Iterator<String> iter = list.iterator(); iter.hasNext();) { sb.append(iter.next()).append(" "); } return sb.toString(); } }
8.4 Using Type-Safe Lists #
package com.jeid.tiger; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class ListTester { public static void main(String[] args) { List<String> list = new LinkedList<String>(); list.add("str1"); list.add("str2"); list.add(new Integer(123)); // <-- String이 아니므로 compile error!! //Iterator에 String type을 명시하므로 정삭작동됨. for (Iterator<String> iter = list.iterator(); iter.hasNext();) { String str = iter.next(); System.out.println("srt = " + str); } //Iterator에 String type을 명시하지 않았으므로 아래 A 부분에서 compile 오류 발생!! for (Iterator iter = list.iterator(); iter.hasNext();) { String str = iter.next(); //A System.out.println("srt = " + str); } //byte, short, int, long, double, float 동시 사용 List<Number> lstNum = new LinkedList<Number>(); lstNum.add(1); lstNum.add(1.2); for (Iterator<Number> iter = lstNum.iterator(); iter.hasNext();) { Number num = iter.next(); System.out.println("num = " + num); } } }
8.5 Writing Generic Types #
class AnyTypeList<T> { //class AnyTypeList<T extends Number> { // <-- 이는 Number를 상속한 type은 허용하겠다는 의미. private List<T> list; //private static List<T> list; // <-- 이는 정적이므로 compile error 발생!!! public AnyTypeList(){ list = new LinkedList<T>(); } public boolean isEmpty(){ return list == null || list.size() == 0; } public void add(T t){ list.add(t); } public T grap(){ if (!isEmpty() ) { return list.get(0); } else { return null; } } }
8.6 새로운 static final enum #
package com.jeid.tiger; import com.jeid.BaseObject; import com.jeid.MyLevel; public class EnumTester extends BaseObject { private static long start = System.currentTimeMillis(); public static void main(String[] args) { try { test(); enum1(); } catch (Exception e) { e.printStackTrace(); } printEllapseTime(); } private static void test() throws Exception { byte[] b = new byte[0]; System.out.println(b.length); } private static void enum1() { //enum TestEnum { A, B }; //enum cannot be local!!! for(MyVO.TestEnum te: MyVO.TestEnum.values()){ System.out.println("Allow TestEnum value : " + te); } System.out.println("---------------------------------------"); MyVO vo = new MyVO(); vo.setName("enum1"); vo.setLevel(MyLevel.A); System.out.println(vo); System.out.println("isA = " + vo.isA() + ", isGradeA = " + vo.isLevelA()+ ", isValueOfA = " + vo.isValueOfA()); System.out.println("getLevelInKorean = " + vo.getLevelInKorean()); } private static void printEllapseTime() { System.out.println("==> ellapseTime is " + (System.currentTimeMillis() - start) + " ms."); } } package com.jeid.tiger; import com.jeid.BaseObject; import com.jeid.MyLevel; public class MyVO extends BaseObject { enum TestEnum { A, B }; // this is same public static final private int id; private String name; private MyLevel grade; // private List<T> list; public MyLevel getLevel() { return grade; } public void setLevel(MyLevel grade) { this.grade = grade; } public boolean isA() { return "A".equals(this.grade); } public boolean isValueOfA() { return MyLevel.valueOf("A").equals(grade); } public boolean isLevelA() { return MyLevel.A.equals(this.grade); } //A,B,C..대신 0,1,2... 도 동일함. public String getLevelInKorean() { switch(this.grade){ case A: return "수"; case B: return "우"; case C: return "미"; case D: return "양"; case E: return "가"; default: return "없음"; } } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
8.7 Using java.util.EnumMap #
package com.jeid.tiger; import java.util.EnumMap; public class EnumMapTester { private enum MyEnum { A, B, C }; // this is same the static final.. public static void main(String[] args) { MyEnum[] enums = MyEnum.values(); System.out.println("MyEnum is " + enums[0] + ", " + enums[1] + ", " + enums[2]); EnumMap<MyEnum, String> em = new EnumMap<MyEnum, String>(MyEnum.class); em.put(MyEnum.A, "수"); em.put(MyEnum.B, "우"); em.put(MyEnum.C, "미"); em.put(MyEnum.B, "가"); //key 중복은 HashMap과 동일하게 overwrite임. for (MyEnum myEnum : MyEnum.values()) { System.out.println(myEnum + " => " + em.get(myEnum)); } } }
8.8 Using java.util.EnumSet #
package com.jeid.tiger; import java.util.EnumSet; public class EnumSetTester { private enum MyEnum { A, B, C, a, b, c }; // this is same the static final.. public static void main(String[] args) { MyEnum[] enums = MyEnum.values(); System.out.println("MyEnum is " + enums[0] + ", " + enums[1] + ", " + enums[2]); EnumSet<MyEnum> es1 = EnumSet.of(MyEnum.A, MyEnum.B, MyEnum.C); EnumSet<MyEnum> es2 = EnumSet.of(MyEnum.a, MyEnum.b, MyEnum.c); EnumSet<MyEnum> es3 = EnumSet.range(MyEnum.a, MyEnum.c); if (es2.equals(es3)) { System.out.println("e2 is same e3."); } for (MyEnum myEnum : MyEnum.values()) { System.out.println(myEnum + " contains => " + es1.contains(myEnum)); } } }
8.9 Convert Primitives to Wrapper Types #
package com.jeid.tiger; public class AutoBoxingTester { public static void main(String[] args) { int i = 0; Integer ii = i; // boxing. JDK 1.4에서는 incompatible type error가 발생 했었으나 Tiger에서는 괜찮다. int j = ii; // unboxing for (ii = 0; ii < 5; ii++) { // Integer인데도 ++ 연산자 지원. } i = 129; ii = 129; if (ii == i) { System.out.println("i is same ii."); } // -128 ~ 127 사이의 수는 unboxing이 되어 == 연산이 허용되지만, // 그 범위 외의 경우 Integer로 boxing된 상태므로 equals를 이용해야함. // 이는 버그가 발생했을 경우 찾기 쉽지 않은 단점도 내포하고 있다.!! checkIntegerSame(127, 127); // same checkIntegerSame(128, 128); // Not same checkIntegerEquals(128, 128); // equals checkIntegerSame(-128, -128); // same checkIntegerSame(-129, -129); // Not same checkIntegerEquals(-129, -129); // equals System.out.println("--------------------------------------------"); Boolean arriving = false; Boolean late = true; String ret = arriving ? (late ? "도착했지만 늦었네요." : "제시간에 잘 도착했군요.") : (late ? "도착도 못하고 늦었군요." : "도착은 못했지만 늦진 않았군요."); System.out.println(ret); StringBuilder sb = new StringBuilder(); sb.append("appended String"); String str = "just String"; boolean mutable = true; CharSequence chSeq = mutable ? sb : str; System.out.println(chSeq); } private static void checkIntegerSame(Integer ii, Integer jj) { if (ii == jj) { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is same ii."); } else { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is NOT same ii!!"); } } private static void checkIntegerEquals(Integer ii, Integer jj) { if (ii.equals(jj)) { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is equals ii."); } else { System.out.println("ii = " + ii + ", jj = " + jj + " ==> jj is NOT equals ii!!"); } } }
8.10 Method Overload resolution in AutoBoxing #
package com.jeid.tiger; public class OverloadTester { public static void main(String[] args) { double d = 10; Integer ii = new Integer(10); doSomething(10); doSomething(1000); doSomething(ii); doSomething(d); } private static void doSomething(Integer ii) { System.out.println("This is doSomething(Integer)"); } private static void doSomething(double d) { System.out.println("This is doSomething(double)"); } }
8.11 가변적인 argument 개수 ... #
package com.jeid.tiger; public class VarArgsTester { public static void main(String[] args) { setNumbers(1, 2); setNumbers(1, 2, 3, 4); setNumbers(1); // setNumbers(); //해당 되는 method가 없어 compile error!! System.out.println("=============================================="); setNumbers2(1, 2, 3, 4); setNumbers2(1); setNumbers2(); } // this is same setNumbers(int first, int[] others) private static void setNumbers(int first, int... others) { System.out.println("-----------setNumbers()----------- : " + first); for (int i : others) { System.out.println("i = " + i); } } // this is same setNumbers(int[] others) private static void setNumbers2(int... others) { System.out.println("-----------setNumbers2()----------- : " + (others != null && others.length > 0 ? others[0] : "null")); for (int i : others) { System.out.println("i = " + i); } } }
8.12 The Three Standard Annotation #
//정상적인 사용 @Override public int hashCode(){ return toString().hashCode(); } //스펠링이 틀려 compile error!! @Override public int hasCode(){ //misspelled => method does not override a method from its superclass error!! return toString().hashCode(); }
package com.jeid.tiger; public class AnnotationDeprecateTester { public static void main(String[] args){ DeprecatedClass dep = new DeprecatedTester(); dep.doSomething(10); //deprecated } } class DeprecatedClass { @Deprecated public void doSomething(int ii){ //deprecated System.out.println("This is DeprecatedClass's doSomething(int)"); } public void doSomethingElse(int ii){ System.out.println("This is DeprecatedClass's doSomethingElse(int)"); } } class DeprecatedTester extends DeprecatedClass { @Override public void doSomething(int ii){ System.out.println("This is DeprecatedTester's doSomething(int)"); } }
package com.jeid.tiger; import java.util.ArrayList; import java.util.List; public class AnnotationSuppressWarningsTester { @SuppressWarnings({"unchecked", "fallthrough"} ) private static void test1(){ List list = new ArrayList(); list.add("aaaaaa"); } @SuppressWarnings("unchecked") private static void test2(){ List list = new ArrayList(); list.add("aaaaaa"); } //warning이 없는 소스. private static void test3(){ List<String> list = new ArrayList<String>(); list.add("aaaaaa"); } }
8.13 Creating Custom Annotation Types #
package com.jeid.tiger; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Documented @Target( { ElementType.TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.ANNOTATION_TYPE }) @Retention(RetentionPolicy.RUNTIME) public @interface MyAnnotation { String columnName(); String methodName() default ""; } //사용하는 쪽.. public class AnnotationTester { @MyAnnotation(columnName = "test", methodName = "setTest") private String test; @MyAnnotation(columnName = "grpid") public String grpid; .... } //위의 test 멤버의 경우 다음과 같이 접근 가능하다. Field testField = cls.getDeclaredField("test"); if (testField.isAnnotationPresent(MyAnnotation.class)) { Annotatioin anno = testField.getAnnotation(MyAnnotation.class); System.out.println(anno.columnName() + ", method = " + anno.methodName()); }
9.1 for/in 의 자주 사용되는 형태 #
//1. 가장 단순한 형태인 배열(array) String[] strs = { "aaa", "bbb", "ccc" }; for (String str : strs) { System.out.println(str); } //2. List by using Iterator List<Number> lstNum = new LinkedList<Number>(); lstNum.add(1); lstNum.add(1.2); for (Iterator<Number> iter = lstNum.iterator(); iter.hasNext();) { Number num = iter.next(); System.out.println("num = " + num); } //3. List를 바로 사용 List<String> lst = new LinkedList<String>(); lst.add("aaaaa"); lst.add("bbbbb"); lst.add("ccccc"); lst.add("ddddd"); for (String str : lst) { System.out.println("str = " + str); } // 4. List of List List[] lists = { lst, lst }; for (List<String> l : lists) { for (String str : l) { System.out.println("str = " + str); } }
10.1 static member/method import #
//예를 들어 System.out.println() 이라는 것을 사용하기 위해서는 다음의 import 문이 필요하다. import java.lang.System; //물론 java.lang 이기에 import 문이 필요없지만 예를 들자면 그렇다는 것이다.&^^ //허나, Tiger에서는 다음과 같이 사용할수 있다. import static java.lang.System.out; ... out.println(...); // method를 import 한다면.. import static java.lang.System.out.println; ... println(...);
11 References #
- http://java.sun.com/j2se/1.4.2/docs/index.html
- http://java.sun.com/j2se/1.5.0/docs/index.html
- SUN의 JLS
- http://java.sun.com/docs/books/jls/html/index.html
- Java 핵심원리 - 마에바시 가즈야 저 - 영진닷컴
- Java 1.5 Tiger - Brett McLaughlin 저 - O'Reilly
출처: http://dna.daum.net/technote/java/PrincipleOfJavaInternalForDeveloperEasyToLost