Java - 참조(reference)

Yuri Lee·2020년 10월 7일
0

복제

전자화된 시스템의 가장 중요한 특징은 복제다. 현실의 사물과 다르게 전자화된 시스템 위의 데이터를 복제 하는데는 비용이 거의 들지 않는다. 바로 이러한 특징이 소프트웨어를 기존의 산업과 구분하는 가장 큰 특징일 것이다. 프로그래밍에서 복제가 무엇인가를 살펴보자.

기본 데이터 타입이 있다는 말은 기본 데이터 타입이 아닌 것이 있다는 뜻!
데이터 타입을 생성할 때 new 를 통해서 생성하는 것들은 기본 데이터 타입이 아니고 참조형 데이터 타입이라고 한다. (참조 데이터 형이다)

package com.yuri.javatutorials.reference;

public class ReferenceDemo1 {

	public static void runValue() {
		int a = 1;
		int b = a;
		b = 2;
		System.out.println("runValue, " + a);
	}

	public static void main(String[] args) {
		runValue();
	}

}

기본 데이터 형을 담을 수 있는 int, a라는 변수에 1을 담았다. 그리고 b에 값에 a를 담고, 다시 b에 2를 넣었을 때 그 값은 어떻게 될까?

결과

runValue, 1

b를 2로 바꿔도 결과는 1이라는 것이다. 결과는 당연하다. 값을 변경한 것은 변수 b이기 때문에 변수 a에 담겨있는 값은 그대로이다. 변수 b의 값에 변수 a의 값이 복제된 것이다. 이를 그림으로 표시하면 아래와 같다.

참조

package com.yuri.javatutorials.reference;

class A {
	public int id;

	A(int id) {
		this.id = id;
	}
}

public class ReferenceDemo1 {

	public static void runValue() {
		int a = 1;
		int b = a;
		b = 2;
		System.out.println("runValue, " + a);
	}

	public static void runReference() {
		A a = new A(1); // a 는 클래스 A의 인스턴스 저장 
		A b = a; // 변수 b의 데이터 타입은 A이고, a를 할당함
		b.id = 2; // 변경
		System.out.println("runReference, " + a.id); // 이 값이 2가 될까 ? 1이 될까? 
	}

	public static void main(String[] args) {
		runValue();
		runReference();
	}

}

/*
runValue, 1
runReference, 2
*/

기본 데이터 타입을 담을 수 있는 변수에 담겨있는 값과 기본 데이터 타입이 아닌 new를 통해서 만드는 데이터 타입이 담겨있는 변수 a는 서로 다르게 동작한다.

구체적인 값을 가진 게 아니라 변수는 인스턴스를 구별할 수 있는 주소값만 가지고 있는 것! 그것을 참조, reference라고 한다.

변수 b에 담긴 인스턴스의 id 값을 2로 변경했을 뿐인데 a.id의 값도 2가 된 것이다. 이것은 변수 b와 변수 a에 담긴 인스턴스가 서로 같다는 것을 의미하다.

참조와 복제의 차이

원본.txt
원본.txt - 바로가기 : 원본.txt과 정확히 동일!
원본.txt에 100G가 있더라도 바로가기가 100개 있어도 적게 차지함 ...~
하지만 복제하면 100, 200, 300 .. GB 늘어남 ....

복제는 파일을 복사하는 것이고 참조는 심볼릭 링크(symbolic link) 혹은 바로가기(윈도우)를 만드는 것과 비슷하다. 원본 파일에 대해서 심볼릭 링크를 만들면 원본이 수정되면 심볼릭 링크에도 그 내용이 실시간으로 반영되는 것과 같은 효과다. 심볼릭 링크를 통해서 만든 파일은 원본 파일에 대한 주소 값이 담겨 있다. 누군가 심볼릭 링크에 접근하면 컴퓨터는 심볼릭 링크에 저장된 원본의 주소를 참조해서 원본의 위치를 알아내고 원본에 대한 작업을 하게 된다. 다시 말해서 원본을 복제한 것이 아니라 원본 파일을 참조(reference)하고 있는 것이다. 덕분에 저장 장치의 용량을 절약할 수 있고, 원본 파일을 사용하고 있는 모든 복제본이 동일한 내용을 유지할 수 있게 된다. 참조는 전자화된 세계의 극치라고 할 수 있다.

프로그래밍에서 광범위하게 사용하는 라이브러리라는 개념도 일종의 참조라고 할 수 있다. 공용 라이브러리를 사용하게 되면 하나의 라이브러리를 여러 애플리케이션에서 공유해서 사용하게 된다. 라이브러리의 내용이 변경되면 이를 참조하고 있는 애플리케이션에도 내용이 반영되게 된다. 또 우리가 변수를 사용하는 이유도 말하자면 참조를 위해서라고 할 수 있을 것이다. 본질을 파악하면 이해력도 높아지고 암기할 것도 줄어든다.

정리하면 변수에 담겨있는 데이터가 기본형이면 그 안에는 실제 데이터가 들어있고, 기본형이 아니면 변수 안에는 데이터에 대한 참조 방법이 들어있다고 할 수 있다.

참조 데이터 형과 매개 변수

다시보기.....😢😢😢😢😢

package com.yuri.javatutorials.reference;

public class ReferenceParameterDemo {

	static void _value(int b) {
		b = 2;
	}

	public static void runValue() {
		int a = 1;
		_value(a); //a가 b로 들어간 것이니 int b = a;와 같다는 뜻, 그 상태에서 b = 2로 바꾸면 b와 연결되어있는 인스턴스인 a의 값을 2로 바꾼 것이다? 아님 실행해보면 1임
		System.out.println("runValue, " + a);
	}

	static void _reference1(A b) {
		b = new A(2);
	}

	public static void runReference1() {
		A a = new A(1);
		// 변수 a의 인스턴스를 담았음. 기본 데이터 타입이 아니므로 참조 , id 값은 1인 상태 / A b = a;라는 뜻 , 그리고 그 밑에서 
		// b = new A(2);를 실행하면 변수 b가 만들어짐, id값이 2인 인스턴스를 참조하고 있음. 그래서 b의 값이 바뀌었다고 해도 a에게 변화를 줄 수 없음 
		_reference1(a);
		System.out.println("runReference1, " + a.id);
	}

	static void _reference2(A b) { //A b 는 A b = a;라는 뜻 
		b.id = 2; // b와 연결되어있는 인스턴스의  id를 2로 바꾼 것! 따라서 a.id 역시 2가 됨...
	}

	public static void runReference2() {
		A a = new A(1); // 변수 a가 인스턴스를 참조하고 있고 , A b = a;라는 뜻  변수 b는 a를 참조하고 있음
		_reference2(a);
		System.out.println("runReference2, " + a.id);
	}

	public static void main(String[] args) {
		runValue(); // runValue, 1
		runReference1(); // runReference1, 1
		runReference2(); // runReference2, 2
	}

}

/*
runValue, 1
runReference1, 1
runReference2, 2
*/

이 글은 생활코딩의 자바 강좌를 바탕으로 정리한 내용입니다.

profile
Step by step goes a long way ✨

0개의 댓글