'자바의 정석 3rd Edition'을 공부하며 정리한 내용입니다.
2. 변수의 타입
- 자료형(data tpye): 값(data)의 종류(type)에 따라 값이 저장될 공간의 크기와 저장형식을 정의한 것
- 종류: 문자형(char), 정수형(byte, short,int, long), 실수형(float, double) 등
- 변수를 선언할 때는 저장하려는 값의 특성을 고려해 가장 알맞은 자료형을 변수의 타입으로 선택
기본형과 참조형
- 기본형 변수: 실제 값(data)를 저장
- 종류: 논리형(boolean), 문자형(char), 정수형(byte, short, int, long), 실수형(float, double)
- 참조형 변수: 어떤 값이 저장되어 있는 주소(memory address)를 값으로 가짐
- 메모리 주소: 메모리에는 1 byte단위로 일련번호가 붙어있는데, 이 번호를 메모리 주소 또는 주소라고 함. 객체의 주소는 객체가 저장된 메모리 주소를 의미
- 종류: 8개의 기본형을 제외한 나머지 타임
- 참조형 변수를 선언할 때는 변수의 타입으로 클래스의 이름을 사용. 클래스의 이름이 참조변수의 타입이 됨. 새로운 클래스를 작성한다는 것은 새로운 참조형 변수를 추가하는 것
- 참조형 변수 선언 방법: 기본형 변수와 같이 변수 이름 앞에 타입을 적어주는데 참조변수의 타입은 클래스의 이름
클래스이름 변수이름;
- 참조 변수는 null 또는 객체의 주소를 값으로 가지며 참조변수의 초기화는 아래와 같음
Date today = new Date()
- 자바는 참조형 변수 간의 연산을 할 수 없으므로 실제 연산에 사용되는 것은 모두 기본형 변수
참고) 자료형(data type) vs 타입(type)
- 기본형은 저장할 값(data)의 종류에 따라 구분되므로 기본형의 종류를 얘기할 때는 '자료형(data type)'이라는 용어를 사용
- 참조형은 항상 '객체의 주소(4 byte 정수)'를 저장하므로 값(data)이 아닌, 객체의 종류에 의해 구분되므로 참조형 변수의 종류를 구분할 때는 '타입(type)'이라는 용어를 사용
- 타입(type)이 자료형(data type)을 포함하는 보다 넓은 의미의 용어이므로 굳이 구분하지 않아도 됨
2.1 기본형(primitive type)
종류/크기 | 1 byte | 2 byte | 4 byte | 8 byte |
---|
논리형 | boolean | | | |
문자형 | | char | | |
정수형 | byte | short | int | long |
실수형 | | | float | double |
- 논리형(boolean)
- true와 false 중 하나의 값을 가지며 조건식과 논리적 계산에 사용
- 다른 기본형과의 연산이 불가능. boolean을 제외한 나머지 7개의 기본형은 서로 연산과 변환이 가능
- 문자형(char)
- 문자를 저장하는데 사용되며 변수에 하나의 문자만 저장할 수 있음
- 내부적으로 정수(유니코드)로 저장하기 때문에 정수형과 다르지 않으며, 정수형 또는 실수형과 연산도 가능
- 정수형(byte, short, int, long)
- 주로 int를 사용(CPU가 가장 효율적으로 처리할 수 있는 타입). byte는 이진 데이터를 다룰 때 사용되며, short는 C언어와의 호환을 위해 추가됨
- 효율적인 실행보다 메모리를 절약하려면 byte나 short를 선택
- int 타입은 대략 10자리 수의 값을 저장할 수 있음. 7~9자리의 수를 계산할 때는 넉넉하게 long 타입(약 19자리)로 선언하는 것이 좋음
- 실수형(float, double)
- 실수를 저장하는데 사용. 주로 double를 사용함
- 정수형과 저장형식이 달라서 같은 크기라도 훨씬 큰 값을 표현할 수 있으나 오차가 발생할 수 있다는 단점이 있음. 따라서 정밀도가 중요!
- 정밀도가 높을수록 발생할 수 있는 오차의 범위가 줄어듦. float이 정밀도는 7자리인데, 이것은 10진수로 7자리의 수를 오차없이 저장할 수 있다는 것을 의미
- float는 큰 값을 저장할 수 있지만, 정밀도가 7자리 밖에 되지 않으므로 높은 정밀도가 필요한 경우에는 변수 타입으로 double을 선택
2.2 상수와 리터럴(constant & literal)
1. 상수(constant)
- 값을 저장할 수 있는 공간 but 한 번 값을 저장하면 다른 값으로 변경 불가
- 상수 선언 방법은 변수와 동일. 변수의 타입 앞에 키워드 'final'을 붙여주면 됨
final int MAX_SPEED = 10
- 상수는 반드시 선언과 동시에 초기화해야 하며, 그 후부터는 상수의 값을 변경할 수 없음
final int MAX_SPEED;
final int MAX_VALUE = 100;
MAX_VALUE = 200;
- 상수의 이름은 모두 대문자로 하는 관례. 여러 단어로 이루어져 있는 경우 '_'로 구분
2. 리터럴(literal)
- 12, 133, 3.14, 'A'와 같은 값들이 '상수'인데, 프로그래밍에서는 상수를 '값을 한 번 저장하면 변경할 수 없는 저장공간'으로 정의하였기 때문에 이와 구분해 상수를 다른 이름으로 불러야 했음
- 따라서 상수 대신 리터럴이라는 용어를 사용
변수(variabl) 하나의 값을 저장하기 위한 공간
상수(costant) 값을 한번만 저장할 수 있는 공간
리터럴(literal) 그 자체로 값을 의미하는 것
3. 상수가 필요한 이유
int triangleArea = (20 *10) / 2 ;
int rectangleArea = 20 * 10 ;
- 위 코드에서 10과 20이 아닌 다른 값을 이용해 결과를 얻고 싶다면 여러 곳을 수정해야 함
final int WIDTH = 20;
final int HEIGHT = 10
int triangleArea = (WIDTH *HEIGHT) / 2 ;
int rectangleArea = WIDTH * HEIGHT ;
-
이전 코드에 비해 면적을 구하는 공식의 의미가 명확해짐
-
다른 값으로 계산할 경우에도 여러 곳을 수정할 필요없이 상수의 초기화만 다른 값으로 해주면 됨
-
상수는 리터럴에 '의미있는 이름'을 붙여 코드의 이해와 수정을 쉽게 만듦
4. 리터럴의 타입과 접미사
종류 | 접미사 |
---|
논리형 | 없음 |
정수형 | L |
실수형 | f, d |
문자형 | 없음 |
문자열 | 없음 |
- 정수형과 실수형에는 여러 타입이 존재하므로 리터럴에 접미사를 붙여 타입을 구분
- 정수형인 경우, long 타입의 리터럴에 접미사 'l' 또는 'L'을 붙이고, 접미사가 없으면 int 타입의 리터럴
- byte와 short 타입의 리터럴은 별도로 존재하지 않으며 byte와 short 타입의 변수에 값을 저장할 때는 int 타입의 리터럴을 사용
- 10진수 외에도 2, 8, 16진수로 표현된 리터럴을 변수에 저장할 수 있으며, 16진수라는 것을 표시하기 위해 리터럴 앞에 접투사 '0x' 또는 '0X'를, 8진수의 경우에는 '0'을 붙임
- 실수형에서는 float 타입의 리터럴에 접미사 'f' 또는 'F'를 붙이고, double 타입의 리터럴에는 접미사 'd' 또는 'D'를 붙임
- 정수형에서는 int가 기본 자료형인 것처럼 실수형에서는 double이 기본 자료형이라서 접미사 'd'는 생략이 가능
- 리터럴에 소수점이나 10의 제곱을 나타내는 기호 E 또는 e, 그리고 접미사 f,F,d,D를 포함하고 있으면 실수형 리터럴로 간주
5. 타입의 불일치
- 리터럴의 타입은 저장될 변수의 타입과 일치하는 것이 일반적이지만, 타입이 달라도 저장범위가 넓은 타입에 좁은 타입의 값을 저장하는 것은 혀용
int i = 'A'
long l = 123;
double d = 3.14f
- 리터럴의 값이 변수의 타입의 범위를 넘어서거나, 리터럴의 타입이 변수의 타입보다 저장범위가 넓으면 컴파일 에러 발생
int i = 0x123456789;
float f= 3.14
- byte와 short 타입의 리터럴은 따로 존재하지 않으므로 int 타입의 리터럴을 사용. 단, short 타입의 변수가 저장할 수 있는 범위에 속한 것이어야 함
byte b = 65;
short s = 0ㅌ1234;
6. 문자 리터럴과 문자열 리터럴
- 문자 리터럴: 'A'와 같이 작은 따옴표로 문자 하나를 감싼 것
- 문자열 리터럴: 두 문자 이상을 큰 따옴표로 감싼 것
char ch = 'J' ;
String name = "JAVA"
- char 타입의 변수는 단 하나의 문자만 저장. 문자열을 저장하기 위해서는 String 타입을 사용
- 문자열 리터럴은 ""안에 아무런 문자도 넣지 않는 것을 허용 => 빈 문자열(empty string)
- 문자 리터럴은 반드시 ''안에 하나의 문자가 있어야 함
- 원래 String은 클래스이므로 객체를 생성하는 연산자 new를 사용해야 하지만 위와 같은 표현도 허용
String name = "JA" + "VA";
String str = name + 8.0;
- 덧셈 연산자를 이용해 문자열을 결합할 수 있음
- 덧셈 연산자는 피연산자가 모두 숫자일 때는 두 수를 더하지만, 피연산자 중 어느 한쪽이 String이면 나머지 한 쪽을 먼저 String으로 변환한 다음 두 String을 결합
- 기본형과 참조형 구별 없이 어떤 타입의 변수도 문자열과 덧셈연산을 수행하면 그 결과는 문자열이 됨
- 덧셈 연산자는 왼쪽에서 오른쪽의 방향으로 연산을 수행하기 때문에 결합순서에 따라 결과가 달라짐
- 기본형 타입의 값을 문자열로 변환할 때 빈 문자열("")을 더해주면 됨
2.3 형식화된 출력 - printf()
println()
은 사용하기엔 편하지만 변수의 값을 그대로 출력하므로, 값을 변환하지 않고는 다른 형식으로 출력할 수 없음
printf()
는 '지시자(specifier)'를 통해 변수의 값을 여러 가지 형식으로 변환하여 출력
- 지시자(specifier)은 값을 어떻게 출력할 것인지를 지정해주는 역할
- 정수형 변수에 저장된 값을 10진 정수로 출력할 때는 지시자 '%d'를 사용
- 변수의 값을 지정된 형식으로 변환해서 지시자 대신 넣음
System.out.printf("age: %d", age);
-> System.out.printf("age: %d", 14);
-> System.out.printf("age: 14");
- 출력하려는 값이 2개라면, 지시자도 2개를 사용해야하며 출력될 값과 지시자의 순서는 일치해야 함 (개수 제한 없음)
printf()
는 println()
과 다르게 출력 후 줄바꿈을 하지 않음. 줄바꿈을 하려면 지시자 '%n'을 넣어줘야 함
- 자주 사용되는 지시자 (지시자 전체 목록은 Java API에서 Formatter 클래스를 찾으면 됨)
지시자 | 설명 |
---|
%b | 불리언(boolean) 형식으로 출력 |
%d | 10진(decimal) 정수의 형식으로 출력. C언어와 다르게 char 타입은 사용 불가 |
%o | 8진(octal) 정수의 형식으로 출력 |
%x, %X | 16진(hexa-decimal) 정수의 형식으로 출력 |
%f | 부동 소수점(floating-point)의 형식으로 출력. 소수점 아래 6자리까지만 출력. 자리수 지정 가능 |
%e, %E | 지수(exponent) 표현식의 형식으로 출력 |
%c | 문자(character)로 출력 |
%s | 문자열(string)로 출력 |
- 10진수를 2진수로 출력해주는 지시자는 없기 때문에, 정수를 2진 문자열로 변환해주는
Integer.toBinarySting(int i)
를 사용해야 함
2.4 화면에서 입력받기 - Scanner
- Scanner 클래스를 사용하려면 한 문장을 추가해줘야 함
import java.util.*;
Scanner scanner = new Scanner(System.in);
nextLine()
이라는 메서드를 호출하면, 입력 대기 상태에 있다가 입력을 마치고 Enter를 누르면 입력한 내용이 문자열로 반환됨
String input = scanner.nextLine();
int num = Integer.parseInt(input);
- Scanner 클래스에는
nextInt()
, nextFloat()
와 같이 변환없이 숫자로 바로 입력받을 수 있는 메서드가 있고, 이 메서드를 사용하면 문자열을 숫자로 변환해주지 않아도 됨
int num = scanner.nextInt();
- 위의 메서드는 화면에서 연속적으로 값을 입력받아 사용하기 어렵기 때문에 모든 값을
nextLine()
으로 입력받아 적절히 변환하는 것이 더 나음
- 숫자가 아닌 문자 또는 기호를 입력하면, 입력받은 문자열을 숫자로 변환하는 과정인
Integer.parseInt()
에서 에러가 발생. 공백을 입력하지 않도록 주의!