final 키워드는 변수를 변경할 수 없도록 지정할 때 사용한다. 사전적으로 따져보면 final이란 entity가 단 한 번만 할당될 수 있다고 선언하는 것이라고 한다. final로 초기화한 뒤에 값을 변경하려고 하면 컴파일 에러가 발생한다.
특히 static 과 final을 모두 지정한 필드를 '클래스 상수'라고 부른다. 보통 클래스 상수는 대문자로 기술하여 일반 변수와 구분되도록 한다.
String name = "홍길동"; //일반변수
final String THANKYOU = " 고객님 감사합니다!"; //final 변수
String message = name + THANKYOU;
final 키워드는 변수, 메서드, 클래스에 붙일 수 있다
- final 변수
해당 변수가 생성되고 값이 지정되면, 값이 고정된다.
public class AbsoluteZ {
public static void main(String[] args) {
final double absoluteZero = -273.15;
// absoluteZero = -120; //값을 변경할 수 없음
}
}
- final 메서드
메서드에 final이 붙으면 하위클래스에서 오버라이딩을 할 수 없다.
오버라이딩을 할 수 없다는 것은 즉, 하위클래스에서 재정의하여 상위클래스의 메서드를 숨길 수 없다는 것을 의미한다.
코드 예제
Bird 클래스와 이를 상속받는 Sparrow 클래스를 통해 final 의 특성에 대해 알아보자.
Bird 클래스
public class Bird {
final int footCount = 2;
void sing(){
System.out.println("노래 부른다");
}
final void fiy(){
System.out.println("하늘 난다");
}
static final void wake(){
System.out.println("일찍 일어나는 새가 벌레를 잡는다");
}
}
Bird 클래스를 상속받은 Sparrow 클래스
- sing() 메서드는 오버라이딩해서 메서드를 재정의했다
- fly() 메서드는 final 키워드가 붙어있으므로 오버라이드 할 수 없다. 메서드를 생성할 수는 있지만 호출시 상위클래스의 메서드가 호출되기 떄문에, fly() 에 작성한 코드는 일종의 dead code가 된다
- wake() 메서드는 static final 키워드가 붙어있다. 같은 이름의 메서드를 생성하는 것도 불가하다.
public class Sparrow extends Bird{
@Override
void sing() {
System.out.println("나는 꾀꼬리 같은 소리로 아침을 깨우지");
}
void fly(){
//메서드를 선언할 수는 있지만 메서드 명이 동일할 뿐
//Bird 클래스의 메서드를 오버라이드한 것은 아니다
System.out.println("이 메서드는 출력 안된다");
}
// void wake(){} //오버라이드 불가
}
public class MainEx {
public static void main(String[] args) {
Bird bird01 = new Bird();
bird01.fiy();
bird01.sing();
Bird.wake();
System.out.println();
Sparrow sparrow = new Sparrow();
sparrow.fiy();
sparrow.sing();
sparrow.wake();
System.out.println();
int foot = sparrow.footCount;
System.out.println("다리 개수 : "+ foot);
}
}
실행 결과
하늘 난다 노래 부른다 일찍 일어나는 새가 벌레를 잡는다 하늘 난다 나는 꾀꼬리 같은 소리로 아침을 깨우지 일찍 일어나는 새가 벌레를 잡는다 다리 개수 : 2 |
- final 클래스
클래스에 final이 붙은 경우 안타깝게도 더이상 하위(자손)클래스를 가질 수 없다. 즉, extends 가 허용되지 않는다는 의미이다. 우리가 자주 애용하는 String 클래스가 대표적인 final 클래스이다.
static final
보통 final 앞에 static 수식자를 붙인 static final 을 선언하여 사용하는 편이 많다. static 으로 선언하면 Java T메모리 static 영역에 할당되어 모든 클래스에서 접근 및 참조할 수 있다. 한번만 객체가 생성되면 다른 클래스에서 중복하여 생성할 필요가 없다. 또한 인스턴스를 생성하지 않고도 접근이 가능해진다. 정리를 해보자면
- 모든 클래스에서 참조할 수 있고
- 인스턴스를 생성하지 않고도 접근할 수 있고
- 값이 고정되어 변경될 우려를 하지 않아도 되는
아주아주 중요한 절대값 1개에 static final 이라고 선언하게 된다.
'Java > 기본' 카테고리의 다른 글
[Java] 스레드(Thread) - 스레드 개념 및 생성하기 (0) | 2021.07.07 |
---|---|
[Java] 타입문제예방하기102 - 열거형(enum)이란 (0) | 2021.07.01 |
[Java] 타입문제예방하기101 - 제네릭(Generic) 이란 (0) | 2021.06.30 |
[Java] 타입변환(type casting) - 자동타입변환, 강제타입변환 (0) | 2021.06.30 |
[Java] 컬렉션프레임워크202 - Properties (0) | 2021.06.25 |