2010-08-02 12 views
7

thể trùng lặp:
Why is String final in Java?Tại sao cuối cùng là lớp Chuỗi?

Có những khoảnh khắc khác nhau trong cuộc sống lập trình của tôi mà tôi muốn các lớp String đã không chính thức/niêm phong/NotInheritable.

Kiến trúc sư ngôn ngữ đang cố ngăn tôi làm điều đó sẽ ném cờ lê khỉ vào tác phẩm.

Thay vào đó, con khỉ lếch ra các kiến ​​trúc sư ngôn ngữ nào muốn ngăn tôi ném vào các tác phẩm bằng cách hạn chế tôi mở rộng lớp String?

Bạn có thể liệt kê danh sách ưu điểm của lớp chuỗi mở rộng không?

+0

Tôi nhận ra có các lớp khác như số học được niêm phong cuối cùng. Chúng tôi có thể bắt đầu bằng cách phân tích chuỗi đầu tiên nhưng nhận xét của bạn không cần phải bị hạn chế đối với Chuỗi. –

+0

+1 ... Tôi cũng muốn một lần trong cuộc sống của mình để mở rộng lớp String, mặc dù tôi không nhớ tại sao –

+0

Như bạn đã đề cập java (tag), điều này đã được hỏi trước: http://stackoverflow.com/questions/2068804/why-is-string-final-in-java –

Trả lời

5

Chuỗi là immutable class có nghĩa là nếu bạn không thể sửa đổi trạng thái của nó sau khi bạn tạo. Nếu bạn có thể sửa đổi một chuỗi sau khi nó đã nhập một thư viện khác, hoặc một bản đồ ví dụ kết quả sẽ là không thể đoán trước.

Một lỗi của API Java là BigIntegerBigDecimal không phải là cuối cùng có nghĩa là bạn cần thực hiện bản sao phòng thủ của các đối tượng này khi nhận chúng từ mã không đáng tin cậy. Ngược lại, bạn luôn có thể tin tưởng rằng String sẽ vẫn nhất quán.

không đáng tin cậy BigInteger:

public class DestructiveBigInteger extends BigInteger { 

    public DestructiveBigInteger(String value) { 
     super(value); 
    } 

    public BigInteger add(BigInteger val) { 
     return BigInteger.ONE; // add() method does not behave correctly 
    } 

    public BigInteger subtract(BigInteger val) { 
     throw new UnsupportedOperationException("subtract is broken"); 
    } 
} 

Điều tương tự cũng là không thể với String. Như đã nêu trong Effective Java, bạn cần phải thực hiện các bản sao phòng thủ của các loại đối tượng:

public void setValue(BigInteger value) { 
    this.value = new BigInteger(value.toByteArray()); 
} 
+0

Xây dựng, xin vui lòng. –

+1

Đảm bảo bạn biết sự khác biệt giữa từ khóa * cuối cùng * và từ khóa * bịt kín *. Các lớp được đánh dấu * cuối cùng * là CSONG * được đóng dấu * hiệu quả, nhưng đó không phải là điểm thực của từ khóa * cuối cùng *. Lớp * * cuối cùng là ** không thay đổi **, nghĩa là không thể sửa đổi sau khi tạo. Các lớp không thể thay đổi cũng phải được niêm phong, nếu không người ta có thể kế thừa, ghi đè và thêm vào một số hành vi không thay đổi. Chuỗi không thay đổi trong Java vì các chuỗi có thể thay đổi là ** nguy hiểm **, và, thẳng thắn, rắc rối hơn chúng đáng giá. Hầu hết các ngôn ngữ hiện đại (Python, Javascript, C#, Java), sử dụng các chuỗi bất biến. – Ender

4

Chuỗi là cuối cùng bởi vì nó đại diện cho một kiểu dữ liệu không thay đổi. Manifold terribleness sẽ dẫn đến việc mở rộng String một cách ngây thơ bởi vì có rất nhiều thư viện phụ thuộc vào tính bất biến của các đối tượng String.

Mở rộng chuỗi để làm cho nó có thể thay đổi sẽ ẩn với bất kỳ mã nào mà Sting đi qua, nhưng sẽ có các hiệu ứng phụ rất đáng ngạc nhiên và khó chịu như đột nhiên không thể tải các giá trị từ HashMaps mặc dù bạn thực sự có chuỗi của từ khóa hashCode sẽ bị tấn công.

+0

Nếu tôi muốn sử dụng String cho các phím của một bản đồ, tôi sẽ sử dụng String. Nếu tôi muốn sử dụng một String mở rộng làm khóa cho một bản đồ, đó là chính xác những gì tôi muốn làm - để ngăn chặn nó được truy cập với các đối tượng String cơ sở. Lập luận bất biến dường như không giữ nước cho tôi. –

+0

Nhưng một chuỗi mở rộng * sẽ * là một chuỗi. Vì vậy, bạn có thể sử dụng nó như là chìa khóa của một bản đồ từ String. Không thể lấy được sẽ không ngăn bạn viết một lớp mở rộng khả năng của String (sử dụng composition). Nó chỉ dừng bạn tạo ra các thể hiện của lớp đó thành các chuỗi. – jwg