Java - 얕은 복사와 깊은 복사

컴퓨터/Java

728x90
반응형

프로그래밍과 메모리

프로그래밍을 하는 과정에서 데이터가 메모리에서 어떻게 동작하고 있는지를 알고 있는다는 것은 아주 중요한 일입니다. 다양한 변수 , 함수 , 객체 등이 다 메모리 안에서 저장되고 그것을 꺼내 쓰는 것이기 때문입니다. 하지만 Java 같은 언어에서는 메모리에 대한 직접적인 개념이 바로 보여주고 있지 않아, 공부를 하는데 어려움을 느끼기도 합니다. Java언어에서 메모리를 어떻게 이용하는지 간단하게 알아보도록 하겠습니다.

 

얕은 복사와  깊은 복사

Java 등 많은 프로그래밍 언어를 다루다 보면 많이 듣는 용어 중 하나입니다.  C언어나 C++ 등을 배워 포인터의 개념을 이해하고 있다면 이런 얕은 복사와 깊은 복사에 대한 이해가 조금 더 쉬울 것입니다. 우리가 인스턴스 변수, 일반 변수 , 배 열등 다양한 방식으로 값을 제어하기 위한 변수를 선언하면 어떠한 메모리 공간에 데이터를 넣는 것입니다.  이런 다양한 변수들은 사실 2가지의 값을 개념이  정립되어야만 사용할 수 있습니다.

 

  • 메모리 공간과 크기 (자료형과 메모리의 주소)
    • 변수의 자료형과 이름으로 접근 (사용자에게 간접적으로 표현해 준다)
  • 메모리 공간에 들어있는 데이터의 제어
    • 실제 연산 또는 대입 연산을 통해 사용

아래 그림을 참조하시면 조금 더 이해가 쉬울 것입니다.

 

class A
{
	int number;
}

선언된 클래스 A를 인스턴스 변수 Test로생성을 하게 된다면 메모리 공간에서는 그림과 같이 될 것입니다. 그리고 정리하자면 아래와 같습니다.

  • 인스턴스 변수 Test는 메모리 주소 FB98부터 시작된다.
  • Test 안의 number는 십진수 100을 대입시킨다.

얕은 복사

그렇다면, 아래와 같은 경우에는 어떻게 될까요?

class A
{
	int number;
}
public class CopyTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		A Test = new A();
		Test.number = 100;
		A TestCopy = Test;	
		System.out.println(Test.number);
		System.out.println(TestCopy.number);
		Test.number = 200;
		System.out.println(Test.number);
		System.out.println(TestCopy.number);
	}
}

결괏값을 한번 확인해 보면 위와 같은 결과가 나옵니다. 새로운 TestCopy라는 클래스에 Test를 대입하면 Test안에 있는 데이터의 값이 들어가는 것이 아닌 메모리의 주소가 복사되는 개념이 되는 것입니다. 따라서 TestCopy 변수는 Test의 메모리 주소를 참조하여 동일한 메모리 주소를 같고 있는 것입니다. 

이런 개념을 바로 얕은 복사라고 하며 메모리 주소 안에 값을 공유하여 공동 제어하는 형태가 됩니다. 

이 얕은 복사의 개념을 이용하면 다른 변수들을 이용하여 공통된 하나의 값을 제어 하를 할 수 있는 특징이 생깁니다. 

 

깊은 복사

그렇다면 깊은 복사는 어떤지 알아봅시다. 깊은 복사의 개념은 얕은 복사의 개념과는 다르게 그 값 자체를 새로운 공간에 할당시키는 것입니다. 위의 예제와 동일한 class를 통해 깊은 복사를 구현하면 아래의 소스코드와 같습니다.

 

class A
{
	int number;
}
public class CopyTest {
	public static void main(String[] args) {
		// TODO Auto-generated method stub

		A Test = new A();
		Test.number = 100;
		A TestCopy = new A();
        TestCopy.number = Test.number;
        
		System.out.println(Test.number);
		System.out.println(TestCopy.number);
		Test.number = 200;
		System.out.println(Test.number);
		System.out.println(TestCopy.number);
	}
}

위처럼 깊은 복사의 개념을 사용, 즉 메모리 주소를 복사하는 것이 아닌 새로운 메모리 공간을 할당(인스턴스 생성)을 한 후 값을 대입을 시켰습니다. 이런 식으로 값의 복사가 이루어지는 것이 바로 깊은 복사의 개념입니다.

 

 

추가로 공부하면 좋을 내용

사실 Java에서 깊은 복사와 얕은 복사의 개념은 이렇게 메모리의 구조로 설명하는 것이 아닌 사용방법과 특징에 대해서만 많이 얘기합니다. 하지만 왜 그런지 어느 정도의 이유를 알고 추적을 한다면 기억하기에도 좋고 잘 활용할 수 있을 것입니다. 이 내용에 대해 더 궁금하다면 C언어나 C++ 등에서 포인터의 개념을 한번 추가로 공부해 보시길 권유드립니다.

 

728x90
반응형

Commnet

G91개발일지

Gon91(지구일)

91년생 공학엔지니어의 개발일지

TODAY :

YESTER DAY :

TOTAL :