본문으로 건너뛰기

Ch 2.4 기본형 (Primitive Types)

자바가 제공하는 8가지 기본 자료형은 크게 논리형, 문자형, 정수형, 실수형의 4가지 범주로 나눌 수 있습니다. 이 섹션에서는 각 유형의 특징과 활용법을 자세히 살펴봅니다.

기본형 메모리 크기 시각화

1 byte  │ boolean │ byte    │
2 bytes │ char │ short │
4 bytes │ int │ float │
8 bytes │ long │ double │

1 byte = 8 bits
bit는 0 또는 1 두 가지 상태만 가짐

1. 논리형: boolean

논리형은 truefalse 두 가지 값만을 가질 수 있습니다. 기본값(default value)은 false입니다. 논리형 변수는 대답(yes/no), 스위치(on/off), 조건(참/거짓) 등의 논리적 상태를 표현하는 데 사용됩니다.

노트

JVM 명세상 boolean은 int(4 bytes)로 처리되는 경우가 많지만, 배열 등에서는 1 byte로 취급됩니다. 정확한 크기는 JVM 구현에 따라 다릅니다.

public class BooleanExample {
public static void main(String[] args) {
boolean isPowerOn = true;
boolean hasPermission = false;
boolean isAdult = (20 >= 18); // 조건식 결과를 바로 대입
boolean isEmpty = "".isEmpty(); // 메서드 결과도 대입 가능

System.out.println("전원 상태: " + isPowerOn);
System.out.println("권한 보유: " + hasPermission);
System.out.println("성인 여부: " + isAdult);
System.out.println("빈 문자열: " + isEmpty);

// 논리 연산
System.out.println("AND: " + (isPowerOn && hasPermission)); // false
System.out.println("OR: " + (isPowerOn || hasPermission)); // true
System.out.println("NOT: " + (!isPowerOn)); // false
}
}

출력:

전원 상태: true
권한 보유: false
성인 여부: true
빈 문자열: true
AND: false
OR: true
NOT: false

2. 문자형: char

