2012-03-19 28 views
8

Sự khác biệt giữa StringBuilderStringBuffer trong Java cũng được ghi lại và cũng là touched upon in StackOverflow.Tại sao không có StringBuilder và StringBuffer thực hiện một giao diện chung?

Về cơ bản, StringBuilder là bản sao không được đồng bộ hóa StringBuffer, với khá nhiều giao diện tương tự vì nó được dự định là thay thế thả nhanh hơn cho StringBuffer. API của chúng thực tế giống hệt nhau và chúng thực sự là các lớp con của cùng lớp không thể truy cập được lớp trừu tượng trong JDK hiện tại.

Điều mà tôi tự hỏi, đó là lý do tại sao chúng không phải là liên quan đến công khai. Có cả hai lớp thực hiện một giao diện chung hoặc thậm chí có StringBuffer làm lớp con của StringBuilder sẽ có ý nghĩa, cho phép sự tồn tại của mã được chia sẻ cho cả hai lớp.

Vậy tại sao sự tách biệt này bị buộc phải? Có phải vì vậy các lập trình viên sẽ không vô tình trộn chuỗi an toàn với mã không an toàn không? Hay đó chỉ là một sự giám sát thiết kế mà bây giờ sẽ được thừa hưởng vào cuối đời đời?

EDIT:

Để làm cho mọi việc rõ ràng: Tôi có thể suy đoán trên tại sao mọi thứ như thế này, nhưng tôi hy vọng để tham khảo cụ thể để quyết định thực tế, ví dụ trong quá trình JSR. Bất cứ điều gì có thể làm sáng tỏ điều gì, với tôi, là một tình huống thỉnh thoảng gây ra một số khó khăn.

EDIT 2:

Thực tế là cả hai lớp thực hiện Appendable hoàn toàn quên khuấy đi. Có lẽ bởi vì giao diện cụ thể đó là vô ích cho hầu hết các mục đích - nó chỉ có thể nối thêm một ký tự đơn hoặc một đối tượng đã chuẩn bị và đó là nó. Trong hầu hết các trường hợp, nó không hữu ích hơn cả hai lớp là lớp con của Object.

EDIT 3:

Vâng, đây là lý do cho chính xác câu hỏi này từ a semi-official source:

Đánh giá bởi nhóm thư viện:

Đó là do thiết kế mà StringBuffer và StringBuilder chia sẻ không phổ biến supertype công khai. Chúng không có ý định thay thế: một là một lỗi (StringBuffer) và cái kia (StringBuilder) là thay thế của nó.

Rõ ràng việc thiếu một siêu kiểu chung có thể, trong một số trường hợp, làm chậm việc di chuyển được hy vọng từ StringBuffer sang StringBuilder. Mặt lật là bằng cách thêm một kiểu siêu phổ biến, chúng tôi sẽ lấy các lỗi của trước đây và giữ chúng trong một giao diện công khai để ở bên chúng tôi trong tất cả thời gian . Điều này không chỉ làm chậm quá trình di chuyển: nó làm hỏng nó.

Trả lời

3

Tôi không có tham chiếu JSR nhưng từ điểm kinh nghiệm của tôi. Dưới đây là vài lý do:

  • StringBuffer như một lớp con của StringBuilderđược không phải là một ý tưởng tốt cho lý do hiệu suất. Để đảm bảo an toàn cho chủ đề an toàn StringBuffer, bạn phải che giấu mọi cuộc gọi đến StringBuilder vốn rất tốn kém.

  • Thêm vào điểm trên, bạn có thể tiếp tục tối ưu hóa, nếu bạn có thể truy cập trực tiếp so với bên trong của một lớp đó là lý do tại sao Java thêm java.lang.concurrent qua java.util.Collections.synchronized* apis. Khi có nhiều quyền truy cập trực tiếp hơn, hãy cung cấp thêm tùy chọn để tối ưu hóa. Để suport điểm này Reference from the IBM blog

  • Tiếp tục thêm vào điểm đầu tiên, tôi không nghĩ rằng đây là một sự giám sát thiết kế như cả lớp đang final nên chắc chắn họ không muốn những lớp học để được subclassed.

  • Về cùng một giao diện, cả hai lớp đều triển khai cùng một giao diện tức là Serializable, Appendable, CharSequence. Vì vậy, họ là thả thay thế. Điều duy nhất là họ không thực hiện một giao diện chung nhưng thay vào đó là ba giao diện chung. Có ý nghĩa, vì không cần phải có một giao diện cồng kềnh mà về mặt kỹ thuật sẽ là tổng của các giao diện hiện tại (Serializable, Appendable, CharSequence).

