함수의 인자를 어떻게 처리
하는지 이해해야 한다.실제 값을 복사
하여 함수의 매개변수에 전달하는 방식이 때문에 종종 Java의 동작이 "Call by Reference"처럼 보일 수 있다. 함수 내에서 참조형 변수를 통해 객체를 수정하면 원본 객체에도 변경이 반영되기 때문이다. 그러나 이는 참조의 값이 복사되었기 때문이며, 실제로 메모리 주소 자체가 전달되는 것은 아니다.
값을 복사
하여 함수의 매개변수에 할당스택 메모리 공간
에 저장된다. 이 공간은 함수 호출 시 생성되며 함수 종료 시 소멸한다.public class Test {
public static void main(String[] args) {
int n = 10;
System.out.println(n); //10
test(10); //5
System.out.println(n); //10
// 값이 바뀌지 않는다는 걸 볼 수 있다.
}
public static void test(int n) { //test 함수의 지역 변수 n에 할당
n -= 5;
System.out.println(n);
}
}
String
, Arrays
, 사용자가 정의한 클래스 객체 등이 여기에 해당객체의 주소(참조)가 복사
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
for (int num : arr) System.out.print(num + " ");
System.out.println();
test(arr); // 1. 참조의 복사 : arr의 주소값이 test 함수의 매개변수 a에 복사
for (int num : arr) System.out.print(num + " "); // main 메서드로 돌아와서 arr의 값을 다시 출력하면, 수정된 값들(10, 20, 30)이 출력
}
public static void test(int[] a) { //a와 arr는 동일한 배열 객체
for (int i = 0; i < a.length; i++) {
a[i] *= 10; // 2. 객체 변경의 영향 : test 함수 내에서 a를 통해 배열을 변경하면, 이는 arr이 가르키는 동일한 배열 객체에 영향을 미침
}
}
}
// 결과
1 2 3
10 20 30
⇒ 참조 자체의 변경: 만약 test
함수 내에서 a
에 새로운 배열을 할당한다면, 이는 arr
에 영향을 주지 않는다. 왜냐하면 이 경우 a
의 참조가 새로운 객체를 가리키게 되지만, arr
는 여전히 원래의 객체를 가리키기 때문
매개변수(parameter)
는 프로그래밍에서 함수나 메서드를 정의할 때 사용되는 변수유효한 지역 변수(local variable)
즉, 함수 밖에서는 그 값에 접근할 수 없다."매개변수(parameter)"와 "인자(argument)"는 종종 혼용되어 사용되지만, 기술적으로는 약간의 차이가 있다. 매개변수는 함수를 정의할 때 선언되는 변수를 의미하는 반면, 인자는 함수를 호출할 때 실제로 전달되는 값이다. 예를 들어,
add(5, 3)
에서5
와3
은add
함수에 전달되는 인자이다.
실제 메모리에 접근하고 수정
할 수 있으며, 이러한 변경은 함수 외부의 해당 인자에도 영향을 미친다.void exampleFunction(int[] arr) {
arr[0] = 50;
}
int main() {
int[] x = {10};
exampleFunction(x);
// x[0]은 이제 50이다.
}
자바에서는 Primitive Type과 Reference Type이 있다. 이는 기본형과 참조형이라고 하며, 서로 조금은 다른 특징을 가지고 있다.
stack 영역에 생성
된다.Null 값을 가질 수 없다.
heap 영역에 저장
한다.
스택(Stack)
과힙(Heap)
은 메모리를 할당하고 관리하는 두 가지 주요 방법으로 이들은 메모리 관리의 중요한 측면이며, 특히 자바와 같은 언어에서 중요한 역할
스택 오버플로우(stack overflow)
가 발생할 수 있다.OutOfMemoryError
가 발생할 수 있다.[ 스택 메모리 ] [ 힙 메모리 ]
+-------------+ +-------------+
| | | |
| 함수 호출 | | 객체 |
| 스택 프레임 | | 동적 할당 |
| 로컬 변수 | | 참조형 데이터 |
| | | |
+-------------+ +-------------+
public void recursiveFunction(int num) {
if(num == 0) return;
else recursiveFunction(num + 1);
} // recursiveFunction은 자기 자신을 끝없이 호출히여 각 호출마다 스택 프레임이 하나씩 추가되므로, 결국 스택 메모리의 한계에 도달하여 오버플로우가 발생