본문 바로가기
Programming/Languages (Java, etc)

JAVA는 call by reference 없습니다.

by kghworks 2022. 7. 19.

출처 : https://9gag.com/gag/aOYewbR

 

java는 call by reference 없습니다.

 

목차

  • call by value와 call by reference, 기본형 (primitive type)과 참조형 (reference type)
  • java가 call by reference처럼 보이는 이유
  • 개인적인 생각
  • 참고

call by value와 call by reference, 기본형 (primitive type)과 참조형 (reference type)

 

call by value (pass by value)
  • 메서드 호출 시 값 (value, 변수의 내용)을 전달
  • 호출자 (호출 scope)의 변수와 매개변수는 서로 완전히 다른 변수

 

call by reference (pass by reference)
  • 메서드 호출 시 참조(주소)를 전달합니다.
  • 호출자 (호출 scope)의 변수와 매개변수는 서로 완전히 같은 변수
  • 수신한 메서드(scope)에서 변수 수정 시 호출자의 변수에도 똑같이 수정됨

 

이전 포스팅에서 jvm의 메모리 구조를 기본형과 참조형에 따라 설명한 바 있으니 이 부분도 참고하시길 바랍니다.

 

출처 : https://kghworks.tistory.com/48

 간단히 말하면 기본형 (int, double, boolean 등)은 stack의 변수 안에 value를 담고, 참조형 (Integer, Obejct, Array, Map 등) 은 stakc의 변수 값에는 객체의 주소 값, 객체는 별도의 Heap영역에 할당한다는 것입니다.

 이게 다입니다. 더 알고 싶으시면 아래로 가서 보시면 됩니다.

 

https://kghworks.tistory.com/48

 

stack, heap (스택과 힙) - 자바의 메모리 런타임

목차 자바의 메모리 영역 스택 (stack) 힙 (heap) 가비지 컬렉션 (Gabage Collection) 자바의 메모리 영역 자바의 메모리 구조는 크게 스택과 힙으로 나뉩니다. 스택 (stack) 기본 타입 (long, int, boolean,...)..

kghworks.tistory.com

 


java가 call by reference처럼 보이는 이유

 

기본형 (primitive type)

public static void main(String args[]) {
    int a = 1;

    System.out.println("a : " + a);

    changeValue(a);

    System.out.println("a : " + a);
}


private static void changeValue(int a) {
    a = 0;
}

 

 swap() 호출 후 a 값에 변함이 없는 건 당연합니다. swap에서 다루는 변수 a는 main()에서 다루는 a와 전혀 다른 변수이기 때문입니다. 서로 scope가 다른 지역변수들인 거죠. 이번엔 참조형을 보겠습니다.

 

참조형 (reference type)

private static void changeValue(int[] items) {
    items[0] = 999;
}

public static void main(String args[]) {

    int[] items = {1, 2, 3};

    System.out.println("호출 전 : " + Arrays.toString(items) );

    changeValue(items);

    System.out.println("호출 후 : " + Arrays.toString(items)) ;

}

  swap 후에 값이 바뀝니다. 그런데 이건 call by reference가 아닙니다.  

 이 지점에서 java의 객체는 참조형이기 때문에 call by reference라고 헷갈립니다. 하지만 단지  swap에서의 items 주소 값과 changeValue에서의  items 주소 값이 같기 때문에 일어난 현상에 불과합니다. 

 

 그럼 call by reference 맞는데? 아닙니다.

 

 call by value로 주소 값(value)을 전달하여, 두 변수 안에는 같은 주소 값을 같고 있을 뿐 두 변수는 서로 별도로 분리되어 존재합니다. 그림으로 보겠습니다.

 

  • changeValue() 호출 시 items의 주소 값을 담아 새로운 items 변수 선언 (-> call by reference 아님. 단순 주소값의 복사)
  • items 변수는 서로 다른 scope에 존재함 (지역변수)
  • items 변수 값은 같음 (= 참조 주소 값이 같음)
  • items의 index 0을 999로 변경하면 main()의 items도 변함

 

 같은 값을 가진 서로 다른 변수일 뿐입니다. 그런데 그 변수가 가진 값이 주소 값이기 때문에 call by reference로 착각하는 것이죠. call by reference려면 두 변수가 완전히 같아야 합니다. 

 

 하나만 더 보겠습니다.

private static void swap(Integer a, Integer b) {
    Integer temp = a;
    a = b;
    b = temp;
}

public static void main(String args[]) {
    Integer a = new Integer(1);
    Integer b = new Integer(2);

    System.out.println("a => " + a.intValue());
    System.out.println("b => " + b.intValue());

    swap(a, b);

    System.out.println("a => " + a.intValue());
    System.out.println("b => " + b.intValue());
}

 

이제 위 코드를 토대로 아래 그림을 유추하실 수 있다면 좋겠습니다.


개인적인 생각

 

From the authors of Java: "There is exactly one parameter passing mode in Java - pass by value - and that helps keep things simple." The Java Programming Language, 2nd ed. by Ken Arnold and James Gosling, section 2.6.1, page 40, 3rd paragraph.

 

 일단 팩트는  java 에는 call by value만 있습니다. (java 창시자가 그렇다고 합니다..)

JAVA에만 입각해서 보면, call by "VALUE"에서 value가 변수의 값인데, 참조형(객체)이라면 변숫값이 주소 값 (reference)이고, 이 또한 명백히 value이기 때문에 call by reference는 없다는 것입니다.

 

참조 주소 값도 value라는 것이죠.

 

C의 시각

 C 언어도 call by reference를 지원하지 않습니다. 그러나 java에서의 참조형 call by value와 같은 것을 call by address라 칭하고 '이를 통해  call by reference를 구현할 수 있다.'로 정의합니다.

 

 

 그에 반해 JAVA는 전달하는 변숫값이 참조 주소 값이라도 '값 (value)'이기 때문에 call by value로 보는 것 같습니다.

 

  • java : "전달한게 참조주소 값인데, 주소 '값'도 사실 value니까 call by value"
  • C : "전달한게 주소(address)면 다른 scope에서도 원래 객체에 영향이 가니까, 어느정도 call by reference를 구현한거지. 이건 call by address라고 하자"

 


참고

https://stackoverflow.com/questions/40480/is-java-pass-by-reference-or-pass-by-value

 

Is Java "pass-by-reference" or "pass-by-value"?

I always thought Java uses pass-by-reference. However, I've seen a blog post that claims that Java uses pass-by-value. I don't think I understand the distinction they're making. What is the explana...

stackoverflow.com

gpt야 call by reference 있니?

 

'Programming > Languages (Java, etc)' 카테고리의 다른 글

static 변수에 @Value inject  (0) 2022.10.24
JSP란  (0) 2022.10.05
분할정복 알고리즘  (0) 2022.06.23
싱글톤 패턴 (Singleton pattern)  (0) 2022.05.10
알고리즘의 기본 - 시간복잡도  (0) 2022.03.18

댓글