본문 바로가기

Java/Chapter 03. 상수와 형변환

[Java] 03.01 - 상수

들어가며

 상수는 '값이 변하지 않는 수'를
의미한다.

 하지만 자바에서는 한번 그 값이
정해지면

 이후로는 변경이 불가능한
변수도 상수라고 한다.

 

자바의 일반적인 상수

 변수를 선언할 때,

 그 앞에 'final'이라는 선언을
추가하면

 그 변수는 '상수'가 된다.

 그리고 다음 두 가지 특징을
지니게 된다.

  • 값을 딱 한 번만 할당할 수 있다.
  • 한 번 할당된 값은 변경이 불가능하다.

 그럼 다음 예제를 통해서
상수가 갖는 위의 2가지
특징을 확인하겠다.

public class temp {
    public static void main(String[] args){
       final int MAX_SIZE = 100;
       final char CONST_CHAR = '상';
       final int CONST_ASSIGNED;
       CONST_ASSIGNED = 12;

       System.out.println("상수1 : " +  MAX_SIZE);
       System.out.println("상수2 : " +  CONST_CHAR);
       System.out.println("상수3 : " +  CONST_ASSIGNED);
    }
}
/*
실행 결과
상수1 : 100
상수2 : 상
상수3 : 12
*/

 위 예제에서는 다음과 같이

 변수의 선언에 'final'을
추가하였다.

 따라서 이 변수는 값의 변경이
불가능한 상수가 된다.

final int MAX_SIZE = 100;    // 상수 MAX_SIZE의 선언

 다음과 같이 상수를 선언만 하고
값을 할당하지 않으면

 한 번은 값을 할당할 수 있다.

 그러나 그 이후로는 역시 값의
변경이 불가능하다.

final int CONST_ASSIGNED;
CONST_ASSIGNED = 12;

 그리고 예제에서 보이듯이,

 관례상 상수의 이름은 다음의
2가지 사항을 지켜서 명명한다.

  • 상수의 이름은 모두 대문자로 짓는다.
  • 이름이 둘 이상의 단어로 이뤄질 경우, 단어 사이에 언더바를 넣는다.

 

리터럴(Literals)에 대한 이해

 다음 문장에서는 변수를
선언함과 동시에

 157이라는 값을 초기화하였다.

 이때 대입 연산자의 오른편에
위치한 숫자 157을 가리켜

 '리터럴' 또는 '리터럴 상수'라고
한다. (그냥 '상수'라고도 한다.)

int num = 157;

 컴파일러는 위 문장에서
숫자 157을 int형 정수로
인식한다.

컴파일러는 숫자(리터럴)를 int형 정수로 인식한다.
그렇게 약속되어 있다.

 자바의 정수 표현 방법에는
int와 long을 포함하여

 4가지가 존재하고,

 실수 표현 방법에도 float과
double의 2가지가 존재한다.

 따라서 이렇듯 숫자를 접했을 때,

 이를 '무엇으로 인식할지에
대한 일종의 약속'이 필요하고,

 이 약속에 근거하여 표현된
숫자를 가리켜

 '리터럴' 또는 '리터럴 상수'라
한다.

 그런데 이와 관련하여 다음과
같은 의문이 생길 수도 있다.

int num = 157에서 157이 int형인 이유는
num이 int형이기 때문인가?

 그렇다면 다음의 문장을
컴파일해 보자.

참고로 int형의 표현 범위는 -2,147,483,648 ~ 2,147,483,647이다.
long num = 3147483647;

 위의 문장을 컴파일하면 다음과
같은 오류가 발생한다.

Error: java: integer number too large
또는
error: integer number too large: 3147483647

 이 메시지의 내용과 의미를
풀어서 정리하면 다음과 같다.

니가 입력한 숫자는 int형 정수여야 하는데
값이 너무 크다

 즉 왼편에 있는 변수의
자료형에 상관없이

 정수는 int형으로 표현하기로
약속되어 있다.

 그래서 위와 같은 오류
메시지가 발생하는 것이다.

 그렇다면 long형 변수에
3147483647과 같이

 큰 값을 어떻게 저장할
