Java 기초 (17) 배열 복사 메소드 clone, System.arraycopy, Arrays.copyOf / 깊은 복사

코린이서현이·2023년 7월 19일
0

Java

목록 보기
17/46

🔥오늘의 목표🔥

자바에서는 배열을 복사하는 System.arraycopy, Arrays.copyOf,clone에 대해서 알아보자.

📕 복사하기

  • 기본자료형 복사
  • 클래스형 복사

📖 기본 자료형 복사하기

  • 기본자료형은 따로 깊은 복사가 필요없다.

📒 clone()

  • Java지만 다른 언어로 작성된 메소드이다.
	int[] scores = { 1, 2, 3, 4, 5 };
	int[] newScores = scores.clone();

더알아보기

📒 System.arraycopy()

  • 바로 배열에 대입할 수는 없는 것 같고, 선언된 배열을 가지고 메소드만 작성해서 사용하는 듯하다.
	System.arraycopy(원본배열, 원본 배열의 복사 시작 인덱스, 대상배열,대상배열 시작인덱스, 복사할 요소의 개수)

📒 Arrays.copyOf

  • 대상배열을 쓰지 않는 대신 대상배열에 대입해야한다.
	Arrays.copyOf(원본배열, 원본 배열에서 복사해올 길이)

✍️ 예시코드
기본자료형의 경우는 원본값을 변경하다고 하더라도 복사배열값이 변경되지는 않는다.

  public class CopyTest {

      public static void main(String[] args) {

          int[] array = {0,1,2,3,4};

          int[] clonearray = array.clone();
          int[] copyOFarray = Arrays.copyOf(array,5);
          int[] arraycopyarray = new int[5];
          System.arraycopy(array, 0, arraycopyarray,0, 5);

          array[3]=6;

          System.out.println(Arrays.toString(array));			//[0, 1, 2, 6, 4]
          System.out.println(Arrays.toString(clonearray));		//[0, 1, 2, 3, 4]
          System.out.println(Arrays.toString(copyOFarray));		//[0, 1, 2, 3, 4]
          System.out.println(Arrays.toString(arraycopyarray));	//[0, 1, 2, 3, 4]
		}
	}

✍️예시코드
: 문자열 배열 복사도 원본값 변경을 한다고 해도 복사값 변경이 가능하다.

  public class CopyTest {

      public static void main(String[] args) {

          //String 배열 복사하기
          String[] starray = {"사과","배","감"};

          String[] clonestarray = starray.clone();
          String[] copyOFstarray = Arrays.copyOf(starray,3);
          String[] arraycopystarray = new String[3];
          System.arraycopy(starray, 0, arraycopystarray,0, 3);

          starray[2]="귤";

          System.out.println(Arrays.toString(starray));				// [사과, 배, 귤]
          System.out.println(Arrays.toString(clonestarray));		//[사과, 배, 감]
          System.out.println(Arrays.toString(copyOFstarray));		//[사과, 배, 감]
          System.out.println(Arrays.toString(arraycopystarray));	//[사과, 배, 감]

      }

  }

📖 객체배열 복사

  • 객체 배열 복사는 어떻게 복사를 하던 항상 객체의 인스턴스 주소가 복사된다.
    = 복사객체가 고유의 값을 가지는 것이 아니라, 원본 객체의 인스턴스주소를 가지게 된다.
    따라서 원본 객체값을 변경하면 복사객체값도 변경이된다.
    ✍️ 예제코드
    : 원본 객체 배열값 변경
  import java.util.Arrays;

  class Object {
      int n;

      Object(int i){
          this.n = i;
      }
  }

  public class CopyTest {

      public static void main(String[] args) {

          //객체 생성
          Object[] object = new Object[3];

          int j = 0;
          for(int i = 0; i < object.length; i++) {
              object[i] = new Object(j);
              j++;

          }
          //객체 복사
          Object[] cloneObject = object.clone();
          Object[] copyOFObject = Arrays.copyOf(object,3);
          Object[] arraycopyObject = new Object[3];
          System.arraycopy(object,0,arraycopyObject,0,3);
		
          //원복객체값 변경
          object[0].n = 3;

          for(int i = 0 ; i < object.length; i++) {
              System.out.println(object[i].n);			// 3 , 1 , 2
          }

          for(int i = 0 ; i < cloneObject.length; i++) {
              System.out.println(cloneObject[i].n);		// 3 , 1 , 2
          }

          for(int i = 0 ; i < copyOFObject.length; i++) {
              System.out.println(copyOFObject[i].n);	// 3 , 1 , 2
          }
          for(int i = 0 ; i < arraycopyObject.length; i++) {
              System.out.println(arraycopyObject[i].n);	// 3 , 1 , 2
          }		

      }	
  }

