개요
'2. 변수와 자료명 (1)'에서 이어집니다.
참조
참조(Reference)는 주솟값을 저장하는 것입니다.
메모리 사용 영역
JVM은 운영체제에서 할당 받은 메모리 영역을 메소드 영역(Method Area), 힙 영역(Heap Area), JVM 스택(Stack)으로 구분합니다.
메소드 영역은 JVM이 시작될 때,
생성되고 모든 스레드(thread)를 공유하는 영역입니다.
코드에서 사용되는 class를 class loader을 통해 읽고,
class별로 정적(static) 필드와 상수, 메서드 코드, 생성자(constructor)* 코드 등을 분류해서 저장합니다.
힙 영역은 객체와 배열과 같은 래퍼런스 타입 변수의 실제 값이 생성되는 영역이고,
이들은 JVM 스택 영역의 변수 또는 다른 객체가 참조합니다.
참조하는 값이 없다면, 가비지 컬렉터(Garbage Collector)가 감지하여, 자동으로 해제합니다.
JVM 스택 영역은, 메소드를 호출하면 프레임을 추가(push)하고,
종료되면 프레임을 제거(pop)하는 동작을 수행합니다.
프리미티브 변수는 스택 영역이 직접 값을 가지고 있지만,
래퍼런스 변수는 스택 영역에 힙 영역의 객체 주소를 가집니다.
참조 변수의 연산
프리미티브 변수는 ==, != 연산을 ‘같다’와 ‘같지 않다’로 인식하지만,
래퍼런스 변수는 동일한 객체를 참조하는지의 여부로 이를 인식합니다.
즉, 래퍼런스 변수들이 같은 값을 참조할 경우 ==를, 다른 값을 참조할 경우 !=를 의미합니다.
📢 출력 예시
true
ABC
arr1과 arr2는 같은 값을 참조하므로, arr1 == arr2는 항상 true가 출력됩니다.
new 연산자
배열과 문자열은 둘 다 래퍼런스 변수지만, 두 개는 참조하는 방식이 약간 다릅니다.
📢 출력 예시
str1과 str2는 같은 값을 참조합니까? true
arr1과 arr2는 같은 값을 참조합니까? false
문자열은 값이 같은 경우 항상 같은 값을 참조하고, 배열은 서로 다른 값을 참조합니다.
하지만, 입력한 값이 같다고 하더라도 참조하는 값이 달라야 하는 상황이 생길 수도 있습니다.
이 경우에는 new 연산자를 사용합니다.
📢 출력 예시
str1과 str2는 같은 값을 참조합니까? false
new 연산자는 heap 영역에 새로운 객체를 만들기 때문에, ‘객체 생성 연산자’라고도 부릅니다.
스레드*: 프로그램을 실행할 때, 실행 흐름의 최소 단위
생성자**: 객체의 초기화를 담당하는 메소드
배열
배열은 같은 타입의 데이터를 연속된 공간에 나열하고,
각 데이터에 인덱스(index)를 부여해놓은 자료구조입니다.
배열은 기본적으로 다음 조건을 만족해야 합니다.
1. 배열 내 인덱스의 모든 자료형이 같다.
배열의 정의에 따라, int형인 경우 모든 인덱스는 int, float형인 경우 모든 인덱스는 float여야 합니다.
2. 한 번 생성된 배열은 크기를 변경할 수 없다.
크기가 5인 배열을 생성한 경우, 프로그램 실행 도중, 배열의 크기를 줄이거나 늘릴 수 없습니다.
1차원 배열
배열을 선언하는 방법은 두 개가 있습니다.
배열은 참조 변수이므로, 선언시 heap 영역에 그 값이 저장되고,
이를 가리키는 주솟값이 stack에 저장됩니다.
또한, 이들은 아무 값을 입력하지 않는다면,
타입의 기본값이 저장됩니다.
배열이 참조할 것이 없다면, null 값으로 초기화할 수 있습니다.
배열을 생성하는 방법은 크게 두 가지로 나뉩니다.
값 목록으로 배열을 생성하거나, new 연산자를 이용하는 방법입니다.
new 연산자를 통해 배열을 생성할 경우, 기본값으로 자동 초기화됩니다.
배열의 길이란, 배열에 저장될 수 있는 전체 항목의 개수를 의미합니다.
코드에서 배열의 길이를 얻는 방법은 length 필드(field)*를 읽는 것입니다.
📢 출력 예시
5
length 필드는 읽기 전용이기 때문에, 값을 임의로 변경할 수 없습니다.
2차원 배열 및 다차원 배열
값이 행과 열 또는 그 이상으로 구성되어 있는 배열을 다차원 배열이라고 합니다.
3차원 이상의 배열은 복잡하므로, 여기서 직접 다루지는 않고 2차원 배열만 다룹니다.
2차원 배열의 선언 방법은 다음과 같습니다.
📢 출력 예시
3
4
4
4

