▸JAVA/기본 상식

Java의 메모리 구조_메소드의 매개변수 [3/3]

코데방 2019. 12. 9.
728x90

이전 글에서 8가지 원시타입의 변수를 제외한 모든 변수는 참조 변수라고 했습니다. 이 구조를 이해하면 메소드 사용 시 실수를 피할 수 있습니다. C언어를 해보신 분들은 C언어의 함수와 포인터와 동일한 원리라고 이해하시면 됩니다.

 


 

아래 코드를 보시고 결과를 한 번 예측해보세요.

package study.first;

/* Public class */
public class Main {
		
	public static void main(String[] args) {
	
		String arr = "Hello";
		print(arr);
		System.out.println(arr);
	}
	
	
	static void print(String text) {
		
		text += " world";		
	}
}

 


 

정답은 "Hello"만 출력됩니다. C언어의 포인터를 다뤄보신 분들은 이유를 아실 것 같습니다. 힌트는 참조변수는 힙 영역에 값이 있고 그 값을 가리키기만 한다라는 것입니다. 함수에 String arr 변수가 전달되면서 가지고 있던 주소가 그대로 전달돼 같은 값을 가리키고 있습니다. 하지만 arr과 text는 서로 다른 스택 프레임에 들어가 있는 전혀 다른 변수입니다.

 

 


 

그래서 함수 내에서 "text += " world" 명령을 통해 text에 내용을 추가해주면 아래와 같이 별도의 문자열이 힙 영역에 생성되고 text가 가지고 있는 주소값이 변경됩니다. 원래 arr이 가리키고 있는 주소에는 전혀 영향을 주지도 않고 힙 영역에 들어 있는 "Hello"라는 문자열에도 전혀 영향을 주지 않습니다.

메소드가 종료되고 스택 프레임이 사라지면 text 변수도 사라지고 힙 영역의 "Hello World"문자열은 GC(가비지 컬렉터)가 없애버립니다.

 

 

 

 

 


 

따라서 해당 문자열 자체를 바꿔주고 싶다면 아래와 같이 새로운 주소를 리턴값으로 받아서 arr에 넣어줘야 합니다. 그럼 arr은 새로운 "Hello World"문자열의 주소를 가지게 되고 기존 "Hello"문자열은 참조변수를 잃어서 GC가 청소해줍니다.

package study.first;

/* Public class */
public class Main {
		
	public static void main(String[] args) {
	
		String arr = "Hello";
		arr = print(arr);
		
		System.out.println(arr);
	}
	
	
	static String print(String text) {
		
		text += " world";	
		return text;
	}
}

 

 

 


 

원시타입 또한 메소드의 인자값으로 전달해주게 되면 값을 복사해서 다른 스택 프레임으로 넘겨주는 것입니다. Java에서 메소드 간에 지역 변수 값을 공유할 수 있는 방법은 인자값 전달과 리턴값밖에 없습니다.

배열이나 인스턴스와 같이 그 주소안에 있는 특정한 값을 바꿔주는 행위는 다릅니다. 해당 메모리 주소의 값을 직접 바꿔주게 됩니다. 즉, 객체 전체의 메모리 주소에서 원시타입 단위의 메모리 주소까지 들어가면 값을 바꾸는 행위가 가능합니다.

 

package study.first;

import java.util.Arrays;

/* Public class */
public class Main {

	public static void main(String[] args) {
	
		int[] arr = {0,1,2,3};
		
		print(arr);
		System.out.println(Arrays.toString(arr));
	}

	static void print(int[] arr2) {
		
		arr2[1] = 100;
	}
}

 

 


 

하지만 역시 아래와 같은 코드를 짜면 위의 예시와 같은 이유로 잘못된 코드가 됩니다.

 

package study.first;

import java.util.Arrays;

/* Public class */
public class Main {

	public static void main(String[] args) {
	
		int[] arr = {0,1,2,3};
		
		print(arr);
		System.out.println(Arrays.toString(arr));
	}

	static void print(int[] arr2) {
		
		arr2 = new int[] {2,3,4,5};
	}
}

728x90

댓글

💲 추천 글