C언어를 공부하다 JAVA를 공부 하면서 가장 먼저 느끼는점은 "포인터"의 유무이다.
JAVA를 사용하다 보면 C언어를 사용 할 때 주의했던 포인터에 대해 크게 신경쓰지 않게 된다.
이는 JAVA는 call by reference가 존재 하지 않기 때문인가? 그렇다면 JAVA는 전부 call by value를 사용하는 것인가? 라는 의문이 들게 되었고 이번 토픽의 주제가 되었다
먼저 각각 의미를 알아보자
Call by Value
위키 검색
In call by value, the argument expression is evaluated, and the resulting value is bound to the corresponding variable in the function (frequently by copying the value into a new memory region). If the function or procedure is able to assign values to its parameters, only its local variable is assigned—that is, anything passed into a function call is unchanged in the caller's scope when the function returns.
위 내용에 따르면 call by value 메커니즘은 함수로 인자를 전달 할 때 전달될 변수의 인자값을 복사하여 함수의 인자를 전달한다고 합니다.
이 전달 받은 변수는 지역 변수 특징을 가지며 Caller는 변수를 복사를 하여 넘겨 주었으므로 Callee가 받은 이 변수에 대해서 변경은 Caller에게 영향을
주지 않습니다.
가장 쉬운 예로 swap 함수가 있습니다.
void swap(int v1,int v2){
int tmp=0;
tmp =v1;
v1=v2;
v2=tmp;
}
void main()
{
int x=10,y=20;
swap(x,y);
printf("%d %d",x,y);
return ;
}
결과는 10 , 20 이 나옵니다.
이는 swap함수를 진행 했지만 단지 인자로 전달된 x,y의 복사된 값(10,20)이 전달 됬기 때문입니다. 이 복사된 값을 저장하는 새로운 변수 v1,v2 가 생성되고 이 값에 대해서만 변경이 일어났기 때문입니다.
Call by Reference
Call by reference (also referred to as pass by reference) is an evaluation strategy where a function receives an implicit reference to a variable used as argument, rather than a copy of its value. This typically means that the function can modify (i.e. assign to) the variable used as argument—something that will be seen by its caller.
위 내용은
Call by reference는 인자로 사용될 변수의 레퍼런스를 함수로 전달하며 , 그것이 변수의 값은 아니다 라고 되어있다.
이것 역시 swap 함수를 이용해 예를 들어보자
void swap(int *v1,int *v2){
int tmp=0;
tmp =*v1;
*v1=*v2;
*v2=tmp;
}
void main()
{
int x=10,y=20;
swap(&x,&y);
printf("%d %d",x,y);
return ;
}
결과는 20 10 이 나오게된다.
x y 의 값이 서로 잘 변경되어진것을 볼수 있다.
바로 이렇게 인자로 레퍼런스를 넘겼기 때문에 호출한곳에서도 적용이 되어지게 된다
그렇다면 이번에 IN JAVA 에서는 어떻게 적용되어지는지 한번 확인해보자.
JAVA는 call by reference? call by value?
예시 코드를 만들어 확인 해보자.
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 | public class CallByX { public static void main(String[] args) { CallByX callByX = new CallByX(); Person oimb =new Person("oimb"); changePerson(oimb); System.out.println(oimb.name); } static void changePerson(Person person){ person = new Person("rimbong"); //person.name = "rimbong"; } } class Person { String name; public Person(String person_name) { this.name = person_name; } } | cs |
결과는 ?
oimb
결과는 아무런 변경이 없습니다.
이는 call by value의 특징에 해당 되어집니다. 이는 name이 oimb인 객체 자체(oimb )를 rimbong 을 갖는 객체(person)로 변경되어진것이 아니라
새로 주소가 할당 되어지고 여기에 name값 rimbong을 넣은 객체가 바뀌어진것입니다.
즉 쉽게 설명 하자면 oimb(저장된 레퍼런스 : 0x00 , 자체 레퍼런스 : 0x01 )가 인자로 전달되고 이후 person(복사된 레퍼런스 :0x00, 자체 레퍼런스 : 0x02)
으로 복사가 되어진 이후에 다시 new Person에 의해서 person에 복사된 레퍼런스가 "rimbong"으로 변경 되어집니다.
하지만 Caller가 인자로 전달한 oimb의 값이 변경이 되어진것은 아니죠
다음 예를 보면 이번에는 정말 쉬운 예입니다
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 | public class CallByX { public static void main(String[] args) { CallByX callByX = new CallByX(); Person oimb =new Person("oimb"); changePerson(oimb); System.out.println(oimb.name); } static void changePerson(Person person){ person.name = "rimbong"; } } class Person { String name; public Person(String person_name) { this.name = person_name; } } | cs |
결과는 ?
rimbong 이 되어집니다.
이는 앞서 설명 했듯이 자체 레퍼런스가 아닌 저장된 레퍼런스를 넘겻고 이 저장된 레퍼런스의 name을 변경한것 입니다.
이는 자체 레퍼런스를 참조하는것 없이 단순하게 저장된 레퍼런스로 가서 name의 속성을 변경한 것이지요 따라서 이는 call by value에 해당 됩니다
저장된 레퍼런스로 가니까 call by reference 아니야? 라고 생각 할수 있지만
call by reference란 자체 레퍼런스 를 찾아가서 그 값에 대한 변경이 이루어져야만 합니다.
위 두가지 사실로 명확하게 알아야 할 사실이 있는데
call by value에서 value는 단순한 primitive 값 뿐만 아니라 객체에 대한 포인터값 ( 저장된 레퍼런스) 까지 스코프에 해당된다는것을 알수 있습니다.
마지막으로 JAVA는 왜 call by reference 기능이 없는 것인가?
개인적인 사견으로는 java의 class의 특징이라고 생각한다
C에서는 class 와 비슷한 역할? 을 하는 구조체가 있다. 하지만 class와 차이가 있는데 이것은 바로 함수를 내포할 수 있는가에 대한 유무이다.
자바는 class 내부에 함수(매서드)를 담을 수 있다 하지만 구조체에서는 불가능 하다
이것 왜? call by reference와 관련이 있지? 라는 의문을 가질 수 있는데
C에서는 어떤 구조체든간에 어떠한 수행을 위해서는 코드에 있는 함수를 호출 하는것이 불가피하고 이때 실제적 값의 변화를 위해서는 변수의 포인터를 넘길 수밖에 없다.
하지만 JAVA 에서는 함수를 내포하기 때문에 객체의 래퍼런스를 담고있는 변수만 있다면 그 객체 내부의 함수를 사용하면 되므로 따로 그 변수(객체) 자체의 포인터(레퍼런스) 값은 필요없는 것이다.
이는 내 개인적 사견이므로 맹목하지는 말아주세요!
이상으로 C 와 JAVA에서 혼동이 일어 날수 있는 부분 Value or Reference에 대한 정리를 마치겠습니다.!
끄적끄적 REST API ? <1> (0) | 2019.03.12 |
---|---|
IP address (0) | 2018.07.10 |
3-WAY Handshake (0) | 2018.06.27 |
Unicode,UTF (0) | 2018.06.25 |
BASE64 (0) | 2018.06.25 |