안녕하세요, 코린이의 코딩 학습기 채니 입니다.
개인 포스팅용으로 내용에 오류 및 잘못된 정보가 있을 수 있습니다.
☞ call by value
10의 값을 갖고 있는 변수를 만들어 test1의 매개인자로 넘겨주었습니다.
public class CallByValueReferenceStudy {
public static void main(String[] args) {
CallByValueReferenceStudy study = new CallByValueReferenceStudy();
int a = 10;
study.test1(a);
System.out.println("a = " + a);
}
public void test1(int n) {
n *= 30;
System.out.println("n = " + n);
}
}
@콘솔출력값
n = 300
a = 10
test1의 매개인자로 a(10)을 넘겨주었고, 해당 값은 매개변수인 n이 받았습니다.
그 후 n에는 30을 곱한 후 출력해봤을 때, n의 값은 300을 리턴하고, a는 그대로 10을 리턴하게 됩니다.
메모리 상으로 봤을 때는 아래와 같습니다.
여기까지가 study.test1(a)를 하였을 때의 메모리 구조 입니다.
변수 a가 갖고 있는 값인 10을 그대로 n이 넘겨받았으므로 n에는 넘겨받은 10이 들어있게 됩니다.
n값에 30을 곱하였을 때의 메모리 구조입니다.
n의 공간에는 기존 넘겨받은 a의 값인 10이 없어지게 되고 30을 곱한 300이 들어가있습니다.
따라서 n을 출력했을 때는 300, a를 출력했을 때는 10이 출력되는 것입니다.
마치 얕은 복사와 같은 원리입니다!
☞ call by reference
이번에는 1, 2, 3의 값을 갖고 있는 int형 배열을 매개인자로 넘겨주었습니다.
public class CallByValueReferenceStudy {
public static void main(String[] args) {
CallByValueReferenceStudy study = new CallByValueReferenceStudy();
int[] arr = {1, 2, 3};
study.test2(arr);
System.out.println("arr = " + Arrays.toString(arr));
}
public void test2(int[] brr) {
brr[1] = 20;
System.out.println("brr = " + Arrays.toString(brr));
}
}
@콘솔출력값
brr = [1, 20, 3]
arr = [1, 20, 3]
test2의 매개인자로 int형 배열 arr(1, 2, 3)을 넘겨주었고, 해당 값은 매개변수인 brr이 받았습니다.
그 후 brr[1]의 값을 20으로 변경 후 출력해보았을 때, 배열 arr과 배열 brr 모두 [1, 20, 3]을 리턴하게 됩니다.
메모리 상으로 봤을 때는 아래와 같습니다.
여기까지가 study.test2(arr)를 하였을 때의 메모리 구조 입니다.
배열은 참조형이므로 arr에는 실제 값이 아닌 주소값을 갖고 있으므로, brr 또한 arr의 주소값을 넘겨받게 됩니다.
brr[1]의 값을 20으로 변경하였을 때의 메모리 구조입니다.
arr와 brr모두 같은 객체를 공유하고 있으므로 brr에서 값 변경을 하면 arr에도 동일하게 적용됩니다.
같은 객체의 주소값을 갖고 있기 때문에 어느 곳에서 값 변경을 하던 arr, brr이 출력하는 값은 같게 됩니다.
이 또한 얕은 복사와 동일하게 적용되는 것이죠!
하지만, String 참조형은 예외입니다.
☞ String 참조형
이번에는 "안녕"의 값을 갖고 있는 String 참조형을 매개인자로 넘겨주었습니다.
public class CallByValueReferenceStudy {
public static void main(String[] args) {
CallByValueReferenceStudy study = new CallByValueReferenceStudy() {
String str = "안녕";
study.test3(str);
System.out.println("str = " + str);
}
public void test3(String s) {
s += "하세요";
System.out.println("s = " + s);
}
}
@콘솔출력값
s = 안녕하세요
str = 안녕
test3의 매개인자로 String 참조형 "안녕"을 넘겨주었고, 해당 값은 매개변수인 s가 받았습니다.
그 후 s의 값을 "안녕하세요"로 변경 후 출력해보았을 때, str는 "안녕", s는 "안녕하세요"를 리턴하였습니다.
String도 참조형으로 배열과 동일하게 s와 str 모두 변경된 "안녕하세요"가 출력될 줄 알았더니, 기존 str의 값은 유지 되는 것을 볼 수 있습니다.
메모리 상으로 봤을 때는 아래와 같습니다.
여기까지가 study.test3(str)를 하였을 때의 메모리 구조 입니다.
String은 참조형이므로 s에는 실제 값이 아닌 주소값을 갖고 있으므로, s 또한 str의 주소값을 넘겨받게 됩니다.
따라서 같은 객체를 가리키고 있겠죠.
s의 값을 "안녕하세요"로 변경하였을 때의 메모리 구조입니다.
기존 "안녕"에서 + "하세요"가 아닌 새로운 객체인 "안녕하세요"가 만들어지고 s에는 넘겨받았던 "안녕"을 가리키는 주소값이 아닌 새롭게 만들어진 "안녕하세요"의 주소값으로 변경된 것을 확인할 수 있습니다.
String 참조형은 변경 불가한 특징이 있기 때문입니다.
언뜻보면 문자열을 변경한 것으로 보이지만, 내부적으로는 변경이 아닌 새로운 객체를 만들어 그 주소값을 참조하도록 변경되는 것이죠.
따라서 str는 "안녕", s는 "안녕하세요"를 출력하게 되는 것입니다.
만약 기존 str에도 변경된 "안녕하세요"를 대입하고 싶다면, s를 리턴하여 str에 대입해주면 됩니다.
public class CallByValueReferenceStudy {
public static void main(String[] args) {
CallByValueReferenceStudy study = new CallByValueReferenceStudy();
String str = "안녕";
str = study.test3(str);
System.out.println("str = " + str);
}
public String test3(String s) {
s += "하세요";
System.out.println("s = " + s);
return s;
}
}
@콘솔출력값
s = 안녕하세요
str = 안녕하세요
리턴 타입을 String으로 변경하여 "안녕하세요"를 가리키는 s를 리턴하면 study.test3(str)에는 "안녕하세요"를 가리키는 주소값이 리턴 되게 됩니다.
그 값을 다시 str에 담아주면 동일하게 "안녕하세요"를 출력하게 되겠죠!
'Java > Java' 카테고리의 다른 글
생성자) 기본 생성자, 파라미터 생성자, 생성자 오버로딩, this() (0) | 2022.03.17 |
---|---|
메소드) 재귀 메소드 (Recurison) (0) | 2022.03.17 |
메소드) 메소드 오버로딩, 메소드 시그니처란? (0) | 2022.03.17 |
메소드) 인스턴스 메소드, static 메소드 (0) | 2022.03.17 |
접근 제한자) 멤버 및 생성자의 접근 제한자, 클래스의 접근 제한자 (0) | 2022.03.16 |