프로그래밍을 할 때 대표적인 함수호출 방법은 Call by value 와 Call by refernce가 있다.
뜻을 그대로 해석하면 값에 의한 호출과 주소에 의한 호출로 해석될 수 있다.
call by value호출의 예를 들어보자
package javaBasic;
public class Test020 {
public static void main(String[] args) {
int a = 1;
int b = 2;
int temp = a;
a = b;
b = temp;
System.out.println("a: "+a+" b: "+b); // a: 2 b: 1
}
}
일반적으로 자바에서 사용되는 일반적인 swap방식은 다음과 같다.
1. 임시로 빈 값인 temp를 생성한다.
2. 변수 a의 값을 복사하여 temp에 담는다.
3. 변수 a에 b의 값을 복사하여 담는다.
4. temp에 변수 a의 값이 복사됐기 때문에 변수 b에 담는다.
코드를 작성할 때 swap방식이 여러번 사용된다면 함수로 만들어서 사용하는 것이 편리하기 때문에 함수로 만들어보자
package javaBasic;
public class Test020 {
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
System.out.println("a: "+a+" b: "+b); // a: 2 b: 1
}
public static void main(String[] args) {
int a = 1;
int b = 2;
swap(a,b);
System.out.println("a: "+a+" b: "+b); // a: 1 b: 2
}
}
다음과 같은 함수를 작성한다면 정상적으로 swap이 작동할까?
Java에서는 Call by value방식으로 함수를 호출하기 때문에 다음과 같은 코드는 swap이 정상적으로 작동하지 않는다.
즉 sawp(a,b) 코드를 작성할 때 a와 b에는 a와 b의 주소값이 swap 함수의 parameter에 전달되는 것이 아닌 a와 b의 복사된 값이 전달 된 것이다.
따라서 swap함수가 호출되더라도 실질적인 a와 b의 값은 비뀌지 않는다.
package javaBasic;
public class Test020 {
public static void pow(int a) {
a = a * a;
System.out.println("a: "+a); // a: 16
}
public static void main(String[] args) {
int a = 4;
pow(a);
System.out.println("a: "+a); // a: 4
}
}
다음과 같이 직관적인 예시를 들 수 있다. 수를 제곱해주는 pow함수를 생성했다. 함수내에서는 a값이 16이지만 함수 밖에서는 a값이 4로 출력된다.
결과적으로 함수의 parameter로 전달되는 변수는 변수 자체가 전달되는 것이 아닌 변수의 값이 복사되어 전달되기 때문에 실제로 함수로 전달된 a와 함수 밖 a는 다르다고 할 수 있다.
그렇다면 Call by reference 방식은 자바에서 구현되지 않는가?
배열을 사용하여 구현해보자.
Call by value 방식으로 배열의 두 원소를 swap한 경우다.
package javaBasic;
public class Test020 {
public static void swap(int a, int b) {
int temp = a;
a = b;
b = a;
}
public static void main(String[] args) {
int []arr = {1,2,4,3,5};
swap(arr[2],arr[3]);
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 1 2 4 3 5
}
}
}
배열을 오름차순으로 할 때 arr의 세번째 값과 네번째 값을 swap하고자 한다.
하지만 방금전에 사용했던 Call by value방식의 함수를 호출했다면 다음과 같이 Swap이 발생하지 않을 것이다.
배열 자체를 parameter에 던져주어 배열의 두 원소를 swap한 경우다.
package javaBasic;
public class Test020 {
public static void swap(int arr[], int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
public static void main(String[] args) {
int []arr = {1,2,4,3,5};
swap(arr,2,3);
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 1 2 3 4 5
}
}
}
다음 swap함수는 배열자체를 parameter로 받았다.
자바에서는 참조형 변수와 배열과 같은 경우 Call by refernce와 같은 효과를 낸다고 한다. 그렇다고 Call by reference방식은 아니라고 한다? 사실 정확히는 나도 잘 모르겠다.
따라서 다음과 같은 경우에는 정상적으로 swap이 발생하기 때문에 1 2 3 4 5로 출력 된다.
참조형 변수로 swap함수를 사용한 예시
package javaBasic;
class Human{
public int age;
}
public class Test020 {
public static void swap(Human a, Human b) {
int temp = a.age;
a.age = b.age;
b.age = temp;
}
public static void main(String[] args) {
Human a = new Human();
a.age = 20;
Human b = new Human();
b.age = 24;
swap(a,b);
System.out.println("a.age: "+a.age+" "+"b.age: "+b.age); // a.age: 24 b.age: 20
}
}
다음과 같은 경우는 Human이라는 클래스를 만들어 참조형 변수로 사용했다.
swap함수는 int와 같은 자료형 변수가 아닌 참조형 변수를 받았기 때문에 참조형 변수와 비슷한 효과를 발생시킨다.
따라서 배열과 같이 실제로 human의 age값이 교환되어 출력됨을 알 수 있다.
package javaBasic;
class Human{
public int age;
}
public class Test020 {
public static void swap(int a, int b) {
int temp = a;
a = b;
b = temp;
}
public static void main(String[] args) {
Human a = new Human();
a.age = 20;
Human b = new Human();
b.age = 24;
swap(a.age,b.age);
System.out.println("a.age: "+a.age+" "+"b.age: "+b.age); //a.age: 20 b.age: 24
}
}
따라서 int와 같은 자료형 변수를 함수의 parameter로 받았을 때는 정상적이 swap이 작동하지 않음을 알 수 있다.
결과적으로 자바는 Call by value의 방식으로 함수가 호출되지만 참조형변수와 배열을 parameter로 받는다면 Call by reference의 효과를 낼 수 있다.
C언어와 같은 경우 변수의 reference와 pointer와 같은 개념으로 Call by reference와 Call by value 함수호출에 대한 확실한 구분이 있지만 Java의 경우 그 경계가 모호한 것 같다.
자세한 작동방식은 나도 잘 모르겠다. 더 공부해야겠다.
'JAVA 기초 정리' 카테고리의 다른 글
[JAVA] 예외처리하기 (0) | 2020.04.26 |
---|---|
JAVA 선택정렬(Selection Sort)와 삽입정렬(Insertion Sort) (0) | 2020.03.19 |
JAVA Stack과 Queue구현하기 (0) | 2020.03.08 |
JAVA Node로 Doubly Linked List 구현하기 (0) | 2020.03.08 |
JAVA 와일드카드 제네릭(Generic)과 Object 클래스 (0) | 2020.03.07 |
댓글