모르는 용어 정리
참조 타입 vs 값 타입
참깨빵위에참깨빵_
2024. 10. 13. 20:19
728x90
반응형
아래는 참조 타입, 값 타입을 설명하는 영문 위키백과 내용이다.
https://en.wikipedia.org/wiki/Value_type_and_reference_type
자료형은 값 타입, 참조 타입으로 분류된다. 참조 타입은 항상 참조를 통해 암시적으로 접근하지만 값 타입 변수는 값 자체를 직접 포함한다. 값 타입, 참조 타입의 정확한 속성은 언어마다 다르지만 일반 속성은 아래와 같다
- Boolean, 고정 크기 정수, 부동 소수점 값, 문자 등의 원시 타입은 값 타입이다
- 객체 지향 프로그래밍의 관점에서 객체는 참조 타입에 속한다
- 참조 타입의 변수에 할당하면 단순히 참조가 복사되지만 값 타입 변수에 할당하면 값이 복사된다. 이는 로컬 변수, 객체의 필드, 배열 요소 등 모든 종류의 변수에 적용된다. 함수 호출 시에도 마찬가지로 참조 타입의 매개변수는 참조의 복사본이고 값 타입의 매개변수는 값의 복사본이다
- 참조 타입이 변경 가능한 경우 하나의 참조를 통한 변경은 다른 참조에서도 볼 수 있지만, 값 타입이 변경 가능한 경우 한 값에 대한 변경은 다른 값에서 볼 수 없다
- 참조 타입은 동일성 개념을 지원하므로 참조 타입의 두 값이 같은 객체를 참조하는지 논의하는 게 합리적이며 언어에선 참조 여부를 판단하는 기능을 제공하지만 값 타입은 그렇지 않다
- 참조 타입의 값은 힙에 할당된 객체를 참조하지만 값 타입의 값은 호출 스택(지역 변수, 함수 매개변수의 경우) 또는 해당 포함 엔티티(객체 필드, 배열 요소의 경우) 내부에 포함돼 있다. 참조 타입의 경우 호출 스택, 포함 엔티티 안에 포함되는 건 참조 자체뿐이다
- 참조 타입은 주어진 참조 타입의 모든 값이 자동으로 다른 참조 타입의 값이 되는 서브타입 개념을 지원한다. 값 타입은 하위 유형화를 지원하지 않지만 다른 형태의 암시적 타입 변환(정수를 부동소수점으로 자동 변환 등)을 지원할 수 있다. 또한 특정 값 타입과 참조 타입 간에 암시적 변환이 있을 수 있다(Int를 Integer 객체 타입으로 박싱하거나 언박싱을 통해 역으로 변환하는 것)
< 참조 타입 및 공유를 통한 호출(call by sharing) >
함수 매개변수가 값에 의한 호출 의미론을 사용해서 전달되는 경우에도 참조 타입의 값은 본질적으로 참조기 때문에 매개변수가 참조 타입에 속하는 경우 결과 동작은 참조에 의한 호출(call by reference) 의미론과 어느 정도 유사하다. 이런 동작을 공유에 의한 호출(call by sharing)이라고 한다
공유에 의한 호출은 함수가 매개변수로 받은 객체를 바꾸는 경우 호출자, 함수가 같은 객체에 참조를 갖고 있기 때문에 호출자에게도 변경이 표시된다
함수가 매개변수를 다른 참조에 할당하는 경우는 참조에 의한 호출과 다르다. 이 때 호출자, 함수는 처음엔 두 참조가 모두 같은 객체를 가리키지만 호출자와 함수가 별도 참조를 갖고 있어서 호출자에겐 이 할당이 표시되지 않는다...(중략)
코틀린은 모든 것이 객체로 표현되기 때문에 모든 객체는 참조 타입으로 작동한다. 값 타입으로 작동하는 것처럼 보여도 실제론 참조 타입과 같이 작동한다. 그래서 모든 객체와 enum은 참조 타입이고 모든 원시형은 값 타입으로 취급하는 자바 언어로 예시를 확인한다.
아래는 참조 타입의 예시다.
class Person {
String name;
Person(String name) {
this.name = name;
}
}
public class Main {
public static void main(String[] args) {
Person person1 = new Person("김철수");
Person person2 = person1; // person1과 같은 객체 참조
person2.name = "이영희";
System.out.println("person1 name : " + person1.name);
System.out.println("person2 name : " + person2.name);
}
}
// person1 name : 이영희
// person2 name : 이영희
person1, person2는 모두 같은 Person 객체를 참조한다. 그래서 person2의 이름을 바꾸면 같은 객체를 참조하는 person1도 바뀐 값(=이영희)을 반영하게 된다.
아래는 값 타입의 예시다.
public class Main {
public static void main(String[] args) {
int a = 10;
int b = a;
b = 20;
System.out.println("a : " + a);
System.out.println("b : " + b);
}
}
// a : 10
// b : 20
값 타입은 변수에 실제 값(데이터)이 담기고 복사하면 서로 독립적인 복사본이 생성된다. 그래서 b의 값을 바꿔도 a에 영향을 주지 않는 걸 볼 수 있다. 영문 위키백과의 내용 중 '하나의 참조를 통한 변경은 다른 참조에서도 볼 수 있지만 값 타입이 변경 가능한 경우 한 값에 대한 변경은 다른 값에서 볼 수 없다'가 증명되는 것이다.
두 타입 간의 차이를 표로 정리하면 아래와 같다.
구분 | 값 타입 (Value Type) | 참조 타입 (Reference Type) |
저장 방식 | 변수에 실제 값이 저장됨 | 변수에 객체의 메모리 주소(=참조)가 저장됨 |
할당 방식 | 값을 다른 변수에 할당하면 값이 복사됨 | 값을 다른 변수에 할당하면 참조(주소)가 복사됨 |
변경 시 영향 | 한 변수의 값을 바꿔도 다른 변수에 영향을 주지 않는다 |
객체의 속성을 바꾸면 같은 객체를 참조하는 모든 변수가 변경됨 |
메모리 사용 방식 | 변수가 메모리에 값을 직접 저장 | 변수가 객체의 위치를 가리킴 객체는 힙 메모리에 저장됨 |
주로 쓰이는 경우 | 간단한 숫자, 문자 데이터 기본(원시) 자료형 |
복잡한 데이터 구조(객체, 배열, 컬렉션) |
독립성 | 값이 복사되기 때문에 두 변수는 독립적으로 작동함 |
같은 객체를 참조하므로 여러 변수가 같은 객체를 참조함 |
반응형