Closed ForteEscape closed 2 months ago
일단 배열이 깔끔한 경우는 기본형과 String에 한정되어 있는 듯 합니다. 이것에 대한 이유는 확실하지는 않지만 다음과 같은 것 같습니다.
java에서 int, long, float과 같은 기본형과 String은 값을 바꾸고 싶다면 무조건 = 연산자를 사용해야 합니다. 이를 사용하면 값이 바뀐 배열은 항상 기존과 다른 주솟값을 참조하게 됩니다. 해당 배열은 clone을 사용해 복사본을 만들어 내부의 값을 수정한 순간부터 해당 원소는 다른 주솟값을 참조하게 되고, 이 때문에 기존의 배열에는 아무 영향을 주지 않습니다.
하지만 기본형과 String이 아닌, 예를 들어 직접 만든 class 배열일 경우에는 다릅니다. clone을 사용해 복사본을 만들면 배열의 각 칸은 같은 주소를 참조하고 있습니다. 값을 바꾸는 경우에 = 연산자를 사용해 새로운 객체를 생성해 넣어준다면 새로운 주소를 참조해서 이전의 배열에 영향을 주지 않습니다. 하지만 = 연산자를 사용하지 않고 .으로 접근해 값을 바로 변경한다면 (setter도 마찬가지) 기존의 주소값(원래와 동일함)의 값을 변경하기 때문에 clone을 사용한 배열의 값을 변경했음에도 기존 배열에 영향을 주게 됩니다.
배열을 clone할 때 객체의 clone은 사용하지 않기 때문에 객체의 clone을 재정의하더라도 위와 같은 상황을 해결하지 못합니다.
혹시 위의 가정이 틀렸거나 다른 이유가 있다면 말해주시면 감사하겠습니다.
그리고 테스트 결과 clone()과 복사 생성자를 활용한 경우의 성능 차이는 거의 없지만 복사 생성자가 더 빠릅니다. 하지만 이 차이가 거의 나지 않아서 코드를 복잡하게 만드는 것보다 clone을 이용해 깔끔하게 짜는 것이 더 낫다고 판단한 것 같습니다.
public class ArrayClonePerformance {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,6,7,8,9,10};
//peformance
//clone 사용해서 복사
long before = System.currentTimeMillis();
for(int i=0;i<1000000000;i++)
{
arr.clone();
}
System.out.println("Time Required for Clone: "+ (System.currentTimeMillis()-before));
//peformance
//clone을 사용하지 않고 생성자 복사
//생성자 복사를 진행할 때에는 새로운 배열 만들어서 하나씩 값 대입하게 됨
before = System.currentTimeMillis();
for(int i=0;i<1000000000;i++)
{
ArrayCopy(arr);
}
System.out.println("Time Required for Copy of: "+ (System.currentTimeMillis()-before));
}
public static int[] ArrayCopy(int[] arr) {
int[] copy = new int[arr.length];
for(int j=0;j<arr.length;j++) {
copy[j] = arr[j];
}
return copy;
}
}
결과
Time Required for Clone: 8124
Time Required for Copy of: 7988
Q. 책(p.86)에서 다음과 같이 서술된 부분이 있습니다.