Java - 상수와 리터럴 ( constant 와 literal ) 이란?

상수 ( constant )

상수란 변수와 마찬가지로 "값을 저장할 수 있는 공간"이지만, 변수와 달리 한번 값을 저장하면 달느 값으로 변경할 수 없습니다.

즉, 한 번 선언하면 값은 고정됩니다.

java에서 상수를 선언하는 방법은 변수와 동일하며 변수의 타입 앞에 "final"을 붙여주면됩니다.

그리고 상수의 이름은 모두 대문자로 한다는 규칙에 따라 모두 대문자로 작성합니다.

final int MAX_SPEED = 100; // 상수 MAX_SPEED를 선언하고 초기화
final int MAX_SPEED; // Error : 상수는 선언과 동시에 초기화 해야한다.

final int MIN_SPEED = 10; // MIN_SPEED를 선언과 동시에 초기화했음 
MIN_SPEED = 200; // Error : 상수의 값은 변경될 수 없음.

 


리터럴 ( literal ) 

리터럴이란 변하지 않는 데이터 그 자체를 의미합니다. 리터럴은 "상수"의 다른 이름일 뿐입니다.

 

변수 : 하나의 값을 저장하기 위한 공간

상수 : 값을 한번만 저장할 수 있는 공간 ( 한번 값을 정하면 변하지 않음, 고정 )

리터럴 : 데이터 그 자체의 값을 의미

상수와 리터럴을 왜 따로 부르는가 ?

리터럴이 상수의 다른 이름이라고 했는데, 그러면 왜 굳이 똑같은 것을 따로 사용하는지 의문이 듭니다.

 

 

int triangleArea = (20 * 10) / 2; // 삼각형의 면적 구하기
int rectangleArea = 20 * 10; // 사각형의 면적 구하기

이 코드는 삼각형과 사각형의 면적을 구해 변수에 저장합니다.

근데 만약 가로 세로 길이 ( 20, 10 )를 다른 값으로 변경하고 싶다면 가로 세로 길이 ( 20, 10 ) 이 적용되어 있는 여러 코드를 수정해야합니다.

 

이때 다음과 같이 상수를 이용하여 여러 코드를 수정할 번거로움을 없앨 수 있습니다.

final int WIDTH = 20; // 가로
final int HEIGHT = 10; // 세로

int triangleArea = (WIDTH * HEIGHT) / 2; // 삼각형의 넓이 구하기
int rectangleArea = WIDTH * HEIGHT; // 삼각형의 넓이 구하기

이렇게 상수를 이용한다면, 이전 변수를 선언한 방식에 비해 넓이를 구하는 공식의 의미가 보다 명확해지고,

다른 값으로 변경한다해도 여러 곳을 수정할 필요가 없이 상수의 값만 변경하면 됩니다.

그리고 상수는 리터럴에 "의미있는 이름"을 붙여서 코드의 이해와 수정을 쉽도록 돕습니다.

 

리터럴의 타입과 접미사

변수에 타입이 있는 것처럼 리터럴에도 타입이 있습니다.

위 표를 보면 정수형과 실수형에는 여러 타입이 존재하므로 

정수형의 경우 long타입의 리터럴에 접미사 "L"을 붙이고, 접미사가 없으면 int 타입의 리터럴입니다.

byte와 short 타입의 리터럴은 존재하지 않으며 byte와 short 타입의 변수에 값을 저장할 때는 int타입의 리터럴을 사용합니다.

 

10진수 외에도 2, 8, 16진수로 표현된 리터럴을 변수에 저장할 수 있으며 다음과 같은 접두사를 사용합니다.

int Num = 8; // 10진수
int biNum = 0b0101; // 2진수, 접두사 0b, 0B 사용
int octNum = 010; // 8진수, 접두사 0 사용
int hexNum = 0x10; // 16진수, 접두사 0x 사용

 

실수형의 경우에는 float타입의 리터럴에 접미사 "f"또는 "F"를 붙이고, double 타입의 리터럴에는 접미사 "d" 또는 "D"를 붙입니다.

float pi = 3.14f;
double rate = 1.618d;

정수형에서 int가 기본 자료형이여서 리터럴이 생략되는 것처럼 실수형에서도 double이 기본 자료형이라 접미사 "d"가 생략가능합니다.

즉, 실수형 리터럴인데 접미사가 없으면 double 타입입니다.

