2012-05-28 50 views
13

Trong nguồn cho JDK1.6, các bộ sưu tập phương pháp lớp hoán đổi được viết như thế này:Tại sao Bộ sưu tập.swap sao chép danh sách đầu vào?

public static void swap(List<?> list, int i, int j) { 
    final List l = list; 
    l.set(i, l.set(j, l.get(i))); 
} 

lý do gì cho việc tạo ra một bản sao cuối cùng của danh sách được thông qua? Tại sao họ không chỉ đơn giản sửa đổi danh sách được chuyển trực tiếp? Trong trường hợp này, bạn cũng nhận được cảnh báo kiểu thô.

+2

Dưới đây là các nguồn có liên quan trên Grepcode cho bất cứ ai quan tâm: http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/Collections.java#Collections.swap%28java.util.List%2Cint%2Cint%29 –

+1

Có gì với downvote? –

Trả lời

18

Không có bản sao của danh sách, chỉ có một bản sao của tham chiếu đến danh sách. Từ khóa cuối cùng không quan trọng. Tuy nhiên, điều quan trọng là một loại thô được sử dụng. Nếu tham số sẽ được sử dụng thay vào đó, trình biên dịch sẽ báo cáo một lỗi:

public static void swap(List<?> list, int i, int j) { 
    // ERROR: The method set(int, capture#3-of ?) in the type List<capture#3-of ?> 
    // is not applicable for the arguments (int, capture#4-of ?) 
    list.set(i, list.set(j, list.get(i))); 
} 

Điều này có nghĩa, rằng họ đang sử dụng biến trung gian để phá vỡ những thiếu sót của Generics, và để thoát khỏi các thông báo lỗi.

Câu hỏi thú vị là: Tại sao họ không sử dụng một phương pháp chung? Các mã sau đây hoạt động:

public static <T> void swap(List<T> list, int i, int j) { 
    list.set(i, list.set(j, list.get(i))); 
} 

Câu trả lời là, rằng phương pháp này tạo ra cảnh báo trong mã cũ gọi phương thức với các loại nguyên liệu:

List list = ...; 
// WARNING: Type safety: Unchecked invocation swap2(List, int, int) 
// of the generic method swap2(List<T>, int, int) of type Swap 
Collections.swap(list, 0, 1); 
+0

Vì vậy, họ sử dụng tham chiếu cuối cùng vào danh sách để tránh sử dụng Generics? –

+1

Thật vậy, họ đang sử dụng các biến trung gian để phá vỡ những thiếu sót của generics, và để thoát khỏi thông báo lỗi. – nosid

+3

API không nên bị ô nhiễm với chi tiết triển khai của một phương thức có tham số chung, trong đó ký tự đại diện sẽ đủ (và sạch hơn và dễ hiểu hơn, giả định kiến ​​thức cơ bản về Java). Bây giờ, bạn có thể sử dụng phương thức chung như là một phương thức thực hiện và có phương thức public gọi là (một thành ngữ phổ biến), tuy nhiên, tôi nghi ngờ bytecode phụ có thể thỉnh thoảng đi lên HotSpot inlining (hoặc ai đó lo ngại về điều đó ngay cả khi nó không có) t). –

Các vấn đề liên quan