HOWTO · Java
Java의 생성자에서 배열 초기화
이 게시물은 Java의 생성자에서 배열을 초기화하는 것입니다.
이 페이지의 내용
Java 객체를 만들 때 배열의 초기 내용이 생성자 인수나 다른 초기화 작업에 따라 달라진다면 생성자에서 배열 필드를 초기화하세요. Java의 기본값이 적절하다면 필드에 배열을 할당하는 것만으로 충분합니다. 생성자 안에서 지역 변수로 선언한 배열은 생성자가 실행되는 동안에만 사용할 수 있으며, 객체의 상태로 남지 않습니다.
Java 생성자에서 배열 필드 초기화하기
배열을 인스턴스 필드로 선언한 다음 생성자에서 배열 참조를 할당하세요. 새 객체를 만들 때마다 생성자가 실행되므로, 해당 객체에 전달된 입력값으로 필드를 설정하거나 그 객체에 필요한 값을 계산해 준비할 수 있습니다.
배열 필드와 그 필드가 참조하는 배열은 서로 다른 것입니다. 필드에는 참조가 저장되고, 배열에는 요소가 저장됩니다. new int[size]로 배열을 만들면 요소를 위한 공간이 할당되고 각 요소에 기본값이 지정됩니다. this.values = values처럼 지역 배열을 필드에 할당하면 그 참조가 저장됩니다. 객체가 독립적인 내용을 가져야 한다면 복사본을 사용하세요.
배열에 Java의 기본값 사용하기
Java는 생성자 본문이 실행되기 전에 인스턴스 필드에 기본값을 지정합니다. 생성자에서 배열을 만들면 Java는 배열 요소도 초기화합니다. 숫자 기본형 요소는 0으로 시작하며(정수형은 0, float과 double은 0.0), char 요소는 \u0000, boolean 요소는 false, String 같은 참조 요소는 null로 시작합니다.
예를 들어 private int[] values = new int[3];은 값이 모두 0인 요소 세 개를 가진 인스턴스 필드를 만듭니다. 대신 private int[] values;로 선언한 뒤 생성자에서 values = new int[3];을 할당해도 요소는 여전히 0으로 시작합니다. 별도의 요구사항을 표현하려는 것이 아니라면 같은 값을 다시 쓰는 반복문을 추가할 필요가 없습니다.
생성자에서 특정 값 할당하기
내용이 정해진 배열에는 배열 초기화 구문을 사용하고, 객체마다 호출자가 제공한 내용으로 시작해야 한다면 값을 생성자 매개변수로 받으세요. 예를 들어 this.values = new int[] {1, 2, 3};은 필드에 이 세 값을 할당합니다. 매개변수를 받는 생성자에서는 호출자가 전달한 배열의 이후 변경 사항도 객체에 반영되어야 하는지에 따라 입력 배열을 그대로 할당하거나 복사할 수 있습니다.
아래 예제는 한 클래스에서 여러 방법을 보여 줍니다. 기본값으로 채워지는 필드를 만들고, 전달된 값을 복사하고, 다른 필드의 모든 요소를 한 값으로 채우고, 인덱스로 값을 계산하며, 생성 중에 지역 배열도 사용합니다. 프로그램은 각 배열을 출력하므로 클래스에 맞는 부분을 골라 활용할 수 있습니다.
import java.util.Arrays;
public class ArraySetup {
private final int[] defaults = new int[3];
private final int[] supplied;
private final int[] repeated = new int[3];
private final int[] calculated = new int[3];
public ArraySetup(int[] source) {
supplied = Arrays.copyOf(source, source.length);
Arrays.fill(repeated, 7);
Arrays.setAll(calculated, index -> (index + 1) * 2);
int[] local = {4, 5};
System.out.println("Local: " + Arrays.toString(local));
}
public static void main(String[] args) {
int[] input = {3, 6, 9};
ArraySetup item = new ArraySetup(input);
System.out.println("Defaults: " + Arrays.toString(item.defaults));
System.out.println("Supplied: " + Arrays.toString(item.supplied));
System.out.println("Repeated: " + Arrays.toString(item.repeated));
System.out.println("Calculated: " + Arrays.toString(item.calculated));
}
}
생성자에서 지역 배열 만들기
생성자 안에서 int[] local = {4, 5};처럼 선언하면 지역 변수가 만들어집니다. 생성자 안의 코드는 이 변수를 사용할 수 있지만, 생성자가 반환된 뒤에는 다른 메서드에서 접근할 수 없습니다. 배열을 생성된 객체의 상태로 유지해야 한다면 대신 인스턴스 필드에 할당하세요. 예를 들어 this.values = new int[] {4, 5};처럼 작성할 수 있습니다.
지역 배열은 필드를 만들 때 임시 입력으로 사용하거나 초기화 중에만 필요한 계산에 사용할 수 있습니다. 둘의 차이를 분명히 알아 두세요. 필드나 다른 객체가 배열 참조를 저장하면 배열 객체는 계속 접근 가능한 상태로 남을 수 있지만, 생성자의 지역 변수만으로는 배열이 유지되지 않습니다.
Arrays.copyOf(), Arrays.fill(), Arrays.setAll() 사용하기
배열의 내용을 어떻게 정할지에 따라 도우미 메서드를 선택하세요. Arrays.copyOf(source, source.length)는 원본 요소를 담은 별도의 배열을 만듭니다. 요청한 길이가 원본보다 짧거나 길면 들어갈 수 있는 요소를 복사합니다. 더 긴 배열을 만들 때 추가된 요소에는 해당 타입의 기본값이 지정됩니다. 객체 배열을 복사하면 얕은 복사가 이루어져 참조는 복사되지만 참조 대상 객체 자체가 복제되지는 않습니다.
모든 요소에 같은 값을 지정하려면 Arrays.fill(array, value)을 사용하세요. 인덱스를 바탕으로 각 값을 계산하려면 Arrays.setAll(array, index -> expression)을 사용합니다. 예제에서는 채우기 작업으로 배열 전체에 7을 할당하고, 인덱스 함수로 연속된 짝수를 할당합니다. 이 메서드들은 전달된 배열을 수정하며 새 배열을 만들지는 않습니다.
초기화 방법 선택하기
기본값이 원하는 초기 상태라면 크기를 지정해 배열을 만들고 기본값을 그대로 사용하세요. 값이 적고 정해져 있다면 배열 초기화 구문을 사용하고, 호출자가 내용을 정해야 한다면 생성자 매개변수로 받으세요. 객체가 독립된 배열 구조를 가져야 한다면 입력 배열을 복사하고, 같은 값을 반복해서 넣으려면 Arrays.fill()을, 인덱스에 따라 값을 정하려면 Arrays.setAll()을 사용하세요. 생성이 끝난 뒤에도 배열을 객체의 상태로 유지해야 한다면 인스턴스 필드로 선언하세요.