문자형은 단 하나의 문자를 저장하는 데 사용되며, 작은따옴표(')로 문자를 감싸서 할당해야 합니다. 내부적으로는 문자에 해당하는 유니코드(Unicode) 정수값 이 저장됩니다. 자바의 char는 2 bytes(16bit)로 0~65,535 범위의 유니코드를 지원합니다.

public class CharExample {
public static void main(String[] args) {
// 다양한 char 선언 방법 (모두 'A')
char ch1 = 'A'; // 문자 직접 지정
char ch2 = 65; // 10진수 정수로 지정 (A의 유니코드)
char ch3 = '\u0041'; // 유니코드 16진수 표기법

System.out.println(ch1); // A
System.out.println(ch2); // A
System.out.println(ch3); // A

// char 산술 연산
char next = (char)('A' + 1); // 'A'(65) + 1 = 66 = 'B'
System.out.println(next); // B

// 알파벳 순회
for (char c = 'A'; c <= 'Z'; c++) {
System.out.print(c + " ");
}
System.out.println();
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

// char → int (유니코드 값 확인)
int unicodeValue = 'A';
System.out.println("A의 유니코드: " + unicodeValue); // 65

// 한글도 char로 저장 가능 (유니코드)
char korean = '가';
System.out.println("가의 유니코드: " + (int)korean); // 44032
}
}

char 이스케이프 시퀀스

표기의미유니코드
'\n'줄바꿈 (Line Feed)\u000A
'\t'탭 (Tab)\u0009
'\r'캐리지 리턴\u000D
'\\'백슬래시\u005C
'\''작은따옴표\u0027
'\"'큰따옴표\u0022

3. 정수형: byte

byte 는 1 byte(8 bits)로 -128 ~ 127 범위의 정수를 저장합니다. 작은 범위이지만, 파일 I/O나 네트워크 통신에서 바이너리 데이터를 다룰 때 자주 사용됩니다.

public class ByteExample {
public static void main(String[] args) {
byte min = Byte.MIN_VALUE; // -128
byte max = Byte.MAX_VALUE; // 127

System.out.println("byte 최소값: " + min);
System.out.println("byte 최대값: " + max);

// 실전: 파일에서 1 byte씩 읽기 (의사 코드)
byte[] fileData = {72, 101, 108, 108, 111}; // "Hello" ASCII
for (byte b : fileData) {
System.out.print((char) b); // H, e, l, l, o
}
System.out.println();

// 오버플로우 확인
byte overflow = 127;
overflow++; // 127 + 1 = -128 (오버플로우!)
System.out.println("127 + 1 = " + overflow); // -128
}
}

byte의 실전 사용 사례: 이미지 픽셀 데이터 처리, 파일 읽기/쓰기 스트림, 네트워크 소켓 데이터 전송 시 주로 byte[] 배열 형태로 사용합니다.

4. 정수형: short

short 는 2 bytes(16 bits)로 -32,768 ~ 32,767 범위를 저장합니다. int보다 범위가 작아 메모리를 절약할 수 있지만, 자바의 연산은 기본적으로 int 단위로 처리되기 때문에 short를 사용해도 연산 시 int로 변환됩니다.

public class ShortExample {
public static void main(String[] args) {
short min = Short.MIN_VALUE; // -32768
short max = Short.MAX_VALUE; // 32767

System.out.println("short 최소값: " + min);
System.out.println("short 최대값: " + max);

// short 연산 시 주의: 결과는 int
short a = 100;
short b = 200;
// short c = a + b; // 에러! a+b의 결과는 int
int c = a + b; // 정상
short d = (short)(a + b); // 강제 형변환으로 short에 담기
System.out.println("100 + 200 = " + c); // 300
}
}
노트

실무에서는 short를 거의 사용하지 않습니다. 메모리 절약 효과보다 int와의 형변환 번거로움이 더 크기 때문입니다. 임베디드 시스템이나 C 라이브러리 연동 시에는 가끔 사용됩니다.

5. 정수형: int (가장 중요!)

int 는 4 bytes(32 bits)로 약 -21억 ~ 21억 범위를 저장합니다. 자바에서 정수형 기본 타입 으로, 접미사 없는 정수 리터럴은 모두 int로 처리됩니다. 가장 자주 사용되는 타입입니다.

public class IntExample {
public static void main(String[] args) {
int min = Integer.MIN_VALUE; // -2,147,483,648
int max = Integer.MAX_VALUE; // 2,147,483,647

System.out.println("int 최소값: " + min);
System.out.println("int 최대값: " + max);
System.out.printf("int 최대값 (2^31 - 1): %,d%n", max); // 2,147,483,647

// 일반적인 int 사용 예
int year = 2024;
int dayOfYear = 365;
int totalMinutes = dayOfYear * 24 * 60;
System.out.println("1년의 총 분: " + totalMinutes); // 525600

// 비트 표현 확인
System.out.println("10의 2진수: " + Integer.toBinaryString(10)); // 1010
System.out.println("255의 16진수: " + Integer.toHexString(255)); // ff
System.out.println("8의 8진수: " + Integer.toOctalString(8)); // 10

// Integer 유틸리티 메서드
System.out.println("최대값 비교: " + Integer.max(100, 200)); // 200
System.out.println("최소값 비교: " + Integer.min(100, 200)); // 100
System.out.println("문자열 → int: " + Integer.parseInt("42")); // 42
}
}

6. 정수형: long

long 은 8 bytes(64 bits)로 약 -900경 ~ 900경 범위를 저장합니다. int로 표현할 수 없는 큰 수를 다룰 때 사용합니다. long 리터럴에는 반드시 L 또는 l 접미사를 붙여야 합니다(대문자 L 권장).

public class LongExample {
public static void main(String[] args) {
long min = Long.MIN_VALUE; // -9,223,372,036,854,775,808
long max = Long.MAX_VALUE; // 9,223,372,036,854,775,807

System.out.println("long 최소값: " + min);
System.out.println("long 최대값: " + max);

// 실전: 타임스탬프 (밀리초 단위)
long currentTime = System.currentTimeMillis(); // 1970년 1월 1일부터 현재까지 밀리초
System.out.println("현재 타임스탬프(ms): " + currentTime);

// 파일 크기 (바이트 단위)
long fileSize = 4_294_967_296L; // 4GB = 4 * 1024^3
System.out.printf("파일 크기: %,d bytes%n", fileSize);

// 우주 거리 계산
long lightYearInKm = 9_461_000_000_000L; // 1광년을 km로
long distanceToAndromeda = lightYearInKm * 2_537_000L; // 안드로메다 거리
System.out.printf("안드로메다까지: %e km%n", (double)distanceToAndromeda);

// int 범위 초과 확인
// int overflow = 3_000_000_000; // 에러! int 최대값 초과
long safe = 3_000_000_000L; // long이면 OK
System.out.println("30억: " + safe);
}
}

타임스탬프, 파일 크기, 인구 수, 금융 거래 금액 등 큰 수를 다룰 때는 long을 사용하세요. 특히 System.currentTimeMillis()의 반환 타입이 long입니다.

7. 실수형: float

float 은 4 bytes(32 bits)로 소수점 이하 약 7자리 정밀도를 제공합니다. float 리터럴에는 반드시 f 또는 F 접미사를 붙여야 합니다.

public class FloatExample {
public static void main(String[] args) {
float min = Float.MIN_VALUE; // 가장 작은 양수 값
float max = Float.MAX_VALUE; // 최대값

System.out.println("float 최소 양수: " + min); // 1.4E-45
System.out.println("float 최대값: " + max); // 3.4028235E38

float pi = 3.141592f;
System.out.println("float PI: " + pi); // 3.141592

// 정밀도 문제 확인 (약 7자리)
float precise = 1.23456789f;
System.out.println("정밀도 7자리: " + precise); // 1.2345679 (8번째 자리 반올림)

// 부동소수점 오차
float result = 0.1f + 0.2f;
System.out.println("0.1 + 0.2 = " + result); // 0.3 이 아닐 수 있음!
}
}
경고

부동소수점 정밀도 문제: float과 double은 이진수로 소수를 표현하기 때문에 일부 값(0.1, 0.3 등)은 정확히 표현되지 않습니다. 정확한 소수 계산이 필요하면 BigDecimal을 사용하세요.

8. 실수형: double (기본 실수형)

double 은 8 bytes(64 bits)로 소수점 이하 약 15자리 정밀도를 제공합니다. 접미사 없는 소수 리터럴은 기본적으로 double로 처리됩니다. 가장 많이 사용되는 실수형 입니다.

public class DoubleExample {
public static void main(String[] args) {
double min = Double.MIN_VALUE; // 가장 작은 양수 값
double max = Double.MAX_VALUE; // 최대값

System.out.println("double 최소 양수: " + min); // 4.9E-324
System.out.println("double 최대값: " + max); // 1.7976931348623157E308

double pi = 3.14159265358979323846;
System.out.printf("PI (15자리): %.15f%n", pi); // 3.141592653589793

// 특수값
System.out.println("양의 무한대: " + Double.POSITIVE_INFINITY); // Infinity
System.out.println("음의 무한대: " + Double.NEGATIVE_INFINITY); // -Infinity
System.out.println("숫자 아님: " + Double.NaN); // NaN
System.out.println("0.0 / 0.0 = " + (0.0 / 0.0)); // NaN

// BigDecimal - 정확한 소수 계산이 필요한 경우
java.math.BigDecimal bd1 = new java.math.BigDecimal("0.1");
java.math.BigDecimal bd2 = new java.math.BigDecimal("0.2");
java.math.BigDecimal sum = bd1.add(bd2);
System.out.println("BigDecimal 0.1 + 0.2 = " + sum); // 0.3 (정확!)
}
}

금융 계산(은행, 쇼핑몰 결제 등)에서는 double 대신 BigDecimal 을 사용해야 합니다. double의 부동소수점 오차가 금액 계산에서 치명적인 버그를 일으킬 수 있습니다.

9. 각 기본형 최대/최소값 한눈에 보기

public class AllLimits {
public static void main(String[] args) {
System.out.println("=== 정수형 범위 ===");
System.out.printf("byte: %d ~ %d%n", Byte.MIN_VALUE, Byte.MAX_VALUE);
System.out.printf("short: %d ~ %d%n", Short.MIN_VALUE, Short.MAX_VALUE);
System.out.printf("int: %,d ~ %,d%n", Integer.MIN_VALUE, Integer.MAX_VALUE);
System.out.printf("long: %d ~ %d%n", Long.MIN_VALUE, Long.MAX_VALUE);

System.out.println("\n=== 실수형 범위 ===");
System.out.printf("float: %e ~ %e (정밀도: %d자리)%n",
Float.MIN_VALUE, Float.MAX_VALUE, 7);
System.out.printf("double: %e ~ %e (정밀도: %d자리)%n",
Double.MIN_VALUE, Double.MAX_VALUE, 15);

System.out.println("\n=== 기타 ===");
System.out.println("char 최소: " + (int)Character.MIN_VALUE); // 0
System.out.println("char 최대: " + (int)Character.MAX_VALUE); // 65535
}
}

출력:

=== 정수형 범위 ===
byte: -128 ~ 127
short: -32768 ~ 32767
int: -2,147,483,648 ~ 2,147,483,647
long: -9223372036854775808 ~ 9223372036854775807

=== 실수형 범위 ===
float: 1.401298e-45 ~ 3.402823e+38 (정밀도: 7자리)
double: 4.900000e-324 ~ 1.797693e+308 (정밀도: 15자리)

=== 기타 ===
char 최소: 0
char 최대: 65535

10. 실전 예제: 타입별 오버플로우 시연

public class OverflowDemo {
public static void main(String[] args) {
System.out.println("=== byte 오버플로우 ===");
byte byteMax = Byte.MAX_VALUE; // 127
System.out.println("127: " + byteMax);
byteMax++;
System.out.println("127 + 1 = " + byteMax); // -128 (오버플로우!)

System.out.println("\n=== short 오버플로우 ===");
short shortMax = Short.MAX_VALUE; // 32767
System.out.println("32767: " + shortMax);
shortMax++;
System.out.println("32767 + 1 = " + shortMax); // -32768 (오버플로우!)

System.out.println("\n=== int 오버플로우 ===");
int intMax = Integer.MAX_VALUE; // 2147483647
System.out.printf("%,d%n", intMax);
intMax++;
System.out.printf("%,d (오버플로우!)%n", intMax); // -2147483648

System.out.println("\n=== long으로 오버플로우 방지 ===");
long safeLong = (long)Integer.MAX_VALUE + 1;
System.out.printf("%,d (정상)%n", safeLong); // 2147483648

System.out.println("\n=== float 정밀도 손실 ===");
float f = 0.1f;
float sum = 0.0f;
for (int i = 0; i < 10; i++) {
sum += f;
}
System.out.println("0.1 * 10 = " + sum); // 1.0000001 (오차 발생!)

System.out.println("\n=== double로 개선 ===");
double d = 0.1;
double dsum = 0.0;
for (int i = 0; i < 10; i++) {
dsum += d;
}
System.out.println("0.1 * 10 = " + dsum); // 1.0 (더 정확하지만 완전하지 않음)
}
}

정리

타입크기특징주요 사용처
boolean1 bit~1 bytetrue/false조건 판단, 플래그
char2 bytes유니코드 문자단일 문자 처리
byte1 byte-128~127파일/네트워크 I/O
short2 bytes-32768~32767거의 미사용
int4 bytes기본 정수형일반 정수 계산
long8 bytes매우 큰 정수타임스탬프, 파일크기
float4 bytes소수 7자리 정밀도그래픽, 물리 연산
double8 bytes소수 15자리 정밀도일반 실수 계산