ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] 기본형 vs 참조형
    언어/Java 2024. 11. 5. 09:26

    https://www.inflearn.com/course/lecture?courseSlug=%EA%B9%80%EC%98%81%ED%95%9C%EC%9D%98-%EC%8B%A4%EC%A0%84-%EC%9E%90%EB%B0%94-%EA%B8%B0%EB%B3%B8%ED%8E%B8&unitId=194660&tab=curriculum

    아래 내용은 위 링크에서 더 자세히 볼 수 있습니다. 

    자바에서 참조형을 제대로 이해하는 것은 정말 중요하다

    기본형 vs 참조형 1

    • 기본형
      • 사용하는 값을 변수에 직접 넣을 수 있는 기본형
      • 들어 있는 값을 그대로 계산에 사용할 수 있다.
    • 참조형
      • 데이터에 접근하기 위해 참조(주소)를 저장하는 데이터 타입
      • 참조형은 들어있는 참조값을 그대로 사용할 수 없다. ex) 주소끼리 더하고 빼면 뭐하냐 이상한 메모리에 접근이나 하겠지..
      • String도 클래스이다. 따라서 참조형이다. 그런데 기본형처럼 문자값을 바로 대입할 수 있다. 문자는 매우 자주 다루기 때문에 자바에서 특별 취급 받아버림 
    // Primitive Type
    int a = 10;
    int b = 20;
    int sum = a + b;
    sout(sum); // 30
    
    // Reference Type
    Student student1 = new Student();
    Student student2 = new Student();
    sout(student1); // 0x001
    sout(student2); // 0x002

    기본형 vs 참조형 2

    자바는 항상 변수의 값을 복사해서 대입한다.
    package ref;
    
    public class VarChange1 {
        public static void main(String[] args) {
            int a = 10;
            int b = a;
            System.out.println("a :" + a);   // 10
            System.out.println("b :" + b);   // 10
    
            a = 20;
            System.out.println("a :" + a);   // 20
            System.out.println("b :" + b);   // 10
    
            b = 30;
            System.out.println("a :" + a);  // 20
            System.out.println("b :" + b);  // 30
        }
    }
    package ref;
    
    public class VarChange2 {
        public static void main(String[] args) {
            Data dataA = new Data();
            dataA.value = 10;
    
            Data dataB = dataA;
    
            System.out.println("dataA 참조값: " + dataA); // 주소
            System.out.println("dataB 참조값: " + dataB); // 주소
            System.out.println("dataA value: " + dataA.value); // 10
            System.out.println("dataB value: " + dataB.value); // 10
    
            // dataA change
            dataA.value = 20;
            System.out.println("변경 dataA.value =  20");
            System.out.println("dataA.value: " + dataA.value);   // 20
            System.out.println("dataB.value: " + dataB.value);   // 20
    
            // dataB change
            dataB.value = 30;
            System.out.println("변경 dataB.value =  30");
            System.out.println("dataA.value: " + dataA.value);   // 30
            System.out.println("dataB.value: " + dataB.value);   // 30
        }
    }
    • dataB change에서 dataB =dataA의 주소를 가리킨다. 주소를 찾아가서 값을 바꿨으니가 dataA.value도 바뀌는 것이다.

    기본형 vs 참조형3

    자바는 항상 변수의 값을 복사해서 대입한다.
    메서드 호출도 마찬가지이다.
    package ref;
    
    public class MethodChange2 {
        public static void main(String[] args) {
            Data dataA = new Data();
            dataA.value = 10;
            System.out.println("메서드 호출 전 dataA.value : " + dataA.value);
            changeReference(dataA);
            System.out.println("메서드 호출 후 dataA.value : " + dataA.value);
        }
    
        public static void changeReference(Data dataX) {
            dataX.value = 20;
        }
    
        /*
        * 20으로 바뀔 거 같다. 그 이유는
        * dataA의 주소가 0x001이면
        * 메서드에 파라미터에 인자로 들어갈 때 주소값이 들어가는 것 0x001
        * 따라서 0x001.value = 20; 으로 바꾸었으니 20이 될 것이다.
        * */
    }
    • C의 포인터 개념을 알고 있으면 떠올리기 쉬울 듯 하다.
    • 참조값이 복사되어 전달된다. 0x001이 전달. 따라서 dataA와 dataX는 둘 다 같은 곳을 바라보고 있다. 

    메서드 객체 바꾸기

    package ref;
    
    public class Method2 {
        public static void main(String[] args) {
            Student student1 = createStudent("학생1", 16, 90);
            Student student2 = createStudent("학생2", 18, 80);
            printStudent(student1);
            printStudent(student2);
    
        }
    
        static Student createStudent(String name, int age, int grade) {
            Student student = new Student(); // 0x001
            student.name = name;
            student.age = age;
            student.grade = grade;
            return student;
        }
    
        public static void printStudent(Student student) {
            // 0x001 값을 넘겨서 가능하구나 !!
            System.out.println("name : " + student.name + ", age : " + student.age
            + ", grade: " + student.grade);
        }
    }
    • createStudent 라는 메서드를 만들고 객체를 생성하는 부분도 이 메서드 안에 포함했다.
    • 클래스 정보를 기반으로 새로운 객체를 생성했다.
    • 궁금했던 점 : 새로운 객체를 사용할 때 객체는 고유한 메모리 주소를 가지는 가? 그렇다고 한다.
    • 새로운 객체는 힙 영역에서 계속 생성된다고 한다. 사용하지 않으면 가비지 컬렉터가 알아서 해주는 데(묵시적) 만약 계속 참조되고 있다면, 힙 오버 플로우가 발생할 수도 있다고 한다. 사실상 런타임때 outOfMemoryError를 내기 때문에 비슷하지만, 약간 다른 느낌 넘어간다.
Designed by Tistory.