Pointer (참조자료형)

김명래·2022년 9월 5일
0

OOP

목록 보기
2/4

Pointer의 유래

포인터라는 사냥개는 목표물을 사냥하는것이 아닌 위치를 알려주는 사냥개이다.

프로그래밍에서 포인터도 이와같다.
해당 값을 가져오는것이 해당 값이 가지고있는 메모리 공간 주소 즉, 주소값(위치)를 가지고 오는것. 이때 포인터가 가리키는 값을 가져오는 것을 역참조 라고한다.

사실 이 예제는 C 에서 다루는것이 맞을지도 모른다.
하지만 JAVA 에서도 이 개념을 모르면 난감한 경우가 있다.

먼저 C 에서 예제를 보자.

#include <stdio.h>

int main(void) {
	int *p;
	int test = 2;
	
	p = &test; // test의 주소값을 가져온다는 의미
	
	printf("%p\n", p); 
	
	printf("%d\n", *p); //역참조
	
	return 0;
}
/////////////////////////출력값//////////////////////
0x7fffe8aa86b4
2

천천히 살펴보면 쉽다 첫번째로 출력한것은 test가 위치한 "주소"이고

두번째로 출력한것은 test의 "값"이다.

따라서 *p 라는 변수는 주소값을 가지고 있는것인대 이것은 여러모로 많이 적용된다

참고하자면 *p의 크기는 사용자의 프로그램의 따라 달라지는데 32Bit의 프로그램은 4Bytes 64Bit의 프로그램은 8Bytes를 사용하게된다
32Bit의 프로그램에서 표현가능한 메모리크기는 4,294,967,296 Byte이고 이는 4GB가 된다. 즉, 최대 가용할 수 있는 메모리가 4GB라는것. 따라서 가용할 수 있는 모든 메모리의 경우의 수를 표현하기 위해서는 4Bytes 크기의 자료형이어야 하기 때문이다.
최근에는 64Bit OS나 64Bit JVM 을 사용함으로 8Bytes크기를 가진다.

대충 포인터에 대해 이해했으면 이제 자바에 참조 자료형을 보자.

String

거의 자바에서 대표격으로 나오는 참조자료형의 근본.

시원하게 다음 예제를 보자

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
	public static void main (String[] args) throws java.lang.Exception
	{
		String str = "김명래"; // 김명래라는 문자열을 생성하고 그 위치를 참조하는 변수 str
		String str2 = "김명래";//new keyword를 사용하지 않으면 메모리에서 먼저 동일한 자료가 있는지 확인
			                   //"김명래"이라는 동일한 자료가 있으므로 동일한 자료가 있는 주소를 참조하여
			                   // str2변수에 그 주소(100)를 대입한다.
			                   
		String str3 = new String("문자열"); // new keyword 사용시 메모리에서 동일한 자료를 찾지않고 바로 
		                                 //생성하여 새로운 주소를 할당 받는다.
		                                 
		if(str == str2){
			System.out.println("str 과 str2는 같은 문자열이네요 !");
		}else{
			System.out.println("너 다르구나 ! ");
		}
		
		if(str != str3){
			System.out.println("str과 str3는 다른 문자열이군요 ! ");
		}
		
	}
}
///////////////////////출력
str 과 str2는 같은 문자열이네요 !
str과 str3는 다른 문자열이군요 ! 

분명 str과 str3는 같은 문자열임에도 불구하고 프로그램은 같지않다고 판단했다 왜 일까 ?
서로 참조하는 주소가 다르기 때문이다.
값이 같다고해서 주소까지 같다는건 아니라고 볼 수 있다. 따라서 문자열 비교를 할땐 equals method를 사용하는것.

그리고 한번 더 짚고나갈 예제는 다음과 같다.

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
	public static void main (String[] args) throws java.lang.Exception
	{
		int test = 10;
		Test t = new Test();
		t.sum(test);
		System.out.println("test의 값 : " + test);
		Member m = new Member();
		m.setNumber(20);
		System.out.println("m의 number값" + m.getNumber());
		t.setMemberNumber(m);
		System.out.println("m의 number값" + m.getNumber());
	}
	
	
}

class Test{
	public void sum(int arg1){
		arg1+=10;
		System.out.println("sum 함수 실행 결과 : " + arg1);
	}
	public void setMemberNumber(Member m){
		m.setNumber(40);
	}
}
class Member{
	private int number;
	
	public void setNumber(int number){
		this.number = number;
	}
	public int getNumber(){
		return this.number;
	}
}
/////////////결과 값
sum 함수 실행 결과 : 20
test의 값 : 10
m의 number값20
m의 number값40

천천히 살펴보자 먼저 sum 함수를 실행했을때는 test 의 값이 변하지 않았고
Member 의 필드로 선언된 number는 함수실행이후 값이 바뀌어있는것을 확인할 수 있다.
왜 일까 ?
이유는 다음과 같다.
sum 함수를 실행했을때는 "arg1"이라는 변수에 test값을 대입했고 "arg1"의 값에 10을 더한것이다.
따라서 arg1 과 test는 전혀 다른 사이라는것.

이를 우리는 깊은 복사라고 부른다.

하지만 Member m의 경우는 다르다.

setMemberNumber함수를 실행했을때 m의 값을 넘겨준것이 아닌 "주소"를 넘겨준것이기때문에
결국 같은값을 참조하게 된것이다.

이렇게 같은 값을 "참조"하게 되는것을 얕은 복사라고 부른다.

profile
독자보다 필자를 위해 포스팅합니다

0개의 댓글