Tính bất biến của các chuỗi trong Java


218

Hãy xem xét ví dụ sau.

String str = new String();

str  = "Hello";
System.out.println(str);  //Prints Hello

str = "Help!";
System.out.println(str);  //Prints Help!

Bây giờ, trong Java, các đối tượng String là bất biến. Sau đó, làm thế nào đến đối tượng strcó thể được gán giá trị "Trợ giúp!". Điều này có mâu thuẫn với tính bất biến của các chuỗi trong Java không? Ai đó có thể vui lòng giải thích cho tôi khái niệm chính xác của bất biến?

Biên tập:

Đồng ý. Bây giờ tôi nhận được nó, nhưng chỉ là một câu hỏi tiếp theo. Những gì về mã sau đây:

String str = "Mississippi"; 
System.out.println(str); // prints Mississippi 

str = str.replace("i", "!"); 
System.out.println(str); // prints M!ss!ss!pp! 

Điều này có nghĩa là hai đối tượng được tạo lại ("Mississippi" và "M! Ss! Ss! Pp!") Và các strđiểm tham chiếu đến một đối tượng khác sau replace()phương thức?


str chỉ là một tài liệu tham khảo không phải đối tượng
ahmednabil88

Tôi hy vọng điều này sẽ giúp Pushkarrajpujari.com/article/strings-in-java
Pushkarraj Pujari

Câu trả lời:


316

strkhông phải là một đối tượng, nó là một tham chiếu đến một đối tượng. "Hello""Help!"là hai Stringđối tượng riêng biệt . Do đó, str trỏ đến một chuỗi. Bạn có thể thay đổi những gì nó trỏ tới , nhưng không phải là mà nó trỏ vào .

Lấy mã này, ví dụ:

String s1 = "Hello";
String s2 = s1;
// s1 and s2 now point at the same string - "Hello"

Bây giờ, không có gì 1 chúng ta có thể làm điều s1đó sẽ ảnh hưởng đến giá trị của s2. Chúng đề cập đến cùng một đối tượng - chuỗi "Hello"- nhưng đối tượng đó là bất biến và do đó không thể thay đổi.

Nếu chúng ta làm một cái gì đó như thế này:

s1 = "Help!";
System.out.println(s2); // still prints "Hello"

Ở đây chúng ta thấy sự khác biệt giữa việc đột biến một đối tượng và thay đổi một tham chiếu. s2vẫn trỏ đến cùng một đối tượng như chúng ta đã đặt ban đầu s1. Thiết s1để "Help!"chỉ thay đổi tài liệu tham khảo , trong khi Stringđối tượng nó ban đầu được gọi còn lại không thay đổi.

Nếu dây có thể thay đổi, chúng ta có thể làm điều gì đó như thế này:

String s1 = "Hello";
String s2 = s1;
s1.setCharAt(1, 'a'); // Fictional method that sets character at a given pos in string
System.out.println(s2); // Prints "Hallo"

Chỉnh sửa để đáp ứng chỉnh sửa của OP:

Nếu bạn nhìn vào mã nguồn cho String.replace (char, char) (cũng có sẵn trong src.zip trong thư mục cài đặt JDK của bạn - một mẹo chuyên nghiệp là nhìn vào đó bất cứ khi nào bạn tự hỏi làm thế nào một cái gì đó thực sự hoạt động), bạn có thể thấy đó là gì nó là như sau:

  • Nếu có một hoặc nhiều lần xuất hiện oldChartrong chuỗi hiện tại, hãy tạo một bản sao của chuỗi hiện tại nơi tất cả các lần xuất hiện oldCharđược thay thế bằng newChar.
  • Nếu oldCharkhông có trong chuỗi hiện tại, trả về chuỗi hiện tại.

Vì vậy, có, "Mississippi".replace('i', '!')tạo ra một Stringđối tượng mới . Một lần nữa, các lưu ý sau:

String s1 = "Mississippi";
String s2 = s1;
s1 = s1.replace('i', '!');
System.out.println(s1); // Prints "M!ss!ss!pp!"
System.out.println(s2); // Prints "Mississippi"
System.out.println(s1 == s2); // Prints "false" as s1 and s2 are two different objects

Bài tập về nhà của bạn bây giờ là để xem đoạn mã trên sẽ làm gì nếu bạn đổi s1 = s1.replace('i', '!');thành s1 = s1.replace('Q', '!');:)


1 thực tế, nó có thể chuỗi đột biến (và các đối tượng bất biến khác). Nó đòi hỏi sự phản chiếu và rất, rất nguy hiểm và không bao giờ nên được sử dụng trừ khi bạn thực sự quan tâm đến việc phá hủy chương trình.


15
+1 cho phương pháp hư cấu, nó thể hiện sự khác biệt giữa đối tượng bất biến và các đối tượng khác.
Zappi

1
Cảm ơn gustafc cho các ví dụ chính xác và giải thích rõ ràng .... Nhưng bạn có thể trả lời phần đã chỉnh sửa trong câu hỏi không? Điều đó sẽ làm cho sự hiểu biết của tôi rõ ràng.
Light_handle

17
Tôi chưa bao giờ thấy một câu trả lời như thế này trước đây. Thảo luận từng chi tiết.
Michael 'Maik' Ardan

+1 Đây là một ý tưởng, các đối tượng bất biến trong java giống như sao chép theo giá trị, bạn có thể có 2 tham chiếu đến Chuỗi, nhưng bạn nên xem xét chúng 2 Chuỗi riêng biệt vì nó không thay đổi và làm việc với một trong số chúng sẽ không ảnh hưởng đến khác
Khaled.K

1
Java - bạn càng nghĩ bạn biết nhiều, bạn càng thực sự biết ít.
zeeshan 17/03/2017

23

Đối tượng strtham chiếu có thể thay đổi, nhưng Stringbản thân các đối tượng thực tế không thể.

Các Stringđối tượng chứa chuỗi "Hello""Help!"không thể thay đổi giá trị của chúng, do đó chúng là bất biến.

Tính bất biến của Stringcác đối tượng không có nghĩa là các tham chiếu trỏ đến đối tượng không thể thay đổi.

Một cách mà người ta có thể ngăn strtham chiếu thay đổi là khai báo nó như finalsau:

final String STR = "Hello";

Bây giờ, cố gắng gán khác Stringđể STRsẽ gây ra một lỗi biên dịch.


Nhưng trong trường hợp này, đối tượng Chuỗi là 'str', đầu tiên chứa giá trị 'Xin chào' và sau đó được gán giá trị mới 'Trợ giúp!'. Chính xác thì ý bạn là gì khi "Các đối tượng Chuỗi chứa chuỗi" Xin chào "và" Trợ giúp! "Không thể thay đổi giá trị của chúng, do đó chúng không thay đổi được." ??? Xin lỗi nếu đây là một câu hỏi ngớ ngẩn. Nhưng iv phải xóa nó ...
Light_handle

2
Bạn đã từng cố gắng lập trình trong C chưa? Chỉ cần đọc đoạn mồi trên con trỏ và bạn sẽ hiểu câu trả lời của coobird một cách hoàn hảo.
Ryan Fernandes

Xem ... Đây là điều tôi muốn tránh ... Tôi biết bạn là một lập trình viên tuyệt vời ... và tôi chỉ đang cố gắng học java ở đây ... Vì vậy, nếu bạn có thể trả lời chính xác câu hỏi của tôi thì hãy trả lời nó .. .
Light_handle

Bạn đang nhầm lẫn giữa các tham chiếu và các đối tượng - strkhông phải là "đối tượng" mà nó là một tham chiếu đến đối tượng. Nếu bạn đã String str = "Hello";theo dõi thì String anotherReference = str;bạn không có 2 đối tượng Chuỗi, bạn có một đối tượng (chữ "Xin chào") và 2 tham chiếu đến nó ( stranotherReference).
Nate

