상수
- 상수는 변하지 않는 수를 말한다.
- final이라는 예약어를 사용해서 선언할 수 있다.
- 왜 굳이 사용해야하는가?
1. 만약 작업(Job)이라는 객체가 있고 그 객체가 state라는 변수를 가지고있다.
2. 만약 Job의 상태가 완료라면 job.setState("Completion")이라고 하기로했고, 저 코드는 1000번 정도 쓰였다.
3. 헌데, 고객사에서 상태가 완료되면 "Finish"로 해달라는 요청이 왔고 이를 해결하기 위해서 1000번을 다 수정해줘야한다.
4. 여기서 만약 final String COMPLETION_STATE = "Completion" 이라고 설정해 두고,
job.setState(COMPLETION_STATE)라고 선언했다면, Completions을 finish 로만 바꾸면 모든 코드가 수정된 효과를 가질 수 있다.
5. 결정적으로 변하지 않는 값을 상수로 해두면, 좀더 직관적인 코드를 완성할 수 있기때문에 되도록 저런 변수는 상수로 처리하는 것이 바람직한 코딩 스타일이다.
- 또한 클래스도 상수가 될 수 있다.
final Test t1 = new Test();
t1 = new Test(); // 오류
t1.num = 10; // 이건 가능하다.
- 위와 같이 상수로 선언된 변수에 새로운 값을 할당할 수 없다.
- 하지만 클래스 안에 데이터는 변경이 가능하다.
리터럴이란?
- 리터럴은 데이터 그 자체를 뜻 한다.
- 프로그램에서 사용하는 숫자, 문자, 논리값을 뜻함
int a = 10
- 위에서 10과 같이 변하지 않는 데이터(boolean, char, double, long, int)를 리터럴(literal)이라고 부른다.
- 그렇다면 클래스는 인스턴스가 될 수 있을까? -> 될 수 없다. -> 값이 언제 바뀔지 모르기 때문이다.
- 하지만 예외로 객체 리터럴이 존재 하는데 이들은 한번 생성하면 객체 안의 데이터가 변하지 않는다. -> 만약 변할 상황이면 새로운 객체를 생성한다. -> 그 예로 String, Color 같은 클래스가 있다.
- 리터럴은 상수풀에 있음
상수 풀이란?
- 위와 같이 하드디스크에 있는 프로그램이 메모리로 로드될때, 상수, 리터럴, static변수 와같은 것들은 미리 메모리를 잡고 위치해있다.
- 로직이 실행되면서 메모리에 등록되는 것이 아니라 프로그램이 처음으로 메모리에 로드되는 순간 상수풀에 자리를 잡는다.
final String literal = "Hello";
final String object = new String("Hello");
Assert.assertTrue(literal.equals(object));
Assert.assertFalse(literal == object);
- 첫 번째 Hello 는 상수풀에 저장된다.
- 두 번째 Hello 는 힙영역에 저장된다.
- equals는 true가 나오고 ==는 false가 나온다.
- 리터럴로 선언 되었을 경우 함수 풀에 저장되는 과정은 아래와 같다.
- 먼저 intern()메소드를 호출해서 현재 함수 풀(constant pool)에 해당 문자열이 있는지 확인한다.
- 없다면 함수 풀에 해당 변수를 저장한다.