Tại sao String là bất biến trong Java?


177

Tôi đã được hỏi trong một cuộc phỏng vấn tại sao String là bất biến

Tôi đã trả lời như thế này:

Khi chúng ta tạo một chuỗi trong java như thế String s1="hello";thì một đối tượng sẽ được tạo trong nhóm chuỗi (hello)s1 sẽ trỏ đến hello . Bây giờ, nếu chúng ta làm lại String s2="hello";thì một đối tượng khác sẽ không được tạo nhưng s2 sẽ trỏ đến hello vì trước tiên JVM sẽ kiểm tra nếu cùng một đối tượng có mặt trong nhóm chuỗi hay không. Nếu không có thì chỉ có một đối tượng mới được tạo khác.

Bây giờ nếu java giả sử cho phép chuỗi có thể thay đổi sau đó nếu chúng ta thay đổi s1 để hello worldsau đó s2 giá trị cũng sẽ cóhello world rất java String là không thay đổi.

Bất cứ ai có thể xin vui lòng cho tôi biết nếu câu trả lời của tôi là đúng hay sai ?


46
Tại sao luôn khó trả lời. Câu trả lời đúng nhất có lẽ là: Bởi vì các nhà thiết kế ngôn ngữ cho rằng đó là một ý tưởng tốt.
Keppil


3
Câu trả lời của bạn không phải là vấn đề. C ++ std::stringcó thể thay đổi, nhưng chúng cũng có nhóm chuỗi (tốt, chính xác hơn là nhóm mảng ký tự).
Siyuan Ren

1
@rocking Thành thật mà nói, việc đó đúng hay không phụ thuộc vào cách họ đọc nó. Vấn đề là, Java có thể có một chuỗi chuỗi vì các chuỗi là bất biến. Nếu họ quyết định tạo chuỗi có thể thay đổi thì họ đã không sử dụng nhóm chuỗi; do đó, có thể không chính xác khi nói "chuỗi chuỗi, do đó chuỗi bất biến"; theo cách khác. Các lý do để chọn các chuỗi bất biến được nêu ra dưới đây và nhóm chuỗi là một chiến lược hoạt động điều đó. Tuy nhiên, câu trả lời của bạn không sai , nó dường như không hoàn chỉnh. Bạn sẽ phải chờ xem họ nói gì.
Jason C

34
Tôi chỉ đơn giản là không thể hiểu tại sao câu hỏi này đã được đóng lại. Câu trả lời liên quan được cho là thậm chí không phải về Java và không đề cập đến chủ đề chính của câu hỏi này, đó là "tại sao". Đối với tôi điều này là một trong những trường hợp của một cộng đồng vô trách nhiệm hành động theo câu hỏi mà họ không biết gì về nó. Tôi đã đề cử nó để mở lại.
Edwin Dalorzo

Câu trả lời:


163

String là bất biến vì nhiều lý do, đây là một bản tóm tắt:

  • Bảo mật : các tham số thường được biểu diễn dưới dạngString trong các kết nối mạng, các url kết nối cơ sở dữ liệu, tên người dùng / mật khẩu, v.v ... Nếu có thể thay đổi, các tham số này có thể dễ dàng thay đổi.
  • Đồng bộ hóa và đồng thời: làm cho Chuỗi bất biến tự động làm cho chúng trở nên an toàn do đó giải quyết các vấn đề đồng bộ hóa.
  • Bộ nhớ đệm : khi trình biên dịch tối ưu hóa các đối tượng Chuỗi của bạn, nó sẽ thấy rằng nếu hai đối tượng có cùng giá trị (a = "test" và b = "test") và do đó bạn chỉ cần một đối tượng chuỗi (cho cả a và b, hai đối tượng này sẽ chỉ vào cùng một đối tượng).
  • Tải lớp : Stringđược sử dụng làm đối số cho tải lớp. Nếu có thể thay đổi, nó có thể dẫn đến lớp sai được tải (vì các đối tượng có thể thay đổi thay đổi trạng thái của chúng).

Điều đó đang được nói, tính bất biến của Stringchỉ có nghĩa là bạn không thể thay đổi nó bằng API công khai của nó. Thực tế bạn có thể bỏ qua API thông thường bằng cách sử dụng sự phản chiếu. Xem câu trả lời tại đây .

Trong ví dụ của bạn, nếu Stringcó thể thay đổi, thì hãy xem xét ví dụ sau:

  String a="stack";
  System.out.println(a);//prints stack
  a.setValue("overflow");
  System.out.println(a);//if mutable it would print overflow

