Journey to CS/프로그래밍 언어

[Java] 기본형(Primitive)과 참조형(Reference)의 메모리 구조 차이

Cordilog 2026. 1. 22. 15:41

자바의 변수는 데이터를 저장하는 방식에 따라 크게 두 가지로 나뉜다.

이 둘의 차이는 '데이터가 메모리의 어디에, 어떻게 저장되는가'에 있다.

1. 기본형 (Primitive Type)

C언어의 일반 변수와 같다.

메모리의 스택(Stack) 영역에 실제 값(Literal)을 직접 저장한다.

int, double, boolean 등 8가지 타입이 존재하며, null을 가질 수 없다.

종류 타입 이름 크기 저장 가능한 값의 예시 비고
논리형 boolean 1 bit* true, false 조건문(if)에서 주로 사용
문자형 char 2 byte 'A', '가', '3' 문자 하나만 저장 (작은따옴표 사용)
정수형 byte 1 byte -128 ~ 127 파일 데이터 등 매우 작은 단위
  short 2 byte -32,768 ~ 32,767 C언어 호환 외엔 잘 안 씀
  int 4 byte 약 -21억 ~ 21억 정수의 기본형 (가장 많이 씀)
  long 8 byte 매우 큰 숫자 숫자 뒤에 L을 붙여야 함 (예: 3000000000L)
실수형 float 4 byte 소수점 7자리 정도 숫자 뒤에 f를 붙여야 함 (예: 3.14f)
  double 8 byte 소수점 15자리 정도 실수의 기본형 (더 정밀함)

 

2. 참조형 (Reference Type)

 

C언어의 포인터와 유사하다.

실제 데이터(객체)는 힙(Heap) 영역에 생성되고, 변수(Stack)에는 그 데이터가 있는 힙 메모리의 주소값만 저장된다.

클래스, 배열, 인터페이스 등이 여기에 속한다.

 

클래스 (Class)

가장 일반적인 참조형.

  • String: 문자열
  • Wrapper Class: 기본형 8가지를 객체로 감싼 것. (int → Integer, double → Double)
  • 사용자 정의 클래스: 개발자가 직접 만든 클래스.
    • 예: class Student { ... } → Student 타입이 생김.

배열 (Array)

자바에서는 배열도 객체 취급을 받는다.

  • int[] arr: int형 값들이 들어있지만 배열 껍데기 자체는 참조형.
  • String[] strs: 참조형 안에 참조형이 들어있는 형태.

인터페이스 (Interface)

구현체(클래스)를 담을 수 있는 타입.

  • List<String> list = new ArrayList<>();
    • 여기서 List가 인터페이스 타입.

열거형 (Enum)

관련된 상수들을 모아놓은 타입.

  • Day today = Day.MONDAY;



💡String은 배열인가, 객체인가? 

 

1️⃣ C 언어 관점 (String = 배열)

C 언어 같은 저수준(Low-level) 언어에서는 문자열이 진짜로 문자의 배열(Character Array)이다.

  • char str[] = "Hello";
  • 메모리에 H, e, l, l, o, \0(끝을 알리는 문자)가 순서대로 저장된다.

2️⃣ Java / Python / C#  관점 (String = 객체)

현대적인 언어에서 String은 배열을 감싸고 있는 '클래스(Class)'이자 '객체(Object)'이다.

  • 내부 구현: String 객체를 뜯어보면 그 안에 데이터를 저장하기 위한 배열(byte[] 혹은 char[])이 들어있다.
  • 기능 추가: 단순한 배열 기능 외에 .substring(), .length(), .equals() 같은 편리한 기능을 제공하기 위해 객체로 감싸둔 것이다.
  • 불변성 (Immutability): 배열은 값을 바꿀 수 있지만(arr[0] = 'A'), Java의 String은 한 번 만들면 내부의 값을 바꿀 수 없다. (값이 바뀌는 것처럼 보이는 건 새로운 String 객체를 다시 만들기 때문)

📌코드 예시

기본형은 값이 복사되고, 참조형은 주소가 복사된다는 점이 중요하다.

public class TypeDifference {
    public static void main(String[] args) {
        // 1. 기본형: 값 복사
        int a = 10;
        int b = a;  // 10이라는 값이 복사됨
        b = 20;     // b를 바꿔도 a는 그대로 10

        // 2. 참조형: 주소 복사 (shallow copy)
        int[] arr1 = {10, 20};
        int[] arr2 = arr1; // 0x1234 같은 주소값이 복사됨
        
        arr2[0] = 99; // 같은 주소를 보고 있으므로
        // 결과: arr1[0]도 99로 변경되어 보임
        
        System.out.println("기본형 a: " + a); // 10
        System.out.println("참조형 arr1[0]: " + arr1[0]); // 99
    }
}
코드 의미 타입 값의 예시
arr2 배열이 있는 위치(참조) int[ ] (참조형) 0x100 (주소값)
arr2[0] 그 위치의 첫 번째 칸 int (기본형) 10 → 99 (실제 데이터)