Java는 call by value이다.

Choizz·2023년 8월 15일
0

Java

목록 보기
11/11

이번 포스팅은 Java라는 언어가 call by value인지 call by reference인지 확인해 시간을 가지려고 합니다.

공부를 하다가도 계속 헷갈려서 이번에 정리를 하려고 합니다.

call by value는 값을 호출하는 것을 의미하고,
call by reference는 메모리 주소값을 호출하는 것을 의미합니다.

결론부터, 말씀드리자면, Java는 call by Value입니다.


Call by Value

위에서 언급한대로 call by value는 인자에 저장되어 있는 값을 호출하는 것 입니다.

  • 아래 코드를 보면, a 변수에 1이 할당됩니다.
  • 기본형 타입은 변수에 값 자체를 저장합니다.
  • increase 함수에 들어가는 매개변수에는 변수 a가 복사되어 들어갑니다.
  • 즉, increase 메서드에서는 a의 값인 1이 들어가고 1이 증가됩니다.
  • 그리고 리턴된 값을 다시 a에 할당하면 a는 2가 됩니다.
public int increase(int a){
   return ++a;
}

public static void main(String[] args){
	int a = 1;
    a = increase(a);
    System.out.println(a); // 2
}
  • 만약, 아래 코드처럼 increase 함수에 리턴 값이 없는 void라면 어떻게 될까요?
  • increase 메서드에서 a를 증가시켰지만, a는 여전히 1입니다.
  • 기본형 타입은 값 자체를 가지고 있기 때문에 increase 메서드에서 파라미터로 받은 a를 증가시켜도 increase 메서드 내에서 a를 증가시키고 그 증가한 값을 다시 변수에 할당해 주지 않으면 메서드가 종료되면서 사라집니다(Stack frame에 저장됐다 사라짐).
  • 즉, increase 외부에 있는 a에는 전혀 영향이 없는 것입니다.
public void increase(int a){
   ++a;
}

public static void main(String[] args){
	int a = 1;
    increase(a);
    System.out.println(a); // 1
}

정리하면, Java는 call by value이고, 기본형 타입은 값 자체를 가지고 있기 때문에 변수에 값 자체를 복사해서 호출하는 형식입니다.


Call by reference

call by reference 메모리 주소값을 호출합니다.


참조 변수를 call하면 어떻게 될까??

다시 한번 말하지만, Java는 call by Value입니다.
그래서 call by value를 합니다. 어떤 것을?? 메모리 주소값을!!!!
call by value로 참조 변수를 호출하는 것은 메모리 주소를 복사해서 가지고 오는 것입니다.

  • 아래 코드에서 Test 클래스를 임의로 생성하고 필드로 size를 뒀습니다.
  • Main 클래스의 main 메서드에서 Test 객체를 생성하고 size를 1로 할당했습니다.
  • 그 후 increase 메서드의 파라미터로 위에서 만든 test를 넣고, test의 사이즈를 2로 바꿉니다.
  • 그 후 size를 출력하면, 증가한 2가 출력됩니다.
public class Test {
    int size;
}

---------------------------------------------------------

public class Main {
	
    private static void increase(Test test) {
      test.size = 2;
    }
    
    public static void main(String[] args) {
        Test test = new Test();
        test.size = 1;
        System.out.println(test.size); // 1 출력
        increase(test);
        System.out.println(test.size); // 2 출력
    }
}

  • test 객체가 파라미터로 넘어갈 때, 주소 값의 복사본이 넘어갑니다.
  • 그리고 test 복사본의 size가 2로 변경됐을 때, 원본의 test도 size가 2로 변경되는 것입니다.
  • 당연한 일입니다. 메모리 주소값이 같으니까요!

이거 call by reference 아니에요??

참조 변수를 call by value하는 것은 해당 레퍼런스의 메모리 주소값을 복사하는 것이고, call by reference는 메모리 주소값 자체 즉, 원본을 가지고 오는 것 입니다.

  • 아래 코드에서, increase 메서드에서 파라미터로 받은 test에 새로운 객체를 할당하고 있습니다.
  • 그 후, 새로 할당한 test의 size를 3으로 줍니다.
  • 그런데, main 메서드에서 test.size를 출력하면 1이 출력됩니다.
public class Test {
    int size;
}

---------------------------------------------------------

public class Main {
	
    private static void increase(Test test) {
      test = new Test();
      test.size = 3;
    }
    
    public static void main(String[] args) {
        Test test = new Test();
        test.size = 1;
        System.out.println(test.size); // 1 출력
        increase(test);
        System.out.println(test.size); // 1 출력
    }
}

왜 이런 결과가 생길까요?? call by value이기 때문입니다.

test의 복사본에 새로운 객체가 할당되면서 원본 test 객체와의 관련이 없어진 것입니다.

만약 call by reference 였다면 어떻게 돼야했을까요??

  • call by reference는 메모리 주소값 자체를 가지고 옵니다. 복사가 아닙니다!
  • 따라서, 아래 그림처럼, test에 새로운 객체가 할당돼야하고, size를 출력했을 경우 3이 나와야 했을 것입니다!

정리

  • Java는 call by value이다.
  • 참조 변수의 경우 참조 변수의 메모리 주소값을 복사해서 값으로 호출한다.

reference

profile
집중

0개의 댓글