본문 바로가기

프로그래밍 언어/JAVA

JAVA 입문 - 배열

지난 글: [프로그래밍 언어/JAVA] - JAVA 입문 - 싱글톤 패턴

 

배열

배열이란 같은 자료형인 여러 개의 변수들을 한 번에 관리할 수 있게 하는 자료형이다.

 

배열 선언과 초기화

배열을 사용하기 위해서는 배열을 선언해야 한다. 

배열도 변수와 마찬가지로 자료형을 함께 선언한다.

자료형[] 배열이름 = new 자료형[개수];
자료형 배열이름[] = new 자료형[개수];

배열을 선언하는 문법은 위와 같다.

배열을 이루는 각각의 자료를 배열 요소라고 한다. 배열 요소는 자료형이 모두 같다.

저장하려는 자료의 성격에 맞게 자료형을 정하고 선언하려는 배열 요소 개수만큼 [ ] 안에 적는다.

new 예약어는 배열을 새로 만들라는 의미이다.

배열을 선언하면 선언한 자료형과 배열 길이에 따라 메모리가 할당된다.

 

배열 초기화하기

JAVA에서 배열을 선언하면 그와 동시에 각 요소의 값이 초기화 된다.

정수는 0, 실수는 0.0, 객체 배열은 null로 초기화되며, 밑처럼 배열 선언과 동시에 특정 값으로 초기화할 수도 있다.

int[] studentID = new int [] {101, 102, 103}; //개수는 생략

아래와 같이 값을 넣어 초기화할 때 [ ] 안에 개수를 쓰면 오류가 발생한다.

int[] studentID = new int[3] {101, 102, 103}; //오류 발생

선언과 동시에 초기화할 때 아래처럼 new int[ ]를 생략할 수도 있다.

int[] studentID = {101, 102, 103}; //int형 요소가 3개인 배열 생성

하지만 다음과 같이 배열의 자료형을 먼저 선언하고 초기화하는 경우에는 new int[ ]를 생략할 수 없다.

int studentID; //배열 자료형 선언
studentID = new int[] {101, 102, 103};

 배열 사용하기

더보기

선언한 배열의 각 요소에 값을 넣을 때나 배열 요소에 있는 값을 가져올 때는 [ ]를 사용한다.

studentID[0] = 10; //배열의 첫 번째 요소에 값 10을 저장
더보기

 인덱스 연산자 [ ]

[ ]는 배열을 처음 선언할 때 사용하는 연산자다. 이를 인덱스 연산자라고 한다.

인덱스 연산자의 기능은 배열 요소가 저장된 메모리의 위치를 찾아주는 역할이다.

배열에서 [4] 인덱스 연산을 하면 4번째 요소의 위치를 찾아 해당 위치의 메모리에 값을 넣거나 가져올 수 있다.

num[3] = 15; //배열의 4번째 요소에 값 15를 저장
age = num[3]; //age 변수에 num 배열의 4번째 요소 값을 저장
더보기

배열 순서는 0부터 n-1번까지이다. 0번 요소를 배열의 첫 번째 요소라고 한다.

JAVA의 배열은 배여 길이를 나타내는 length 속성을 갖는다. 

배열 길이는 처음에 선언한 배열의 전체 요소 개수를 의미한다.

전체 길이를 알고 싶은 배열 이름 뒤에 도트 연산자(.)를 붙이고 length 속성을 쓰면 배열 길이를 반환한다.

배열 전체 길이만큼 수행문을 반복해야 할 때는 숫자를 직접 사용하는 것보다 length 속성을 사용하는 것이 좋다.

 

전체 배열의 길이와 유효한 요소 값

우리가 배열을 사용할 때 처음 선언한 배열 길이만큼 값을 저장해서 사용하는 경우는 많지 않다고 한다.

그래서 전체 배열 길이와 현재 배열에 유효한 값이 저장되어 있는 배열 요소 개수가 같다고 혼동하면 안된다.

출력 결과

double형으로 길이가 5인 배열을 선언하고 배열의 첫 번째 요소(data[0])부터 세 번째 요소(data[2])까지만 값을

