2011-11-04 35 views
8

Từ Java 6 TreeSet<E> Tài liệu:Tại sao TreeSet <E> loại bỏ Java (Object) không có một E

boolean remove(Object o): 
    Removes the specified element from this set if it is present. 

Tại sao điều này chấp nhận một đối tượng thay vì kiểu generic E? Các đối tượng duy nhất có thể được thêm vào là loại E, do đó, nó theo sau là loại có thể tháo rời duy nhất phải thuộc loại E.

+5

liên quan: http://stackoverflow.com/questions/857420/what-are-the-reasons-why-map-getobject-key-is-not-fully-generic –

+0

bản sao có thể có của [Tại sao không phải Java Các bộ sưu tập loại bỏ các phương thức chung chung?] (Http://stackoverflow.com/questions/104799/why-arent-java-collections-remove-methods-generic) – PhoneixS

Trả lời

4

remove(), như get() là cần thiết để làm việc khi đưa ra một bằng yếu tố (về .equals()). Trong Java, có thể (và trong một số trường hợp, bắt buộc) cho các đối tượng của các lớp khác nhau bằng nhau. Do đó, bạn không nên hạn chế loại.

0

Vâng, mỗi E cũng là một đối tượng, và có lẽ bạn có E không phải là E tại thời điểm (ví dụ: từ nguồn Sự kiện), điều này giúp bạn thuận tiện hơn. Nếu không, bạn chỉ cần bỏ nó vào E để loại bỏ nó.

Từ quan điểm bình đẳng, điều này không quan trọng: Địa chỉ tham chiếu của đối tượng đã cho sẽ được kiểm tra nếu nó bằng nội dung của tập hợp, vì vậy không quan trọng là lớp nào.

9

Lấy câu trả lời từ những nhận xét đầu tiên gửi:

Quan niệm:

Một huyền thoại phổ biến là nó là ngu ngốc và ác, nhưng nó đã được cần thiết vì tính tương thích ngược. Tuy nhiên, đối số không phù hợp; API là chính xác cho dù bạn xem xét khả năng tương thích hay không.

lý do thật:

Thống nhất, phương pháp Framework Java Collections (và Google Bộ sưu tập Thư viện quá) không bao giờ hạn chế các loại thông số của họ trừ khi đó là cần thiết để ngăn chặn các bộ sưu tập từ nhận bị hỏng.

đọc thêm ở đây: Why does Set.contains() take an Object, not an E?

0

Đây thực sự là một vấn đề. Nếu ai đó gọi số remove(o)o không phải là E, thì đó thường là lỗi lập trình cố gắng xóa nhầm điều. Loại kiểm tra không thành công để bảo vệ chúng tôi khỏi lỗi.

Mặc dù IDE tốt (IntelliJ) có thể phát hiện các vấn đề như vậy và cảnh báo chúng tôi, nhà thiết kế API phải cung cấp chữ ký chính xác hơn để sử dụng kiểm tra loại trình biên dịch. (IDE lừa ở đây - nó biết ý nghĩa của Set.remove() vì nó là một API chuẩn. IDE sẽ không cung cấp trợ giúp tương tự cho API tùy chỉnh)

Đối với API truy vấn như , chấp nhận tham số không phải là E một sai lầm tầm thường. Vì vậy, chúng ta có thể có cả hai

boolean contains(Object o); 
boolean contains2(E o); 

Đối với đột biến API như remove(), nó gây tranh cãi liệu có nên chấp nhận một phi E tranh cãi.Tuy nhiên, cuộc tranh luận sẽ là tranh luận, vì thực tế của xóa bỏ - thực sự không có lựa chọn nào khác ngoài chấp nhận lập luận không phải E và im lặng về nó. Tuy nhiên, chúng tôi có thể có hai phương pháp

boolean remove(Object o); 
boolean remove2(E o); 

Trong hầu hết các trường hợp, người lập trình có thể gọi contains2/remove2 để đảm bảo an toàn hơn.

+0

Bạn có nói 'remove2/contains2' là các phương thức TreeSet không? Tôi không thấy điều đó trong api ... – ComputerDruid

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