Java - 기본형 & 참조형

develkkm·2025년 9월 10일

0부터 시작하는 Java

목록 보기
11/27

기본형과 참조형


기본형(Primitive Type) vs 참조형(Reference Type)

Java의 변수 타입은 크게 두 가지로 나눌 수 있다.

  • 기본형(Primitive Type): int, long, double, boolean처럼 실제 값을 직접 변수에 저장한다.
  • 참조형(Reference Type): String, 배열(int[]), 클래스(Student student1)처럼 객체가 위치한 메모리 주소(참조값)를 저장한다.

즉,

  • 기본형 변수에는 사용할 값 자체가 들어있고,
  • 참조형 변수에는 객체가 있는 위치(주소)가 들어있다.
int a = 10;          // 변수 안에 값 10이 직접 저장됨
Student s = new Student(); // 변수 안에는 Student 객체의 참조값만 저장됨

기본형과 참조형의 계산 차이

  • 기본형은 값을 직접 가지고 있으므로 연산이 가능하다.
  • 참조형은 주소만 가지고 있으므로 연산할 수 없다.
int a = 10, b = 20;
int sum = a + b; // OK

Student s1 = new Student();
Student s2 = new Student();
s1 + s2; // 오류 발생!

단, 참조형 안에 있는 기본형 멤버 변수를 꺼내면 연산할 수 있다.

s1.grade = 100;
s2.grade = 90;
int sum = s1.grade + s2.grade; // OK

변수 대입과 복사

Java의 대원칙: 항상 변수에 들어있는 값을 복사해서 대입한다.

  • 기본형은 값을 직접 복사한다.
  • 참조형은 참조값(주소)을 복사한다.

기본형 대입

int a = 10;
int b = a;

a = 20;
System.out.println("a = " + a); // 20
System.out.println("b = " + b); // 10

ab는 값 자체를 따로 가지고 있으므로 영향을 주지 않는다.


참조형 대입

Data dataA = new Data();
dataA.value = 10;

Data dataB = dataA; // 참조값 복사
  • dataAdataB는 같은 객체를 가리키게 된다.
  • 따라서 하나를 수정하면 다른 쪽도 함께 변경된다.
dataA.value = 20;
System.out.println(dataB.value); // 20

dataB.value = 30;
System.out.println(dataA.value); // 30

메서드 호출과 값 전달

메서드 호출 시에도 동일하게 값이 복사되어 전달된다.

기본형 전달

public static void main(String[] args) {
    int a = 10;
    changePrimitive(a);
    System.out.println("a = " + a); // 10
}

static void changePrimitive(int x) {
    x = 20;
}
  • a의 값 10이 복사되어 x에 전달된다.
  • x를 바꿔도 a에는 영향이 없다.

참조형 전달

public static void main(String[] args) {
    Data dataA = new Data();
    dataA.value = 10;
    changeReference(dataA);
    System.out.println("dataA.value = " + dataA.value); // 20
}

static void changeReference(Data dataX) {
    dataX.value = 20;
}
  • dataA의 참조값이 dataX에 복사된다.
  • 같은 객체를 가리키므로, dataX를 통해 변경하면 dataA도 영향을 받는다.

변수와 초기화

멤버 변수(필드)

  • 클래스에 선언된 변수
  • 객체 생성 시 자동 초기화
    • 숫자 → 0
    • boolean → false
    • 참조형 → null
class InitData {
    int value1;      // 자동 초기화 → 0
    int value2 = 10; // 명시적 초기화 → 10
}

지역 변수

  • 메서드 내부에서 선언된 변수
  • 자동 초기화되지 않음 → 반드시 직접 초기화 필요
public static void main(String[] args) {
    int x; // 초기화하지 않으면 사용 불가
    x = 5;
}

null

참조형 변수에는 객체의 위치가 들어가야 하지만, 아직 참조할 객체가 없을 때는 null을 넣을 수 있다.

Data data = null;
System.out.println(data); // null
  • null은 "아직 아무 객체도 참조하지 않는다"는 의미다.
  • 따라서 null 자체는 안전하게 변수에 저장될 수 있다.

NullPointerException (NPE)

하지만 null에 대해 객체처럼 접근하려 하면 문제가 발생한다.

Data data = null;
data.value = 10; // NPE 발생!
  • null은 실제 객체가 아니므로 그 안에 필드나 메서드가 존재하지 않는다.
  • 따라서 . (dot) 연산을 하면 NullPointerException이 발생한다.

실무에서 자주 발생하는 오류이므로, 항상 null 체크를 습관화해야 한다.


가비지 컬렉터(GC)

Java는 메모리 관리를 자동으로 수행한다.

  • 더 이상 참조되지 않는 객체는 가비지(쓰레기)로 분류된다.
  • 가비지 컬렉터(Garbage Collector, GC)가 이를 탐지해 메모리에서 제거한다.
Data data1 = new Data();
data1 = null; // 기존 객체는 참조하는 변수가 없음 → GC 대상

즉, 개발자가 직접 free() 같은 메모리 해제를 하지 않아도 된다.
하지만 null을 잘못 다루면 GC가 처리하기 전에 NPE를 만나는 경우가 많다.

profile
알던것을 더 확실하게

0개의 댓글