저장했다. 11행 for문에서 i가 0부터 배열 길이인 data.length 미만까지 반복하여 저장된 요소 값을 출력한다.

배열의 네 번째 요소부터는 값을 저장하지 않았기에 0.0이 출력되는 것이 보인다.

만약 위 코드에서 값이 저장된 배열 요소만 정확히 출력하려면 새로운 변수를 선언하고 배열 요소 순서대로

값을 저장할 때마다 그 변수 값을 증가시키면 된다.

그리고 반복문 종료의 조건을 배열의 length 속성이 아닌 해당 변수를 사용하면 된다.

출력 결과

6행에서 유효한 값이 저장된 배열 요소 개수를 저장할 size 변수를 선언하고, 배열 요소에 순서대로 값을 저장할 때마다

size 변수의 값을 하나씩 증가시킨다. 즉 유효한 값을 저장하고 있는 배열 요소의 개수를 알 수 있다.

따라서 12행 반복문은 전체 배열 길이만큼 반복하는 것이 아니라 유효한 요소 개수만큼만 반복한다.

 

문자 저장 배열 만들기

더보기

문자 자료형 배열을 만들고 알파벳 대문자를 A부터 Z까지 저장한 후 각 요소 값을 알파벳과 정수 값으로 출력해보자.

출력 결과

 

객체 배열 사용하기

더보기

참조 자료형으로 선언하는 객체 배열은 int나 char 등 기본 자료형 배열과 사용 방법이 조금 다르다.

우선 Book 클래스를 만들고 이 클래스로 객체 배열을 만들어 보자.

Book 클래스 생성

Book 클래스는 책 이름과 저자를 멤버 변수로 갖는 클래스이며 디폴트 생성자 외에도 책 이름과 저자를 

매개변수로 받는 생성자를 하나 더 구현했다.

다른 코드에서 이 클래스를 사용할 때 멤버 변수 값을 가져오거나 지정할 수 있도록 get( ), set( ) 메서드도

구현했다.

마지막으로 책의 정보를 출력해주는 showInfo( ) 메서드도 구현했다.

 

이제 도서관에 책이 5권 있다고 가정하고 Book 클래스를 사용하여 책 5권을 객체 배열로 만들어보자.

출력 결과

이 코드의 5행에서 Book[ ] library = new Book[5]; 문장은 Book 인스턴스 5개가 바로 생성된 것이 아니다.

Book[ ] library = new Book[5];문장에서는 각각의 Book인스턴스 주소 값을 담을 공간이 5개 생성된 것이다.

그래서 이 문장을 실행하면 Book 주소 값을 담을 공간이 5개 만들어지고 자동으로 각 공간은 '비어 있다'는 의미의

null 값으로 초기화 되어 출력 결과가 null로 이루어진 것이다.

 

이제 각 배열 요소에 인스턴스를 생성해 넣어보자. Book 클래스에서 구현한 생성자를 사용한다.

출력 결과

배열의 각 요소에 Book 인스턴스를 만들어 직접 저장했다.

 

배열 복사하기

더보기

기존 배열과 자료형 및 크기가 똑같은 배열을 새로 만들거나 배열의 모든 요소에 자료가 꽉 차서 더 큰 배열을

만들어 기존 배열에 저장된 자료를 가져오려 할 때 배열을 복사한다.

배열을 복사하는 방법은 두 가지이다.

첫 번째는 기존 배열과 배열 길이가 같거나 더 긴 배열을 만들고 for문을 사용하여 각 요소 값을 반복해서

복사하는 방법이다. 

두 번째는 System.arraycopy( ) 메서드를 사용하는 방법이다.

System.arraycopy(src, srcPos, dest, destPos, length) 메서드에서 각 매개변수의 의미는 다음과 같다.

 

System.arraycopy( ) 메서드를 사용한 다음 사진을 보자.

출력 결과

사진에서 array1 배열에서 array2 배열로 요소 값을 복사한다.

9행의 문장은 array1의 요소0번부터 4개를 복사해서 대상 배열 array2의 요소 1번부터 붙여 넣는다.

이 때 복사할 대상 배열의 전체 길이가 복사할 요소 개수보다 작다면 오류가 난다.

