일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 31 |
- 운영 체제
- sw expert academy
- 요세푸스
- 부동소수점
- 다단계 칫솔 판매
- 프로그래머스
- 티스토리챌린지
- 토마토
- 순열
- 오블완
- 데이터
- 고정소수점
- 구현
- swea
- 기능 개발
- 백준
- 도둑질
- java
- 괄호 회전하기
- 컴퓨터구조
- 코테
- 메뉴 리뉴얼
- 베스트 앨범
- 표 편집
- Comparable
- Call-by-Value
- 컴퓨터 구조
- 조합
- Comparator
- 자바
- Today
- Total
감자는 아직 꿈을 꾼다.
[꼬꼬무-자바] 자바는 Call-By-Value ? Call-By-Reference? 본문
😁Call - By - Value vs Call - By - Reference
C/C++를 경험한 사람이라면 모두 위 주제에 대하여 어느 정도는 알고 있을 것이다.
포인터,&주소참조자? 이런 개념들 말이다. 하지만 오늘 C/C++에 대해 말하려 하는 게 아니다.
위의 기준은 인수를 전달하는 방식의 차이로 구분된다.
자바는 어떻게 인수를 전달할까?
결론은 자바는 무조건 Call - By - Value 다!!
🖥️Call - By - Value ?
-> 변수의 복사본을 전달 ( 값을 복사 )
인수로 변수의 복사값을 전달하는 방식이다. 함수를 호출하면 스택프레임에 영역이 할당된다.
main역시도 함수고 스택영역에 할당 되어있다.
main에서 지역변수 a,b를 선언하고 새롭게 함수를 호출해서 인자로 전달하면
main의 a,b가 전달 되는 것이 아니라 새로운 함수의 스택프레임이 할당되고
그곳에 a,b의 복사본이 새롭게 생성된다.
메모리에 새롭게 할당 되는 방식이므로 메모리 효율적이지 못하다.
하지만 원본 데이터를 보호한다는 장점이 있다.
이후 자바에서의 방식을 소개하며 그림을 보면 어느정도 이해에 도움이 될 것이다,
✈️Call - By - Reference ?
-> 참조에 의한 호출
참조 자체를 인수로 넘기는 방식으로 원본의 데이터에 수정 작업이 그대로 반영되어서 적용된다. 그렇기에 메모리 효율적이다. 위에서 말했듯 변수의 복사본을 전달하는 방식은 스택에 메모리를 그대로 차지하기 때문에 메모리 효율적이지 못하다. 하지만 참조 자체를 넘기면 스택 영역에 새롭게 메모리 할당이 필요 없기때문이다.
하지만 그렇기에 보안에 위험하다. 참조를 넘긴 다는 건 원본에 그대로 영향을 미칠 수 있다는 것이기에
그래서 이런 call-by-reference 상황에는 immutable 객체를 전달하는 방식을 쓰기도 한다.
🥸자바는 Call - By - Value !
자바의 자료형은 primitive type (원시형) / reference type ( 참조형 ) 으로 나뉜다.
primitive type - Numeric ( byte,short,int,long,float,double,char ) , Boolean ( boolean )
reference type - Class, Interface, Enum, Array, String, Integer 등
원시 타입은 Stack 영역에 저장된다.
참조 타입의 객체는 Heap에 저장되며 Stack영역에 있는 변수가 객체의 주소값을 가지고 있다.
실제 코드를 보면서 자바에서는 왜 Call - By - Value 인지 보도록 하자.
public class Solution {
public static void main(String[] args) {
int[] arr = {1,2,3};
mul(arr);
System.out.println(Arrays.toString(arr));
}
private static void mul(int[] arr_2) {
arr_2[0] *=100;
}
}
출력값 : [100,2,3]
그림과 같이 메인에서 선언된 arr은 Array즉 참조 타입으로 설명한 바와 같이 스택영역에 있는 arr변수가 Heap의 주소값인 A를 가지고 있다. 이상태에서 mul함수를 호출하면서 arr를 전달하면 arr의 주소값을 가지고 있는 arr_2라는 새로운 변수가 mul 스택 프레임 영역에 할당되는 것이다. 그림과 같이 mul호출에 의해 arr의 인덱스 0번 값이 100곱해진 것을 확인 할 수있다. 실제로 출력하면 100,2,3이 출력된다.
이러면 도대체 Call-By-Reference랑 다를 게 뭐야?
아니 이러면 주소값을 전달해서 원본데이터를 수정하면 Call-By-Reference 잖아
라고 생각할 수 있다. 하지만 엄연히 다르다. 다음 코드를 보자
public class Solution {
public static void main(String[] args) {
int[] arr = {1,2,3};
mul(arr);
System.out.println(Arrays.toString(arr));
}
private static void mul(int[] arr_2) {
arr_2 = new int[] {2,3,4};
}
}
출력값: [1,2,3]
출력값을 보면 1,2,3으로 전혀 arr 원본의 데이터 값이 변경되지 않았다.
그림과 같다. 실제로 arr_2는 객체를 생성하는 순간 새로운 주소값인 B를 가르키게 되면서 원본의 데이터가 수정되지 않는 것이다. Call-By-Reference라면 참조 자체가 전달되어 원본 값인 arr의 A주소값에 있는 데이터가 수정 되었을 것이다.
하지만 그냥 단순히 주소값만 전달 된것이다. 자바에서는 원시형으로 변수값을 복사해서 전달하던지 주소값을 전달하던지 Call-By-Value 인것.
단순하게 원시형이면 변수값으로 연산을 진행하는 것이고
주소값이면 해당 메모리의 주소를 참조해서 값을 가져오는 것
그러면 왜 자바는 Call-By-Value 일까
-> 위에서 언급한 것처럼 자바는 C/C++ 처럼 메모리를 타이트하게 관리할 필요 없이 GC가 관리하기에
C처럼 포인터를 자유롭게 사용해서 보안상 문제를 막는 것
c에서는 실제로 포인터 때문에 Dangling-pointer 문제 등 다양한 메모리 관련 문제가 존재한다.
이는 c언어 특성인 것으로 알다시피 성능과 메모리관리 두가지 사이에서의 Trade off인것이다
마무리
자바는 값으로 호출한다.
'개발적 감자 > [꼬꼬무-자바]' 카테고리의 다른 글
[꼬꼬무-자바] Comparable vs Comparator (0) | 2024.11.07 |
---|