자바는 Call By Value?

Seop·2023년 11월 26일

java

목록 보기
1/2
post-thumbnail

Evaluation Strategy

In a programming language, an evaluation strategy is a set of rules for evaluating expressions.[1] The term is often used to refer to the more specific notion of a parameter-passing strategy[2] that defines the kind of value that is passed to the function for each parameter (the binding strategy)[3] and whether to evaluate the parameters of a function call, and if so in what order (the evaluation order).

Evaluation strategyRepresentative LanguagesYear first introduced
Call by referenceFORTRAN IIPL/I1958
Call by valueALGOLCSchemeMATLAB[9]1960
Call by nameALGOL 60Simula1960
Call by copy-restoreFortran IVAda[10]1962
Call by needSASL,[11] HaskellR[12]1971[13]
Call by sharingCLUJavaPythonRubyJulia1974[14]
Call by reference parametersC++PHP,[15] C#,[16] Visual Basic .NET[17]1985[18]
Call by reference to constC++C1985[18]

위키 백과 - Evaluation strategy

프로그래밍 언어에서 평가 전략이란 함수나 메서드에 인자를 전달하는 방식을 의미합니다. 대표적으로 널리 알려진 것이 Call-By-Reference, Call-By-Value가 있죠.

Call By Value

#include <iostream>
using namespace std;
 
void swap(int x, int y) {
	int tmp = x;
	x = y;
	y = tmp;
}
 
int main() {
	int a = 10;
	int b = 20;

	cout << "a : " << a << endl;
	cout << "b : " << b << endl;

	swap(a, b);
	cout << "after swap" << endl;
 
	cout << "a : " << a << endl;
	cout << "b : " << b << endl;
}

Result

a : 10
b : 20
after swap
a : 10
b : 20

C++을 배우면 나오는 함수 부분에서 나오는 예제입니다. swap 함수의 의도는 두 변수의 값을 변경하고자 하는 것인데 제대로 시행되지 않았죠.

그 이유는 바로 해당 함수는 만을 전달 했고, 별도의 공간에서 시행되었기 때문입니다.


#include <iostream>
using namespace std;
 
void swap(int *a, int *b) {
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
 
int main() {
	int a = 10;
	int b = 20;
 
	cout << "a : " << a << endl;
	cout << "b : " << b << endl;

	swap(&a, &b);
	cout << "after swap" << endl;
 
	cout << "a : " << a << endl;
	cout << "b : " << b << endl;
}

Result

a : 10
b : 20
after swap
a : 20
b : 10

위의 함수와는 다르게 이 코드에서 swap 함수는 주솟값을 전달받습니다.
그리고 주솟값에 실제로 접근하여 내부의 값을 조정하죠.

그렇게 때문에 실제로 두 값이 바뀌게 됩니다.

포인터로 유명한 C++에서는 위와 같이 해결하는 것을 알았습니다.
그렇다면 자바에서는 어떻게 값을 전달할까요?

Call by Reference? Call by Value?

위의 위키 백과에서도 확인할 수 있듯이 Call-By-Sharing 이라는 방식으로 값을 전달합니다.

public class Main {  
    public static void main(String[] args) {  
        int[] arr = {1, 2, 3};  
        printArr(arr);  
        foo(arr);  
        printArr(arr);  
        goo(arr);  
        printArr(arr);  
    }  
  
    static void foo(int[] arr) {  
        arr[0] = 5;  
    }  
  
    static void goo(int[] arr) {  
        int[] newArr = new int[]{5, 6, 7};  
        arr = newArr;  
    }  
  
    static void printArr(int[] arr) {  
        System.out.println(Arrays.toString(arr));  
    }  
}

실행 결과

19:41:29: Executing ':Main.main()'...

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes

> Task :Main.main()
[1, 2, 3]
[5, 2, 3]
[5, 2, 3]

BUILD SUCCESSFUL in 162ms
2 actionable tasks: 2 executed
19:41:29: Execution finished ':Main.main()'.
public class MutImut {  
    public static void main(String[] args) {  
        String str = "hello";  
        StringBuilder sb = new StringBuilder("hello");  
  
        System.out.println(str + ", " + sb.toString());  
        foo(str);  
        goo(sb);  
        hoo(sb);  
        System.out.println(str + ", " + sb.toString());  
    }  
  
    static void foo(String str) {  
        str = "world";  
    }  
  
    static void goo(StringBuilder sb) {  
        sb = new StringBuilder("world");  
    }  
  
    static void hoo(StringBuilder sb) {  
        sb.append("hahaha");  
    }  
}

실행 결과

19:45:34: Executing ':MutImut.main()'...

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes

> Task :MutImut.main()
hello, hello
hello, hellohahaha

BUILD SUCCESSFUL in 159ms
2 actionable tasks: 2 executed
19:45:34: Execution finished ':MutImut.main()'.

값이 원하는 대로 변경될 때도 있지만, 원하는 대로 변경되지 않을 때도 존재합니다.
변경될 때도 존재하니깐 Reference 일까요?

아니면 Value?
정답은 Value 입니다! 정확히는 Call-by-Sharing 이죠. 하지만 대다수의 사람들도 그렇고 Call by Value 방식으로 칭하고 있습니다.

그러면 인자로 넘겨준 값이 변경된 경우는 어떤 경우인 것 일까요?

mutable 객체는 변경할 수 있지만, immutable 객체는 변경할 수 없습니다.
새로운 객체로 대체를 할 수도 없습니다!!!

String은 불변 객체이기 때문에 변경과 대체가 실행되지 않습니다.
StringBuilder의 경우네는 가변 객체이지만, 새로 할당한 경우(대체를 시도한 경우)에는 변경이 적용되지 않습니다!!

profile
어제보다 더 나은 개발자가 되고파요

0개의 댓글