본문 바로가기

Java/Chapter 13. 배열(Array)

[Java] 13.01 - 1차원 배열의 이해와 활용(1)

들어가며

 배열은 '자료형이 같은 둘 이상의
값'을 저장할 수 있는 메모리 공간을
의미한다.

 그리고 배열은 그 구조에 따라서
'1차원 배열'과 '다차원 배열'로
나뉜다.

 

1차원 배열의 생성 방법

 1차원 배열은 다음과 같이
정의할 수 있다.

타입이 같은 둘 이상의 데이터를 저장할 수 있는
1차원 구조의 메모리 공간

 그런데 자바는 배열도 인스턴스로
처리한다.

 즉 '자바 에서는 배열도 인스턴스'이다.

 그럼 다음 문장을 모자.

 이는 5개의 int형 값을 저장할 수
있는 1차원 배열의 생성문이다.

int[] ref = new int[5];

 위의 문장에서 등호를 기준으로
왼편, 오른편에 위치한 것은

 각각 '참조변수의 선언'과
'배열의 생성'이다.

int[] ref    // int형 1차원 배열 인스턴스를 참조할 수 있는 '참조변수의 선언'
new int[5]    // int형 값 5개를 저장할 수 있는 '배열 인스턴스의 생성'

 물론 다음과 같이 참조변수의
선언과 배열 인스턴스의 생성을
구분할 수도 있다.

public class Main {
    public static void main(String[] args) {
        int[] ref;          // 참조변수의 선언
        ref = new int[5];   // 배열 인스턴스의 생성
        ....
    }
}

 참조변수의 선언에서 int[]는
참조할 대상에 대한 자료형
정보를 나타낸다.

 그런데 여기에 참조할 배열의
길이 정보는 보이지 않는다.

 즉 int[]형으로 선언된 참조변수는
int형 1차원 배열을 길이에 상관없이
참조할 수 있다.

그림 58 - 배열의 참조변수

 다시 배열의 생성 문장으로
돌아와서, 다음 문장을 실행하면,

int[] ref = new int[5];

 다음의 형태로 메모리 공간에
배열이 생성된다.

 아래의 그림의 목적은, 배열이
인스턴스임을 강조하는데 있다.

 그림에서 length는 인스턴스 변수이다.

그림 59 - 배열의 생성

 그럼 다음 예제를 통해서,

 '다양한 배열의 생성의 예'와 더불어
'배열이 인스턴스임'을 보이겠다.

 그리고 이후로는 '배열 인스턴스'라
하지 않고 그냥 '배열'이라 하겠다.

class ArrayIsInstance {
    public static void main(String[] args) {
        // 길이가 5인 int형 1차원 배열의 생성
        int[] ar1 = new int[5];

        // 길이가 7인 double형 1차원 배열의 생성
        double[] ar2 = new double[7];

        // 배열의 참조변수와 인스턴스 생성 분리
        float[] ar3;
        ar3 = new float[9];

        // 배열의 인스턴스 변수 접근
        System.out.println("배열 ar1의 길이: " + ar1.length);
        System.out.println("배열 ar2의 길이: " + ar2.length);
        System.out.println("배열 ar3의 길이: " + ar3.length);
    }
}

/*
출력 결과
배열 ar1의 길이: 5
배열 ar2의 길이: 7
배열 ar3의 길이: 9
*/

 위 예제에서는 배열의 인스턴스
변수 'length'에 접근하여 배열의
길이 정보를 출력하였다.

 이렇듯 인스턴스 변수에 접근이
가능하다는 것은

 배열이 인스턴스임을 보이는
결과이기도 하다.

 그리고 위의 예제에서 보이지는
않았지만,

 다음과 같이 1차원 배열의 참조변수는
배열의 길이에 상관없이 참조가
가능하다.

public static void main(String[] args) {
    int[] ar = new int[50];
    System.out.println("length: " + ar.length); // length = 50
    ar = new int[100];
    System.out.println("length: " + ar.length); // length = 100
}

 그리고 배열은 int, double과
같은 기본 자료형을 대상으로만
생성할 수 있는 것이 아니다.

  다음 예제에서 보이듯이
인스턴스를 저장할 수 있는
배열의 생성도 가능하다.

class Box {
    private String conts;

    Box(String cont) {
        this.conts = cont;
    }

    public String toString() {
        return conts;
    }
}

class ArrayIsInstance2 {
    public static void main(String[] args) {
        Box[] ar = new Box[5];    // 길이가 5인 Box형 1차원 배열의 생성
        System.out.println("length : " + ar.length);    // length: 5
    }
}

/*
출력 결과
length : 5
*/

 위 예제에서는 Box 클래스를
정의하고,

 이 클래스의 인스턴스 5개를
저장할 수 있는 배열을 다음과
같이 생성하였다.

Box[] ar = new Box[5];

 여기서 주의할 사실은 다음과 같다.

이는 Box 인스턴스 5개를 저장할 수 있는 참조변수의 배열이다.

 즉 이는 Box 인스턴스의 생성과는