Tôi không có quyền chỉnh sửa, nhưng nếu có, tôi sẽ chỉnh sửa câu 1 của coobirds thành: "Các tham chiếu str có thể thay đổi, nhưng bản thân các đối tượng String thực tế thì không thể."
j3App

10

Light_handle Tôi khuyên bạn nên đọc Kích thước cốc - một câu chuyện về các biến sốVui lòng chuyển qua giá trị (Kích thước cốc tiếp tục) . Điều này sẽ giúp rất nhiều khi đọc các bài viết ở trên.

bạn đa đọc chung chưa? Đúng. Tốt

String str = new String();

Điều này tạo ra một "điều khiển từ xa" mới gọi là " str" và đặt giá trị đó thành giá trị new String()(hoặc "").

ví dụ trong bộ nhớ, điều này tạo ra:

str --- > ""

str  = "Hello";

Điều này sau đó thay đổi điều khiển từ xa " str" nhưng không sửa đổi chuỗi gốc "".

ví dụ trong bộ nhớ, điều này tạo ra:

str -+   ""
     +-> "Hello"

str = "Help!";

Điều này sau đó thay đổi điều khiển từ xa " str" nhưng không sửa đổi chuỗi gốc ""hoặc đối tượng mà điều khiển từ xa hiện đang trỏ tới.

ví dụ trong bộ nhớ, điều này tạo ra:

str -+   ""
     |   "Hello"
     +-> "Help!"

Do "" và "Hello" có thu gom rác không?
Mitchin Timsina

@PrabinTimsina Đây thực sự là một câu hỏi mới. Nó được trả lời: stackoverflow.com/questions/15324143/ Khăn
Michael Lloyd Lee mlk

9

Hãy chia nó thành một số phần

String s1 = "hello";

Tuyên bố này tạo ra chuỗi chứa hello và chiếm không gian trong bộ nhớ, tức là trong Nhóm chuỗi liên tục và gán nó cho đối tượng tham chiếu s1

String s2 = s1;

Câu lệnh này gán cùng một chuỗi hello cho tham chiếu mới s2

         __________
        |          |
s1 ---->|  hello   |<----- s2
        |__________| 

Cả hai tham chiếu đều trỏ đến cùng một chuỗi để xuất ra cùng một giá trị như sau.

out.println(s1);    // o/p: hello
out.println(s2);    // o/p: hello

Mặc dù Stringbất biến , việc gán có thể khả thi nên s1 bây giờ sẽ tham chiếu đến ngăn xếp giá trị mới .

s1 = "stack";    
         __________
        |          |
s1 ---->|  stack   |
        |__________|

Nhưng những gì về đối tượng s2 đang chỉ vào xin chào nó sẽ như vậy.

         __________
        |          |
s2 ---->|  hello   |
        |__________|

out.println(s1);    // o/p: stack
out.println(s2);    // o/p: hello

Vì Chuỗi là Máy ảo Java không thay đổi nên sẽ không cho phép chúng tôi sửa đổi chuỗi s1 bằng phương thức của nó. Nó sẽ tạo tất cả các đối tượng String mới trong pool như sau.

s1.concat(" overflow");

                 ___________________
                |                   |
s1.concat ----> |  stack overflow   |
                |___________________|

out.println(s1);    // o/p: stack
out.println(s2);    // o/p: hello
out.println(s1.concat); // o/p: stack overflow

Lưu ý nếu String có thể thay đổi thì đầu ra sẽ là

out.println(s1);    // o/p: stack overflow

Bây giờ bạn có thể ngạc nhiên tại sao String có các phương thức như concat () để sửa đổi. Theo đoạn trích sẽ xóa sự nhầm lẫn của bạn.

s1 = s1.concat(" overflow");