EDIT:

  • Để @MatthewFlaschen điểm, rằng có những apis mà là cùng b/w StringBufferStringBuilder nhưng không phải trong bất kỳ các giao diện thực hiện. Điều này là nhiều hơn để làm với khả năng tương thích ngược. Bạn muốn thêm api mới nhưng giao diện đang được nhiều lớp khác sử dụng, vì vậy việc thay đổi giao diện có thể không khả thi. Đó là một suy nghĩ tốt về quyết định mà những người Java có thể đã thực hiện. Vì vậy, tôi sẽ không nói sai lầm của nó.

EDIT 2:

SIDE LƯU Ý: Một điều cần lưu ý là StringBuffer được giới thiệu vào 1.0 và StringBuilder trong 1,5. Vì vậy, các apis mà có trong cả hai lớp học nhưng không phải trong giao diện được giới thiệu sau này và không phải tại thời điểm tạo ra các lớp quá.

+0

Có các phương pháp, ví dụ: nối thêm (dài) trong cả hai lớp nhưng không có giao diện nào. –

+0

Mặc dù tôi nghĩ như thế nào Vector và ArrayList mở rộng AbstractList, StringBuffer và StringBuilder có thể đã mở rộng một lớp trừu tượng tương tự. Tôi đã không nhìn vào nguồn mới nhất, nhưng StringBuilder dường như là một rip-off thẳng của StringBuffer trừ đi việc đồng bộ hóa. –

+0

@MatthewFlaschen append() là từ Phụ lục. –

2

Thực tế, cả hai thực hiện Appendable.

Tôi không đồng ý rằng điều này là vô ích.Theo kinh nghiệm của tôi, một phần lớn việc sử dụng StringBuilder/StringBuffer chỉ là xử lý các chuỗi (thực hiện CharSequence). Đối với phần còn lại, bạn có thể gọi String.valueOf trước khi chuyển nó vào.

Sẽ thuận tiện hơn nếu có giao diện khác cũng có các phương thức khác như append(long). Nhưng điều đó không cần thiết.

Sẽ hợp lý khi có giao diện chung. Chúng có các đặc tính hiệu suất và luồng khác nhau, nhưng điều đó đúng và đúng với nhiều giao diện trong JDK.

Ví dụ: CopyOnWriteArrayList trong danh sách chuỗi an toàn dựa trên mảng (danh sách mới cho mỗi lần viết), trong khi LinkedList là danh sách được liên kết không an toàn.

+0

Bạn không trả lời câu hỏi hoặc thậm chí cung cấp bất kỳ thông tin chi tiết nào về lý do tại sao. – FriendlyGuy

+0

@MackieChan, tôi không đồng ý. Tôi nói "Sẽ là hợp lý để có một giao diện chung.", Đó là một cách khác để nói, "Vâng, đó là một sự giám sát thiết kế". –

+0

Thành thật mà nói, có thể chắp thêm tâm trí của tôi, chủ yếu là vì tôi thường xuyên nối thêm số e.t.c. trong mã của tôi. Tôi không thực sự thấy rằng giao diện cụ thể rất hữu ích, bởi vì nó buộc bạn phải chuyển đổi mọi thứ thành chuỗi trước. Chưa kể rằng nội dung hiện có là bất biến ... – thkala

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