float pi = 3.14; // Error : float 타입 변수에 접미사가 없으므로 double 타입으로 인식
double rate = 1.618; // OK 접미사가 없으므로 double 타입으로 인식

 

자료형 실수형 리터럴 다른 형태의 동등한 표현
double 10. 10.0
double .10 0.10
float 10f 10.0f
float 3.14e3f 3140.0f
double 1e1 10.0
double 1e-3 0.001

여기서 중간에 있는 e는 10의 제곱을 나타내는 기호로 대문자 "E"나 "e"로 나타냅니다.

( e3의 경우 10의 3승 => 1000 , e-3의 경우 10의 -3승 1/1000 이 됩니다. )

 

또한 2의 제곱을 의미하는 "p"나 "P" 기호도 있습니다.

( p1의 경우 2의 1승 => 2, p4의 경우 2의 4 승 => 16, p-1의 경우 2의 -1승 => 1/2 = 0.5 가 됩니다. ) 

 

타입의 불일치

리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 보통이지만,

타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 허용됩니다.

int i = 'A'; // OK : 문자 'A'의 유니코드인 65가 변수 i 에 저장
long l = 123; // OK : int보다 long 타입의 범위가 더 넓으므로 가능
double = 3.14f; // OK : float 보다 double 타입이 더 범위가 넓으므로 가능.

 

하지만, 리터럴의 값이 변수의 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타입보다 저장범위가 넓으컴파일 에러가 발생합니다.

int i = 0x123456789; // Error : int 타입의 범위는 10자린데 10자리를를 넘는 값을 저장했기 때문
float f = 3.14; // Error : float 타입보다 double 타입의 범위가 넓기 때문.

 

문자 리터럴과 문자열 리터럴

'A' 같이 작은 따옴표 ( ' ' )문자 하나를 감싼 것을 '문자 리터럴' 이라고 하고, 두 문자 이상은 큰 따옴표 ( " " ) 로 감싸야 하며, "문자열 리터럴"이라고 합니다. 

char ch = 'J'; // char는 단 하나의 문자만 저장할 수 있으므로 char ch = 'JAVA';는 안된다.

String name = "JAVA"; // 변수 name에 문자열 리터럴 "JAVA"를 저장

( 원래 String의 경우 클래스이므로 String name = new String("JAVA");로 new 연산자를 사용해야 하지만 특별히 위와 같은 표현도 허용됩니다. )

char 타입의 변수는 단 하나의 문자만 저장할 수 있으므로, 여러 문자를 포함한 "문자열"을 저장하기 위해선 String타입을 사용해야 합니다.

 

문자열 리터럴은 ""안에 아무런 문자도 넣지 않는 것이 가능하며, 이를 빈 문자열이라고 합니다.

하지만 문자 리터럴은 반드시 '' 안에 하나의 문자가 있어야합니다.

String str = ""; // OK : String 타입은 빈 문자열 가능
char test = ''; // Error : char 타입은 반드시 '' 안에 하나의 문자 필요
char test = ' '; // OK : 공백 문자도 가능하다.
char test = 'A'; // OK : A 문자로 변수 test를 초기화

 

 

덧셈 연산자

덧셈 연산자 + 를 이용해 여러 문자열들을 결합할수 있습니다.

덧셈 연산자는 피연산자가 모두 숫자일 때는 두 수를 더하지만, 

피연산자 중 어느 한 쪽이 String이면 나머지 한쪽을 먼저 String으로 변환한 다음 두  String을 결합합니다.

public class StringEx {

	public static void main(String[] args) {
		String name = "JA" + "VA";
		String str = name + 8.0;
		
		System.out.println(name);
		System.out.println(str);
		System.out.println(7 + " ");
		System.out.println(" " + 7);
		System.out.println(7 + "");
		System.out.println("3" + 7);
		System.out.println(7 + "7");
		System.out.println(7 + 7 + "7");
		System.out.println(7 + 7 + "");
	}

}

위 결과를 보면 JAVA의 경우 숫자 8.0을 문자열로 변환하여 합쳐 JAVA8.0이 되었고,

"3" + 7의 경우도 3과 7을 더하는 것이 아닌 7을 문자열로 바꿔 문자열 3과 7을 합쳐 37이 출력되었습니다.

7 + 7 + "7"의 경우 7 + 7은 둘다 숫자이기에  두 수를 더하고 그 뒤 "7"의 경우는 문자열이기에 7 + 7의 한 결과인 14를 문자열로 변환해 "7"과 합쳐 "147"이 되었습니다.