14
Làm thế nào để nó có thể ảnh hưởng đến an ninh?
Archit Maheshwari

2
Ai đó có thể giải thích tải lớp với một ví dụ nếu có thể?
Viraj

6
Liên quan đến bảo mật, nếu tôi quan tâm đến việc thay đổi các tham số kết nối, điều đó rất đơn giản vào thời gian chạy (với trình gỡ lỗi, v.v.). Liên quan đến tải lớp, nếu Stringcó thể thay đổi, thì trình nạp lớp sẽ lấy chuỗi được truyền vào, tạo một bản sao và không thay đổi bản sao của nó. Khi nghĩ về một vấn đề với java.lang.Strings có thể thay đổi , hãy nghĩ đến cách C ++ giải quyết vấn đề này (vì nó có thể thay đổi std::stringđược
Sự giới hạn có giới hạn

Về bảo mật, làm thế nào một chuỗi có thể thay đổi có thể được thay đổi khi chương trình đang chạy?
MasterJoe2

Vì String là bất biến, nên mã băm của nó được lưu trữ tại thời điểm tạo và nó không cần phải tính lại.
Abdul Alim Shakir

45

Các nhà phát triển Java quyết định Chuỗi là bất biến do thiết kế khía cạnh , hiệu quả và bảo mật sau đây .

Chuỗi thiết kế được tạo trong vùng nhớ đặc biệt trong heap java được gọi là "Chuỗi thực tập". Trong khi bạn tạo Chuỗi mới (Không phải trong trường hợp sử dụng hàm tạo Chuỗi () hoặc bất kỳ hàm Chuỗi nào khác sử dụng bên trong hàm tạo Chuỗi () để tạo đối tượng Chuỗi mới; Hàm tạo Chuỗi () luôn tạo hằng chuỗi mới trong nhóm trừ khi chúng ta gọi phương thức intern () ) nó tìm kiếm nhóm để kiểm tra xem nó đã tồn tại chưa. Nếu nó tồn tại, sau đó trả về tham chiếu của đối tượng String hiện có. Nếu Chuỗi không bất biến, việc thay đổi Chuỗi bằng một tham chiếu sẽ dẫn đến giá trị sai cho các tham chiếu khác.

Theo này bài viết trên DZone:

Chuỗi bảo mật được sử dụng rộng rãi làm tham số cho nhiều lớp java, ví dụ: kết nối mạng, mở tệp, v.v ... Chuỗi không phải là bất biến, một kết nối hoặc tệp sẽ bị thay đổi và dẫn đến mối đe dọa bảo mật nghiêm trọng. Các chuỗi có thể thay đổi cũng có thể gây ra vấn đề bảo mật trong Reflection, vì các tham số là các chuỗi.

Hiệu quả Mã băm của chuỗi thường được sử dụng trong Java. Ví dụ: trong HashMap. Không thể thay đổi đảm bảo rằng mã băm sẽ luôn giống nhau, để có thể lưu vào bộ nhớ cache mà không phải lo lắng về các thay đổi. Điều đó có nghĩa là, không cần phải tính toán mã băm mỗi khi sử dụng.


7
Sự hiểu biết của bạn về nhóm chuỗi là không chính xác. Các hằng chuỗi được tạo trong nhóm thực tập, nhưng hoàn toàn có thể có nhiều hơn một đối tượng chuỗi có cùng văn bản. Tôi đồng ý rằng các chuỗi là bất biến cho phép gộp, nhưng không có nhiều nhóm như bạn đã nêu.
Jon Skeet

@JonSkeet Bạn nói đúng. Chuỗi s1 = Chuỗi mới ("kiểm tra"); câu lệnh tạo hằng chuỗi mới trong nhóm intern trừ khi chúng ta gọi phương thức intern (). Cảm ơn bạn đã đào sâu kiến ​​thức của tôi về chuỗi thực tập.
Alex Mathew

2
Nó không chỉ đơn thuần là sử dụng hàm tạo chuỗi - hầu hết mọi thứ tạo ra chuỗi mới, ví dụ chuỗi con, tách, concat, v.v. sẽ tạo ra chuỗi mới. Hằng số thời gian biên dịch là trường hợp đặc biệt ở đây, không phải là tiêu chuẩn ...
Jon Skeet

Chuỗi con @JonSkeet (), concat (), thay thế () v.v ... được sử dụng bên trong String constructor để tạo đối tượng chuỗi mới. Cảm ơn bạn đã cải thiện câu trả lời của tôi.
Alex Mathew

2
@JonSkeet - Tất cả những câu trả lời này nói rằng tính bất biến cải thiện "bảo mật", nhưng không giải thích làm thế nào. Tất cả đều liên kết đến một bài viết dzone mơ hồ cũng không giúp được gì. Các câu trả lời / liên kết không giải thích làm thế nào một chuỗi có thể thay đổi có thể được thay đổi khi mã đang chạy. Bạn có thể vui lòng giải thích?
MasterJoe2

25

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ế Stringnhư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ị Nareshsẽ đượ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, csẽ 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 aví dụ a.replace("a", "").

Lý tưởng nhất là anên có giá trị Nreshnhưng b, cvẫ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, ctấ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 Nareshsẽ 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 avì thay đổi trong đối tượng chuỗi, NareshJVM sẽ tạo một đối tượng mới gán cho nó avà 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.Objectcá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 HashMapkhóa.

Đọc thêm về lý do tại sao Chuỗi là bất biến và cuối cùng trong Java .


1
Về bảo mật - Làm thế nào giá trị chuỗi có thể thay đổi có thể thay đổi trong bộ nhớ? Làm thế nào một người khác có thể truy cập vào các tài liệu tham khảo biến của chúng tôi?
MasterJoe2

Đây không phải là về cách người ta có thể truy cập vào các tài liệu tham khảo, đó là điều gì nếu ai đó có quyền truy cập vào đó? như đã đề cập "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 ai có quyền truy cập vào tài liệu tham khảo biến của chúng tôi. "
Naresh Joshi

Làm thế nào quan trọng ở đây. Nó có thể có được quyền truy cập vào các tài liệu tham khảo hoặc không. Nếu có thể, sau đó bạn có thể đặt tên cho 1-2 kỹ thuật *** (tức là cách thức) có thể được sử dụng để làm điều đó không? Nếu không thể, thì quan điểm về bảo mật là không thể áp dụng. *** Ví dụ - Đặt tên một kỹ thuật để tấn công DB của ứng dụng web -> SQL Injection. Bạn có biết bất kỳ kỹ thuật như thế này để tấn công các tài liệu tham khảo?
MasterJoe2

Như đã đề cập, "Nó có thể xảy ra do mã viết sai hoặc bất kỳ thay đổi nào được thực hiện bởi người khác có quyền truy cập vào các tham chiếu biến của chúng tôi". vd chuỗi bây giờ sau khi gọi tất cả các phương thức điều khiển này trả về phương thức của bạn và bạn đang sử dụng lại chuỗi đó nhưng nó đã bị thay đổi.
Naresh Joshi

2
Vui lòng tiết lộ bất kỳ chi nhánh nào và không sử dụng trang web như một cách để quảng bá trang web của bạn thông qua việc đăng bài. Xem Làm thế nào để tôi viết một câu trả lời tốt? .
Yvette - Phục hồi Monica

21

Lý do quan trọng nhất theo này bài viết trên DZone:

Chuỗi liên tục Pool ... Nếu chuỗi có thể thay đổi, việc thay đổi chuỗi bằng một tham chiếu sẽ dẫn đến giá trị sai cho các tham chiếu khác.

Bảo vệ

Chuỗi được sử dụng rộng rãi làm tham số cho nhiều lớp java, ví dụ: kết nối mạng, mở tệp, v.v ... Chuỗi không phải là bất biến, một kết nối hoặc tệp sẽ bị thay đổi và dẫn đến mối đe dọa bảo mật nghiêm trọng. ...

Hy vọng nó sẽ giúp bạn.


@JasonC Tôi chỉ muốn biết câu trả lời của mình có sai hay không. Tôi đã tham dự cuộc phỏng vấn và chờ kết quả. Nếu câu trả lời đã nói với họ là đúng thì tôi sẽ được chọn
rung chuyển

1
Theo hiểu biết của tôi, câu trả lời của bạn là chính xác, nhưng không thay đổi có nghĩa là tài liệu tham khảo sẽ không bao giờ thay đổi vị trí trỏ. Tất cả là tốt nhất cho cuộc phỏng vấn của bạn.
JDGuide

1
Nếu chấp nhận điểm số 1 của bạn, thì tất cả các đối tượng sẽ không thay đổi.
nicomp

Xin chào JDeveloper, tôi đã chỉnh sửa câu trả lời của bạn để đưa ra sự ghi nhận đúng đắn cho nguồn câu trả lời của bạn. Hãy nhớ luôn luôn sử dụng dấu ngoặc kép cho các bản sao nguyên văn của nội dung. Cảm ơn!
NickL

Bài viết DZone chứa các lỗi lớn về hoạt động của nhóm Strign. Nó chỉ dành cho hằng số. Xóa bỏ lý do đã nêu là không hợp lệ.
Hầu tước Lorne

4

Tôi đã đọc bài đăng này Tại sao Chuỗi là bất biến hoặc Cuối cùng trong Java và giả sử rằng sau đây có thể là lý do quan trọng nhất:

Chuỗi là bất biến trong Java vì các đối tượng Chuỗi được lưu trong bộ đệm Chuỗi . Vì các chuỗi ký tự được lưu trong bộ nhớ cache được chia sẻ giữa nhiều khách hàng , luôn có rủi ro, trong đó hành động của một khách hàng sẽ ảnh hưởng đến tất cả các khách hàng khác.


1

Bạn đúng rồi. Stringtrong java sử dụng khái niệm String Poolnghĩa đen. Khi một chuỗi được tạo và nếu chuỗi đã tồn tại trong nhóm, tham chiếu của chuỗi hiện có sẽ được trả về, thay vì tạo một đối tượng mới và trả về tham chiếu của nó. Nếu một chuỗi không bất biến, thay đổi chuỗi bằng một tham chiếu sẽ dẫn đến giá trị sai cho các tài liệu tham khảo khác.

Tôi sẽ thêm một điều nữa, vì Stringlà bất biến, nó an toàn cho đa luồng và một thể hiện Chuỗi đơn có thể được chia sẻ qua các luồng khác nhau. Điều này tránh việc sử dụng đồng bộ hóa cho an toàn luồng, Chuỗi được ngầm định thread safe.


0

Lớp chuỗi là FINAL có nghĩa là bạn không thể tạo bất kỳ lớp nào để kế thừa nó và thay đổi cấu trúc cơ bản và làm cho Sting có thể thay đổi.

Một biến đối tượng khác và các phương thức của lớp String được cung cấp sao cho bạn không thể thay đổi String đối tượng đối tượng một khi được tạo.

Lý do những gì bạn đã thêm không làm cho Chuỗi trở nên bất biến. Tất cả điều này nói lên cách Chuỗi được lưu trữ trong heap. Ngoài ra, chuỗi chuỗi cũng tạo ra sự khác biệt lớn về hiệu suất


11
Nếu lớp được khai báo là cuối cùng, điều đó có nghĩa là lớp không thể được kế thừa, nhưng điều đó không có nghĩa là các trường đối tượng của lớp không thể thay đổi và do đó lớp là bất biến.
Dmitry Bychenko

@Zeeshan: Các lớp ví dụ bạn đưa ra đều bất biến.
Siyuan Ren

0

Chuỗi được cung cấp dưới dạng bất biến bởi các hệ thống vi mô của Sun, bởi vì chuỗi có thể được sử dụng để lưu trữ làm khóa trong bộ sưu tập bản đồ. StringBuffer có thể thay đổi. Đó là lý do, Nó không thể được sử dụng làm khóa trong đối tượng bản đồ


0

Lý do quan trọng nhất của Chuỗi được tạo thành bất biến trong Java là xem xét Bảo mật . Tiếp theo sẽ là bộ nhớ đệm .

Tôi tin rằng các lý do khác được đưa ra ở đây, chẳng hạn như hiệu quả, đồng thời, thiết kế và chuỗi xuất phát từ thực tế là Chuỗi được tạo ra không thay đổi. Ví dụ. Chuỗi Pool có thể được tạo vì String là bất biến và không phải là cách khác.

Kiểm tra bảng điểm phỏng vấn của Gosling tại đây

Từ quan điểm chiến lược, họ có xu hướng thường không gặp rắc rối. Và thường có những điều bạn có thể làm với bất biến mà bạn không thể làm với những thứ có thể thay đổi, chẳng hạn như kết quả bộ đệm. Nếu bạn chuyển một chuỗi cho một phương thức mở tệp hoặc nếu bạn chuyển một chuỗi cho một hàm tạo cho nhãn trong giao diện người dùng, trong một số API (như trong rất nhiều API Windows), bạn sẽ truyền vào một mảng các ký tự. Người nhận đối tượng đó thực sự phải sao chép nó, vì họ không biết gì về thời gian lưu trữ của nó. Và họ không biết chuyện gì đang xảy ra với vật thể, liệu nó có bị thay đổi dưới chân họ không.

Cuối cùng, bạn gần như bị buộc phải sao chép đối tượng vì bạn không biết liệu mình có sở hữu nó hay không. Và một trong những điều tốt đẹp về các đối tượng bất biến là câu trả lời là "Vâng, tất nhiên là bạn làm." Bởi vì câu hỏi về quyền sở hữu, ai có quyền thay đổi nó, không tồn tại.

Một trong những điều buộc String phải bất biến là bảo mật. Bạn có một phương pháp mở tập tin. Bạn truyền một chuỗi cho nó. Và sau đó, nó thực hiện tất cả các loại kiểm tra xác thực trước khi thực hiện cuộc gọi hệ điều hành. Nếu bạn quản lý để thực hiện một cái gì đó đã làm thay đổi Chuỗi một cách hiệu quả, sau khi kiểm tra bảo mật và trước cuộc gọi của HĐH, thì bạn sẽ bùng nổ. Nhưng Chuỗi là bất biến, vì vậy kiểu tấn công đó không hoạt động. Ví dụ chính xác đó là những gì thực sự đòi hỏi rằng String là bất biến


0

Ngoài những câu trả lời tuyệt vời, tôi muốn thêm một vài điểm. Giống như String, Array giữ một tham chiếu đến phần bắt đầu của mảng, vì vậy nếu bạn tạo hai mảng arr1arr2làm một cái gì đó như thế arr2 = arr1này sẽ làm cho tham chiếu arr2giống như arr1việc thay đổi giá trị trong một trong số chúng sẽ dẫn đến thay đổi một mảng khác chẳng hạn

public class Main {
    public static void main(String[] args) {
        int[] a = {1, 2, 3, 4};
        int[] b = a;
        a[0] = 8;
        b[1] = 7;
        System.out.println("A: " + a[0] + ", B: " + b[0]);
        System.out.println("A: " + a[1] + ", B: " + b[1]);
        //outputs
        //A: 8, B: 8
        //A: 7, B: 7
    }
}

Không chỉ vậy, nó sẽ gây ra lỗi trong mã mà nó còn có thể (và sẽ) bị người dùng độc hại khai thác. Giả sử nếu bạn có một hệ thống thay đổi mật khẩu quản trị viên. Trước tiên, người dùng phải nhập newPasswordvà sau đó oldPasswordnếu oldPasswordgiống như adminPasschương trình thay đổi mật khẩu adminPass = newPassword. giả sử rằng mật khẩu mới có cùng tham chiếu với mật khẩu quản trị viên để một lập trình viên xấu có thể tạo một tempbiến để giữ mật khẩu quản trị viên trước khi người dùng nhập dữ liệu nếu oldPasswordbằngtemp nó thay đổi mật khẩu khácadminPass = temp. Ai đó biết rằng có thể dễ dàng nhập mật khẩu mới và không bao giờ nhập mật khẩu cũ và abracadabra mà anh ta có quyền truy cập quản trị viên. Một điều khác tôi không hiểu khi tìm hiểu về Chuỗi tại sao JVM không tạo chuỗi mới cho mọi đối tượng và có một vị trí duy nhất trong bộ nhớ cho nó và bạn chỉ có thể làm điều đó bằng cách sử dụng new String("str");Lý do bạn không muốn luôn sử dụng newlà bởi vì nó không hiệu quả về bộ nhớ và nó chậm hơn trong hầu hết các trường hợp đọc thêm .


0

Nếu HELLOlà Chuỗi của bạn thì bạn không thể thay đổi HELLOthànhHILLO . Tài sản này được gọi là tài sản bất biến.

Bạn có thể có nhiều biến Chuỗi con trỏ để trỏ Chuỗi HELLO.

Nhưng nếu HELLO là char Array thì bạn có thể đổi HELLO thành HILLO. Ví dụ,

char[] charArr = 'HELLO';
char[1] = 'I'; //you can do this

Câu trả lời:

Ngôn ngữ lập trình có các biến dữ liệu bất biến để có thể được sử dụng làm khóa trong cặp khóa, giá trị. Biến chuỗi được sử dụng làm khóa / chỉ mục, vì vậy chúng là bất biến .


-1

Từ Securityquan điểm chúng ta có thể sử dụng ví dụ thực tế này:

DBCursor makeConnection(String IP,String PORT,String USER,String PASS,String TABLE) {

    // if strings were mutable IP,PORT,USER,PASS can be changed by validate function
    Boolean validated = validate(IP,PORT,USER,PASS);

    // here we are not sure if IP, PORT, USER, PASS changed or not ??
    if (validated) {
         DBConnection conn = doConnection(IP,PORT,USER,PASS);
    }

    // rest of the code goes here ....
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.