JAVA

[Java] 기본형 vs 참조형

songsua 2024. 10. 19. 01:57
  • 기본형(Primitive Type): `int` , `long` , `double` , `boolean` 처럼 변수에 사용할 값을 직접 넣을 수 있는 데이 터 타입을 기본형이라 한다.
  • 참조형(Reference Type): `Student student1` , `int[] students` 와 같이 데이터에 접근하기 위한 참조 (주소)를 저장하는 데이터 타입을 참조형이라 한다. 참조형은 객체 또는 배열에 사용된다

 

메서드 호출 

package ref;

public class MethodChange02 {
        public static void main(String[] args) {
            int a = 10;
            System.out.println("메서드 호출 전: a = " + a); changePrimitive(a); 
            System.out.println("메서드 호출 후: a = " + a);
        }
        static void changePrimitive(int x) {
            x = 20;
        }
}

int 형인 기본형에 대한 메서드 호출인 경우,

a = 10 인 값은 그대로 가지고 가기 때문에, 메서드 a 값을 호출 하면 10 이 나온다.

 

그렇다면 참조형 변수의 메서드 호출은 어떨까?

package ref;

public class Methodchange01 {
    public static void main(String[] args) {
        Data data1 = new Data();
        data1.value = 10;
        System.out.println("메서드 호출 전: " + data1.value);
        Change(data1);
        System.out.println("메서드 호출 후 :" + data1.value);

    }
    static void Change(Data datax) {
        datax.value = 100;
    }
}

 

메서드 호출 전은 data1의 value 값 10을 가져왔다.

메서드 호출 후는 data x 의 100 을 가져오는데, 왜 그럴까?

 

data1 의 참조값 10을 가지고 있다.

 

같은 change 메서드에서  dataA 값을 가지고 있던 것을  dataX 의 값을 복사하여 가지게 된다.

 

기본형에 대한 메서드 호출은 그 값에 대한 복사이고

참조형에 대한 메서드 호출은 참조값을 복사하여 그대로 가져가게 된다.

  • **기본형**: 메서드로 기본형 데이터를 전달하면, 해당 값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수 (파라미터)의 값을 변경해도, 호출자의 변수 값에는 영향이 없다.
  • **참조형**: 메서드로 참조형 데이터를 전달하면, 참조값이 복사되어 전달된다. 이 경우, 메서드 내부에서 매개변수(파 라미터)로 전달된 객체의 멤버 변수를 변경하면, 호출자의 객체도 변경된다.


메서드를 사용하여 참조값을 넘기기

package ref;

public class Method03 {
    public static void main(String[] args) {
        Student student1 = new Student();
        student1.name = "학생";
        student1.age = 12;
        student1.grade = 78;


        Student student2 = new Student();
        student2.name = "학생2";
        student2.age = 11;
        student2.grade = 90;
        //아래와 같은 println 을 사용하지 않고 static void 를 이용해서 호출하기
        //System.out.println("이름:"+ student1.name + "나이 :" + student1.age + student1.grade + "성적");
        //System.out.println("이름:"+ student2.name + "나이 :" + student2.age + student2.grade + "성적");
        printStudent(student1);
        printStudent(student2);
        //1번의 참조값을 받아서 아래의 'printstudent'에게 값을 넘길 것이다.

    }
    //참조값을 넘겨보자
    static void printStudent(Student student) {
        System.out.println("이름:"+ student.name + " 나이 :" + student.age + " 성적: "+ student.grade );

    }

}

 

  • static: 이 키워드는 메서드가 인스턴스화된 객체와는 독립적으로 호출될 수 있음을 나타냅니다. 즉, 클래스의 인스턴스가 없어도 클래스 이름으로 직접 호출할 수 있습니다.
  • void: 이 메서드가 아무 값도 반환하지 않음을 의미합니다. 즉, 결과를 출력하는 것이 목적이지, 다른 데이터로 반환되지는 않습니다.

 

아래와 같이 static void 매세더이름 (클래스 객체이름, 참조1, 참조2, 참조3 )  넣어 둔 다음,

객체.변수 = 값 으로 하나하나 안적어도 아래와 같이 메서드를 이용해서 한꺼번에 적용할 수 있다.

package ref;

public class Method03 {
    public static void main(String[] args) {
        Student student1 = new Student();
        intiStudent(student1, "학생" , 12 , 78);
        //student1.name = "학생";
        //student1.age = 12;
        //student1.grade = 78;


        Student student2 = new Student();
        initStudent(student2, "학생2" , 11 , 98);

        // student2.name = "학생2";
       // student2.age = 11;
       // student2.grade = 90;
        printStudent(student1);
        printStudent(student2);
        //1번의 참조값을 받아서 아래의 'printstudent'에게 값을 넘길 것이다.

    }

    static void intiStudent(Student student, String name, int age, int grade) {
        student.name = name;
        student.age = age;
        student.grade = grade;
        //인스턴스에서 넘어온 매게변수를 대입해준다.
    }

}

 

 

 

  • initStudent(Student student, ...)` : 전달한 학생 객체의 필드에 값을 설정한다. `
  • printStudent(Student student, ...)` : 전달한 학생 객체의 필드 값을 읽어서 출력한다.

더 나아가서 

Student student1 = new Student();
printStudent(student1, "학생" , 12 , 78);
Student student2 = new Student();
printStudent(student2, "학생2" , 11 , 98);

 

이렇게 중복으로 적는 것도 안하고 싶다.! 그럼 어떻게 해야할까..

 

package ref;

import static ref.Method03.printStudent;

public class Method04 {
    public static void main(String[] args) {
       Student student1 = createStudent("학생" , 12 , 78);
       Student student2 = createStudent( "학생2", 11, 98);

    //    Student student1 = new Student();
        //printStudent(student1, "학생" , 12 , 78);
        //Student student2 = new Student();
        //printStudent(student2, "학생2" , 11 , 98);

        // student2.name = "학생2";
       // student2.age = 11;
       // student2.grade = 90;
        printStudent(student1);
        printStudent(student2);
        //1번의 참조값을 받아서 아래의 'printstudent'에게 값을 넘길 것이다.

    }

    static Student createStudent(String name, int age, int grade) {
        Student student = new Student();
        //객체 생성을 여기서 진행 한다.
        student.name = name;
        student.age = age;
        student.grade = grade;
        return student;
        //return 을 사용하여 참조값을 전부 생성 완료 하였다.
        //그럼 맨위의 메서드를 호출하여

    }
    static void printStudent(Student student) {
        System.out.println("이름:" + student.name + " 나이:" + student.age + " 성적:" + student.grade);
    }
}

위에 짠 순서를 보면,

1.  createStudent 메서드 생성 

2. 메서드 안에 클래스의 student 객체 생성

3. return 으로 인해 다시 맨 위의 객체 참조값을 받음

4. 아래의 printStudent 메서드를 값을 받아 Student 클래스에 있는 객체들의 참조값을 전부 출력