관계가 없다.

 위의 문장을 통해 5개의 Box 인스턴스를
저장할 수 있는 배열이 생성될 뿐이다.

 

배열을 대상으로 한 값의 저장과 참조

 다음의 배열이 생성된 상태에
값을 저장하는 방법과

  저장된 값을 참조하는 방법을
설명하고자 한다.

int[] ar = new int[3];

  이 배열의 첫 번째 공간에 값을
저장하는 방법은 다음과 같다.

ar[0] = 7;    // 배열 ar의 첫 번째 요소에 정수 7 저장

 이렇듯 배열 요소의 위치를
지정하는 인덱스 값은 0에서부터
시작한다.

 따라서 배열 ar의 두 번째, 세 번째
요소에 값을 저장하는 방법은 다음과
같다.

ar[1] = 7;    // 배열 ar의 두 번째 요소에 정수 8 저장
ar[2] = 7;    // 배열 ar의 세 번째 요소에 정수 9 저장

 배열에 저장된 값을 참조하는
방법도 이와 유사하다.

 다음은 배열 ar의 모든 요소에
저장된 값을 더하는 방법을
보여준다.

int num = ar[0] + ar[1] + ar[2];

 앞서 보인 Box형 배열의 인스턴스
저장 및 참조 방법도 이와 동일하다.

  다만 저장 대상에서 차이가
있을 뿐이다.

 그럼 이와 관련하여 다음 예제를 보자.

class ArrayIsInstance2 {
    public static void main(String[] args) {
        Box[] ar = new Box[3];

        // 배열에 인스턴스 저장
        ar[0] = new Box("First");
        ar[1] = new Box("Second");
        ar[2] = new Box("Third");

        // 저장된 인스턴스의 참조
        System.out.println(ar[0]);
        System.out.println(ar[1]);
        System.out.println(ar[2]);
    }
}

/*
출력 결과
First
Second
Third
*/

 위의 예제에서 배열 생성 이후에
다음과 같이 인스턴스를 생성하여
저장하였다.

ar[0] = new Box("First");
ar[1] = new Box("Second");
ar[2] = new Box("Third");

 이와 같이 인스턴스를 생성하고
저장했을 때의 배열과 인스턴스의
관계는 다음과 같다.

그림 60 - 배열의 인스턴스 저장 모델

 그리고 이렇게 배열에 저장된
인스턴스는 다음과 같이 참조한다.

System.out.println(ar[0]);

 한 가지 예를 더 보이겠다.

 다음 예제에서는 String형 배열에
문자열을 저장하고 참조하는 코드를
보인다.

class StringArray {
    public static void main(String[] args) {
        String[] sr = new String[7];
        sr[0] = new String("Health");
        sr[1] = new String("Health regen.\n");
        sr[2] = new String("Resource");
        sr[3] = new String("Resource regen.");
        sr[4] = new String("Armor");
        sr[5] = new String("Magic resist");
        sr[6] = new String("Move speed");

        int cnum = 0;

        for (int i=0; i < sr.length; i++)
            cnum += sr[i].length();

        System.out.println("총 문자의 수: " + cnum);
    }
}

/*
출력 결과
총 문자의 수: 70
*/

 위 예제에 관심있게 볼 부분은
다음 반복문이다.

 이 반복문에서는 반복 변수 i를
이용하여 모든 배열 요소에 접근하였다.

for (int i=0; i < sr.length; i++)
    cnum += sr[i].length();    // String 인스턴스의 length 메소드 순차적 호출

 이렇듯 반복문을 이용하면 배열의
순차적 접근을 진행하는 문장을
구성할 수 있다.

 그리고 이것이 배열이 갖는
대표적인 장점 중 하나다.

 참조변수 일곱 개를 선언하여
일곱 개의 문자열을 저장할 수는
있다.

 그러나 단 두 줄의 코드만을
이용해서

 모든 문자열에 접근하는 것은
배열이 아니면 불가능하다.

 

배열을 생성과 동시에 초기화하기

 배열도 변수와 마찬가지로 생성과
동시에 초기화가 가능하다.

int[] arr = new int[3];

 이 배열을 생성과 동시에 초기화
하려면,

 초기화할 값들을 다음과 같이
중괄호를 이용해서 나열하면 된다.

int[] arr = new int[3] {1, 2, 3};    // 컴파일 오류 발생

 그런데 위의 문장에서는 초기화할
값들의 수를 통해 배열의 길이 정보를
계산할 수 있으므로,

 이 경우, 배열의 길이 정보를
생략하도록 약속하였다.

 즉 위의 문장은 다음과 같이
수정해야 한다.

int[] arr = new int[] {1, 2, 3};

 위의 문장을 통해 생성되는
배열의 길이는 3이다.

 그리고 위의 문장은 다음과
같이 줄여서 표현할 수도 있다.

int[] arr = {1, 2, 3};

 물론 위의 문장에 의해 생성되는
배열의 길이도 3이다.


참고 및 출처

윤성우의 열혈 Java 프로그래밍
국내도서
저자 : 윤성우
출판 : 오렌지미디어 2017.07.05
상세보기