기술스택/자바(Spring)

자바 기본 형/참조 형 (+Garbage Collection)

ys.k 2025. 2. 5. 21:04

포스팅에 앞서 내용이 틀릴 수 있습니다.
해당 부분 지적 감사히 받습니다.

 

오늘은 김영한의 실전 자바 기초 편을 결제하였다.

 

한 번도 온라인 강의를 돈 주고 사본적이 없는데, 김영한 자바 입문 편을 보고 난 후 강의의 퀄리티가 마음에 들어 결제하였다.

 

김영한 실전자바 - 기초 편은 44000원으로 부담스럽지 않은 가격이다.

 

결제 후 강의의 1/5 정도 들은 상태인데, 벌써 굉장히 만족스럽다.

 

빨리 내용을 습득 후 다음 결제가 기다려질 정도이다.

 

서론이 길었는데 본론으로 가보자.

 

자바에서는 변수, 객체 등을 선언할 때, 2가지 형태가 있다.

 

바로 기본형과 참조형이다.

 

기본형과 참조형의 차이가 무엇일까?

 

바로 생성된 변수에 어떠한 값이 들어가는지가 그 차이점이다.

 

기본형 : int, double, boolean, long -- String을 제외한 변수

참조형 : String, Class, int [] -- 객체, 배열

 

으로 나누어진다.

 

강의를 듣다 보면 굉장히 강조되는 부분이 하나 있다.

 

대원칙 : 자바에서 모든 대입 연산자는 값을 복사해서 대입한다.

 

프로그래밍을 공부하면서 암기보다는 이해가 중요하다고 한다.

 

하지만 위 원칙은 앞으로 있을 자바에 대해 더 깊은 이해를 위해 암기부터 하자.

 

아래 코드 예시를 보자.

 

 

먼저 Student Class를 만들어 주었다.

public class Student {
    String name;
    int age;
}

 

 Student 객체를 2개 생성하였다.

public class test1 {
    public static void main(String[] args) {

        Student st = new Student();
        Student st2 = new Student();

        st.name = "ysk";
        st.age = 26;

        st2 = st;

        System.out.println("이름 : " + st2.name + ", 나이 : " + st2.age);
    }
}

 

바로 위에서 Class 또한 객체라고 하였고 이는 참조형이라고 하였다.

 

따라서 Student st = new Student(); 가 실행되는 순간 st에 새로운 Student 객체의 주솟값(참조값) 이 저장되었다.

 

st2 또한 마찬가지이다.

 

st 객체의 name과 age에 값을 넣어주었다.

 

그리고 대원칙을 다시 떠올려보자.

 

대원칙 : 자바에서 모든 대입 연산자는 값을 복사해서 대입한다.

 

st2 = st를 하였다.

 

이 과정에서 st의 주솟값이 st2에게 그대로 복붙 되었다.

 

건물이 하나 있고, 이 주소지를 st에 저장하였었는데, st2에도 이 건물의 주소지를 넣은 것 과 같은 대입이 일어난 것이다.

 

즉 st, st2 가 같은 주솟값을 가지게 된 것이다.

 

실행결과를 보자

 

우리는 분명 st에 값을 넣었지만 st2에도 같은 값이 들어가 있는 것을 볼 수 있다.

 

그러면 코드를 조금 더 추가해 보자.

 

public class test1 {
    public static void main(String[] args) {

        Student st = new Student();
        Student st2 = new Student();

        st.name = "ysk";
        st.age = 26;

        st2 = st;

        st.name = "jhk";
        st. age = 23 ;

        System.out.println("이름 : " + st2.name + ", 나이 : " + st2.age);
    }
}

 

st2 = st;

이후에 다시 st의 값을 수정하였다.

 

출력 결과가 어떻게 될까?

결국 객체는 두 개이지만 하나의 참조값을 갖고 있게 되어, 두 개의 객체가 같은 값을 가지게 되는 것이다.

 

이를 응용하면 이런 것도 가능하다.

 

Student Class는 수정사항이 없다.

 

아래처럼 코드를 바꿔보자.

public class test1 {

    public static void main(String[] args) {

        Student st = createStudent("ysk", 26);
        Student st2 = createStudent("jhk", 23);

        System.out.println("이름 : " + st.name + ", 나이 : " + + st.age);
        System.out.println("이름 : " + st2.name + ", 나이 : " + + st2.age);
    }

    static Student createStudent(String name, int age){
        Student st = new Student();
        st.name = name;
        st.age = age;
        return st;
    }
}

 

굉장히 깔끔해졌다.

 

여기서 중요한 복습 1가지.

 

메소드에 static을 붙여주었는데, 붙이지 않으면 해당 클래스 인스턴스를 생성 후 메소드를 실행할 수 있다.

 

static은 클래스 로더가 처음 컴파일 할 때, 미리 저장해 두니까 바로 실행이 가능하기 때문

 

우리는 Student Class를 만들었다.

 

하지만 이는 int, String 같이 반환 타입으로도 쓰일 수가 있다.

 

즉 Class를 만든 순간 사용자 정의 타입을 만들었다고 생각해도 된다 (다만 참조형).

 

아까 전에 Class는 참조형이라고 이야기했다.

 

Class 또한 참조값(주소값)이 반환이 가능하다는 이야기이다.

 

따라서 메소드를 통해 Student 객체의 주솟값을 설정해 준 후, 클래스 변수에 값을 할당해 주었다.

 

메소드가 종료됨과 동시에 해당 Student 주솟값을 반환시키면 해당 주솟값을 참조하는 변수가 존재하게(st) 된다.

 

Student st = createStudent("ysk", 26);

 

바로 이 부분이다.

 

Student 타입의 st 변수에 새로 생성된 주솟값을 반환받은 것이다.

 

여기에서 추가로 한 가지..

 

[ Garbage Collection ]

자바에는 Gc(Garbage Collection) 라는 것이 있다.
만약 생성된 객체, 혹은 참조형 변수의 주솟값이 더이상 사용되는(저장되거나 가르켜지는) 곳이 없다면
Gc가 해당 인스턴스를 삭제(메모리 해제) 시킨다.
만약 주솟값을 메소드에서 반환받지 않거나, 반환받더라도 주솟값이 저장되지 않았다면?
Gc에 의해 해당 메모리는 날아가게 될 것이다.
        
(GarbageCollection은 바로바로 삭제되지 않고, 어느정도 쌓이면 한번에 메모리 해제를 시킨다)

 

따라서 무언가 Class 내부에서 Student가 선언되었고 메소드가 끝남과 동시에 해당 데이터가 날아갈 거 같은 그런 기분이 들지만, 참조값을 반환시켜 사용가능한 형태로 아주 깔끔한 코드가 되었다.

 

자바 공부를 하다 보니 그래도 재미를 느껴 다행이다.

 

마지막으로 기본형 참조형에 대해 중요한 것을 조금 더 정리해보자.

- 기본형은 산술연산이 가능하지만, 참조형은 산술연산이 불가능하다( 사실 필요도 없다.. 물론 주솟값에 1씩 더하면 다음 값을 받아올 수 있겠지만, c의 경우 자바는.. 굳이?)

- 기본형 변수는 Null 할당이 불가능하다.

- 기본형은 값, 참조형(배열, 객체)은 주소를 저장한다.