2차원 배열이 선언될 때,
가장 먼저 열의 개수만큼의 길이를 가진 배열 multi_arr이 heap에 저장되고,
multi_arr는 stack 영역에 생성되어, multi_arr를 참조하게 됩니다.
(multi_arr과 multi_arr은 이름만 같을 뿐, 둘은 다릅니다. multi_arr은 스택 영역에 저장된 힙 영역을 참조하는 값이고, multi_arr은 힙 영역에 저장된 실제 값입니다.)
배열 multi_arr 의 3개의 값은 또한, heap 영역에 저장되어 있는,
행의 개수만큼의 길이를 가진 배열 multi_arr[0], multi_arr[1], multi_arr[2]에 각각 참조합니다.
따라서, 배열의 길이를 구해본다면, 위와 같은 결과가 발생하게 됩니다.
예를 들어, multi_arr.length는 배열 multi_arr를 참조하므로 길이는 3,
multi_arr[0].length는 배열 multi_arr[0]를 참조하므로 길이는 4가 됩니다.
비정방형 배열
또한, 2차원 배열은 수학의 행렬과 비슷한 개념으로 접근할 수 있지만,
행렬과 달리 꼭 정방형일 필요는 없습니다.
이 경우, 다음과 같이 계단식으로 배열이 생성됩니다.

객체를 참조하는 배열
래퍼런스 변수를 배열로 사용할 경우, 그 배열은 객체들의 주솟값을 가지게 됩니다.
예를 들어, 문자열 배열의 경우, 배열의 각 항목은 배열의 값이 아닌, String 객체의 주솟값을 가지게 됩니다.
즉, String[] 배열은 String 객체를 참조하게 되는 것입니다.
즉, 다차원 배열과 비슷하게,
stack 영역에는 heap에 저장된 String 타입 배열 객체를 참조하게 되고,
그 배열 객체의 값들은 각각의 String 객체를 참조하게 됩니다.
문자열은 그 값이 같으면 같은 주솟값을 가리키기 때문에,
문자열의 값이 같아도 다른 주솟값을 가리키고 싶은 경우, new를 사용해야 합니다.
📢 출력 예시
true
false
true
0번째 값과 1번째 값은 같은 주소를 참조하고, 2번째 값은 다른 주소를 참조합니다.
따라서, 위와 같은 결과가 발생합니다.
배열 복사
배열은 크기가 정해진 경우 더 이상 크기를 변경할 수 없기 때문에,
더 큰 크기가 필요하다면, 기존 배열을 크기가 더 큰 배열에 복사하는 방법이 있습니다.
배열을 복사하는 방법은 for문을 이용하거나, System.arraycopy() 메소드를 사용합니다.
System.arraycopy() 호출하는 방법은 다음과 같습니다.
📢 출력 예시
A, B, C, null, null
복사한 새 배열의 항목은 이전 배열의 항목이 참조하는 객체와 동일합니다.
필드*: 클래스의 상태를 나타내는 변수. 객체의 고유 데이터, 부품, 혹은 현재 상태를 저장하는 역할
타입 추론, var
타입 추론이란, 자료형이 정해지지 않은 변수에 대해 컴파일러가 변수의 타입을 스스로 찾아낼 수 있도록 하는 기능입니다. 자료형을 따로 명시할 필요가 없기 때문에, 소스 코드의 가독성을 높일 수 있습니다.
타입 추론을 하는 방법으로 var을 사용하는 방법이 있는데, var은 지역 변수만 사용 가능합니다.
하지만, var은 반드시 선언시 초기화가 필요하고, null 또는 배열, 람다식 타입을 추론할 수 없습니다.
📢 출력 예시
55
10
var1은 “5”를 String으로 추론하여, 연산시 정수를 문자열로 자동 타입 변환을 하였습니다.
var2는 5를 int로 추론하여, 연산시 두 정수의 합을 출력하였습니다.
정리
변수는 코딩을 하면서 정말 많이 사용하므로, 확실히 숙지하여야 합니다.
Java에서는 두 개의 영역에 변수를 나눠서 저장하기 때문에, 이에 대한 이해도 필요합니다.
'프리미티브(기본) 타입의 실제값은 스택 영역에, 래퍼런스(참조) 타입의 실제값은 힙 영역에 저장되고, 스택 영역에는 래퍼런스 타입의 주솟값을 가리키는 변수가 저장된다.'로 요약할 수 있겠습니다.
다음에는 '연산자'를 다룹니다.
'Java > 기본 개념' 카테고리의 다른 글
| 6. 클래스와 객체 (1) (0) | 2024.05.23 |
|---|---|
| 5. 조건문과 반복문 (0) | 2024.05.20 |
| 4. 연산자 (0) | 2024.05.17 |
| 2. 변수와 자료명 (1) (1) | 2024.05.15 |
| 1. Hello, World! (0) | 2024.05.11 |