Post

[JAVA] 기본형과 참조형 알아보기

기본형과 참조형

김영한의 실전 자바 기본편을 보며 정리해보는 자바의 기본형과 참조형

기본형과 참조형 썸네일

자바의 변수 데이터 타입은 크게 사용하는 값을 변수에 직접 넣을 수 있는 기본형, 객체가 저장된 메모리의 위치를 가리키는 참조값을 넣을 수 있는 참조형으로 분류할 수 있다. 자바에서 참조형을 제대로 이해하는 것은 C언어의 포인터를 이해하는 것 만큼 중요하다! 오늘은 이 기본형과 참조형에 대해서 알아보자.

Call By Value 방식

💡 중요: 자바는 Call By Value 방식을 사용한다!

기본형과 참조형에 대해 설명하기 전에, 간단하게 Call By Value 방식을 알아두고 가야 한다. 함수가 인수를 전달할 때 사용되는 방식은 Call By Value 방식과 Call By Reference 방식으로 나뉜다.

Call By Value는 함수가 인수로 전달받은 값을 복사하여 처리하는 방식이다. 변수가 가진 값을 복사하여 전달하므로 함수 내에서 값을 변경해도 원본 값은 변경되지 않는 불변성을 보장한다.

더 자세한 내용은 다음에 다뤄보기로 하고, 지금은 일단 “자바는 항상 변수의 값을 복사해서 대입한다“에 초점을 두자.

기본형

변수에 사용할 값을 직접 넣을 수 있는 데이터 타입

int, boolean, double, boolean과 같이 소문자로 되어 있고, 변수에 사용할 값을 직접 넣을 수 있는 데이터 타입을 기본형이라고 한다.

int형 변수 ba를 대입하는 코드를 살펴보자.

1
2
int a = 10;
int b = a;

위와 같은 경우를 그림으로 그려보면 다음과 같다.

기본형 메모리 구조

변수 ba를 대입하는 경우, a에 저장된 10을 복사b에 저장하게 된다.

실제적으로 변수 안에 존재하는 값만 복사한다는 것이 중요한 포인트다!

따라서 이후에 ab를 변경하더라도 각각의 변수에 영향을 끼치지 않는다.

1
2
a = 20;
b = 30;

기본형 메모리 구조2

또, 해당 값은 실제 값이기 때문에 별도의 조작 없이 바로 사용할 수 있다.

1
2
a = b + 10; // 30 + 10
b = a + 10; // 20 + 10

참조형

데이터에 접근하기 위한 참조(주소)를 저장하는 데이터 타입

Dog dog, int[] values와 같이 객체나 배열은 데이터에 접근하기 위한 주소를 저장하고 있다. 이런 참조형 변수를 통해 뭔가 하려면 참조값을 통해 해당 위치로 이동해야 한다.

동작 방식을 살펴보기 위해 Data라는 클래스를 만들어 보자.

1
2
3
public class Data {
    int value;
}

멤버 변수로 int value를 가지는 Data 클래스를 생성했다. 이제 이 클래스를 이용해서 인스턴스를 만들어 주자.

1
2
3
4
5
public static void main(String[] args) {
        Data dataA = new Data();
        dataA.value = 10;
        Data dataB = dataA; // 참조값만 B에 들어간 것
    }

참조형 메모리 구조

dataA 변수는 새로 만들어진 Data 인스턴스의 참조값을 저장하고 있다.

따라서 dataBdataA를 대입한다는 것은 dataA가 가지고 있는 참조값(Data 인스턴스의 주소)을 복사해서 저장한다는 뜻이다.

값을 복사해서 저장한다는 것은 기본형과 비슷하지만, 연산과 대입 시에 차이점이 드러나게 된다.

1
2
3
4
        // dataA 변경
        dataA.value = 20;
        // dataB 변경
        dataB.value = 30;

참조형 메모리 구조2

참조형 변수의 경우 주소값을 가지고 있기 때문에 기본형처럼 +, - 등의 연산이 불가능하다.