Ở đây chúng ta đang gán giá trị đã sửa đổi của chuỗi trở lại tham chiếu s1 .

         ___________________
        |                   |
s1 ---->|  stack overflow   |
        |___________________|


out.println(s1);    // o/p: stack overflow
out.println(s2);    // o/p: hello

Đó là lý do tại sao Java quyết định String là lớp cuối cùng. Nếu không, bất kỳ ai cũng có thể sửa đổi và thay đổi giá trị của chuỗi. Hy vọng điều này sẽ giúp một chút.


6

Đối tượng chuỗi được tham chiếu lần đầu tiên strkhông bị thay đổi, tất cả những gì bạn đã làm là strtham chiếu đến một đối tượng chuỗi mới.


5

Chuỗi sẽ không thay đổi, tham chiếu đến nó sẽ. Bạn đang nhầm lẫn sự bất biến với khái niệm các finallĩnh vực. Nếu một trường được khai báo là final, một khi nó đã được chỉ định, nó không thể được gán lại.


5

Về phần thay thế câu hỏi của bạn, hãy thử điều này:

String str = "Mississippi"; 
System.out.println(str); //Prints Mississippi 

String other = str.replace("i", "!"); 
System.out.println(str); //still prints Mississippi 
System.out.println(other);  // prints M!ss!ss!pp!

4

Mặc dù java cố gắng bỏ qua nó, nhưng strkhông có gì hơn một con trỏ. Điều này có nghĩa là khi bạn viết lần đầu tiên str = "Hello";, bạn tạo một đối tượng strtrỏ đến. Khi bạn gán lại strbằng cách viết str = "Help!";, một đối tượng mới được tạo và "Hello"đối tượng cũ sẽ được thu gom rác bất cứ khi nào java cảm thấy như vậy.


3

Tính không thay đổi ngụ ý rằng giá trị của một đối tượng được khởi tạo không thể thay đổi, bạn không bao giờ có thể biến "Xin chào" thành "Trợ giúp!".

Biến str là một tham chiếu đến một đối tượng, khi bạn gán một giá trị mới cho str bạn không thay đổi giá trị của đối tượng mà nó tham chiếu, bạn đang tham chiếu một đối tượng khác.


3

Lớp chuỗi là bất biến và bạn không thể thay đổi giá trị của đối tượng bất biến. Nhưng trong trường hợp của Chuỗi, nếu bạn thay đổi giá trị của chuỗi hơn nó sẽ tạo ra chuỗi mới trong nhóm chuỗi và hơn tham chiếu chuỗi của bạn đến giá trị đó không phải là chuỗi cũ. do đó, bằng cách này, chuỗi là bất biến. Hãy lấy ví dụ của bạn,

String str = "Mississippi";  
System.out.println(str); // prints Mississippi 

nó sẽ tạo một chuỗi "Mississippi" và sẽ thêm nó vào chuỗi String để bây giờ str đang trỏ đến Mississippi.

str = str.replace("i", "!");  
System.out.println(str); // prints M!ss!ss!pp! 

Nhưng sau khi hoạt động ở trên, một chuỗi khác sẽ được tạo ra "M! Ss! Ss! Pp!" và nó sẽ được thêm vào chuỗi String. và bây giờ str đang chỉ vào M! ss! ss! pp!, không phải Mississippi.

Vì vậy, bằng cách này, khi bạn sẽ thay đổi giá trị của đối tượng chuỗi, nó sẽ tạo thêm một đối tượng và sẽ thêm nó vào nhóm chuỗi.

Hãy có thêm một ví dụ

String s1 = "Hello"; 
String s2 = "World"; 
String s = s1 + s2;

ba dòng trên sẽ thêm ba đối tượng của chuỗi vào nhóm chuỗi.
1) Xin chào
2) Thế giới
3) HelloWorld


2

Sử dụng:

String s = new String("New String");
s.concat(" Added String");
System.out.println("String reference -----> "+s); // Output: String reference -----> New String

