18강. 객체 배열 사용하기

철새·2022년 2월 21일
0
  • Do it! 자바 프로그래밍 입문 온라인 강의를 수강하며 작성하였습니다.
  • Section 1. 자바의 핵심 - 객체지향 프로그래밍
  • 18강 "객체 배열 사용하기"
  • 객체 배열 만들기 > 배열 복사하기 > 객체 배열 복사하기 > 향상된 for문

객체 배열 만들기

  • 참조 자료형을 선언하는 객체 배열
  • 배열만 생성한 경우 요소는 null로 초기화 된다.
  • 각 요소를 new를 활용하여 생성하여 저장해야 한다.

예제는 Book 클래스를 생성하여 객체 배열을 만들어 보았다.

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 showBookInfo() {
		System.out.println(bookName + ", " + author);
	}
	
	
	public String getBookName() {
		return bookName;
	}
	public void setBookName(String bookName) {
		this.bookName = bookName;
	}
	public String getAuthor() {
		return author;
	}
	public void setAuthor(String author) {
		this.author = author;
	}
}

main이 있는 BookArray 클래스에서 객체 배열을 생성한 후 출력하면 null로 초기화되어 있는 것을 확인할 수 있다.

public class BookArray {
	public static void main(String[] args) {
		Book[] library = new Book[5];
		
		for(int i=0; i<library.length; i++) {
			System.out.println(library[i]);
		}
	}
}

int, double과 같은 기본 자료형으로 배열을 생성하면 해당 자료형이 차지하는 크기(int면 4byte 등)와 배열의 개수만큼의 공간이 만들어진다.
하지만 객체 배열에서는 처음부터 객체가 만들어지는 것이 아니라 객체가 가리킬 주소의 자리가 만들어진다. 때문에 나중에 객체를 new 키워드를 통해 직접 생성해주어야 한다.

즉, 위 코드는 library 배열에 Book 객체가 5개 생성된 것이 아니라 주소의 자리가 5개 생성된 상태이다.

따라서 그림처럼 배열 안에 다시 객체를 넣어주어야 한다.

public class BookArray {
	public static void main(String[] args) {
		Book[] library = new Book[5];
		
		library[0] = new Book("태백산맥", "조정래");
		library[1] = new Book("데미안", "헤르만 헤세");
		library[2] = new Book("어떻게 살 것인가", "유시민");
		library[3] = new Book("토지", "박경리");
		library[4] = new Book("어린 왕자", "생텍쥐페리");
		
		for(int i=0; i<library.length; i++) {
			System.out.println(library[i]);
		}
		for(int i=0; i<library.length; i++) {
			library[i].showBookInfo();
		}
	}
}


배열의 각 자리에 Book 객체를 생성하였고, 객체 주소를 반환하는 것을 확인할 수 있다.

배열 복사하기

  • 기존 배열과 같은 배열을 만들거나 배열이 꽉 찬 경우 더 큰 배열을 만들고 기존 배열 자료를 복사할 수 있다.
  • System.arraycopy(src, srcPos, dest, destPos, length);
매개변수설명
src복사할 배열 이름
srcPos복사할 배열의 첫 번째 위치
dest복사해서 붙여 넣을 대상 배열 이름
destPos복사해서 대상 배열에 붙여 넣기를 시작할 첫 번째 위치
lengthsrc에서 dest로 자료를 복사할 요소 개수
public class ArrayCopy {
	public static void main(String[] args) {
		int[] arr1 = {10, 20, 30, 40, 50};
		int[] arr2 = {1, 2, 3, 4, 5, 6, 7, 8, 9};
		
		System.arraycopy(arr1, 0, arr2, 1, 4);
		for(int i=0; i<arr2.length; i++) {
			System.out.println(arr2[i]);
		}
	}
}

System.arraycopy(arr1, 0, arr2, 1, 4); 을 해석해보면
arr1의 0번째부터 복사할 것이고, arr2의 1번째부터 붙여넣을 것인데, 4개를 복사할 것이라는 의미이다.
arr2를 출력해보면 0번째 요소는 바뀌지 않고 1번째부터 4개는 변한 것을 확인할 수 있다.
붙여넣을 배열의 size가 복사할 size를 초과하면 에러가 발생한다.

