일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 자바 고급2편 - io
- 스프링 mvc2 - 검증
- 자바의 정석 기초편 ch2
- 스프링 mvc1 - 스프링 mvc
- 자바 중급1편 - 날짜와 시간
- 자바의 정석 기초편 ch1
- 스프링 mvc2 - 로그인 처리
- 람다
- 2024 정보처리기사 수제비 실기
- 스프링 트랜잭션
- 자바의 정석 기초편 ch6
- 자바의 정석 기초편 ch4
- 자바 고급2편 - 네트워크 프로그램
- 자바의 정석 기초편 ch9
- @Aspect
- 스프링 mvc2 - 타임리프
- 자바의 정석 기초편 ch12
- 자바로 계산기 만들기
- 데이터 접근 기술
- 자바의 정석 기초편 ch7
- 자바의 정석 기초편 ch5
- 자바의 정석 기초편 ch14
- 자바 기초
- 스프링 입문(무료)
- 스프링 고급 - 스프링 aop
- 자바의 정석 기초편 ch13
- 자바로 키오스크 만들기
- 2024 정보처리기사 시나공 필기
- 자바의 정석 기초편 ch11
- 자바 중급2편 - 컬렉션 프레임워크
- Today
- Total
개발공부기록
Java는 Call By Value? Call By Reference? 본문
Call By Value
설명
- 메서드 호출 시 인자로 전달되는 값 자체를 복사하여 넘긴다는 뜻이다
- 즉, 원본 값은 메서드 내부로 복사되어 별도의 독립적인 변수로 사용된다
기본형(primitive type)
- 기본형 데이터(int, double, boolean 등)은 값 자체가 복사되어 전달된다.
- 메서드 내에서 변경된 값은 원본 변수에 영향을 주지 않는다
참조형(reference type)
- 객체의 참조값(주소)가 복사되어 전달된다.
- 메서드 내에서 참조값 자체를 바꿔 재할당 하면 원본 참조에는 영향을 주지 않는다.
- 하지만 객체의 속성(상태)를 변경하면 같은 객체를 참조하고 있으므로 원본 객체에도 변경이 반영된다
Call By Reference
설명
- 메서드 호출 시 인자의 참조(메모리 주소)를 직접 전달하는 방식이다
- 인자의 참조 자체가 메서드 내부로 전달되기 때문에 메서드 내에서 매개변수의 값을 변경하면 원본 값도 함께 변경된다
기본형(primitive type)
- 기본형 데이터는 참조에 의한 호출이 일반적으로 사용되지 않는다
참조형(reference type)
- 참조 주소를 직접 전달하기 때문에 메서드 내에서 인자의 내용을 변경하면 원본 데이터에도 동일하게 반영된다
- 새로운 객체를 할당하면 원본 개체의 참조도 변경, 즉 메서드 내부에서 새로운 객체를 할당하면 원본 변수도 새 객체를 가리키게 된다.
Java는 무엇일까?
자바는 기본적으로 모든 인자 전달이 Call By Value 방식이다
다만 객체의 경우 '참조값을 복사하여 전달'하기 때문에 마치 Call By Reference 처럼 보일 수 있는데 실제로는 참조 값 자체를 복사한 것이니 때문에 Call By Value 방식이다.
Call By Reference 방식으로 동작하는 대표적인 언어는 C++가 있다.
Java 기본형 예시

자바에서 기본형인 경우에는 위의 그림처럼 int b 변수에 a를 할당하여도, 주소값이 아닌 리터럴 1이 복사 되어 b에 저장된다
그렇기 때문에 이후에 b의 값을 2로 변경해도 a와는 전혀 무관하다.

출력해보면 결과깂이 a = 1, b = 2로 출력되는 것을 확인할 수 있다.
Java 참조형 예시
자바는 이 참조형 때문에 Call By Reference 방식으로 동작한다고 오해하는 경우가 많지만 자바는 객체가 저장된 메모리 주소값을 복사해서 대입하기 때문에 Call by Value이다

내부에 int값을 가지고 있는 참조형 MyInteger가 있다.

먼저 new MyInteger()로 MyInteger 객체를 생성하면 힙 메모리에 올라가게되고 고유의 주소값을 가지는데, 이 주소값을 MyInteger myInteger1에 복사해서 저장한다
그 이후 myInteger1의 내부 필드에 2를 저장하면서 상태를 변경한다

MyInteger 타입 myInteger2 변수를 선언하고 myInteger1이 저장하고 있는 메모리 주소값을 myInteger2에 복사하여 저장한다
그 이후 myInteger2의 내부 필드에 3을 저장하면서 상태를 변경한다
그러면 myInteger1과 myInteger2의 필드의 값은 각각 무엇을 출력할까?

정답은 모두 3이된다.

myInteger2에 myInteger1의 주소값을 복사해서 저장했기 때문에 myInteger2와 myInteger1은 같은 MyInteger 인스턴스의 메모리 주소를 가지고 있으므로 같은 인스턴스를 가리키게 된다
그러므로 두 개의 변수를 이용하여 인스턴스의 상태를 변경하게 되면 두 변수가 가리키고 있는 MyInteger의 인스턴스는 동일하기 때문에 두 변수의 값이 모두 변경된 것 처럼 보이는 것이다
이 지점이 Call By Reference 처럼 보이게 하는 지점인데, 이건 주소 값을 복사해서 각 변수들이 같은 메모리 주소를 가리키고 있기 때문에 벌어진 일이라는 것을 명확하게 인지해야한다.
다음을 보면 확실이 이해할 수 있을 것이다

myInteger2 변수에 새로운 MyInteger() 인스턴스를 생성하여 완전히 새로운 메모리 주소를 복사하여 저장한다.
그리고 새로운 인스턴스 주소를 저장하고 있는 myInteger2의 필드의 값을 10으로 변경한다.
이런 상태에서 출력하면 어떻게 될까?

정답은 myInteger1과 myInteger2는 이제 서로 다른 메모리 주소를 가지고 있기 때문에 myInteger2의 상태만 변경되어 myInteger1는 그대로 3을 출력하게되고 myInteger2는 10을 출력하게 된다.

즉, 자바는 Call By Value의 방식으로 값을 복사해서 전달하기 때문에 myInteger2에 새로운 객체를 생성해서 새로운 메모리주소를 할당했을 때, myInteger1과 동일한 주소를 가지고 있지만 서로 별개의 변수이므로 myInteger2에만 새로운 메모리 주소가 할당된 것이다.
만약 Call By Reference 였다면 myInteger2에 새로운 객체가 할당 되었을 때 myInteger1에도 새로 할당된 객체의 메모리 주소가 할당되어 myInteger1의 필드 값도 10이 되었을 것이다.