Chúng tôi không thể chắc chắn về những gì các nhà thiết kế Java thực sự nghĩ trong khi thiết kế String
nhưng chúng tôi chỉ có thể kết luận những lý do này dựa trên những lợi thế mà chúng tôi có được từ tính bất biến của chuỗi, Một số trong đó là
1. Sự tồn tại của chuỗi liên tục Pool
Như đã thảo luận trong Why Why được lưu trữ trong bài viết Chuỗi liên tục Pool , mọi ứng dụng tạo ra quá nhiều đối tượng chuỗi và để lưu JVM từ lần đầu tiên tạo ra nhiều đối tượng chuỗi và sau đó thu gom chúng. JVM lưu trữ tất cả các đối tượng chuỗi trong một vùng bộ nhớ riêng gọi là chuỗi hằng số chuỗi và sử dụng lại các đối tượng từ nhóm lưu trữ được lưu trữ đó.
Bất cứ khi nào chúng ta tạo một chuỗi JVM theo nghĩa đen, lần đầu tiên sẽ thấy liệu chữ đó có hiện diện trong nhóm không đổi hay không và nếu có, tham chiếu mới sẽ bắt đầu trỏ đến cùng một đối tượng trong SCP.
String a = "Naresh";
String b = "Naresh";
String c = "Naresh";
Trong ví dụ đối tượng chuỗi trên có giá trị Naresh
sẽ được tạo ra trong SCP chỉ một lần và tất cả các tài liệu tham khảo a
, b
, c
sẽ trỏ đến cùng một đối tượng nhưng những gì nếu chúng tôi cố gắng thực hiện thay đổi trong a
ví dụ a.replace("a", "")
.
Lý tưởng nhất là a
nên có giá trị Nresh
nhưng b
, c
vẫn không thay đổi vì với tư cách là người dùng cuối, chúng tôi chỉ thực hiện thay đổi a
. Và chúng ta đều biết a
, b
, c
tất cả đều chỉ cùng một đối tượng vì vậy nếu chúng ta thực hiện một sự thay đổi trong a
, những người khác cũng nên phản ánh sự thay đổi.
Nhưng tính bất biến của chuỗi giúp chúng ta thoát khỏi kịch bản này và do tính bất biến của đối tượng chuỗi đối tượng chuỗi Naresh
sẽ không bao giờ thay đổi. Vì vậy, khi chúng ta thực hiện bất kỳ thay đổi nào thay a
vì thay đổi trong đối tượng chuỗi, Naresh
JVM sẽ tạo một đối tượng mới gán cho nó a
và sau đó thực hiện thay đổi trong đối tượng đó.
Vì vậy, chuỗi String chỉ có thể do tính bất biến của String và nếu String không thể bất biến, thì việc lưu trữ các đối tượng chuỗi và sử dụng lại chúng sẽ không có khả năng vì bất kỳ biến nào sẽ thay đổi giá trị và làm hỏng các giá trị khác.
Và đó là lý do tại sao nó được JVM xử lý rất đặc biệt và đã được cung cấp một vùng nhớ đặc biệt.
2. An toàn chủ đề
Một đối tượng được gọi là an toàn luồng khi nhiều luồng đang hoạt động trên nó nhưng không ai trong số chúng có thể làm hỏng trạng thái của nó và đối tượng giữ trạng thái giống nhau cho mọi luồng tại bất kỳ thời điểm nào.
Vì chúng ta không thể sửa đổi một đối tượng bất biến sau khi tạo ra nó làm cho mọi đối tượng bất biến là luồng an toàn theo mặc định. Chúng ta không cần phải áp dụng bất kỳ biện pháp an toàn luồng nào cho nó như tạo các phương thức đồng bộ.
Vì vậy, do đối tượng chuỗi tự nhiên bất biến của nó có thể được chia sẻ bởi nhiều luồng và ngay cả khi nó bị thao túng bởi nhiều luồng, nó sẽ không thay đổi giá trị của nó.
3. Bảo mật
Trong mọi ứng dụng, chúng ta cần truyền một số bí mật, ví dụ như tên người dùng \ mật khẩu, URL kết nối và nói chung, tất cả thông tin này được truyền dưới dạng đối tượng chuỗi.
Bây giờ, giả sử nếu String không tự nhiên là bất biến thì nó sẽ gây ra mối đe dọa bảo mật nghiêm trọng cho ứng dụng vì các giá trị này được phép thay đổi và nếu được phép thì chúng có thể bị thay đổi do mã viết sai hoặc bất kỳ người nào khác có quyền truy cập vào tài liệu tham khảo biến của chúng tôi.
4. Đang tải lớp
Như đã thảo luận trong Tạo đối tượng thông qua Reflection trong Java với Ví dụ , chúng ta có thể sử dụng Class.forName("class_name")
phương thức để tải một lớp trong bộ nhớ, một lần nữa gọi các phương thức khác để làm như vậy. Và thậm chí JVM sử dụng các phương thức này để tải các lớp.
Nhưng nếu bạn thấy rõ tất cả các phương thức này chấp nhận tên lớp là một đối tượng chuỗi, thì Chuỗi được sử dụng trong tải lớp java và tính bất biến cung cấp bảo mật rằng lớp chính xác đang được tải bởi ClassLoader
.
Giả sử nếu String sẽ không bất biến và chúng tôi đang cố tải java.lang.Object
cái được thay đổi thành org.theft.OurObject
ở giữa và bây giờ tất cả các đối tượng của chúng tôi có hành vi mà ai đó có thể sử dụng cho những thứ không mong muốn.
5. Bộ nhớ đệm HashCode
Nếu chúng ta sẽ thực hiện bất kỳ thao tác băm nào trên bất kỳ đối tượng nào, chúng ta phải ghi đè hashCode()
phương thức và cố gắng tạo mã băm chính xác bằng cách sử dụng trạng thái của đối tượng. Nếu trạng thái của một đối tượng đang bị thay đổi, điều đó có nghĩa là mã băm của nó cũng sẽ thay đổi.
Do String là bất biến nên giá trị mà một đối tượng chuỗi đang giữ sẽ không bao giờ bị thay đổi, điều đó có nghĩa là mã băm của nó cũng sẽ không thay đổi, điều này tạo cho lớp String cơ hội lưu trữ mã băm của nó trong quá trình tạo đối tượng.
Có, đối tượng String lưu trữ mã băm của nó tại thời điểm tạo đối tượng làm cho nó trở thành ứng cử viên tuyệt vời cho các hoạt động liên quan đến băm vì mã băm không cần phải tính toán lại giúp chúng ta tiết kiệm thời gian. Đây là lý do tại sao String chủ yếu được sử dụng làm HashMap
khóa.
Đọc thêm về lý do tại sao Chuỗi là bất biến và cuối cùng trong Java .