👉 실행화면
: 복사배열의 값도 변경됨을 확인 할 수 있다.

3 1 2
3 1 2
3 1 2
3 1 2 

📕 객체 배열 깊은 복사

: 객체배열의 경우 인스턴스주소가 복사됨을 배웠다.
따라서 고유의 객체배열을 가지고 싶을때에는 인스턴스를 만들고 그 값을 직접 복사해야한다.

📒깊은 복사 내가 고민한 방법
인스턴스 변수 하나하나 복사를 해준다.

package test;


class Object {
	int n;

	Object() {
		
	}
	
	Object(int i){
		this.n = i;
	}
}

public class CopyTest {

	public static void main(String[] args) {
		
	Object[] ob = new Object[3];
	
	for (int i =0; i<3; i++ ) {
		ob[i] = new Object(i);
	}
	
	Object[] newob = new Object[3];
	
	for (int i =0; i<3; i++ ) {
   		//객체 배열에는 생성자를 이용해 객체를 필수로 생성해야한다.
		newob[i] = new Object();
		//인스턴스 변수 직접 대입
        newob[i].n = ob[i].n;
	}
	
	ob[0].n = 3;
	for (int i =0; i<3; i++ ) {
		System.out.println(ob[i].n);		//3 , 1 , 2 출력
	}
	
	for (int i =0; i<3; i++ ) {
		System.out.println(newob[i].n);		//0 , 1 , 2 출력
	}	
	}
}	

👉 실행화면
: 깊은 복사가 이루어짐을 확인 할 수 있다.

3 1 2
0 1 2

➕클래스는 다양한 인스턴스 변수가 존재하기 때문에 Cloneable 인터페이스 구현을 사용하는 것이 좋다고 한다.
이 부분은 좀 심화부분인 것 같아서 추후에 추가하도록 하겠다...
더 알아보기
더 알아보기

📖 복사 생성자와 복사 팩토리를 사용하는 방법

📒 복사 생성자

:복사대상인스턴스를 복사해주는 메소드

📒 복사 팩토리

:복사대상인스턴스 객체 생성까지 해주는 공장
⚠️ 인스턴스를 생성하지 않고도 이용할 수 있도록 static예약어를 사용해야한다.
더 알아보기

✍️예시코드

class Object {
	int n;

	Object() {
	}
	
	//해당 클래스를 넣어서 복사해주는 생성자
	Object(Object original){
		this.n = original.getn(); 
	}
	
	Object(int i){
		this.n = i;
	}
	
	int getn() {
		return this.n;
	}
    
	//인스턴스를 생성하지 않고도 이용할 수 있도록 static예약어를 사용해야한다.
	static Object copyObject (Object original) {
		Object copyObject = new Object();
		copyObject.n = original.getn();
		return copyObject;
	}
	
}

public class CopyTest {

	public static void main(String[] args) {
		
	Object[] ob = new Object[3];
	
	for (int i =0; i<3; i++ ) {
		ob[i] = new Object(i);
	}

	//복사 생성자를 이용
	Object[] newob = new Object[3];
	for (int i =0; i<3; i++ ) {
		//생성시 원하는 객체를 넣어 복사할 수 있게 함.
		newob[i] = new Object(ob[i]);
	}
	
	//복사팩토리를 이용
	Object[] pactob = new Object[3];
	for ( int i = 0; i < 3; i++) {
		//따로 new 예약어를 쓰지 않는다.
		pactob[i] = Object.copyObject(ob[i]);
	}
	
	ob[0].n = 3;

	for (int i =0; i<3; i++ ) {
		System.out.println(ob[i].n);			// 3 1 2
	}
	
	for (int i =0; i<3; i++ ) {
		System.out.println(newob[i].n);			// 0 1 2
	}	
	for (int i =0; i<3; i++ ) {
		System.out.println(pactob[i].n);		//0 1 2
	}
	}	
}

✍️ 실행화면

3 1 2
0 1 2
0 1 2

🔥오늘의 느낀 점🔥

아침에 일어나서 미리미리 공부를 시작해야겟다..!!
profile
24년도까지 프로젝트 두개를 마치고 25년에는 개발 팀장을 할 수 있는 실력이 되자!

1개의 댓글

comment-user-thumbnail
2023년 7월 19일

정말 잘 읽었습니다, 고맙습니다!

답글 달기