Việc gọi clone () trên một mảng cũng sao chép nội dung của nó?


92

Nếu tôi gọi clone()phương thức trên mảng Đối tượng kiểu A, nó sẽ sao chép các phần tử của nó như thế nào? Bản sao có tham chiếu đến các đối tượng giống nhau không? Hay nó sẽ gọi (element of type A).clone()cho từng người trong số họ?


3
Bạn phải gọi bản sao trên mỗi phần tử.
Peter Lawrey

Câu trả lời:


77

clone()tạo ra một bản sao nông. Có nghĩa là các phần tử sẽ không được nhân bản. (Điều gì sẽ xảy ra nếu họ không triển khai Cloneable?)

Bạn có thể muốn sử dụng Arrays.copyOf(..)để sao chép mảng thay vì clone()(mặc dù sao chép là tốt cho mảng, không giống như bất kỳ thứ gì khác)

Nếu bạn muốn nhân bản sâu, hãy kiểm tra câu trả lời này


Một ví dụ nhỏ để minh họa mức độ nông cạn của clone()ngay cả khi các phần tử là Cloneable:

ArrayList[] array = new ArrayList[] {new ArrayList(), new ArrayList()};
ArrayList[] clone = array.clone();
for (int i = 0; i < clone.length; i ++) {
    System.out.println(System.identityHashCode(array[i]));
    System.out.println(System.identityHashCode(clone[i]));
    System.out.println(System.identityHashCode(array[i].clone()));
    System.out.println("-----");
}

Bản in:

4384790  
4384790
9634993  
-----  
1641745  
1641745  
11077203  
-----  

2
Và, nếu bạn đang đi để làm điều đó, cá nhân tôi muốn sử dụngSystem.arrayCopy
corsiKa

1
clone()là một lựa chọn tốt để sử dụng với các mảng..chất riêng. Bloch đề cập rằng anh ấy sẽ chỉ sử dụng nó cho các mảng và không có gì khác. System.arrayCopyỔn. Arrays.copyOf(..)là một giải pháp thay thế khác dễ sử dụng hơn.
Bozho

Tôi rút lại - tôi sẽ sử dụng Arrays.copyOf:-) Nó có một chữ ký phương thức giúp đơn giản hóa các biến (vâng, nó hạn chế bạn, nhưng nó hoàn hảo cho hầu hết các trường hợp) và ít nhất trong JDK của tôi, nó được triển khai bằng cách sử dụng System.arrayCopy. Cảm ơn vì mẹo đó!
corsiKa

@Bozho, từ ví dụ của bạn. array [i] và clone [i] sẽ tham chiếu đến cùng một đối tượng nên hai sysouts đầu tiên giống nhau. Nhưng mảng [i] .clone cũng sẽ tham chiếu đến chính mảng [i] vậy tại sao mảng [i] .clone () lại trả về một giá trị mã băm khác?
abhihello123

@weakstudent, array[i].clone()KHÔNG đề cập đến array[i]. Đó là những gì mà một phần của ví dụ đang chứng minh.
Dathan

19

Nếu tôi gọi phương thức clone () trên mảng Đối tượng kiểu A, nó sẽ sao chép các phần tử của nó như thế nào?

Các phần tử của mảng sẽ không được sao chép.

Bản sao có tham chiếu đến các đối tượng giống nhau không?

Đúng.

Hay nó sẽ gọi (phần tử của loại A) .clone () cho mỗi người trong số họ?

Không, nó sẽ không gọi clone()bất kỳ phần tử nào.


6

Mảng nguyên thủy 1D thực hiện sao chép các phần tử khi nó được nhân bản. Điều này thôi thúc chúng ta sao chép mảng 2D (Array of Arrays).

Hãy nhớ rằng bản sao mảng 2D không hoạt động do triển khai bản sao nông của clone().

public static void main(String[] args) {
    int row1[] = {0,1,2,3};
    int row2[] =  row1.clone();
    row2[0] = 10;
    System.out.println(row1[0] == row2[0]); // prints false

    int table1[][]={{0,1,2,3},{11,12,13,14}};
    int table2[][] = table1.clone();
    table2[0][0] = 100;
    System.out.println(table1[0][0] == table2[0][0]); //prints true
}

1
Bạn đang nói với tôi rằng tôi có thể clone1D mảng nguyên thủy và nhận bản sao sâu? Điều đó rất tuyệt vời! Giá vé tốt Arrays.copyOfRange(), System.arraycopy()!
Janez Kuhar

1
Đúng vậy! 1D mảng của nguyên thủy được sao chép khi mảng được nhân bản
Thamme Gowda

1
Hãy lưu ý rằng Thamme Gowda N nói "nguyên thủy". Bản sao của mảng đối tượng sẽ chỉ là bản sao của các tham chiếu.
Kristiaan

bởi vì nguyên thủy không có trạng thái, chúng vốn là bất biến. Bạn không thể tạo một bản sao cạn của nguyên thủy, vì không có tài liệu tham khảo
Xerus

5

Bản sao là một bản sao nông của mảng.

Mã kiểm tra này in ra:

[1, 2] / [1, 2]
[100, 200] / [100, 2]

bởi vì MutableIntegerđược chia sẻ trong cả hai mảng như objects[0]objects2[0], nhưng bạn có thể thay đổi tham chiếu objects[1]một cách độc lập với objects2[1].

import java.util.Arrays;                                                                                                                                 

public class CloneTest {                                                                                                                                 
    static class MutableInteger {                                                                                                                        
        int value;                                                                                                                                       
        MutableInteger(int value) {                                                                                                                      
            this.value = value;                                                                                                                          
        }                                                                                                                                                
        @Override                                                                                                                                        
        public String toString() {                                                                                                                       
            return Integer.toString(value);                                                                                                              
        }                                                                                                                                                
    }                                                                                                                                                    
    public static void main(String[] args) {                                                                                                             
        MutableInteger[] objects = new MutableInteger[] {
                new MutableInteger(1), new MutableInteger(2) };                                                
        MutableInteger[] objects2 = objects.clone();                                                                                                     
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                                
        objects[0].value = 100;                                                                                                                          
        objects[1] = new MutableInteger(200);                                                                                                            
        System.out.println(Arrays.toString(objects) + " / " + 
                            Arrays.toString(objects2));                                                               
    }                                                                                                                                                    
}                                                                                                                                                        
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.