[day04] java-basic : 배열
1. 배열
1.1 배열이란?
- 배열이란 연속적인 공간에 같은 타입의 자료들을 모아둔 집합이다.
-
일일히 변수명을 각자 지정해주는 것이 귀찮고 번거롭기 때문에 컴퓨터에게 변수를 생성하라고 명령하기 위해 생겨난 기능이다.
- new를 이용해서 만들어진 애들(heap 영역의 아이들)은 대부분 객체라고 한다.
- 배열도 new 키워드를 통해서 만들어지기 때문에 객체라고 할 수 있다.
-
heap영역에는 변수명이 저장되지 않고 주소값만 저장되기 때문에, stack영역에 주소값을 기억하고 있는 참조변수가 필요하다.
- 배열을 쓴다고 필요한 메모리 공간이 줄어들지는 않는다.
- 배열을 쓰던 각자 저장하던, int 자료 4개를 저장하려면 4byte의 heap 저장공간이 4개 필요한 것은 동일하다.
- 다만, 변수를 하나 만들때마다 컴퓨터는 변수 갯수 만큼 주소값을 일일히 전부 기억해야 하지만,
- 배열은 연속적인 공간에 4개의 변수가 저장되어 있기 때문에 하나의 주소값만 기억하면 된다.
-
왜냐하면 배열은 연속적인 공간으로 이루어져있기 때문에 하나의 주소값만 알면 byte크기만큼 계산해서 각 요소의 주소값을 유추할 수 있기 때문이다.
- 배열에서는 첫번째 요소의 주소값에서부터 같은 타입의 변수가 몇 개 떨어져 있는지 상대적인 숫자로 접근할 수 있다.
- 이를 즉 배열의 index라고 한다.
-
index가 0부터 시작하는 이유는 [첫 번째 요소는 주소값으로부터 0칸 / 두번째 요소는 주소값으로부터 1칸….] 이런식으로 구성되어 있기 때문이다.
- 배열은 크기를 수정할 수 없기 때문에 자바에서는 배열보다는 List를 더 많이 사용한다.
1.2 배열의 선언
[]
은 자바에서 배열을 나타낸다.-
[]
를 하나만 쓰면 일차원배열,[][]
두 개를 쓰면 이차원 배열이다. -
배열의 참조변수 선언방식 :
배열유형(데이터타입) 배열이름(참조변수) []
OR배열유형(데이터타입) [] 배열이름(참조변수)
- 배열의 유형은 기본형이던 참조형이던 모두 가능하다.
-
배열이름은 stack영역에 저장되며 heap영역의 주소값을 기억하는 참조변수이다.
- haep 영역의 공간을 생성하는 키워드는
new
이므로,new int[4];
형식으로 new키워드가 없으면 heap영역의 배열 저장 공간이 생기지 않는다. - 배열, String같이 프로그램을 실행하기 전까지는 JVM이 얼마만큼 크기의 메모리 공간을 확보해야할지 모르는 것들은
new
키워드를 사용해서 heap영역을 만들어줘야 한다. -
배열을 온전히 생성+초기화하려면
int[] arr = new int[4];
의 형식으로 작성해야 한다. new
키워드를 통해서 만들어진 공간은 전부 자동으로 초기화가 발생한다.- 그래서 배열을 heap영역에 만들면 정수배열은 모든값이
int 0
으로 자동 초기화된다. boolean = false
,char = '\u0000'
,float = 0.0
,참조형= null
로 자동 초기화된다.-
자동 초기화 하지 않고, 다른 값으로 초기화하려면
int[4] arr = {1, 2, 3, 4};
로 직접 각 요소 값을 지정해주면 된다. -
‘배열생성 + 다른 값으로 초기화’ 하려면,
int[] arr = new int[]{1, 2, 3, 4};
으로 작성할 수 있다. -
int[4] arr = {1, 2, 3, 4};
와int[] arr = new int[]{1, 2, 3, 4};
의 차이는? : 앞의 것은 기존 참조변수에 대입될 수 없지만, 뒤의 방식은 가능하다. -
배열의 초기화 형식 :
배열이름[인덱스번호] = 값
- 배열이 가진 모든 요소들을 출력하는 방식 3가지
- index를 이용한 출력 : for문과 length 활용하기
- foreach문 이용한 출력 : JDK 1.5버전 이후만 사용 가능
- Arrays.toString() 메소드를 이용한 출력
- java.utill에 속한 메소드로 배열을 문자열로 만들어서 출력해준다.
1.3 이차원배열
- 이차원배열의 선언+ 초기화 :
int[][] arr = new int[일차원배열의 개수][각 일차원배열의 원소 개수];
- 이차원배열은 1차원 배열의 집합이다.
-
그래서 이차원배열은 1차원 배열들의 주소값을 1차원 배열 형태로 기억한다.
-
만약
int[][] arr = new int[3][]
이라면arr[0]
,arr[1]
,arr[2]
에는arr[][]
의 주소값들이 null로 저장되어 있다. - 이차원배열에서 크기를 반환해주는
length
를 사용할 수 있을까? YES!
int[][] arr2 = new int[3][8];
System.out.println( arr2.length ); // result : 3
System.out.println( arr2[1].length ); // result : 8
- 이차원배열은
int[][] arr = { {}, {}, {} }
으로 초기화하면 된다. - 하지만 java에서는 객체지향을 따르기 때문에 이차원배열을 거의 사용하지 않는다.
1.4 참조형 배열 (String)
- 참조자료형 일차원 배열은 이차원 배열 구조를 가진다.
- 왜냐하면 참조자료형은
String[] strArr = {new String("vh"),new String("epd"),new String("dd")};
의 형식으로 배열이 만들어지기 때문이다. - 그림을 그려서 이해해보자면,
1.5 배열의 복사
int[] a = {10, 20, 30};
int[] b = a;
- 위의 경우, b에는 a배열의 heap영역 주소값이 저장된다. shallow copy(얕은 복사)
-
참조변수만 복사되기 때문이다.
- 똑같은 배열을 heap 영역에 하나 더 만들고 싶다면 deep copy(깊은 복사)를 해야한다.
-
이때,
new
키워드로 같은 크기의 배열을 만들고 각 index에 같은 값을 채워주면 된다. System.arraycopy()
는 자바가 제공하는 API이다.-
()
안에는 복사하려는 (배열명, 복사 시작 지점, 복사 당할 배열명, 복사 당하기 시작할 지점, 복사 끝 지점) 순으로 작성된다? - foreach문을 통해 배열안의 요소값을 조작해봤자 shallow copy되기 때문에 원본 배열의 값은 변하지 않는다.
// a배열의 모든 요소에 100을 더하기
for(int num : a) {
num = num + 100;
System.out.println(num);
}
System.out.println("--------------- 배열 원본 출력 ----------------");
for(int num : a) {
System.out.println(num);
}
- foreach문은 num 변수를 활용해 값을 출력하기만 할 뿐, 원본의 값은 변경시킬 수 없다.
int num
은 stack 메모리에 만들어져서 원본의 값이 저장되기만 하기 때문이다.