수 있는가?

 조금 뒤에 그 방법을 소개한다.

 그리고 이후로는 혼란을
줄이기 위해

 리터럴이라는 표현을 사용하지
않겠다.

 대신 리터럴도 '상수'라는
표현을 쓰겠다.

 

정수형 상수의 표현 방법

 앞서 설명했듯이,

 그냥 정수를 쓰면 이는
int형으로 인식된다.

 그리고 이러한 정수는
다음과 같이

 8, 10, 16진수로 표현할
수 있다.

  • 10진수로 int형 정수 표현
int num = 11 + 22 + 33;
  • 8진수로 int형 정수 표현: 숫자 앞에 '0' 삽입
int num = 011 + 022 + 033;
  • 16진수로 int형 정수 표현: 숫자 앞에 '0x' 또는 '0X' 삽입
int num = 0x11 + 0x22 + 0x33;

 위의 정수 표현 방식과
관련하여 다음 예제를 보자.

public class temp {
    public static void main(String[] args){
        int num1 = 123;     // 10진수 표현
        int num2 = 0123;    // 8진수 표현
        int num3 = 0x123;   // 16진수 표현

        System.out.println("num1: " + num1);
        System.out.println("num2: " + num2);
        System.out.println("num3: " + num3);

        System.out.println("11 + 22 + 33 = " + (11 + 22 + 33));
        System.out.println("011 + 022 + 033 = " + (011 + 022 + 033));
        System.out.println("0x11 + 0x22 + 0x33 = " + (0x11 + 0x22 + 0x33));
    }
}
/*
실행 결과
num1: 123
num2: 83
num3: 291
11 + 22 + 33 = 66
011 + 022 + 033 = 54
0x11 + 0x22 + 0x33 = 102
*/

 자바는 byte형과 short형으로
정수를 표현하는 방법을 제공하지
않는다.

 따라서 다음과 같은 덧셈을
byte형이나 short형으로
진행하는 방법은 없다.

System.out.println(3 + 4 + 5);
// → 숫자 3, 4, 5는 int형으로 인식되고 int형 덧셈으로 이뤄진다.

 그렇다면 byte형, short형 변수의
초기화는 어떻게 해야 하는가?

 다음과 같이 초기화 할 수 있을
것인가?

byte num1 = 5;
short num2 = 25;

 자바는 byte형과 short형 정수의
표현 방법을 제공하지 않기 때문에,

 위와 같은 초기화를 허용한다.

 물론 각 자료형의 표현 범위를
넘어서는 정수로 초기화 할 경우,

 컴파일 오류가 발생한다.

 반면에 long형 정수의 표현
방법은 별도로 제공한다.

 따라서 long형 정수를 써야
하는 다음과 같은 경우에는

 컴파일러가 알아서 이를
long형으로 인식해주지 않는다.

System.out.println(3147483647 + 3147483648);
// → 숫자 3147483647과 3147483648은 long형으로 표현 가능한 크기의 정수

 숫자의 끝에 문자 'L' 또는
'l'을 붙이는 것이

 long형 정수의 표현 방법이니,
다음과 같이 문장을 작성해야 한다.

 그렇게 해야지만이, 정상적으로
컴파일이 진행된다.

System.out.println(3147483647L + 3147483648L);

 

정수형 상수 관련 추가로 가능한 것들

 자바는 2진수로 표현하는
방법도 제공한다.

 다음과 같이 2진수 표현 앞에
'0B' 또는 '0b'를 붙여서 표현한다.

byte seven = 0B111;
int num205 = 0B11001101;

 그리고 단위가 큰 수의 표현
및 인식에 도움을 주기 위해

 다음과 같이 중간에 언더바를
삽입하는 것도 허용하고 있다.

int num = 100_000_000;

 이 언더바는 넣고 싶은 곳에
얼마든지 넣을 수 있다.

 숫자를 둘씩 구분해야 하는
상황이라면,

 다음과 같이 넣어도 된다.

int num = 12_34_56_78_90;

 

실수형 상수

 실수를 표현하는 방법은
다음과 같다.

 그리고 이러한 실수형 상수는
double형으로 인식된다.