만약 위 사진에서 요소 4개가 아닌 5개를 복사한다고 코드를 수정하면 array 배열 길이보다 요소 개수가 

많이지므로 오류가 발생한다.

 

객체 배열 복사하기

객체 배열도 마찬가지로 복사가 가능하다. String 클래스를 사용한 경우를 보자.

chapter7 패키지에 Book 클래스는 이미 만들어 두었으므로, 같은 패키지에 ObjectCopy1 클래스를 만들어 진행한다.

출력 결과

위 코드의 출력 결과를 보면 bookArray1 배열에서 bookArray2 배열로 요소 값이 복사된 것이 보인다.

그런데 여기서 우리는 bookArray2 배열의 인스턴스를 따로 만들지 않았는데 각 요소 값이 잘 출력되고 있다.

객체 배열을 사용하려면 꼭 인스턴스를 생성해서 넣어야 한다 했는데 이는 어찌 된 것일까?

 

얕은 복사

위 사진에서 배열을 복사해 출력하기 전 bookArray1 배열 요소 값 하나를 변경해보자.

출력 결과

출력 화면을 보면 18~19행에서 bookArray1 배열 요소 값을 변경했는데 bookArray2 배열 요소 값도

변경된 것을 알 수 있다. 어떻게 이런 일이 발생되었을까?

이유는 객체 배열의 요소에 저장된 값은 인스턴스 자체가 아니고 인스턴스의 주소 값이기 때문이다.

따라서 객체 배열을 복사할 때 인스턴스를 따로 생성하는게 아니라 기존 인스턴스의 주소 값만 복사한다.

결국 두 배열의 서로 다른 요소가 같은 인스턴스를 가리키고 있으므로 복사되는 배열의 인스턴스 값이 변경되면

두 배열 모두 영향을 받는다.

이 같은 복사를 주소 값만 복사한다고 하여 '얕은 복사(shallow copy)'라고 한다.

 

깊은 복사

이제는 bookArray1 배열과 bookArray2 배열의 각 요소가 서로 다른 인스턴스를 가리키게 하는 것을 배워보자.

반복문을 사용하건 System.arraycopy( ) 메서드를 사용하건 객체 배열을 복사하면 항상 인스턴스 주소가 복사된다.

여기서 인스턴스를 따로 관리하고 싶다면 직접 인스턴스를 만들고 그 값을 복사해야 한다.

이를 '깊은 복사(deep copy)'라고 한다.

 

아래 사진은 복사할 배열에 인스턴스를 따로 생성한 후 요소 값을 복사한다.

이렇게 하면 복사한 배열 요소는 기존 배열 요소와 서로 다른 인스턴스를 가리키므로 기존 배열의 요소 값이

변경되어도 영향을 받지 않는다.

출력 결과

 

향상된 for문과 배열

더보기

JAVA 5부터 제공되는 향상된 for문(enhances for loop)은 배열의 처음에서 끝까지 모든 요소를 참조할 때

사용하면 편리한 반복문이다. 향상된 for문은 배열 요소 값을 순서대로 하나씩 가져와서 변수에 대입한다.

따로 초기화와 종료 조건이 없기에 모든 배열의 시작 요소부터 끝 요소까지 실행한다.

 

아래는 향상된 for문을 연습한 사진이다.

출력 결과

String형으로 선언된 strArray 배열에 문자열 5개를 저장했다.

향상된 for문을 사용해서 String형 lang 변수에 strArray 배열 요소 값을 순서대로 가져와 대입한다.

lang 변수를 출력하면 strArray 배열에 저장된 값이 순서대로 출력된다.

 

참고 서적: 자바 프로그래밍 입문 - 박은종

'프로그래밍 언어 > JAVA' 카테고리의 다른 글

JAVA 입문 - ArrayList 클래스  (0) 2022.05.17
JAVA 입문 - 다차원 배열  (0) 2022.05.16
JAVA 입문 - 싱글톤 패턴  (0) 2022.05.14
JAVA 입문 - 변수 유효 범위  (0) 2022.05.14
JAVA 입문 - static 변수  (0) 2022.05.13