배열의 선언과 초기화
Java 언어뿐만 아니라 모든 언어에서 프로그래밍을 할 때 반드시 변수를 사용하게 됩니다.
대부분의 경우 변수는 선언과 초기화가 필요합니다. 선언은 어떤 변수를 앞으로 사용할 수 있도록 선언하고, 그 변수를 위해 메모리 상에 적절한 크기의 영역을 확보하는 것을 말합니다. 그리고 초기화란 먼저 그 영역에 값을 대입하여 사용할 수 있도록 하는 것을 말합니다.
언어의 종류에 따라 선언을 생략할 수도 있지만, 그런 언어의 경우 처음 값을 대입하는 단계에서 선언과 초기화가 이루어진 것으로 간주합니다.
Java에서 변수를 사용할 때는 반드시 선언과 초기화를 해야 한다는 규칙이 있습니다.
일반 변수 초기화
예를 들어, int형 변수 a를 사용할 수 있도록 하려면 다음과 같이
int a;
해야 합니다. 그러면 처음으로 정수형 변수 a를 사용할 수 있게 된다. 그 후,
a = 5;
와 같이 값을 대입하면 처음으로 변수 a를 사용할 수 있게 된다. 변수를 선언하고 처음 초기값을 대입하는 것을 초기화라고 한다.
만약 이 초기화를 하지 않고 a의 값을 바탕으로 어떤 연산 처리 등을 하려고 하면 예외가 발생하여 프로그램이 강제 종료됩니다.
Java의 배열 변수는 자동으로 초기화된다.
다만, 배열의 경우는 사정이 조금 다르다. 예를 들어, 배열의 선언은 다음과 같이 합니다.
int n = new int[10];
double d = new double[5];
각각 길이 10의 정수형 배열 n, 길이 5의 실수형 배열 d를 선언한 것이다. 이 상태에서 값은 자동으로 0으로 초기화된다.
즉, 배열 변수에 대해서는 초기화를 생략할 수 있는 것입니다.
Java 언어는 C 언어를 기반으로 만들어진 언어인데, C 언어에서는 배열을 선언한 상태에서는 값이 초기화되지 않아 선언과 초기화를 두 번 처리해야 하는 번거로움이 있었습니다.
Java 언어는 그 교훈을 살려 프로그래머의 수고를 덜어주기 위해 고안된 언어입니다.
초기화가 필요한 이유
변수 초기화가 필요한 이유는 초기화하지 않은 상태에서 해당 변수를 사용하여 연산을 수행하려고 하면 예외(런타임 에러)가 발생하여 프로그램이 멈춰버리기 때문입니다.
단, 앞서 언급했듯이 배열 변수의 경우는 예외입니다. 배열 변수는 배열 변수를 선언한 상태에서 초기화가 이루어집니다.
배열이 아닌 변수의 경우 한 개만 값을 설정하면 되므로 편하지만, 배열의 경우 개수가 많기 때문에 초기화를 하기가 쉽지 않습니다. 그래서 Java 언어에서는 선언을 한 상태에서 default_value와 같은 기본값이 설정되어 초기화의 수고를 최소화할 수 있는 구조가 미리 준비되어 있는 것입니다.
참고로 배열의 값이 문자열인 경우, 빈 문자열이 됩니다. 이는 내용이 비어 있는 문자열이라는 뜻으로, 문자열 자체는 존재하지만 길이가 0인, 즉 아무것도 쓰여 있지 않은 빈 문자열이라는 의미입니다.
데이터가 아무것도 없다는 null과는 분명히 의미가 다르므로 주의가 필요합니다.
1차원 배열 초기화
Java에서는 배열이 자동으로 초기화되지만, 배열이라도 0이나 공백이 아닌 미리 정해진 값으로 초기화하고자 하는 경우가 종종 있습니다. 이럴 때, 배열 하나하나에 일일이 값을 대입하는 것은 매우 번거롭다.
그래서 Java 언어에는 초기화자(initializer)라는 배열 변수를 쉽게 초기화할 수 있는 매우 편리한 메커니즘을 제공하고 있습니다. 예를 들면
int a[] = { 1, 2, 3 };
와 같이 선언하면 자동으로 다음과 같은 처리를 한 것과 같은 효과를 얻을 수 있다.
int a[] = new int[3];
a[0] = 1;
a[1] = 2;
a[2] = 3;
배열 변수 초기화
문자열의 경우도 마찬가지다. 예를 들면
String [] s = {“apple”,”banana”,”orange”};
이렇게 하면
String[] s = new String[3];
s[0] = “apple”:
s[1] = “banana”;
s[2] = “orange”;
와 같이 하면 된다,
즉, 초기화자를 사용하면 배열의 선언과 초기화를 동시에 할 수 있다. 이렇게 하면 소스 코드를 매우 짧게 만들 수 있고, 깔끔하고 가독성이 매우 좋아진다.
길이가 극단적으로 긴 배열을 제외하고, 미리 숫자가 정해져 있고 초기화할 값이 정해져 있는 경우 이 초기화자를 사용하면 배열을 쉽게 다룰 수 있습니다.
다차원 배열 초기화
초기화자는 1차원 배열뿐만 아니라 다차원 배열에도 사용할 수 있습니다. 예를 들어, 정수 배열을
int num[][] = {{10, 8, 5}, {9, 16, 4}, {3, 7, 5}};
2차원 배열 초기화
라고 하면 아래와 같은 처리를 한 것이다. 이렇게 함으로써, 배열 변수 num이 격자 안에 초기값이 자동 설정된 상태로 배열 변수 num을 이용할 수 있게 된다.
또한, 이러한 초기화는 불균등해도 상관없다. 예를 들어,
int a[][] = {{1, 2, 3},{4},{5,6,7,8}};
저그 배열 초기화
이렇게 하면 불규칙한 모양의 배열이 만들어진다.
이것도 2차원 배열의 일종인데, 일반적으로 이런 유형의 배열을 저그 배열(jagged array)이라고 부릅니다. 단, 이 저그 배열이라는 단어는 정식 명칭이 아니라 마이크로소프트에서 개발한 C# 언어의 용어입니다.
참고로 저그(jagged)는 '들쭉날쭉하다'라는 뜻으로 말 그대로 들쭉날쭉한 모양을 한 배열을 말합니다.
초기화 시 주의할 점
이처럼 매우 편리한 배열 초기화자이지만, 사용 시 제약이 있습니다. 배열을 선언하는 단계에서 초기화할 모든 값이 정해져 있다는 점입니다.
또한, 초기화해야 할 데이터가 많은 경우에도 적합하지 않습니다. 이론적으로는 100개든 1000개든 초기화자를 사용하여 선언과 초기화를 할 수는 있지만, 프로그래머가 이를 수행하는 것은 거의 불가능할 것입니다. 초기화자를 사용하는 경우, 데이터는 어디까지나 프로그래머가 볼 수 있는 범위의 수로 제한해야 합니다.
따라서 배열을 초기화할 때는 보통처럼 선언과 초기화 처리를 분리할 것인지, 아니면 초기화자를 사용할 것인지는 상황에 따라 적절히 조절할 필요가 있습니다.
다만, 초기화자를 포함한 Java 소스 코드는 조심하지 않으면 복잡해지기 쉽습니다. 따라서 배열 외에도 주석을 붙이는 등 조금이라도 소스 코드를 쉽게 읽을 수 있도록 하는 노력이 필요합니다.
Java 배열과 초기화의 장점
이상으로 Java 배열 초기화에 대해 알아보았는데요, Java 언어에는 프로그래머가 배열 변수를 다룰 때 선언과 초기화를 할 수 있는 다양한 메커니즘이 준비되어 있음을 알 수 있습니다. 프로그래머는 이 구조를 잘 활용하면 읽기 쉽고 디버깅하기 쉬운 프로그램을 만들 수 있습니다.