Неизменность строк в Java - PullRequest
205 голосов
/ 12 октября 2009

Рассмотрим следующий пример.

String str = new String();

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

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

Теперь в Java объекты String неизменны. Тогда как же объекту str может быть присвоено значение «Помогите!». Разве это не противоречит неизменности строк в Java? Кто-нибудь может объяснить мне точную концепцию неизменности?

Edit:

Ok. Теперь я понимаю, но только один дополнительный вопрос. А как насчет следующего кода:

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

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

Означает ли это, что два объекта создаются снова ("Миссисипи" и "M! Ss! Ss! Pp!"), А ссылка str указывает на другой объект после метода replace()?

Ответы [ 25 ]

2 голосов
/ 23 июня 2016

Класс String является неизменным, и вы не можете изменить значение неизменяемого объекта. Но в случае String, если вы измените значение строки, это создаст новую строку в пуле строк, а затем ваша строковая ссылка на это значение, а не старое. таким образом, строка неизменна. Давайте возьмем ваш пример,

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

создаст одну строку "Миссисипи" и добавит ее в пул строк так что теперь ул указывает на Миссисипи.

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

Но после вышеуказанной операции, будет создана еще одна строка "M! ss! ss! pp!" и он будет добавлен в пул строк. а также теперь str указывает на M! ss! ss! pp !, а не на Миссисипи.

таким образом, когда вы измените значение строкового объекта, он создаст еще один объект и добавит его в пул строк.

Давайте рассмотрим еще один пример

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

эта строка из трех выше добавит три объекта строки в пул строк.
1) Привет
2) Мир
3) HelloWorld

2 голосов
/ 14 сентября 2016

Как сказал Линус Толвардс:

Обсуждение дешево. Покажите мне код

Взгляните на это:

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
    }
}

Выход

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

Итак, запомните две вещи:

  • Строки неизменны, пока вы не примените метод, который манипулирует и создает новый (случаи c & d).
  • Метод Replace возвращает один и тот же объект String, если оба параметра совпадают
0 голосов
/ 29 апреля 2019
    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());
    }
}

Будет выдавать что-то вроде этого

1419358369 1419358369

103056 65078777

Цель неизменяемого объекта состоит в том, что его значение не должно изменяться после назначения. Он будет возвращать новый объект каждый раз, когда вы пытаетесь изменить его в зависимости от реализации. Примечание. Чтобы избежать этого, можно использовать Stringbuffer вместо string.

К вашему последнему вопросу: у вас будет одна ссылка и 2 строки в пуле строк. За исключением того, что ссылка будет указывать на m! Ss! Ss! Pp!

0 голосов
/ 20 июля 2018

Если HELLO ваша строка, вы не можете изменить HELLO на HILLO. Это свойство называется свойством неизменности.

У вас может быть несколько строковых переменных-указателей для указания HELLO String.

Но если HELLO - char Array, тогда вы можете изменить HELLO на HILLO. Например,

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

Языки программирования имеют неизменные переменные данных, чтобы их можно было использовать в качестве ключей в паре ключ-значение.

0 голосов
/ 29 ноября 2017

Поскольку String является неизменяемым, поэтому изменения не произойдут, если вы не назначите возвращаемое значение функции для string.so в своем вопросе присвойте значение возвращаемого значения функции swap s.

s = swap (s, n1, n2), тогда значение строки s изменится.

Я также получал неизменное значение, когда писал программу, чтобы получить строку перестановок (хотя она не дает всех перестановок, но это, например, для ответа на ваш вопрос)

Вот пример.

> 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();
> } }

но я не получал перестановочные значения строки из приведенного выше кода. Поэтому я присвоил возвращаемое значение функции подкачки строке и получил измененные значения строки. после присвоения возвращенного значения я получил перестановочные значения строки.

/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; } }
0 голосов
/ 03 октября 2017

Строка Object - сам метод сделан «неизменяемым». Это действие не вызывает изменений: "letters.replace (" bbb "," aaa ");"

Но назначение данных действительно приводит к изменению содержимого строк:

    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);

// Хеш-код строки Object не изменяется.

0 голосов
/ 17 июля 2017

Очень поздно для ответа, но хотел выложить краткое сообщение от автора класса String в Java

Строки являются постоянными; их значения не могут быть изменены после того, как они создано. Строковые буферы поддерживают изменяемые строки. Потому что строка объекты неизменны, они могут быть общими.

Из этой документации можно сделать вывод, что все, что изменяет строку, возвращает другой объект (который может быть новым или интернированным и старым). Не очень тонкий намек на это должен исходить из сигнатуры функции. Подумайте об этом: «Почему они заставляют функцию возвращать объект вместо статуса?».

public String replace(char oldChar, char newChar) 

Также еще один источник, который делает это поведение явным (из документации по замене функций)

Возвращает новую строку, полученную в результате замены всех вхождений oldChar в этой строке с newChar.

Источник: https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replace(char,%20char)

  • автор Ли Бойнтон
  • автор Артур ван Хофф
  • автор Мартин Буххольц
  • автор Ульф Зибис

Источник: JavaDoc of String.

0 голосов
/ 14 июля 2017

Здесь неизменность означает, что экземпляр может указывать на другую ссылку, но исходное содержимое строки не будет изменено при исходной ссылке. Позвольте мне объяснить первым примером, данным вами. Первая строка указывает на «Hello», все в порядке до этого. Второй раз это указывает на «Помощь!». Здесь ул начал указывать на «Помощь!» и ссылка на строку «Hello» потеряна, и мы не можем получить ее обратно.

Фактически, когда str попытается изменить существующее содержимое, тогда будет сгенерирована другая новая строка, и str начнет указывать на эту ссылку. Таким образом, мы видим, что строка в исходной ссылке не изменяется, но это безопасно при ее ссылке, и экземпляр объекта начинает указывать на другую ссылку, поэтому неизменность сохраняется.

0 голосов
/ 30 июня 2017

Строка является неизменной означает, что вы не можете изменить сам объект, но вы можете изменить ссылку на объект. Когда вы вызываете a = "ty", вы фактически изменяете ссылку a на новый объект, созданный строковым литералом "ty". Изменение объекта означает использование его методов для изменения одного из его полей (или поля являются общедоступными и не являются окончательными, чтобы их можно было обновлять извне, не обращаясь к ним через методы), например:

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

Находясь в неизменяемом классе (объявленном как final, чтобы предотвратить изменение с помощью наследования) (его методы не могут изменять его поля, а также поля всегда являются закрытыми и рекомендуются быть окончательными), например, String, вы не можете изменить текущий Строка, но вы можете вернуть новую строку, то есть:

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 голосов
/ 23 сентября 2016

Строка в Java в неизменяемом и окончательном означает, что ее нельзя изменить или изменить:

Случай 1:

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

Вывод: ABC

Причина: ссылка на объект str фактически не изменена, создается новый объект "DEF", который находится в пуле и вообще не имеет ссылки (т.е. потерян).

Случай 2:

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

Вывод: ABCDEF

Причина: в этом случае strтеперь ссылаясь на новый объект "ABCDEF", следовательно, он печатает ABCDEF, т.е. предыдущий объект str "ABC" теряется в пуле без ссылки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...