배열
배열은 동일한 자료형을 묶어 저장하는 참조 자료형이다. 생성할 때 크기를 지정해야 하고, 한 번 크기를 지정하면 절대 변경할 수 없는 특징이 있다.
배열 선언 방법
배열 선언 방법은 배열을 나타내는 대괄호([])가 자료형 뒤에 오는 형태, 변수명 뒤에 오는 형태 두 가지가 있다.
자료형[] 변수명;
자료형 변수명[];
다른 여러 자료형의 표현과 일관성을 유지하기 위해 자료형 뒤에 대괄호를 쓰는 것을 권장한다. 배열을 선언하면 스택 메모리에 변수의 공간만 생성하고, 공간 안은 비운 채로 둔다. 아직 배열의 실제 데이터인 객체를 생성하지 않았기 때문이다. 배열을 빈 공간을 초기화할 때 null(널) 값을 사용한다. 널 값은 힙 메모리의 위치(번지)를 가리키고 있지 않다는 의미다. 즉, 연결된 실제 데이터가 없음을 의미한다.
힙 메모리에 객체 생성
모든 참조 자료형의 실제 데이터(객체)는 힙 메모리에 생성된다. 객체를 생성하기 위해서는 new 키워드를 사용한다. new 자료형[배열의 길이]; // 배열의 길이는 포함할 수 있는 데이터의 수를 의미
배열의 길이는 반드시 지정해야 하며, 지정하지 않을 시 오류가 발생한다.
배열 자료형 변수에 객체 대입
변수를 다룰 때와 같다. 배열을 선언하면서 객체를 바로 대입해도 되고, 따로 구분해 작성해도 된다.
자료형[] 변수명 = new 자료형[배열의 길이];
자료형[] 변수명;
변수명 = new 자료형[배열의 길이];
예를 들어, int[] a = new int[3]; 이라고 입력하게 되면, int 자료형 3개를 저장할 수 있는 공간을 힙 메모리에 넣어두고 어디에 넣었는지를 참조 변수 a에 저장하라는 의미이다. 참고로, 이렇게 배열 선언과 동시에 객체를 생성하면 힙 메모리의 모든 값은 기본 자료형일 때 숫자의 경우 '0'(실수면 0.0), 불리언은 'false'로 초기화 되며, 이외의 모든 참조 자료형(클래스, 배열 등)은 'null'로 초기화 된다.
객체에 값 입력
배열은 값을 저장할 수 있는 공간마다 방 번호가 있는데, 이 번호를 인덱스index라고 한다. 인덱스는 0부터 시작하며, 1씩 증가한다. 배열의 0번째 방, 1번째 방이라고 생각하면 된다. 배열에 값을 입력하거나 출력할 때, 인덱스를 사용한다.
참조 변수명[인덱스] = 값;
1차원 배열을 생성하는 다양한 방법
배열 객체를 생성 후 값 대입 | 자료형[] 참조변수명 = new 자료형[배열의 길이]; 참조변수명[0] = 값; 참조변수명[1] = 값; ... 참조변수명[배열의 길이-1] = 값; |
배열 객체를 생성과 함께 값 대입 | 자료형[] 참조변수명 = new 자료형[]{값, 값, ..., 값}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 가능 |
대입할 값만 입력 | 자료형[] 참조변수명 = {값, 값, ..., 값}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 불가능 |
반복문을 이용해 배열 데이터 읽기
먼저 배열의 길이를 알아야하는데, 자바는 '배열참조변수.length'로 배열의 길이를 알 수 있다. for 문을 사용하거나 for-each 문을 사용하면 큰 배열도 간단히 출력할 수 있다. for-each 문의 문법은 아래와 같다.
for(자료형 변수명: 집합객체){
System.out.println(변수명);
}
예시)
int[] a = new int[100];
a[0] = 1, a[1] = 2, ..., a[99] = 100;
for(int k : a) { // k라는 변수 선언됨
System.out.println(k);
}
마지막으로 배열의 각 원소 값을 출력하는 방법은 Arrays 클래스의 toString() 정적 메서드를 사용하는 것이다. 메서드에 관한 부분은 나중에 나올테니 일단 System.out.println(Arrays.toString(1차원 배열 참조 변수));를 통해 출력 가능하다는 사실만 알면 된다.
2차원 정방 행렬 배열
가로 및 세로 방향의 2차원으로 데이터를 저장하는 배열이 2차원 배열이다. 그 중 직사각형의 형태(모든 행의 길이가 같은 배열)를 띤 배열을 '2차원 정방 행렬 배열'이라고 한다. 2차원 배열을 선언할 때도 대괄호를 사용하며 1차원에서 2차원으로 차원이 1개 늘어났으므로 2개가 사용된다. 3차원이면 3개를 사용하면 된다. 2차원 배열의 선언 방법도 여러 가지가 있다.
자료형[][] 변수명;
자료형 변수명[][];
자료형[] 변수명[];
배열의 위치 표현은 [세로인덱스][가로인덱스]로 표현한다. 2차원 정방 행렬은 객체를 생성하는 데도 4가지 방법이 있다. 가장 중요한 사실은 '메모리는 2차원 데이터를 바로 저장할 수 없다'는 것이다. 2차원 데이터는 1차원 데이터들로 나눠서 저장한다. 즉, 만약 int[]가 int를 저장하는 1차원 배열인 것 처럼, int[][]는 int[]을 저장하는 1차원 배열이다.
2차원 정방 행렬 배열을 생성하는 다양한 방법
배열 객체를 생성 후 값 대입 | 자료형[][] 참조변수명 = new 자료형[행의 길이][열의 길이]; 참조변수명[0][0] = 값; 참조변수명[0][1] = 값; ... 참조변수명[행의 길이-1][열의 길이-1] = 값; |
배열 객체의 행 성분 생성 후 열 성분 생성 |
자료형[][] 참조변수명 = new 자료형[행의 길이][]; // 열의 길이는 빈 칸 참조변수명[0] = 1차원 배열의 생성; 참조변수명[0] = 1차원 배열의 생성; ... 참조변수명[행의 길이-1] = 1차원 배열의 생성; 예시1) int[][] a = new int[2][]; a[0] = new int[3]; a[0][0] = 1; a[0][1] = 2; a[0][2] = 3; a[1] = new int[3]; a[1][0] = 4; a[1][1] = 5; a[1][2] = 6; 예시2) int[][] = new int[2][]; a[0] = new int[]{1, 2, 3}; a[1] = new int[]{4, 5, 6}; |
배열의 자료형과 함께 대입할 값 입력 | 자료형[][] 참조변수명 = new 자료형[][] {{값, 값, ..., 값}, ..., {값, 값, ..., 값}}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 불가능 // 첫 번째 행, ..., 마지막 행 순으로 데이터 값 입력 |
대입할 값만 입력 | 자료형[][] 참조변수명 = {{값, 값, ..., 값}, ..., {값, 값, ..., 값}}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 불가능 // 첫 번째 행, ..., 마지막 행 순으로 데이터 값 입력 |
2번째 방법인 행 성분을 생성 후 열 성분을 생성하는 방식을 보자. 먼저, 행 성분을 생성하는데 참조 변수 a가 가리키는 곳(힙 메모리)으로 가면 생성한 2칸에 방(a[0], a[1])이 있다. 다음으로 a[0] = new int[3];을 실행하게 되는데 힙 메모리에 a[0]에 int형 3칸짜리 방을 만들고 주소를 a[0]에 저장하게 된다. 즉, a -> a[0] / a[1] -> a[0][0], a[0][1], a[0][2] / a[1][0], a[1][1], a[1][2] 순서로 가리키게 되는 것이다.
2차원 비정방 행렬 배열
2차원 비정방 행렬은 각 행마다 열의 길이가 다른 2차원 배열을 의미한다. 각 행별로 들쑥날쑥하지만, 1차원 배열을 원소로 포함하고 있는 1차원 배열이라는 동일한 개념을 가져간다.
2차원 정방 행렬 배열을 생성하는 다양한 방법
배열 객체의 행 성분 생성 후 열 성분 생성 |
자료형[][] 참조변수명 = new 자료형[행의 길이][]; // 열의 길이는 빈 칸 참조변수명[0] = 1차원 배열의 생성; 참조변수명[0] = 1차원 배열의 생성; ... 참조변수명[행의 길이-1] = 1차원 배열의 생성; 예시1) int[][] a = new int[2][]; a[0] = new int[2]; a[0][0] = 1; a[0][1] = 2; a[1] = new int[3]; a[1][0] = 3; a[1][1] = 4; a[1][2] = 5; 예시2) int[][] = new int[2][]; a[0] = new int[]{1, 2}; a[1] = new int[]{3, 4, 5}; |
배열의 자료형과 함께 대입할 값 입력 | 자료형[][] 참조변수명 = new 자료형[][] {{값, 값, ..., 값}, ..., {값, 값, ..., 값}}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 불가능 // 첫 번째 행, ..., 마지막 행 순으로 데이터 값 입력 |
대입할 값만 입력 | 자료형[][] 참조변수명 = {{값, 값, ..., 값}, ..., {값, 값, ..., 값}}; // 배열의 길이는 값의 개수로 결정, 선언과 객체 대입 분리 불가능 // 첫 번째 행, ..., 마지막 행 순으로 데이터 값 입력 |
각 행마다 크기가 다른 1차원 배열이 할당된다는 점을 제외하고는 정방 행렬과 동일하다.
2차원 배열의 출력
2차원 배열은 가로, 세로 방향으로 데이터가 분포되어 있어서, 기본적으로 이중 for 문을 사용해야 한다. 비정방 배열은 각 행마다 열의 개수가 다르므로 바깥쪽 for 문에는 행의 개수를 나타내는 a.length, 안쪽 for 문에는 열의 개수를 나타는 a[i].length를 사용해야 한다. 이중 for 문은 이전에 배웠으니 생략한다. 아래는 이중 for-each 문으로 2차원 배열의 원소를 출력하는 예시다.
int[][] a = {{1, 2}, {3, 4, 5}};
for(int[] m: a) {
for(int n : m) {
System.out.println(n);
}
}
main() 메서드의 입력매개변수
public static void main(String[] ar){
....
}
그동안 기계적으로 작성했었던 main() 메서드를 살펴보면 배열이 입력 매개변수의 형태를 띄는 것을 알 수 있다. 자바 코드 실행 시 자바 가상 머신은 가장 먼저 main() 메서드를 실행하는데, 개발자는 main() 메서드를 실행하는 데 필요한 자료를 배열 타입으로 넘겨 줄 수 있는 것이다.
'development > Java' 카테고리의 다른 글
JAVA 공부 해볼까 (10) (6) | 2021.12.18 |
---|---|
JAVA 공부 해볼까 (9) (0) | 2021.12.16 |
JAVA 공부 해볼까 (7) (2) | 2021.12.13 |
JAVA 공부 해볼까 (6) (0) | 2021.12.11 |
JAVA 공부 해볼까 (5) (0) | 2021.12.10 |