배열의 복사
- 배열은 한번 생성하면 크기의 변경이 불가능합니다.
- 때문에 프로그램 중간에 배열의 크기가 변경되어야 한다면, 더 큰 배열을 생성한 후 복사하는 방법을 사용해야 합니다.
- 배열은 내부에 저장되는 자료형이 기본 타입인가, 참조 타입인가에 따라서 저장이 다르게 되기 때문에 복사에서도 이를 유의해야 합니다.
- 배열을 복사하는 방법은 크게 두 가지 방법으로 나뉩니다.
- 얕은 복사: 실제 배열의 데이터값이 저장된 값의 주소를 복사하여 활용
- 깊은 복사: 복사한 배열의 데이터값을 완전히 다른 객체에 새로 생성하여 활용
얕은 복사(shallow copy)
- 얕은 복사를 할 경우 데이터의 주소값을 복사하기 때문에 실제로 힙메모리에 저장되는 데이터는 동일하게 활용합니다.
- 다른 배열을 선언한 후 그냥 다른 배열의 값에 직접 대입하는 방법을 사용하연 얕은 복사가 됩니다.
- 이 경우 실제 메모리에 저장된 데이터의 값이 바뀌면 복사된 배열의 데이터값도 변경됩니다.
배열 얕은 복사 예시
// arr1의 배열 값을 새로운 배열에 그대로 대입
int[] arr1 = {1, 2, 3, 4};
int[] arr2 = arr1;
// 내부 값 변경 시 복사된 배열의 값 확인
arr1[3] = 5;
// arr1만 값을 바꿨지만 arr2도 값이 바뀌게 됨
for(int i = 0; i < arr1.length; i++) {
System.out.print(arr1[i] + ", ");
// 1, 2, 3, 5 출력
}
System.out.println("");
for(int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i] + ", ");
// 1, 2, 3, 5 출력
}
깊은 복사(deep copy)
- 깊은 복사는 배열의 데이터 주소값이 아닌 실제 값을 복사하는 방법입니다.
- 깊은 복사를 하기 위해서는 복사할 배열을 새로 생성 후에 값을 직접 넣는 방식으로 복사합니다.
- 이 경우 배열을 복사해도 원본 배열과 복사된 배열의 데이터가 서로 다른 메모리 주소를 가지게 됩니다.
- 따라서 원본 배열의 실제 데이터 값을 변경하더라도 복사한 배열의 데이터는 변경되지 않습니다.
배열 깊은 복사 예시
// arr1의 배열 값을 새로운 배열에 그대로 대입
int[] arr1 = {1, 2, 3, 4};
int[] arr2 = new int[arr1.length];
// 새로운 배열 생성 후 내부 값을 직접 대입
for(int i = 0; i < arr2.length; i++) {
arr2[i] = arr1[i];
}
// 내부 값 변경 시 복사된 배열의 값 확인
arr1[3] = 5;
// arr1만 값을 바꿨지만 arr2의 값은 바뀌지 않음
for(int i = 0; i < arr1.length; i++) {
System.out.print(arr1[i] + ", ");
// 1, 2, 3, 5 출력
}
System.out.println("");
for(int i = 0; i < arr2.length; i++) {
System.out.print(arr2[i] + ", ");
// 1, 2, 3, 4 출력
}
참조 타입의 배열일 경우의 복사
- 참조 타입 값으로 이루어진 경우 for문을 이용하여 값을 넣어도 주소만 복사되기 때문에 얕은 복사가 됩니다.
- 참조 타입 값을 가진 배열을 깊게 복사하기 위해서는 각 배열에 직접 객체를 만든 후에 값을 복사해야 합니다.
참조 타입 배열의 깊은 복사 예시
// 동작을 확인하는 메인 메서드
public class refernceTypeArrayExample {
public static void main(String[] args) {
Book[] books1 = new Book[3];
Book[] books2 = new Book[books1.length];
Book[] books3 = new Book[books1.length];
// books1의 배열 삽입
Books1[0] = new Book("책1", "저자1");
Books1[1] = new Book("책2", "저자2");
Books1[2] = new Book("책3", "저자3");
// books1의 객체를 books2에 얕게 복사
for(int i = 0; i < books1.length; i++) {
books2[i] = books1[i];
}
// books1의 객체 정보 변경
books1[0].setBookName("책4");
books1[0].setAuthor("저자4");
// books1에서 바뀐 값이 books2에 적용되어있음
// 책4, 저자4 출력
books2[0].checkBookInfo();
// books1의 객체를 books3에 깊게 복사
books3[0] = new Book();
books3[1] = new Book();
books3[2] = new Book();
// 새로 생성한 books3의 객체에 books1의 값을 복사
for(int i = 0; i < books1.length; i++) {
books2[i].setBookName(books1[i].getBookName());
books2[i].setAuthor(books1[i].getAuthor());
}
// books1의 객체 정보 변경
books1[1].setBookName("책5");
books1[1].setAuthor("저자5");
// books1의 변경 사항이 books3에 적용되지 않음을 확인
// 책2, 저자2 출력
books3[1].checkBookInfo();
}
}
// 클래스 선언 영역
// 책의 제목과 저자 이름을 저장하고, 이를 수정 할 수 있는 클래스 정의
public class Book {
private String bookName;
private String author;
public Book() {
}
public Book(String bookName, String author) {
this.bookName = bookName;
this.author = author;
}
public void getBookName() {
return bookName;
}
public setBookName(String bookName) {
this.bookName = bookName;
}
public void getAuthor() {
return author;
}
public setAuthor(String author) {
this.author = author;
}
public checkBookInfo() {
System.out.println(bookName + ", " + author);
}
}
배열 복사 메서드
- 자바에서 제공하는 기본 라이브러리(미리 구현해둔 기능들)의 메서드를 활용하면 배열을 간단하게 복사할 수 있습니다.
(메서드란 특정 매개변수를 이용하여 특정 값을 반환받는 함수의 일종) - Object.clone(): 자바의 Object 클래스에서 제공하는 clone() 메서드를 활용
Object.clone() 메서드 사용 예시
// 메서드 사용 법
복사할 배열.clone();
// 메서드 사용 예시
int[] intarr1 = {1, 3, 5, 7};
int[] intarr2 = intarr1.clone;
// 복사 결과 확인
for(int i = 0; i < intarr1.length; i++) {
System.out.print(intarr1[i] + ", ");
// 1, 3, 5, 7, 출력
}
System.out.println("");
for(int i = 0; i < intarr2.length; i++) {
System.out.print(intarr2[i] + ", ");
// 1, 3, 5, 7, 출력
}
- Arrays.copyOf(), Arrays.copyOfRange(): Arrays 클래스에서 제공하는 copyOf(), copyOfRange() 메서드를 활용
Arrays.copyOf() 메서드 사용 예시
// Arrays.copyOf() 메서드 사용 법
자료형[] 변수명 = Arrays.copyOf(복사할 배열, 복사할 길이)
// Arrays.copyOf() 메서드 사용 예시
int[] intarr1 = {1, 3, 5, 7};
int[] intarr2 = Arrays.copyOf(intarr1, 3);
// Arrays.copyOfRange() 메서드 사용 법
자료형[] 변수명 = Arrays.copyOf(복사할 배열, 복사 시작 인덱스, 복사할 길이)
// Arrays.copyOf() 메서드 사용 예시
int[] intarr1 = {1, 3, 5, 7};
int[] intarr2 = Arrays.copyOf(intarr1, 0, 2);
- System.arraycopy: 자바의 System 클래스에서 제공하는 arraycopy() 메서드를 활용
System.arraycopy() 메서드 사용 예시
// System.arraycopy() 메서드 사용 법
System.arraycopy(복사할 배열, 복사할 배열의 시작 인덱스, 붙여넣기할 배열 이름, 붙여넣을 지점의 인덱스, 복사할 개수)
// System.arraycopy() 메서드 사용 예시
int[] intarr1 = {1, 3, 5, 7};
int[] intarr2 = new int[intarr1.length];
// intarr1의 배열에서 0번째 인덱스부터 intarr1의 길이까지 복사하여 intarr2의 0번째 인덱스부터 채워넣게 됨
System.arraycopy(intarr1, 0, intarr2, 0, intarr1.length);
'Programing Language > Java' 카테고리의 다른 글
[Java] 접근 제어자(Access Modifier) (0) | 2022.06.27 |
---|---|
[Java] 클래스의 캡슐화(Encapsulation) (0) | 2022.06.24 |
[Java] 연산 우선 순위(Operation Priority) (0) | 2022.06.17 |
[Java] 자바의 참조 자료형(Reference Data Type) (0) | 2022.06.15 |
[Java] 자바 문자열 타입(String Type) (0) | 2022.06.15 |