Nếu bạn thấy ở đây tôi sử dụng concatphương thức để thay đổi chuỗi gốc, nghĩa là "Chuỗi mới" với chuỗi "Chuỗi đã thêm", nhưng tôi vẫn nhận được đầu ra như trước, do đó nó chứng tỏ rằng bạn không thể thay đổi tham chiếu của đối tượng của lớp String, nhưng nếu bạn làm điều này bằng lớp StringBuilder thì nó sẽ hoạt động. Nó được liệt kê dưới đây.

StringBuilder sb = new StringBuilder("New String");
sb.append(" Added String");
System.out.println("StringBuilder reference -----> "+sb);// Output: StringBuilder reference -----> New String Added String

2

Giống như Linus Tolvards đã nói:

Nói là rẻ. Cho tôi xem mã

Hãy xem này:

public class Test{
    public static void main(String[] args){

        String a = "Mississippi";
        String b = "Mississippi";//String immutable property (same chars sequence), then same object

        String c = a.replace('i','I').replace('I','i');//This method creates a new String, then new object
        String d = b.replace('i','I').replace('I','i');//At this moment we have 3 String objects, a/b, c and d

        String e = a.replace('i','i');//If the arguments are the same, the object is not affected, then returns same object

        System.out.println( "a==b? " + (a==b) ); // Prints true, they are pointing to the same String object

        System.out.println( "a: " + a );
        System.out.println( "b: " + b );

        System.out.println( "c==d? " + (c==d) ); // Prints false, a new object was created on each one

        System.out.println( "c: " + c ); // Even the sequence of chars are the same, the object is different
        System.out.println( "d: " + d );

        System.out.println( "a==e? " + (a==e) ); // Same object, immutable property
    }
}

Đầu ra là

a==b? true
a: Mississippi
b: Mississippi
c==d? false
c: Mississippi
d: Mississippi
a==e? true

Vì vậy, hãy nhớ hai điều:

  • Chuỗi là bất biến cho đến khi bạn áp dụng một phương thức thao tác và tạo một cái mới (trường hợp c & d).
  • Phương thức thay thế trả về cùng một đối tượng String nếu cả hai tham số giống nhau

0

Đối với những người thắc mắc làm thế nào để phá vỡ tính bất biến của Chuỗi trong Java ...

import java.lang.reflect.Field;

public class StringImmutability {
    public static void main(String[] args) {
        String str1 = "I am immutable";
        String str2 = str1;

        try {
            Class str1Class = str1.getClass();
            Field str1Field = str1Class.getDeclaredField("value");

            str1Field.setAccessible(true);
            char[] valueChars = (char[]) str1Field.get(str1);

            valueChars[5] = ' ';
            valueChars[6] = ' ';

            System.out.println(str1 == str2);
            System.out.println(str1);
            System.out.println(str2);           
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

    }
}

Đầu ra

true
I am   mutable
I am   mutable

0

Chuỗibất biến . Điều đó có nghĩa là chúng ta chỉ có thể thay đổi tài liệu tham khảo .


String a = "a";
System.out.println("String a is referencing to "+a); // Output: a

a.concat("b");
System.out.println("String a is referencing to "+a); // Output: a

a = a.concat("b");
System.out.println("String a has created a new reference and is now referencing to "+a); // Output: ab

0

Trong Java, các đối tượng thường được truy cập bởi các tham chiếu. Trong đoạn mã của bạn, str là một tham chiếu đầu tiên được gán cho "Hello" (một đối tượng được tạo tự động hoặc được tìm nạp từ nhóm không đổi ) và sau đó bạn đã gán một đối tượng khác "Trợ giúp!" để cùng tham khảo. Một điểm cần lưu ý là tham chiếu giống nhau và được sửa đổi, nhưng các đối tượng thì khác nhau. Một điều nữa trong mã của bạn, bạn đã truy cập ba đối tượng,