double pi = 3.141592;    // 3.141592는 실수형 상수

 따라서 다음과 같이 문장을
구성하면

 두 double형 실수의 덧셈
결과를 확인할 수 있다.

System.out.println(3.0004999 + 2.0004999);

 만약에 위의 두 실수가 double형으로
표현된 상수임을 명시하고 싶다면,

 이를 목적으로 다음과 같이
'D' 또는 'd'를 붙일 수 있다.

 그리고 float형 실수를 표현하고
싶다면,

 다음과 같이 'F' 또는 'f'를
붙이면 된다.

 참고로 다음 문장을 실행해보면

 계산 결과의 오차를 확인할
수 있다.

 즉 이 두 실수의 덧셈은

 float형의 정밀도로 계산하기에는
적절하지 않다.

System.out.println(3.0004999f + 2.0004999f);

 다음과 같이 실수를 표현하는
것도 가능하다.

 물론 이들도 double형 실수이다.

 그리고 다음의 상황에서는

 앞 또는 뒤에 붙은 숫자 0을
생략할 수도 있다.

0.5     →    .5
5.0     →    5.
0.7f    →    .7f
7.0f    →    7.f

 

불형 상수와 문자형 상수

 boolean형이 가질수 있는
값은 다음 2가지 뿐이다.

true    false

 그리고 Chpater 02에서
char형 변수를 설명하면서,

 문자를 다음과 같이 표현함을
보였는데,

 이것이 문자형 상수의 표현
방법이다.

'한'  '글'  'A'  'Z'

 이외에도 '이스케이프 시퀀스
(escape sequence)'문자라는
것이 존재한다.

 이는 유니코드 문자들 중,

 키보드로 입력하기 어려운
문자의 표현을 위한 것이다.

'\b'    // 백스페이스 문자
'\t'    // 탭 문자
'\\'    // 백슬래시 문자
'\''    // 작은따옴표 문자
'\"'    // 큰따옴표 문자
'\n'    // 개행 문자
'\r'    // 캐리지 리턴 문자

 이들 대부분은 문자가 아닌,

 화면상의 어떠한 현상을
나타내는 문자들이다.

 예를 들어서 문자 '\n'은
행을 바꾸는 개행의 의미로
사용된다.

 그리고 큰따옴표와 작은따옴표는
문자열과 문자의 표현에

 사용하도록 약속되어 있기
때문에,

 그 자체의 출력이 필요한
상황을 위해서

 이스케이프 시퀀스 문자
'\''와 '\"'가 정의되었다.

 그럼 이와 관련하여 다음
예제를 보자

public class temp {
    public static void main(String[] args){
        System.out.println("AB" + '\b' + 'C');
        System.out.println("AB" + '\t' + 'C');
        System.out.println("AB" + '\n' + 'C');
        System.out.println("AB" + '\r' + 'C');
    }
}
/*
실행 결과
AC
AB	C
AB
C
C
*/

 위 예제의 다음 문장에 대해서
설명을 하면

 '\r'은 커서를 왼쪽 끝으로
이동시킨다.

 따라서 문자 A의 위치로 커서가
이동한 다음에

 문자가 C가 출력되어 문자 A가
지워진다.

System.out.println("AB" + '\r' + 'C');

 자바는 유니코드를 지원한다고
하였다.

 따라서 다음 수준의 문장을
출력할 수 있다.

 다만 문제는 키보드에 유로화
기호 가 없다는 것이다.

오늘의 환율은 1$에 0.88 입니다.

 이러한 경우에는 '\u'로 이스케이프
시퀀스를 구성하여

 원하는 문자를 출력할 수 있다.

 다음과 같이 '\u'에 이어서,

 유니코드 값을 16진수로 덧붙이면
해당 문자가 출력된다.

문자 유니코드 값 '20AC'  →  '\u20AC'

 그럼 예제를 통해서 해당 문구를
출력해 보겠다.

public class temp {
    public static void main(String[] args){
        System.out.println("오늘의 환률은 1$에 0.88" + '\u20AC' +"입니다.");
    }
}

참고 및 출처

윤성우의 열혈 Java 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2017.07.05
상세보기