pungjoo

final의 용도. 본문

JAVA

final의 용도.

pungjoo.kim 2008.11.10 20:42
들어가면서
final의 용도는 큰 줄기에서는 '한번 정의된 레퍼런스를 변경 할 수 없다.'입니다.
이 final은 아래와 같이 3가지 case로 볼 수 있습니다.

class 확장(extend) 및 mehotd override를 제한
package com.pungjoo.edu;

final public class SomeClass {

public static void main(String[] args) {

new SomeClass(){     //-> A

};

}


위와 같이 final public( 또는 public final )으로 class를 선언하면 extend를 할 수 없게 됩니다. 즉, 해당 class에 대한 변경(?)을 허용하지 않습니다. 컴파일시에 'A' 라인에서 'cannot inherit from final com.pungjoo.edu.SomeClass' 컴파일 오류가 발생합니다.

그러나 class를 확장하는 것은 허용하지만 특정 method를 override를 하는 것을 허용하지 않을 때도 사용 할 수 있습니다.
package com.pungjoo.edu;

public class SomeClass {

public final void someMethod(int para){
}

public static void main(String[] args) {

                        // 익명 클래스                
new SomeClass() {
@Override
public void someMethod(int para){  // --> A  
// 변경..
}
};
  
}

}

위와 같이 본래의 someMethod에 public final( 또는 final public )을 하면 컴파일시에 'A' 라인에서 'cannot override someMethod(int) in com.pungjoo.edu.SomeClass; overridden method is final'이라는 컴파일 오류가 발생합니다.

로컬변수를 inner-class에서 사용 (지역클래스)

package com.pungjoo.edu;

public class SomeClass {

public void someMethod(int x) {
int value = x + 200;

class InnerClass {
void temp() {
System.out.println(value);  // -> A
}
}
}

}

위와 같은 형태에서는 value를 inner class의 temp() method에서 참조를 기본적으로 할 수 없기 때문에 컴파일시에 'local variable value is accessed from within inner class; needs to be declared final' 컴파일 오류가 발생합니다.

이럴 경우는 'int value = x + 200;' 부분을 'final int value = x + 200;'로 final을 추가하면 해결이 됩니다만, 주의 할 점은 value를 final로 선언 했기때문에 해당 value를 변경 할 수는 없게 됩니다.

만약 inner class block(포함)을 벗어난 곳에서 value를 변경하는 구문이 들어가면 'value = 200;' 같이 추가하고 컴파일 한다면 'cannot assign a value to final variable value'라는 컴파일 오류가 발생하게 됩니다.

method parameter 재생성 금지
package com.pungjoo.edu;

import java.util.HashMap;
import java.util.Map;

public class SomeClass {

public void someMethod(Map map) {

Object key = null;

// 이런 저런 처리..

map.get(key);

// 초기화 하자..?
map = new HashMap(); // -> A

}

public static void main(String[] args) {

SomeClass clazz = new SomeClass();
Map map = new HashMap();

String key = "name";
String value = "pungjoo";
map.put(key, value);
clazz.someMethod(map);

System.out.println("Size : " + map.size());

}

}

method의 parameter로 선언된 객체를 new 생성자를 통해 new를 해 버리면 method return시에 자신이 new했기 때문에 위와 같은 경우 '0'이 찍히겠지 싶지만 그렇지 않습니다.
따라서 저런 실수를 원천적으로 막고 싶은 경우는 'public void someMethod(Map map)' 부분을 'public void someMethod(final Map map)'로 선언하면 컴파일시에 ' final parameter map may not be assigned' 컴파일 오류가 나게 됩니다.

만약 정상적으로 초기화하고 싶다면 'A' 부분을 'map.clean();'라고 하는 것이 맞겠죠.

@
Tag
공유하기 링크
1 Comments
댓글쓰기 폼