int[][] arr=new arr[3][2];
"코드1"과 같은 일반적인 2차원 배열을 선언시에 2차원 연속적인 메모리 할당으로 하나의 참조변수에 의해 관리되는 것처럼 생각될 수 있습니다.
하지만, 실제로는 2차원 배열이 연속적인 메모리가 할당된 별도의 정적 자료구조가 아니고 값을 저장하는 1차원 배열들과 각 1차원 배열을 참조하는 배열로 이루어집니다.
int[][] arr=new int[3][];
arr[0] = new int[3]
arr[1] = new int[2]
arr[2] = new int[1]
"코드2"와 같이 선언하였을때 위 그림과 같은 메모리 할당이 일어납니다.
예제코드와 출력 결과로 자세하게 확인해볼 수 있습니다.
System.out.println("-- 참조 배열만 선언 --");
int[][] arr=new int[3][];
System.out.println("arr : "+arr); // 타입과 참조하는 배열의 시작 메모리 주소 확인 가능
// [[I@ => int배열에 대한 배열
System.out.println("arr[0] :" +arr[0]+", arr[1] : "+arr[1]+", arr[2] : "+arr[2]);
// 각 원소가 참조할 int배열이 할당되지 않았으므로 null 출력
System.out.println();
arr[0]=new int[3];
arr[1]=new int[2];
arr[2]=new int[1];
System.out.println("-- 각 참조에 int 배열 할당 후 --");
System.out.println("arr[0] :" +arr[0]+", arr[1] : "+arr[1]+", arr[2] : "+arr[2]); // 각 참조의 타입과 가리키는 배열의 시작 메모리 주소 출력
System.out.println("arr[0] class :" +arr[0].getClass()+", arr[1] class : "+arr[1].getClass()+", arr[2] class : "+arr[2].getClass());
System.out.println();
// 새로운 1차원 배열을 메모리에 할당하여 arr[0]의 참조를 변경.
arr[0]=new int[10];
//메모리 주소가 바뀐것 확인
System.out.println("-- arr[0] 이 가리키는 참조 메모리 주소 바뀜 --");
System.out.println("arr[0] :" +arr[0]);
출력
-- 값이 저장될 1차원 배열 선언 후 출력 --
arr : [[I@7e0ea639
arr[0] :null, arr[1] : null, arr[2] : null-- 각 1차원 배열에 메모리 할당 후 메모리 주소 출력 --
arr[0] :[I@2c6a3f77, arr[1] : [I@246ae04d, arr[2] : [I@62043840
arr[0] class :class [I, arr[1] class : class [I, arr[2] class : class [I-- arr[0] 이 가리키는 1차원 배열 새로 할당 후 참조 메모리 주소 바뀜 --
arr[0] :[I@5315b42e