final 키워드는 이름 그대로 끝 이라는 뜻이다.
변수에 final 키워드가 붙으면 더는 값을 변경할 수 없다.
final은 class, method를 포함한 여러 곳에 붙을 수 있다. 지금은 변수에 붙는 final 키워드이다.
public static void main(String[] args) {
final int data1;
data1 = 10; //최초 한번만 할당 가능
data1 = 20;
final int data2 = 20;
}
final로 data1을 지정해 준 후 최초 한번 10으로 할당한 뒤 20으로 변경을 하면
java: variable data1 might already have been assigned
위와 같은 에러가 발생한다.
final이기에 최초 할당 이후로는 더이상 값의 변경이 불가능 하기 때문이다.
매개변수에도 final 키워드를 붙힐 수 있다.
static void method(final int parameter){
parameter = 20;
}
위와 같은 메소드를 지정할 때 파라미터 값을 final 키워드로 붙히면 메서드 내부에서 값의 변경이 불가능하다.
final을 멤버 변수에 사용할 경우
public class ConstructInit {
final int value;
public ConstructInit(int value) {
this.value = value;
}
}
위 처럼 생성자를 통해서 초기화가 가능하다.
또한 멤버변수에 static final이 붙을 경우 상수 취급을 하며 변수명을 대문자로 작성하는 것이 관례이다.
public class FieldInit {
static final int CONST_VALUE = 10;
final int value = 10;
public FieldInit(int value){
this.value = value;
}
}
위 코드의 CONST_VALUE는 static final이기에 변수명을 대문자로 적어야 한다.
그리고 value는 final이며 생성과 동시에 초기화를 해주었기 때문에 생성자를 통한 변경이 불가능하다.
CONST_VALUE와 같은 경우는 static이라 메서드 영역에 만들어지나 value와 같은 경우는 힙 영역에 생성된다.
하지만 final이기에 각 객체에 생성되는 값은 모두 10이게 되며 결과적으로 메모리를 낭비하게 된다.
그렇기에 CONST_VALUE와 같은 경우를 상수라고 한다.
상수(Constant)
상수는 변하지 않고 항상 일정한 값을 갖는 수를 말한다. 자바에서는 보통 단 하나만 존재하는 변하지 않는 고정된 값을 상수라한다. 이런 이유로 상수는 static final 키워드를 사용한다.
상수의 특징으로는
1. static final 키워드를 사용한다.
2. 대문자를 사용하고 구문은 _로 한다(관례)
3. 필드를 직접 접근해서 사용한다. (상수는 기능이 아니라 고정된 값 자체를 사용하는 것이 목적이기 때문이다.)
4. 상수는 값을 변경할 수 없다. 따라서 필드에 직접 접근해도 데이터가 변하는 문제가 발생하지 않는다.
public class Constant {
public static final double PI = 3.14;
public static final int HOURS_IN_DAY = 24;
public static final int MINUTES_IN_HOUR = 60;
public static final int SECOND_IN_MINUTE = 60;
public static final int MAX_USERS = 1000;
}
애플리케이션 안에는 다양한 상수가 존재할 수 있다. 수학, 시간 등 고정된 값들이기 때문이다.
보통 이런 상수들은 애플리케이션 전반에 사용되기 때문에 public을 자주 사용한다. 특정 위치에 사용되는 상수라면 접근제어자를 통해 가려주어야 한다.
상수는 중앙에서 값을 하나로 관리할 수 있다는 장점도 있다.
상수는 런타임에 변경할 수 없다. 상수를 변경하려면 프로그램을 종료하고, 코드를 변경한 뒤 다시 실행해야 한다.
public static void main(String[] args) {
System.out.println("프로그램 최대 참여자 수 " + 1000);
int currentUserCount = 999;
process(currentUserCount++);
process(currentUserCount++);
process(currentUserCount++);
process(currentUserCount++);
}
private static void process(int currentUserCount){
System.out.println("참여자 수: " + currentUserCount);
if (currentUserCount> 1000){
System.out.println("대기자로 등록합니다.");
return;
}
System.out.println("게임에 참여합니다.");
}
위와 같이 게임 동시 접속자의 수가 최대 1000명인 프로그램이 있다고 가정하자.
지금까지는 잘 동작하는 프로그램이나, 만약 서버를 증설하여 동시접속자가 최대 2000명이 된다면 어떡해야하나?
위와 같은 코드의 문제는 손볼 곳이 한두군데가 아니라는 점이다. 또 다른 개발자들이 보았을때 1000이 의미하는 뜻을 정확하게 파악하기 어렵다.(이런 문제를 매직 넘버라고 한다)
이러한 코드의 문제는 static final 상수값을 적용하여 상수값 하나만 변경시켜 문제를 해결할 수 있다.
public static void main(String[] args) {
System.out.println("프로그램 최대 참여자 수 " + Constant.MAX_USERS);
int currentUserCount = 999;
process(currentUserCount++);
process(currentUserCount++);
process(currentUserCount++);
process(currentUserCount++);
}
private static void process(int currentUserCount){
System.out.println("참여자 수: " + currentUserCount);
if (currentUserCount> Constant.MAX_USERS){
System.out.println("대기자로 등록합니다.");
return;
}
System.out.println("게임에 참여합니다.");
}
즉 상수의 값을 통해 중앙에서 관리할 수 있고, 매직넘버에 대한 문제가 해결된다.
마지막 final 예제이다.
public class Data {
public int value;
}
public static void main(String[] args) {
final Data data = new Data();
//참조 대상의 값은 변경 가능하다.
data.value = 20;
System.out.println("data.value = " + data.value);
}
참조값이 final로 정의되었으나 참조 대상의 값은 변경이 가능하다.
final은 data에만 걸었기 때문에 data가 참조하고 있는 참조값인 x001(임의의 값이다)을 변경 못한다는 것이지 이 변수 이외에 다른 곳에 영향을 주는 것이 아니다.
'공부 > Java' 카테고리의 다른 글
자바 다형성 1편 (Polymorphism) (0) | 2024.09.04 |
---|---|
자바 상속이란 (1) | 2024.09.03 |
자바 메모리 구조와 static (2) | 2024.09.02 |
자바 접근 제어자 (5) | 2024.08.31 |
자바 패키지 (0) | 2024.08.31 |