  1. Khi bạn gọi String mới ().
  2. Khi bạn được chỉ định "xin chào".
  3. Khi bạn được chỉ định "giúp đỡ!".

Gọi String mới () tạo ra một đối tượng mới ngay cả khi nó tồn tại trong nhóm chuỗi, vì vậy nói chung nó không nên được sử dụng. Để đặt một chuỗi được tạo từ String () mới vào nhóm chuỗi, bạn có thể thử intern()phương thức.

Tôi hi vọng cái này giúp được.


0

Tính bất biến tôi có thể nói là bạn không thể tự thay đổi Chuỗi. Giả sử bạn có Chuỗi x, giá trị của nó là "abc". Bây giờ bạn không thể thay đổi Chuỗi, nghĩa là, bạn không thể thay đổi bất kỳ ký tự / s nào trong "abc".

Nếu bạn phải thay đổi bất kỳ ký tự / s nào trong Chuỗi, bạn có thể sử dụng một mảng ký tự và biến đổi nó hoặc sử dụng StringBuilder.

String x = "abc";
x = "pot";
x = x + "hj";
x = x.substring(3);
System.out.println(x);

char x1[] = x.toCharArray();
x1[0] = 's';
String y = new String(x1);
System.out.println(y);

Đầu ra:

hj
sj

0

Hoặc bạn có thể thử:

public class Tester
{
public static void main(String[] args)
{
 String str = "Mississippi"; 
 System.out.println(str); // prints Mississippi 
 System.out.println(str.hashCode());

 str = str.replace("i", "!"); 
 System.out.println(str); // prints M!ss!ss!pp! 
 System.out.println(str.hashCode());
 }
 }

Điều này sẽ cho thấy cách thay đổi mã băm.


0

Chuỗi là bất biến có nghĩa là bạn không thể thay đổi chính đối tượng, nhưng bạn có thể thay đổi tham chiếu đến đối tượng. Khi bạn gọi a = "ty", bạn thực sự đang thay đổi tham chiếu của a thành một đối tượng mới được tạo bởi chuỗi "ty" theo nghĩa đen. Thay đổi một đối tượng có nghĩa là sử dụng các phương thức của nó để thay đổi một trong các trường của nó (hoặc các trường là công khai và không phải là cuối cùng, để chúng có thể được cập nhật từ bên ngoài mà không cần truy cập chúng thông qua các phương thức), ví dụ:

Foo x = new Foo("the field");
x.setField("a new field");
System.out.println(x.getField()); // prints "a new field"

Mặc dù trong một lớp không thay đổi (được khai báo là cuối cùng, để ngăn sửa đổi thông qua kế thừa) (các phương thức của nó không thể sửa đổi các trường của nó và các trường luôn ở chế độ riêng tư và được khuyến nghị là cuối cùng), ví dụ Chuỗi, bạn không thể thay đổi Chuỗi hiện tại nhưng bạn có thể trả về một Chuỗi mới, nghĩa là:

String s = "some text";
s.substring(0,4);
System.out.println(s); // still printing "some text"
String a = s.substring(0,4);
System.out.println(a); // prints "some"

0

Ở đây tính bất biến có nghĩa là thể hiện đó có thể trỏ đến tham chiếu khác nhưng nội dung ban đầu của chuỗi sẽ không được sửa đổi tại tham chiếu ban đầu. Hãy để tôi giải thích bằng ví dụ đầu tiên được đưa ra bởi bạn. Str đầu tiên là trỏ đến "Xin chào", Ok của nó cho đến nay. Lần thứ hai nó chỉ vào "Trợ giúp!". Ở đây str bắt đầu chỉ vào "Trợ giúp!" và tham chiếu của chuỗi "Hello" bị mất và chúng tôi không thể lấy lại được.

Trong thực tế khi str sẽ cố gắng sửa đổi nội dung hiện có, thì một chuỗi mới khác sẽ được tạo và str sẽ bắt đầu trỏ đến tham chiếu đó. Vì vậy, chúng ta thấy chuỗi đó tại tham chiếu ban đầu không được sửa đổi nhưng điều đó an toàn ở tham chiếu và đối tượng của nó bắt đầu trỏ vào tham chiếu khác nhau nên tính không thay đổi được bảo tồn.


0

Rất muộn để trả lời, nhưng muốn đặt một thông điệp súc tích từ tác giả của lớp String trong Java

Chuỗi không đổi; giá trị của chúng không thể thay đổi sau khi chúng được tạo. Bộ đệm chuỗi hỗ trợ chuỗi có thể thay đổi. Bởi vì các đối tượng String là bất biến nên chúng có thể được chia sẻ.

Nó có thể được bắt nguồn từ tài liệu này rằng bất cứ điều gì thay đổi chuỗi, trả về đối tượng khác nhau (có thể là mới hoặc được thực tập và cũ). Gợi ý không quá tinh tế về điều này nên đến từ chữ ký hàm. Hãy suy nghĩ về điều đó, 'Tại sao họ tạo một hàm trên một đối tượng trả về một đối tượng thay vì trạng thái?'.

public String replace(char oldChar, char newChar) 

Ngoài ra một nguồn nữa làm cho hành vi này rõ ràng (Từ tài liệu chức năng thay thế)

Trả về một chuỗi mới do thay thế tất cả các lần xuất hiện của oldChar trong chuỗi này bằng newChar.

Nguồn: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)

  • tác giả Lee Boynton
  • tác giả Arthur van Hoff
  • tác giả Martin Buchholz
  • tác giả Ulf Zibis

