티스토리 뷰

메소드로 인자값을 넘기는 방법



메소드로 인자값을 넘기는 방법은 크게 두 가지가 있다.


Call by value

Call by reference


Call by value라는 것은 그대로 해석하면 '값에 의한 호출'이다. 메소드로 인자값을 넘길때 그 값을 복사하여 넘기는 형태이다. 따라서 이 방식으로 메소드 호출을 하면 메소드 내에서는 복사된 값으로 작업을 하기 때문에 원래의 값을 변경시키지 않는다.


Call by reference'참조에 의한 호출'이다. 인자값을 메소드로 넘겨 줄때 그 객체를 참조하는 주소를 넘겨주는 형태이다. 따라서 메소드 내에서도 원래의 값에 접근이 가능하다.


아래의 예시를 통하여 정확하게 알아보도록 하겠다.



1. 인자값으로 기본형을 사용했을 때

public class Test {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int num1 = 10, num2 = 20;
		
		System.out.println("Before");
		System.out.println("num1 = " + num1);
		System.out.println("num2 = " + num2);
		swap(num1, num2);
		System.out.println("After");
		System.out.println("num1 = " + num1);
		System.out.println("num2 = " + num2);
	}
	
	// 자리 바꾸기 메소드
	static void swap(int num1, int num2) {
		int temp;	// 임시 변수
		
		// 자리 바꾸기
		temp = num1;
		num1 = num2;
		num2 = temp;
	}
}


결과

Before
num1 = 10
num2 = 20
After
num1 = 10
num2 = 20


위의 코드를 보면 swap메소드를 호출한 후에도 그대로 값이 유지된 것을 알 수 있다. 이 결과를 통해 알 수 있는 것은 메소드 안에서 아무리 두 수의 위치를 바꾼다고 해서 원본 데이터가 바뀌는 것이 아니라는 것이다. 메소드 내에서 두 수를 바꾸는 행위는 단지 복사된 값을 바꾸는 것에 불과하다. 따라서 자바는 기본형 데이터를 처리할 때 Call by value 형식으로 처리된다는 것을 알 수 있다. 그렇다면 아래에서 객체를 전달했을 때는 어떠한 결과를 도출하는지 알아보도록 하자.



2. 인자값으로 객체를 사용했을 때(wrapper 클래스 사용)

public class Test {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Integer num1 = 10, num2 = 20;
		
		System.out.println("Before");
		System.out.println("num1 = " + num1);
		System.out.println("num2 = " + num2);
		swap(num1, num2);
		System.out.println("After");
		System.out.println("num1 = " + num1);
		System.out.println("num2 = " + num2);
	}
	
	// 자리 바꾸기 메소드
	static void swap(Integer num1, Integer num2) {
		Integer temp;	// 임시 변수
		
		// 자리 바꾸기
		temp = num1;
		num1 = num2;
		num2 = temp;
	}
}


결과

Before
num1 = 10
num2 = 20
After
num1 = 10
num2 = 20


위의 기본형의 정수 변수를 wrapper클래스로 생성하여 객체로 다루어 보았다. 먼저 wrapper클래스에 대하여 약간의 설명을 하겠다.


코드에는 생략되어 있지만 Integer num1 = 10; 이라는 코드는 자바 내부적으로 new를 호출하여 힙 영역에 객체를 생성하고 스택영역의 지역 변수로 그 것을 참조한다. 풀어서 쓰자면 Integer num1 = new Integer(10); 과 같은 코드이니 오해하지 말자.


객체를 전달하여 두 수가 참조하는 값을 바꿔 보았다. 결과는 기본형을 사용했을 때와 같았다. 이것으로 보아 객체 또한 메소드로 값이 전달될 때 그 참조값은 Call by value의 형태로 전달된다는 것을 알 수 있다.


여기서 의문점이 생긴다. 자바는 기본적으로 포인터를 프로그래머에게 노출시키지 않는다. 따라서 C언어에서 처럼 주소를 인자값으로 넘기는 방식은 불가능하다. 그렇다면 자바는 위와 같은 방식으로 객체를 다룰 수 없다면 메소드 안에서 어떻게 다룰 수 있을까?



3. 인자값으로 객체를 사용했을 때(커스텀 클래스 사용)

public class Test {
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		NumberClass num1 = new NumberClass(10);
		NumberClass num2 = new NumberClass(20);
		
		System.out.println("Before");
		System.out.println("num1 = " + num1.num);
		System.out.println("num2 = " + num2.num);
		swap(num1, num2);
		System.out.println("After");
		System.out.println("num1 = " + num1.num);
		System.out.println("num2 = " + num2.num);
	}
	
	// 자리 바꾸기 메소드
	static void swap(NumberClass num1, NumberClass num2) {
		int temp;	// 임시 변수
		
		// 자리 바꾸기
		temp = num1.num;
		num1.num = num2.num;
		num2.num = temp;
	}
}

class NumberClass {
	int num;
	
	NumberClass (int num) {
		this.num = num;
	}
}


결과

Before
num1 = 10
num2 = 20
After
num1 = 20
num2 = 10


드디어 원하는 결과를 얻었다. 여기서 위와 다른 점은 객체의 참조값을 직접 바꾼것이 아니라 객체의 참조값을 통해서 그 객체의 멤버변수에 접근하여 그 값을 바꿨다는 것이다.


여기서 알 수 있는 중요한 자바의 특성은 객체를 메소드로 넘길 때 객체를 참조하는 지역변수의 실제 주소를 넘기는 것이 아니라 그 지역변수가 가리키고 있는 힙 영역의 객체를 가리키는 새로운 지역변수를 생성하여 그 것을 통하여 같은 객체를 가리키도록 하는 방식이라는 것이다. 아래의 그림을 보면 이해가 쉬울 것이다.





main메소드에서 참조하는 힙 영역의 데이터를 swap 함수에서도 새로운 지역변수를 통해서 참조하는 것을 볼 수 있다. 이제 자바에서는 명확하게 Call by value로 모든 메소드의 호출을 수행하는 것을 알 수 있을 것이다.




결론



생각해보니 이런 부분을 깊히 생각하지 않고 지금까지 공부를 해왔다. 'C언어에서 사용하던 포인터의 개념을 생각하지 않고 프로그래밍해서 편안하구나!'라는 생각을 막연하게 해왔지만 내부적으로 어떻게 동작하는지는 관심을 가지지 않았었다. 이는 추후에 자바를 더 깊이 공부하게 되고 내가 현업으로 갈 수록 이런 지식이 나에게는 더 큰 도움이 될 것이라는 생각이 들었다. 한번쯤 자신이 배우고 있는 언어를 면밀히 살펴보는 것이 바람직하다는 것을 크게 느낀다.




참고



http://trypsr.tistory.com/74

http://wonwoo.ml/index.php/post/1679

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함