객체 배열 복사하기

  • 얕은 복사 : 배열 요소의 주소만 복사되므로 배열 요소가 변경되면 복사된 배열의 값도 변경된다.
public class ObjectCopy {
	public static void main(String[] args) {
		Book[] bookArr1 = new Book[5];
		Book[] bookArr2 = new Book[5];
		
		bookArr1[0] = new Book("태백산맥", "조정래");
		bookArr1[1] = new Book("데미안", "헤르만 헤세");
		bookArr1[2] = new Book("어떻게 살 것인가", "유시민");
		bookArr1[3] = new Book("토지", "박경리");
		bookArr1[4] = new Book("어린 왕자", "생텍쥐페리");
		
		//bookArr1의 객체를 boorArr2에 복사
		System.arraycopy(bookArr1, 0, bookArr2, 0, 5);
		
		//bookArr1의 배열을 수정
		bookArr1[0].setBookName("나목");
		bookArr1[0].setAuthor("박완서");
		
		//bookArr2 출력
		for(int i=0; i<bookArr2.length; i++) {
			bookArr2[i].showBookInfo();
		}
	}
}


bookArr2에는 bookArr1의 값이 복사된 것이 아니라 주소가 복사된 것이라 bookArr1의 요소를 수정하면 bookArr2의 요소도 함께 수정된다.
(정확히는 함께 수정되는 것이 아니라 동일한 인스턴스 주소를 가리키고 있으므로 인스턴스가 수정되면 동시에 바뀌는 것이다.)


  • 깊은 복사 : 각 배열마다 객체를 생성 후, 원래 배열에 있는 객체의 정보를 직접 대입한다.
public class ObjectCopy {
	public static void main(String[] args) {
		Book[] bookArr1 = new Book[5];
		bookArr1[0] = new Book("태백산맥", "조정래");
		bookArr1[1] = new Book("데미안", "헤르만 헤세");
		bookArr1[2] = new Book("어떻게 살 것인가", "유시민");
		bookArr1[3] = new Book("토지", "박경리");
		bookArr1[4] = new Book("어린 왕자", "생텍쥐페리");
		
		//bookArr2 배열에 Book 객체 생성 후 bookArr1의 인스턴스를 대입
		Book[] bookArr2 = new Book[5];
		for(int i=0; i<bookArr2.length; i++) {
			bookArr2[i] = new Book();
			bookArr2[i].setBookName(bookArr1[i].getBookName());
			bookArr2[i].setAuthor(bookArr1[i].getAuthor());
		}
		
		//bookArr1의 배열을 수정
		bookArr1[0].setBookName("나목");
		bookArr1[0].setAuthor("박완서");
		
		//bookArr2 출력
		for(int i=0; i<bookArr2.length; i++) {
			bookArr2[i].showBookInfo();
		}
	}
}


이렇게 하면 서로 다른 인스턴스의 메모리를 요소로 가지게 된다.

객체 배열을 복사할 때는 반드시 깊은 복사를 해야하는 것이 아니라, 복사한 배열이 수정될 일이 없다면 얕은 복사를, 수정될 일이 있다면 깊은 복사를 하면 되는 것이다.

향상된 for문 (enhanced for loop)

  • 배열 요소의 처음부터 끝까지 모든 요소를 참조할 때 편리한 반복문
// 기본 문법
for(자료형 변수 : 배열){
	반복 실행문;
}

// 사용 예제
public class EnhancedForLoop {
	public static void main(String[] args) {
		String[] strArr = {"Java", "Android", "C", "JavaScript", "Python"};
		
		for(String s : strArr) {
			System.out.println(s);
		}
	}
}

변수에 배열의 0번째부터 마지막 요소까지 순차적으로 대입되며, 변수의 자료형은 배열의 자료형과 일치해야 한다.

profile
효율성을 추구하며 세상을 떠도는 철새입니다.

0개의 댓글

관련 채용 정보