자바 프로그램이 실행되면, JVM은 운영체제로부터 필요한 메모리를 할당받는다.
자바 프로그램에서 사용되는 클래스에 대한 정보와 함께 클래스 변수(static variable)가 저장되는 영역.
JVM은 자바 프로그램에서 특정 클래스가 사용되면 해당 클래스의 클래스 파일(.class)를 읽어들여, 해당 클래스에 대한 정보를 메소드 영역에 저장한다.
자바 프로그램에서 사용되는 모든 인스턴스 변수가 저장되는 영역.
JVM은 자바 프로그램에서 new 키워드를 사용하여 인스턴스가 생성되면, 해당 인스턴스의 정보를 힙 영역에 저장한다.
자바 프로그램에서 메소드가 호출될 때 메소드의 스택 프레임이 저장되는 영역.
JVM은 자바 프로그램에서 메소드가 호출되면, 메소드의 호출과 관계되는 지역 변수와 매개변수를 스택 영역에 저장한다.
스택 영역은 메소드의 호출과 함께 할당되며, 메소드의 호출이 완료되면 소멸한다. 스택 영역에 저장되는 메소드의 호출 정보를 스택 프레임(stack frame)이라고 한다.
스택은 후입선출(LIFO) 방식에 따라 동작하므로, push로 데이터를 저장하고 pop으로 데이터를 인출한다. 즉, 가장 늦게 저장된 데이터가 가장 먼저 인출된다.
같은 타입의 변수들로 이루어진 유한 집합.
두 가지 방법으로 선언할 수 있으나, 되도록 첫 번째 방법만 사용하는 것이 좋다.
int[] grade1 = new int[3];
int[] grade2 = new int[3];
grade1[0] = 85;
grade1[1] = 65;
grade1[2] = 90;
grade2[0] = 85;
for (int i = 0; i < grade1.length; i++) {
System.out.print(grade1[i] + " ");
}
for (int i = 0; i < grade2.length; i++) {
System.out.print(grade2[i] + " ");
}
// 85 65 90
// 85 0 0
배열 타입과 초깃값
배열의 길이를 초과하는 인덱스를 사용하면 ArrayIndexOutOfBounds 예외가 발생한다.
괄호({})를 사용하여 초깃값을 나열한 초기화 블록(initialization block)을 이용하여 선언과 동시에 초기화할 수 있다. 초기화 블록에 맞춰 자동으로 배열의 길이가 설정된다.
두 가지 방법을 사용할 수 있으나 다음과 같은 경우에는 두 번째 방법만을 사용해야 한다.
int[] grade1 = {70, 90, 80};
int[] grade2 = new int[]{70, 90, 80};
int[] grade3;
// grade3 = {70, 90, 80}; // 이미 선언된 배열을 이 방법으로 초기화하면 오류가 발생함.
int[] grade4;
grade4 = new int[]{70, 90, 80}; // 이미 선언된 배열은 이 방법으로만 초기화할 수 있음.
초기화 블록의 타입과 배열의 타입은 반드시 일치해야 한다.
int[][] arr1 = new int[2][3];
// arr[0][0], arr[0][1], arr[0][2]
// arr[1][0], arr[1][1], arr[1][2]
int[][] arr2 = {
{10, 20, 30},
{40, 50, 60}
};
행마다 다른 길이의 배열을 요소로 저장할 수 있다.
int[][] arr1 = new int[3][];
arr[0] = new int[2];
arr[1] = new int[4];
arr[2] = new int[1];
int[][] arr2 = {
{10, 20},
{10, 20, 30, 40},
{10}
};
자바에서 배열은 한 번 생성하면 길이를 변경할 수 없다. 따라서 더 많은 데이터를 저장하기 위해서는 큰 배열을 만들고, 이전 배열의 데이터를 새로 만든 배열로 복사한다.
이 중 에서는 배열의 복사만을 위해 만들어진 arraycopy() 메소드가 성능이 가장 좋다.
arraycopy(), copyOf() 메소드와 for문을 이용한 복사는 배열의 길이를 마음대로 늘일 수 있지만 clone() 메소드는 이전 배열과 같은 길이의 배열만 만들 수 있다.
int[] arr1 = new int[]{1, 2, 3, 4, 5};
int newLen = 10;
// 1. System 클래스의 arraycopy() 메소드
int[] arr2 = new int[newLen];
System.arraycopy(arr1, 0, arr2, 0, arr1.length);
// 2. Arrays 클래스의 copyOf() 메소드
int[] arr3 = Arrays.copyOf(arr1, 10);
// 3. Object 클래스의 clone() 메소드
int[] arr4 = (int[])arr1.clone();
// 4. for 문과 인덱스를 이용한 복사
int[] arr5 = new int[newLen];
// 1 2 3 4 5 0 0 0 0 0
// 1 2 3 4 5 0 0 0 0 0
// 1 2 3 4 5
// 1 2 3 4 5 0 0 0 0 0
명시한 배열이나 컬렉션의 길이만큼 반복되어 실행된다.
int[] arr = new int[]{1, 2, 3, 4, 5};
for (int e : arr) {
System.out.print(e + " ");
}
// 1 2 3 4 5
Enhanced for문은 요소를 참조할 때만 사용하는 것이 좋고, 요소의 값을 변경하는 작업에는 for문을 사용한다. Enhanced for문 내부에서 사용되는 배열 요소는 배열 요소 그 자체가 아닌 배열 요소의 복사본이기 때문에, Enhanced for문에서 배열 요소의 값을 변경해도 원본 배열에는 아무 영향을 주지 않는다.