2.1 변수 선언
컴퓨터 메모리(RAM)는 수많은 번지들로 구성된 데이터 저장 공간이다. 프로그램은 데이터를 메모리에 저장하고 읽는 작업을 빈번히 수행한다. 이때 프로그래밍 언어는 메모리를 관리하기 위해 변수를 사용한다.
변수(variable)는 하나의 값을 저장할 수 있는 메모리 번지에 붙여진 이름이다. 변수를 통해 프로그램은 메모리 번지에 값을 저장하고 읽는다. 자바의 변수는 정의한 타입의 값만 저장할 수 있다.
변수를 사용하려면 변수 선언이 필요한데, 변수 선언은 어떤 타입의 데이터를 저장할 것인지 그리고 변수 이름이 무엇인지를 결정하는 것이다.
int age; // 정수 값을 저장하는 age 변수 선언
double value; // 실수 값을 저장하는 value 변수 선언
변수 이름은 첫 번째 글자가 문자여야 하고, 중간부터는 문자, 숫자, $, _를 포함할 수 있다. 또한, 첫 문자를 소문자로 시작하되 캐멀 스타일로 작성하는 것이 관례이다.
캐멀(camel) 스타일
코드를 작성할 때 여러 단어를 혼합하여 명명하는 경우, 대소문자가 섞여있도록 작성하는 스타일을 말한다. 자바 소스 파일명과 변수명을 작성할 때 관례적으로 사용한다.
1. 자바 소스 파일명(클래스명)은 대문자로 시작하는 것이 관례
2. 변수명은 소문자로 시작하는 것이 관례
변수가 선언되었을 때 대입 연산자인 =를 사용하여 값을 저장할 수 있다. 우측 값을 좌측 변수에 대입한다.
int score; // 변수 선언
score = 90; // 값 대입
변수 선언은 메모리에 할당되지 않고 저장되는 값의 타입과 이름만 결정한 것이다. 변수에 최초로 값이 대입될 때 메모리에 할당되고, 해당 메모리에 값이 저장된다.
변수에 최초로 값을 대입하는 행위를 변수 초기화라고 하고, 이때의 값을 초기값이라고 한다. 초기값은 변수를 선언함과 동시에 대입할 수도 있다. 초기화되지 않은 변수는 아직 메모리에 할당되지 않았기 때문에 변수를 통해 메모리 값을 읽을 수 없다.
번수는 선언될 때의 타입에 따라 저장할 수 있는 값의 종류와 허용 범위가 달라진다. 자바는 값을 저장할 수 있는 기본(primitive) 타입 8개를 다음과 같이 제공한다.
값의 분류 | 기본 타입 |
정수 | byte, char, short, int, long |
실수 | float, double |
논리(true/false) | boolean |
2.2 정수 타입
타입 | 메모리 크기 | 저장되는 값의 허용 범위 | ||
byte | 1 byte | 8 bit | -2^7 ~ ( 2^7 - 1) | -128 ~ 127 |
short | 2 byte | 16 bit | -2^15 ~ (2^15 - 1) | -32,768 ~ 32,767 |
char | 2 byte | 16 bit | 0 ~ (2^16 - 1) | 0 ~ 65535 (유니코드) |
int | 4 byte | 32 bit | -2^31 ~ (2^31 - 1) | -2,147,483,648 ~ 2,147,483,647 |
long | 8 byte | 64 bit | -2^63 ~ (2^63 - 1) | -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807 |
각 타입에 저장되는 값의 허용 범위를 모두 외울 필요는 없지만 메모리 할당 크기는 알고 있는 것이 좋다.
메모리 크기를 n이라고 할 때 정수 타입은 다음과 같은 동일한 구조의 2진수로 저장된다.
byte, short, int, long은 모두 부호 있는(signed) 정수 타입이므로 최상위 bit는 부호 bit로 사용되고, 나머지 bit는 값의 범위를 결정한다.
최상위 bit 값 | 값의 범위 |
0 ~ (2^(n-1) - 1) | |
-2^(n-1) ~ -1 |
코드에서 프로그래머가 직접 입력한 값을 리터럴(literal)이라고 부르는데, 변수에 대입할 정수 리터럴은 진수에 따라 작성하는 방법이 다르다.
º 2진수: 0b 또는 0B로 시작하고 0과 1로 작성
int x = 0b1011; // 10진수 값 = 1 × 2^3 + 0 × 2^2 + 1 × 2^1 + 1 × 2^0 = 11
int y = 0B10100; // 10진수 값 = 1 × 2^4 + 0 × 2^3 + 1 * 2^2 + 0 × 2^1 + 0 × 2^0 = 20
º 8진수: 0으로 시작하고 0~7 숫자로 작성
int x = 013; // 10진수 값 = 1 * 8^1 + 3 * 8^0 = 11
int y = 0B10100; // 10진수 값 = 2 * 8^2 + 0 * 8^1 + 6 * 8^0 = 134
º 10진수: 소수점이 없는 0~9 숫자로 작성
int x = 12;
int y = 365;
º 16진수: 0x 또는 0X로 시작하고 0~9 숫자나 A, B, C, D, E, F 또는 a, b, c, d, e, f로 작성
int x = 0xB3; // 10진수 값 = 11 * 16^1 + 3 * 16^0 = 179
int y = 0x2A0F; // 10진수 값 = 2 * 16^3 + 10 * 16^2 + 0 * 16^1 + 15 * 16^0 = 10767
2.3 문자 타입
하나의 문자를 작은 따옴표(')로 감산 것을 문자 리터럴이라고 한다. 문자 리터럴은 유니코드로 변환되어 저장되는데, 자바는 이러한 유니코드를 저장할 수 있도록 char 타입을 제공한다.
유니코드는 정수이므로 char 타입도 정수 타입에 속하기 때문에 char 변수에 유니코드 숫자를 직접 대입할 수 있다.
char var1 = 'A'; // 'A' 문자와 매핑되는 숫자: 65로 대입
char c = 65; // 10진수 65와 매핑되는 문자: 'A'
char 타입의 변수에 초기화를 하려면 작은따옴표(') 두 개 사이에 공백 하나를 포함해서 초기화해야 한다.
2.4 실수 타입
double 타입이 float 타입보다 큰 실수를 저장할 수 있고 정밀도 또한 높다.
타입 | 메모리 크기 | 저장되는 값의 허용 범위(양수 기준) | 유효 소수 이하 자리 | |
float | 4 byte | 32 bit | 1.4 * 10^-45 ~ 3.4 * 10^38 | 7자리 |
double | 8 byte | 64 bit | 4.9 * 10^-324 ~ 1.8 * 10^308 | 15자리 |
float 타입
double 타입
자바는 IEEE754 표준에 근거해서 실수 타입의 값을 부동 소수점(floating-point) 방식으로 메모리에 저장한다.
실수 타입은 가수와 지수를 저장하기 위해 전체 bit를 다음과 같이 나누어 사용한다.
*최상위 1bit: 양수 및 음수를 결정짓는 부호 bit. 0이면 양수, 1이면 음수.
double은 float보다 지수와 가수 부분의 bit 수가 크기 때문에 더 크고 정밀한 실수를 저장할 수 있다. 코드에서 실수 리터럴은 다음과 같이 저장할 수 있다.
10진수 리터럴
double x = 0.25;
double y = -3.14;
e 또는 E가 포함된 10이 거듭제곱 리터럴
double x = 5e2; // 5.0 × 10^2 = 500.0
double y = 0.12E-2; // 0.12 × 10^-2 = 0.0012
※ 컴파일러는 실수 리터럴을 기본적으로 double 타입으로 해석하기 때문에 double 타입 변수에 대입해야 한다. float 타입에 대입할 때 리터럴 뒤에 'f' 또는 'F'를 붙여 컴파일러가 float 타입임을 알 수 있도록 해야 한다.
2.5 논리 타입
참과 거짓을 의미하는 논리 리터럴인 true와 false는 boolean 타입 변수에 다음과 같이 대입할 수 있다.
boolean stop = true;
boolean stop = false;
boolean 타입 변수는 주로 두 가지 상태값을 저장할 필요가 있을 경우에 사용되며, 조건문과 제어문의 실행 흐름을 변경하는 데 사용된다. 연산식 중에서 비교 및 논리 연산의 산출값은 true 또는 false이므로 boolean 타입 변수에 대입할 수 있다.
2.6 문자열 타입
큰따옴표(")로 감싼 여러 개의 문자들들을 문자열이라고 부른다.
String var1 = "A";
String var2 = "홍길동";
문자열 내부에 역슬래쉬(\)가 붙은 문자를 이스케이프(escape) 문자라고 한다. 특정 문자를 포함할 수 있고, 출력에 영향을 미치기도 한다.
이스케이프 문자 | |
\" | " 문자 포함 |
\' | ' 문자 포함 |
\\ | \ 문자 포함 |
\u16진수 | 16진수 유니코드에 해당하는 문자 포함 |
\t | 출력 시 탭만큼 띄움 |
\n | 출력 시 줄바꿈(라인피드) |
\r | 출력 시 캐리지 리턴 |
2.7 자동 타입 변환
자동 타입 변환(promotion)은 자동으로 타입 변환이 일어나는 것을 말한다. 값의 허용 범위가 작은 타입이 허용 범위가 큰 타입으로 대입될 때 발생한다.
기본 타입을 허용 범위 순으로 나열하면 다음과 같다.
byte < short, char < int < long < float < double
2.8 강제 타입 변환
큰 허용 범위 타입을 작은 허용 범위 타입으로 쪼개어서 저장하는 것을 강제 타입 변환(casting, 캐스팅)이라고 한다. 강제 타입 변환은 캐스팅 연산자로 괄호 ()를 사용하여 괄호 안에 쪼개는 타입 단위를 넣는다.
강제 타입의 목적은 원래 값이 유지되면서 타입만 바꾸는 것이다. 그렇기 때문에 작은 허용 범위 타입에 저장될 수 있는 값을 가지고 강제 타입 변환을 해야 한다. 큰 허용 범위 타입의 값을 강제 타입 변환했을 때 작은 허용 범위 타입으로 변환된 값이 작은 허용 범위 타입의 범위를 넘어가게 된다면 값이 손상될 수 있다.
2.9 연산식에서 자동 타입 변환
자바는 실행 성능을 향상시키기 위해 자바 컴파일러가 컴파일 단계에서 연산식을 미리 연산해서 결과를 도출해내고 해당 변수에 결과를 저장하도록 바이트코드를 생성한다. 하지만 변수가 피연산자로 사용되면 실행 시 연산을 수행한다.
정수 타입 변수가 산술 연산식에서 피연산자로 사용되면 byte, short 타입의 변수는 int 타입으로 자동 타입 변환이 되어 연산을 수행한다. 따라서 연산 결과는 int 타입 변수에 저장해야 한다. int 타입보다 큰 long 타입이 피연산자로 사용되면 다른 피연산자는 long 타입으로 변환되어 연산을 수행한다. 따라서 연산 결과는 long 타입 변수에 저장해야 한다.
실수가 연산될 때 피연산자가 동일한 실수 타입이라면 해당 타입으로 연산된다. 하지만 피연산자 중 하나가 double 타입이면 다른 피연산자도 double 타입으로 변환되어 연산되고, 연산 결과 또한 double 타입이 된다. double 타입와 다른 타입으로 연산해야 한다면 double 타입을 해당 타입으로 강제 변환하고 연산을 수행하면 된다.
2.10 문자열을 기본 타입으로 변환
변환 타입 | 사용 예 |
String → byte | String str = "10"; byte value = Byte.parseByte(str); |
String → short | String str = "200"; short value = Short.parseShort(str); |
String → int | String str = "300000"; int value = Int.parseInt(str); |
String → long | String str = "40000000000"; long value = Long.parseLong(str); |
String → float | String str = "12.345"; float value = Float.parseFloat(str); |
String → double | String str = "12.345"; double value = Double.parseDouble(str); |
String → boolean | String str = "true"; boolean value = Boolean.parseBoolean(str); |
기본 타입의 값을 문자열을 변경하는 경우는 아래와 같이 이용하면 된다.
String str = Stirng.valueOf(기본타입값);
2.11 변수 사용 범위
main() 메소드 블록에는 다른 중괄호 {} 블록들이 작성될 수 있다. 조건문, 반복문 등이 가질 수 있는 중괄호 {} 블록 내에서 선언된 변수는 해당 중괄호 {} 블록 내에서만 사용이 가능하고 밖에서는 사용할 수 없다.
- 지역 변수: 메서드 내에서 선언된 변수
- 전역 변수: 클래스 내에서 선언된 변수 (필드)
- 블록 범위: 중괄호 {} 내에서만 유효
2.12 콘솔로 변수값 출력
자바에서는 다양한 출력 방법을 사용할 수 있다.
System.out.println(리터럴-또는-변수);
// System. : 시스템으로
// out. : 출력하는데
// println(리터럴-또는-변수); : 괄호 안의 내용을 출력하고 행을 바꿔라
메소드 | 의미 |
println(내용); | 괄호 안의 내용을 출력하고 행을 바꿔라. |
print(내용); | 괄호 안의 내용을 출력하고 행은 바꾸지 말아라. |
printf("형식문자열", 값1, 값2, ···); | 형식 문자열에 맞추어 뒤의 값을 출력해라. |
printf() 형식 문자열은 다음과 같은 포맷으로 작성한다.
%는 형식 문자열의 시작을 뜻하고, conversion에는 제공되는 값의 타입에 따라 d(정수), f(실수), s(문자열)가 온다.
형식화된 문자열 | 설명 | 출력 형태 | |
정수 | %d %6d %-6d %06d |
정수 6자리 정수. 왼쪽 빈자리 공백 6자리 정수. 오른쪽 빈자리 공백 6자리 정수. 왼쪽 빈자리 0 채움 |
123 _ _ _123 123 _ _ _ 000123 |
실수 | %10.2f %-10.2f %010.2f |
정수 7자리 + 소수점 + 소수2자리. 왼쪽 빈자리 공백 정수 7자리 + 소수점 + 소수2자리. 오른쪽 빈자리 공백 정수 7자리 + 소수점 + 소수2자리. 왼쪽 빈자리 0 채움 |
_ _ _ _ 123.45 123.45 _ _ _ _ 0000123.45 |
문자열 | %s %6s %-6s |
문자열 6자리 문자열. 왼쪽 문자열 공백. 6자리 문자열. 오른쪽 문자열 공백. |
abc _ _ _abc abc _ _ _ |
특수 문자 | \t \n %% |
탭(tab) 줄바꿈 % |
% |
2.13 키보드 입력 데이터를 변수에 저장
키보드로부터 입력된 데이터를 읽고 변수에 저장하는 가장 쉬운 방법은 Scanner를 사용하는 것이다. Scanner 타입 변수를 선언하고, 대입 연산자 =를 사용해서 new 연산자로 생성한 Scanner 객체를 변수에 대입힌다.
그리고 다음과 같이 scanner.nextLine()을 실행하면 키보드로 입력된 내용을 문자열로 읽고 좌측 String 변수에 저장한다.
scanner.nextLine()은 Enter 키가 입력되기 전까지 블로킹(대기) 상태가 되며, Enter 키가 입력되면 지금까지 입력된 모든 내용을 문자열로 읽는다.
'JAVA 개념 > Part 01; 자바 언어 기초' 카테고리의 다른 글
[이것이 자바다] CHAPTER 04. 조건문과 반복문 (0) | 2024.06.15 |
---|---|
[이것이 자바다] Chapter 03. 연산자 │ 개념 (0) | 2024.06.05 |
[이것이 자바다] CHAPTER 01. 자바 시작하기 (0) | 2024.05.31 |