Nguồn: JavaDoc của Chuỗi.


0

Chuỗi đối tượng - các phương thức tự nó được tạo thành "bất biến". Hành động này không tạo ra thay đổi: "Letters.replace (" bbb "," aaa ");"

Nhưng việc gán dữ liệu sẽ khiến các thay đổi đối với nội dung Chuỗi thay đổi:

    letters = "aaa";
    letters=null;
    System.out.println(letters);
    System.out.println(oB.hashCode());
    System.out.println(letters);
    letters = "bbbaaa";
    System.out.println(oB.hashCode());
    System.out.println(letters);

// Mã băm của chuỗi Object không thay đổi.


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

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ị.


0

Tôi sẽ giải thích nó với ví dụ đơn giản


xem xét bất kỳ mảng ký tự nào: vd: char a [] = {'h', 'e', ​​'l', 'l', 'o'}; và một chuỗi: Chuỗi s = "xin chào";


trên mảng ký tự, chúng ta có thể thực hiện các thao tác như chỉ in ba chữ cái cuối bằng cách lặp lại mảng; nhưng trong chuỗi chúng ta phải tạo đối tượng String mới và sao chép chuỗi con cần thiết và địa chỉ của nó sẽ nằm trong đối tượng chuỗi mới.

ví dụ

***String s="hello";
String s2=s.substrig(0,3);***

vì vậy s2 sẽ có "hel";


-1

Chuỗi trong Java trong Bất biến và Cuối cùng chỉ có nghĩa là không thể thay đổi hoặc sửa đổi:

Trường hợp 1:

class TestClass{  
 public static void main(String args[]){  
   String str = "ABC";  
   str.concat("DEF");  
   System.out.println(str);  
 }  
} 

Đầu ra: ABC

Lý do: str tham chiếu đối tượng không bị thay đổi trong thực tế, một đối tượng mới "DEF" được tạo trong nhóm và không có tham chiếu nào cả (tức là bị mất).

Trường hợp 2:

class TestClass{  
 public static void main(String args[]){  
   String str="ABC";  
   str=str.concat("DEF");  
   System.out.println(str);  
 }  
}  

Đầu ra: ABCDEF

