안녕하세요. 스코리아입니다.
이전 시간에는 자바 1차원 배열을 선언하는 방법과 초기화하는 방법에 대해서 알아보았습니다.
[이전 내용] 1차원 배열 선언, 초기화 방법 : https://skorea6.tistory.com/14
오늘은 자바 객체 배열을 선언/구현해 보고, 얕은 복사와 깊은 복사 방법을 예제와 함께 알아보겠습니다.
객체 배열 특징
- 기본 자료형 배열은 선언과 동시에 배열의 크기만큼의 메모리가 할당됩니다.
- 하지만, 객체 배열의 경우에는 요소가 되는 객체의 주소가 들어갈 메모리(4byte, 8byte..)만 할당되고 각 요소 객체는 생성하여 저장해야 합니다.
- 객체 배열을 만들고 나면, 모든 index의 값은 null로 초기화됩니다.
객체 배열 선언, 구현하기
- Book.java 파일을 만들어, Book class를 구현해 보겠습니다.
public class Book {
private String title;
private String author;
public Book() {}
public Book(String title, String author) {
this.title = title;
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public void showBookInfo() {
System.out.println(title + ", " +author);
}
}
- Book 생성자 2개, 그리고 멤버변수인 title(제목), author(글쓴이)에 대한 getter, setter 메소드를 생성해 주었습니다.
- showBookInfo() 메소드를 통해 멤버변수인 title과 author를 출력 가능하게끔 하였습니다.
- BookArrayTest.java 파일을 만들어, 메인함수를 정의하고 Book 객체를 배열로 선언한 뒤, 출력해 봅시다.
Book[] library = new Book[5];
for(Book b : library) {
System.out.println(b);
}
- Book 객체 배열에 아무 값도 입력하지 않았으므로, 기본값인 null로 모두 초기화됩니다.
- 그러므로, 배열의 값들이 모두 null로 출력됩니다.
- 이번에는 Book 객체 배열에 값을 추가해 보겠습니다. new Book()을 이용하여 index별로 값을 추가하였습니다.
Book[] library = new Book[5];
library[0] = new Book("아몬드1", "조1");
library[1] = new Book("아몬드2", "조2");
library[2] = new Book("아몬드3", "조3");
library[3] = new Book("아몬드4", "조3");
library[4] = new Book("아몬드5", "조4");
for(Book b : library) {
System.out.println(b);
b.showBookInfo();
}
- new Book() 키워드를 사용하여 새로운 Book 인스턴스를 객체 배열에 저장하였기 때문에, 각각의 배열 값들은 모두 다른 메모리 주소를 갖게 됩니다.
- b.showBookInfo() 메소드 호출로, title과 author가 잘 나오는 것을 볼 수 있습니다.
객체 복사 - 얕은 복사
- 객체 주소만 복사되어, 한쪽 배열의 요소를 수정하면 같이 수정됩니다.
- 즉, 두 배열이 같은 객체(메모리주소)를 가리킵니다.
- 자바에서 제공되는 배열 복사 메서드: System.arrayCopy(src, srcPos, dest, destPos, length)
Book[] library = new Book[5];
Book[] copyLibaray = new Book[5];
library[0] = new Book("아몬드1", "조1");
library[1] = new Book("아몬드2", "조2");
library[2] = new Book("아몬드3", "조3");
library[3] = new Book("아몬드4", "조3");
library[4] = new Book("아몬드5", "조4");
// 얕은 복사 진행
System.arraycopy(library, 0, copyLibaray, 0, 5);
System.out.println("========= copy library =========");
for(Book b : copyLibaray ) {
b.showBookInfo();
}
// library 값을 변경
library[0].setTitle("리눅스마스터");
library[0].setAuthor("김민지");
System.out.println("========= library =========");
for(Book b : library) {
b.showBookInfo();
}
// copyLibrary 쪽에서도 값이 변경됨
System.out.println("========= copy library =========");
for(Book b : copyLibaray) {
b.showBookInfo();
}
- Stream.arraycopy를 이용하여 library 객체 배열 0번째 index부터 마지막 index까지 copyLibrary 객체 배열에 얕은 복사를 진행하였습니다.
- copyLibrary 배열 출력 결과, library 배열과 동일하게 잘 복사됨을 알 수 있습니다.
- library의 0번째 index 값을 변경해 보았습니다.
- library 배열에서 '리눅스마스터' , '김민지'로 변경된 것이 잘 보입니다.
- copyLibrary 배열에서도 '리눅스마스터' , '김민지'로 변경되었습니다. 그 이유는 두 배열이 얕은 복사를 하였으므로, 두 배열이 같은 객체(메모리주소)를 가리키기 때문입니다.
객체 복사 - 깊은 복사
- 각각의 객체를 생성하여 그 객체의 값을 복사하여 배열이 서로 다른 객체를 가리키도록 만드는 것입니다.
- 즉, 두 배열이 서로 다른 객체(메모리주소)를 가리킵니다.
Book[] library = new Book[5];
Book[] copyLibaray = new Book[5];
library[0] = new Book("아몬드1", "조1");
library[1] = new Book("아몬드2", "조2");
library[2] = new Book("아몬드3", "조3");
library[3] = new Book("아몬드4", "조3");
library[4] = new Book("아몬드5", "조4");
// 깊은 복사 진행
for(int i=0; i<library.length; i++) {
copyLibaray[i] = new Book(library[i].getTitle(), library[i].getAuthor());
}
// library 값을 변경
library[0].setTitle("리눅스마스터");
library[0].setAuthor("김민지");
System.out.println("========= library =========");
for(Book b : library) {
b.showBookInfo();
}
// copy library 쪽에서는 값이 변경되지 않음!
System.out.println("========= copy library =========");
for(Book b : copyLibaray) {
b.showBookInfo();
}
- library가 new Book()을 이용하여 새로운 객체를 만들어 값을 넣는 것처럼, copyLibrary도 new Book()을 이용하여 index마다 새로운 객체를 만들어, 깊은 복사를 진행하였습니다.
- library의 0번째 index 값을 변경해 보았습니다.
- library 배열에서 '리눅스마스터' , '김민지'로 변경된 것이 잘 보입니다.
- copyLibrary 배열에서는 값이 변경되지 않았습니다. 기존 값인 '아몬드1' , '조1' 그대로 출력됩니다. 그 이유는 두 배열이 깊은 복사를 하였으므로, 두 배열이 다른 객체(메모리주소)를 가리키기 때문입니다.
지금까지 자바(Java) 객체 배열을 선언 및 구현해 보았고, 얕은 복사와 깊은 복사 사용방법에 대해서 알아보았습니다.
읽어주셔서, 감사합니다.
'JAVA > 문법' 카테고리의 다른 글
자바 ArrayList 주요 메소드 정리, 사용방법 (3) | 2023.08.23 |
---|---|
자바 2차원 배열 선언, 초기화 방법 (array) (1) | 2023.08.22 |
자바 1차원 배열 선언, 초기화 방법 (array) (1) | 2023.08.19 |
자바 기본형 타입 vs 참조형 타입 차이점 정리 (1) | 2023.08.11 |