대신 . 키워드를 사용해 해당 참조값에 접근할 수 있다.

dataA.value = 20dataA가 가지고 있는 참조값 x001value20을 대입한다는 뜻이다. 따라서 위 그림과 같은 상태가 된다.

참조형 메모리 구조3

dataA를 대입했던 dataB는 어떨까?

dataBData 인스턴스의 주소값인 x001dataA로부터 복사해 가지고 있으므로 x001value30을 대입한다는 뜻이 된다. 마찬가지로 Data 인스턴스의 value 값이 30으로 변경된다.

기본형과 참조형의 메서드 호출

기본형의 메서드 호출

1
2
3
4
5
6
7
8
9
public static void main(String[] args) {
        int a = 10;
        changePrimitive(a);
        System.out.println(a); // 10
    }

    static void changePrimitive(int x) {
        x = 20;
    }

기본형과 참조형의 메서드 호출1

변수 a10이 저장되어 있고 changePrimitive 함수를 호출하면서 a의 값을 전달하게 된다. 전달된 값은 변수 x복사되어 저장된다.

기본형과 참조형의 메서드 호출2

10이 저장된 변수 x20을 대입한다.

x는 지역변수로 changePrimitive 함수가 종료되면 사라지게 된다.

a는 단순히 값을 복사해서 전달했으므로 값에 변동이 없다. 따라서 10을 그대로 출력하게 된다.

참조형의 메서드 호출

1
2
3
4
5
6
7
8
9
10
public static void main(String[] args) {
        Data dataA = new Data();
        dataA.value = 10;
        changeReference(dataA); // dataA의 참조값을 매개변수로 사용
        System.out.println(dataA.value); // 20
    }

    static void changeReference(Data dataX) {
        dataX.value = 20;
    }

기본형과 참조형의 메서드 호출3

dataAData 클래스를 통해 생성된 인스턴스의 참조값이 저장되어 있다.

changeReference 함수를 호출하면서 dataA가 가지고 있는 참조값을 dataX로 복사해 전달하게 된다.

즉, dataA가 가리키고 있는 주소와 dataX가 가리키고 있는 주소가 같아진다.

기본형과 참조형의 메서드 호출4

changeReference 함수 내에서 dataX.value = 20은 해당 참조값의 value20으로 대입하라는 말과 같다. 따라서 위 그림과 같이 value값을 변경하게 된다.

dataA도 같은 주소를 참조하고 있으므로 20을 출력한다.

이런 특성을 활용하면 객체의 참조 값을 전달하거나 반환해 다음과 같이 편리하게 객체의 필드 값을 설정해줄 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    public static void main(String[] args) {
        Dog dog1 = new Dog();
        initStudent(dog1, "웰시 코기", 1, 10);
        Dog dog2 = setDog("말티즈", 7, 8);
    }
    static void initDog(Dog dog, String name, int age, int weight) {
        dog.name = name;
        dog.age = age;
        dog.weight = weight;
    }

    static Dog setDog(String name, int age, int weight) {
        Dog dog = new Dog();
        dog.name = name;
        dog.age = age;
        dog.weight = weight;
        return dog;
    }

정리

  • 기본형은 똑같은 건물 두 채를 세우는 거라면 참조형은 한 건물에 입구를 두 개 만드는 것이다.
  • 자바에서 메서드의 매개변수(파라미터)는 항상 값에 의해 전달되는데, 이 값이 실제 값인지 참조 값인지에 따라 동작이 달라진다.
    • 기본형: 메서드로 기본형 데이터를 전달하면 해당 값을 복사해 전달(호출자의 변수 값에 영향X)
    • 참조형: 메서드로 참조형 데이터를 전달하면 참조 값을 복사해 전달(호출자의 객체도 변경O)
  • 참조형은 실제 인스턴스가 아니라 인스턴스를 가리키는 참조값을 복사해서 전달되는 것이기 때문에 하나의 인스턴스를 여러 곳에서 참조할 수 있다
This post is licensed under CC BY 4.0 by the author.