Lý do: Trong trường hợp này, str hiện đang đề cập đến một đối tượng mới "ABCDEF" do đó nó in ABCDEF tức là đối tượng str trước đó "ABC" bị mất trong nhóm không có tham chiếu.


-1

Vì Chuỗi là bất biến nên các thay đổi sẽ không xảy ra nếu bạn sẽ không gán giá trị trả về của hàm cho chuỗi.so trong câu hỏi của bạn gán giá trị của hàm hoán đổi trả về giá trị cho s.

s = exchange (s, n1, n2); sau đó giá trị của chuỗi s sẽ thay đổi.

Tôi cũng đã nhận được giá trị không thay đổi khi tôi đang viết chương trình để có được một chuỗi hoán vị (Mặc dù nó không đưa ra tất cả các hoán vị nhưng đây là ví dụ để trả lời câu hỏi của bạn)

Đây là một ví dụ.

> import java.io.*;  public class MyString { public static void
> main(String []args)throws IOException {  BufferedReader br=new
> BufferedReader(new InputStreamReader(System.in));  String
> s=br.readLine().trim(); int n=0;int k=0;  while(n!=s.length()) {
> while(k<n){  swap(s,k,n); System.out.println(s); swap(s,k,n); k++; }
> n++; } }  public static void swap(String s,int n1,int n2) { char temp;
> temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s);
> sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString();
> } }

nhưng tôi đã không nhận được các giá trị hoán vị của chuỗi từ mã trên. Vì vậy, tôi đã gán giá trị trả về của hàm hoán đổi cho chuỗi và đã thay đổi giá trị của chuỗi. Sau khi gán giá trị trả về, tôi nhận được các giá trị hoán vị của chuỗi.

/import java.util.*; import java.io.*; public class MyString { public static void main(String []args)throws IOException{
BufferedReader br=new BufferedReader(new InputStreamReader(System.in)); 
String s=br.readLine().trim(); int n=0;int k=0; 
while(n!=s.length()){ while(k<n){ s=swap(s,k,n); 
System.out.println(s); s=swap(s,k,n); k++; } n++; } } 
public static String swap(String s,int n1,int n2){
char temp; temp=s.charAt(n1); StringBuilder sb=new StringBuilder(s); sb.setCharAt(n1,s.charAt(n2)); sb.setCharAt(n2,temp); s=sb.toString(); return s; } }

-1
    public final class String_Test {

    String name;
    List<String> list=new ArrayList<String>();

    public static void main(String[] args) {

        String_Test obj=new String_Test();
        obj.list.add("item");//List will point to a memory unit- i.e will have one Hashcode value #1234

        List<String> list2=obj.list; //lis1 also will point to same #1234

        obj.list.add("new item");//Hashcode of list is not altered- List is mutable, so reference remains same, only value in that memory location changes

        String name2=obj.name="Myname"; // name2 and name will point to same instance of string -Hashcode #5678
        obj.name = "second name";// String is Immutable- New String HAI is created and name will point to this new instance- bcoz of this Hashcode changes here #0089

        System.out.println(obj.list.hashCode());
        System.out.println(list2.hashCode());
        System.out.println(list3.hashCode());

        System.out.println("===========");
        System.out.println(obj.name.hashCode());
        System.out.println(name2.hashCode());
    }
}

Sẽ sản xuất ra đặt một cái gì đó như thế này

141958369 141958369

103056 65078777

Mục đích của đối tượng bất biến là giá trị của nó không nên bị thay đổi một khi được gán. Nó sẽ trả về đối tượng mới mỗi khi bạn cố gắng thay đổi nó dựa trên việc thực hiện. Lưu ý: Stringbuffer thay vì chuỗi có thể được sử dụng để tránh điều này.

Đối với câu hỏi cuối cùng của bạn :: u sẽ có một tham chiếu và 2 chuỗi trong nhóm chuỗi .. Ngoại trừ tham chiếu sẽ trỏ đến m! Ss! Ss! Pp!

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.