Chpt. 2 변수 - 주제 2. 값은 기본형과 참조형으로 나뉜다.
앞선 주제에서 변수의 타입은 변수에 저장할 값에 따라 달라진다고 했다. 종류(type)를 기준으로 이러한 값들을 크기에 따라 분류한 것을 자료형(data type)이라고 한다. 따라서,
모든 값은 종류(type)가 있고 종류(type)를 모르면 해석할 수 없다.
1. 변수, 상수, 리터럴
자료형을 알아보기에 앞서 변수, 상수, 리터럴의 정의에 대해 알아보자.
변수: 하나의 값을 저장하는 공간
상수: 한 번만 저장할 수 있는 변수
리터럴: 그 자체로 값을 의미하는 것
사실 리터럴은 기존 수학에서의 상수를 뜻하지만 자바에서는 위와 같이 상수를 정의했기 때문에 차이점을 주기 위해 리터럴이라는 용어를 따로 붙어준 것이다.
상수는 기존 변수를 선언, 초기화하는 방법과 같지만 앞에 final이라는 키워드를 붙이며 한 번 초기화를 하고 다른 값을 대입하려고 하면 에러가 발생한다. 또한 선언과 동시에 초기화를 하지 않아도 된다.
2. 기본형과 참조형
자료형은 기본형과 참조형으로 나눠지는데 다음과 같은 특징을 갖고 있다.
저장되는 값 | 예 | |
기본형 | 실제 값 = 리터럴 | false, 123, 1.45, 'B', "ABCD" |
참조형 | 메모리 주소 = 객체의 주소 | 0x00 |
객체의 주소에 대해서는 객체 지향에서 다시 다루도록 한다.
1) 기본형의 종류
기본형은 아래의 표와 같이 8개의 타입이 있으며 외우도록 한다. 기본형 이외의 값은 모두 참조형으로 생각한다.
1 byte (= 8 bit) | 2 byte | 4 byte | 8byte | |
논리형 | boolean | |||
문자형 | char | |||
정수형 | byte | short | int | long |
실수형 | float | double |
2) 기본형의 범위
기본형은 0과 1 두 값으로 표현할 수 있는 bit 형식으로 저장된다. 그렇기 때문에 저장 공간의 크기(bit)와 저장 형식(부호 유무)에 따라 각 타입의 저장 가능한 값의 범위가 달라진다. short와 char 두 예시를 통해 알아보자.
[예 1] char의 범위
char의 크기는 2 byte, 즉 16 bit로 표현할 수 있는 값이다. 따라서 char로 표현할 수 있는 정수 값의 범위는 0 ~ 2 n-1이다.
[예 2] short의 범위
short의 크기는 2 byte, 즉 16 bit로 표현할 수 있는 값이다. 하지만 정수형이기 때문에 문자형과 다르게 부호 또한 표현해주어야 한다. 이를 위해 맨 앞 비트를 부호 비트(sign bit)로 할당했다. 따라서 0과 양수를 포함한 215개, 음수 215개, 총 2 X 215 = 216개의 정수를 표현할 수 있다. 범위로 나타내면 -2n-1 ~ 0 ~ 2n-1-1이다.
위 두 예시를 정리하면 다음과 같다.
부호 있는 정수의 범위 0 ~ 2n-1
부호 없는 정수의 범위 -2n ~ 2n-1-1
이와 함께 정수형 int는 -2 31 ~ 2 31 -1, 약 ±20억의 값을 저장할 수 있다는 사실 또한 알아두자. 그리고 이와 같은 저장 형식 때문에 float(정밀도 약 7)과 double(정밀도 약 15)은 정밀도 면에서 차이가 난다.
3. 리터럴의 구분
리터럴의 구분은 접두사 또는 접미사로 한다.
종류 | 리터럴 | 접미사 |
논리형 | false, true | 없음 |
정수형 | 100, 0b100, 0100, 0x100, 100L, 100_000 | L |
실수형 | 3.14, 10., .10, 10f, 1e-3 | f, d |
문자형 | 'A', '2', '\n' | 없음 |
문자열 | "", "A", "ABC", "false" | 없음 |
1) 논리형
false, true 두 가지 값만 허용한다.
2) 정수형
접두사 0b, 0, 0x은 각각 2진수, 8진수, 16진수를 표현하기 위해 사용된다. 접미사 L은 숫자 1과 혼동하지 않기 위해 대문자로 쓰는 것을 권장한다. 또한 크기가 큰 정수인 경우 구분자(_)를 통해 자리수를 구별할 수 있다.
3) 실수형
실수형에는 두 가지 타입 float과 double만 있기 때문에 접미사 f로 둘을 구별한다. f는 생략할 수 없지만 d는 생략 가능하다.
[참고]
10. = 10.0
.10 = 0.10
10f = 10.0f
1e-3 = 1.0 x 10 -3
4) 문자형과 문자열
문자형은 작은 따옴표 안에 한 개의 문자가 들어가지만 문자열은 큰 따옴표 안에 0개에서 n개의 문자가 들어갈 수 있다. 참고로 \n은 하나의 문자로 취급하는 이스케이프 문자라고 한다.
결국 리터럴을 구분할 때는 접미사 L과 f만 신경쓰면 된다.
4. 값의 입력과 출력
System.out.println()은 출력 형식을 지정할 수 없고, 10진수로만 출력이 가능하다라는 단점을 갖고 있다. 이와 같은 단점을 보완하기 위해 System.out.printf() (이하 printf()) 를 사용하며 printf()는 지시자를 사용해 여러 변수의 값을 다양한 형식으로 변환해 출력하게 된다.
1) 값의 출력
[예 1] %d, %n
int age = 26;
int bornYear = 1998;
System.out.printf("Your were born in %d, and age is %d.%n", bornYear, age);
출력 결과는 Your were born in 1998, and age is 26.이며 지시자의 개수에 제한은 없다. printf()는 줄바꿈이 되지 않기 때문에 OS에 독립적인 %n을 쓰도록 한다.
[참고]
지시자 %o, %x를 통해 각각 8진수, 16진수의 정수 형태로 출력할 수 있지만 2진수는 Integer.toBinaryString()을 이용해 출력하도록 한다.
[예 2] %f
실수형의 값을 출력할 때 다음과 같은 방법으로 전체 자리수와 소수점 아래 자리수의 출력 형식을 지정할 수 있다.
%[0-][전체 자리수].[소수점 자리수]f
double pi = 3.1415;
System.out.printf("Pi is <%16.10f>.%n", pi);
System.out.printf("Pi is <%-16.10f>.", pi);
System.out.printf("Pi is <%016.10f>.%n", pi);
[결과]
Pi is < 3.1415000000>.
Pi is <3.1415000000 >.
Pi is <00003.1415000000>.
위 결과는 아래 그림을 참고하면 이해할 수 있다. 참고로 오른쪽 정렬이 기본이며 전체 자리수 앞에 -를 붙이면 왼쪽으로 정렬된다. 또한 - 대신 0을 붙이면 왼쪽 빈자리는 0으로 채워진다.
[예 3] %s
[예 2]와 비슷한 방법으로 문자형의 출력할 글자 수를 조절할 수 있다.
%[-][전체 자리수]s
String sentence = "You are my celebrity";
System.out.printf("<%30s>%n", sentence);
System.out.printf("<%-30s>%n", sentence);
System.out.printf("%.10s", sentence);
[결과]
< You are my celebrity>
<You are my celebrity >
You are my
맨 마지막 줄의 결과를 보자. .을 붙이면 맨 마지막 줄의 결과처럼 원하는 만큼의 글자 수를 정해 출력할 수 있다.
2) 값의 입력
값의 입력은 import문을 먼저 추가하고, Scanner 클래스의 객체를 생성 후, nextLine() 메서드를 사용한다. 입력받은 내용은 문자열 형태이고 만약 정수형으로 바꾸고 싶다면 Integer.parseInt([입력받은 값]) 클래스 메서드를 사용하도록 한다. 만약 입력 받은 내용이 정수 하나라면 nextInt()를 바로 사용해 변수에 저장해도 된다. 일단은 이렇게만 알아두고 자세한 내용은 클래스에 가서 다루도록 하겠다.
import java.util.*;
Scanner scanner = new Scanner(System.in);
// 방법 1
String input = scanner.nextLine();
int num1 = Integer.parseInt(input);
// 방법 2 - 공백과 함께 100 200을 입력하면 num2와 num3에 각각 100, 200이 저장된다.
int num2 = scanner.nextInt();
int num3 = scanner.nextInt();
5. 정수형의 오버플로우
최대값 + 1 = 최소값
최소값 - 1 = 최대값
위의 두 문장만 기억하면 된다. 쉬운 예로 TV의 마지막 채널에서 채널을 하나 올리면 처음 채널로 돌아가고 처음 채널에서 하나 내리면 마지막 채널로 간다.