final 변수와 상수 1
final 키워드는 끝!!!
변수에 final 키워드가 붙으면 더이상 값 변경 X
final 지역 변수
public class FinalLocalMain {
public static void main(String[] args) {
final int data1;
data1 = 10;
//data1 = 20; final은 값은 최초에 한번만 할당 가능
final int data2 = 20;
//data2 = 20; X
method(10);
}
static void method(final int parameter){
//parameter = 20; method = 10으로 이미 할당
}
}
final을 지역 변수에 설정할 경우 최초에 한번만 할당 가능, 변수 값 변경시 compileError
final 지역 변수 선언시 초기화 한 경우 이미 값 할당
매개변수에 final이 붙으면 메서드 내부에서 매개변수의 값을 변경 X
final - 필드 (멤버 변수)
public class ConstructInit {
final int val; //final을 필드에 사용할 경우 생성자를 통해 초기화
public ConstructInit(int val) {
this.val = val;
}
}
final을 필드에 사용할 경우 필드는 생성자를 통해 한번만 초기화 가능
public class FieldInit {
static final int CONST_VALUE= 10;
final int value = 10;
}
final 필드를 필드에서 초기화시, 이미 값 설정 -> 생성자를 통해서 초기화 X
public class FinalFieldMain {
public static void main(String[] args) {
//final 필드 - 생성자 초기화
System.out.println("생성자 초기화");
ConstructInit constructInit = new ConstructInit(10);
ConstructInit constructInit1 = new ConstructInit(20);
System.out.println(constructInit1.val);
System.out.println(constructInit.val);
//필드 초기화 -> 이미 초기화 되어 있기 때문에 변경 불가능
System.out.println("필드 초기화");
FieldInit fieldInit = new FieldInit();
FieldInit fieldInit1 = new FieldInit();
FieldInit fieldInit2 = new FieldInit();
System.out.println(fieldInit.value);
System.out.println(fieldInit1.value);
System.out.println(fieldInit2.value);
System.out.println("상수");
//static 영역
System.out.println(FieldInit.CONST_VALUE);
}
}
final 필드를 초기화 하는 경우 각 인스턴스마다 final 필드에 다른 값 할당 가능.
final을 사용 -> 생성 이후에 값을 변경 X

FieldInit과 같이 final 필드를 필드에서 초기화 -> 모든 인스턴스가 다음 오른쪽 그림과 같은 값을 갖는다.
FieldInit 인스턴스의 모든 value == 10
왜냐면 생성자 초기화와 다르게 초기화 필드의 코드에 해당 값은 미리 정해져 있다.
결과적으로 메모리 낭비
static final
FieldInit.My_VALUE는 static 영역에 존재. 그리고 final 키워드를 사용해서 초기화 값 변하지 X
static 영역은 단 하나만 존재. MY_VALUE 변수는 JVM 상에서 하나만 존재.
이런 이유로 final + 필드 초기화 -> static을 앞에 붙여 사용
final 변수와 상수 2
상수
상수는 변하지 X, 일정한 값을 갖는 수. 자바에서 보통 단 하나만 존재하는 변하지 않는 고정된 값을 상수
이런 이유로 상수는 static final 키워드 사용
대문자로 사용, _ 로 구분
필드를 직접 접근해서 사용
-> 상수는 기능이 아니라 고정값 자체
-> 상수는 값을 변경 X
public class Constant {
//수학
public static final double PI = 3.14;
//시간
public static final int HOUR_IN_DAY = 24;
public static final int SECONDS_IN_MINUTE = 60;
//애플리케이션 설정 상수
public static final int MAX_USERS = 1000;
}
애플리케이션 안에는 당양한 상수 존재.
이런 상수들은 애플리케이션 전반에서 사용 -> public
상수는 중앙에서 값을 하나로 관리
런타임에는 상수 값 변경X
public class ConstMain1 {
public static void main(String[] args) {
System.out.println("프로그램 최대 참여자 수 " + 1000);
int curUserCnt = 999;
process(curUserCnt++);
process(curUserCnt++);
process(curUserCnt++);
}
private static void process(int curCnt){
System.out.println("참여자수 " + curCnt);
if (curCnt > 1000){
System.out.println("대기자로 등록 합니다");
} else {
System.out.println("게임에 참여 합니다 ");
}
}
}
public class ConstMain2 {
public static void main(String[] args) {
System.out.println("프로그램 최대 참여자 수 " + Constant.MAX_USERS);
int curUserCnt = 999;
process(curUserCnt++);
process(curUserCnt++);
process(curUserCnt++);
}
private static void process(int curCnt){
System.out.println("참여자수 " + curCnt);
if (curCnt > Constant.MAX_USERS){
System.out.println("대기자로 등록 합니다");
} else {
System.out.println("게임에 참여 합니다 ");
}
}
}
final 변수와 참조
final은 변수의 값을 변경하지 X, 여기서 변수의 값이란??
변수는 크게 기본형, 참조형 변수
public class Data {
public int value;
}
public class FinalRefMain {
public static void main(String[] args) {
final Data data = new Data();
//data =new Data(); 참조 대상 변경 불가능
//참조 대상의 값은 변경 가능
data.value = 10;
System.out.println(data.value);
data.value = 20;
System.out.println(data.value);
}
}
data.value = 10;
System.out.println(data.value);
data.value = 20;
System.out.println(data.value);
참조형 변수에 data에 final이 붙음 -> 변수 선언 시점에 참조값을 할당, 참조값 변경 X
참조형 변수 data에 final이 붙었다. 이경우 참조형 변수에 들어있는 참조값을 다른 값으로 변경X. 다시 말해 다른 객체를 참조 할 수 없다. 참조형 변수에 들어있는 참조값만 변경 X , 이 변수 이외에 다른 곳에 영향을 준다는 의미는 X

public class Member {
private final Long id;
private String name;
public Member(Long id, String name) {
this.id = id;
this.name = name;
}
public void changeData(String name){
//this.id = id; -> 변경 불가능
this.name = name;
}
public void print(){
System.out.println("id : " + id + " name : " + name );
}
}
public class MemberMain {
public static void main(String[] args) {
Member member = new Member(1L, "Hwang");
member.print();
//member.changeData(2L, "Kim");
member.changeData( "Kim");
member.print();
}
}