В чем разница между изменяемой и неизменной строкой в ​​Java

Насколько мне известно,

изменяемая строка может быть изменена, а неизменяемая строка не может быть изменена.

Здесь я хочу изменить значение String следующим образом:

String str="Good";
str=str+" Morning";

и другой способ,

StringBuffer str= new StringBuffer("Good");
str.append(" Morning");

В обоих случаях я пытаюсь изменить значение str, Может кто-нибудь сказать мне, в чем разница в обоих случаях, и дать мне четкую картину изменчивых и неизменных объектов.

12 ответов

Решение

Случай 1:

String str = "Good";
str = str + " Morning";

В приведенном выше коде вы создаете 3 String Объекты.

  1. "Хорошо" это входит в Струнный пул.
  2. "Утро" также входит в Струнный пул.
  3. "Доброе утро" создано путем объединения "Доброго" и "Утреннего". Этот парень идет в кучу.

Примечание. Строки всегда неизменны. Нет такой вещи, как изменяемая строка. str это просто ссылка, которая в конечном итоге указывает на "Доброе утро". Вы на самом деле, не работаете над 1 объект. у тебя есть 3 отчетливый String Объекты.


Случай 2:

StringBuffer str = new StringBuffer("Good"); 
str.append(" Morning");

StringBuffer содержит массив символов. Это не то же самое, что String, Приведенный выше код добавляет символы в существующий массив. Эффективно, StringBuffer изменчив, его String представление не.

В чем разница между изменяемой и неизменной строкой в ​​Java

неизменяемые существуют, изменчивые нет.

В Java все строки неизменны. Когда вы пытаетесь изменить StringТо, что вы действительно делаете, это создание нового. Тем не менее, когда вы используете StringBuilderвы фактически изменяете содержимое, а не создаете новое.

Джава Stringс неизменны.

В первом примере вы меняете ссылку на Stringтем самым присваивая ему значение двух других Strings комбинированный: str + " Morning",

Наоборот, StringBuilder или же StringBuffer может быть изменено с помощью его методов.


Строка в Java неизменна. Однако, что означает быть изменчивым в контексте программирования - это первый вопрос. Рассмотрим следующий класс,

public class Dimension {
    private int height;

    private int width;

    public Dimenstion() {
    }

    public void setSize(int height, int width) {
        this.height = height;
        this.width = width;
    }

    public getHeight() {
        return height;
    }

    public getWidth() {
        return width;
    }
}

Теперь после создания экземпляра Dimension мы всегда можем обновить его атрибуты. Обратите внимание, что если какой-либо атрибут, в другом смысле состояния, может быть обновлен, например, для класса, то он называется изменяемым. Мы всегда можем сделать следующее,

Dimension d = new Dimension();
d.setSize(10, 20);// Dimension changed
d.setSize(10, 200);// Dimension changed
d.setSize(100, 200);// Dimension changed

Давайте посмотрим, как мы можем создать строку в Java.

String str1 = "Hey!";
String str2 = "Jack";
String str3 = new String("Hey Jack!");
String str4 = new String(new char[] {'H', 'e', 'y', '!'});
String str5 = str1 + str2;
str1 = "Hi !";
// ...

Так,

  1. str1 а также str2 строковые литералы, которые создаются в константном пуле
  2. str3, str4 а также str5 являются строковыми объектами, которые помещаются в память кучи
  3. str1 = "Hi!"; создает "Hi!" в константе String, и это совершенно другая ссылка, чем "Hey!" который str1 ссылка ранее.

Здесь мы создаем строковый литерал или строковый объект. Оба они разные, я бы посоветовал вам прочитать следующий пост, чтобы больше узнать об этом.

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

String str = "Good"; // Create the String literal in String pool
str = str + " Morning"; // Create String with concatenation of str + "Morning"
|_____________________|
       |- Step 1 : Concatenate "Good"  and " Morning" with StringBuilder
       |- Step 2 : assign reference of created "Good Morning" String Object to str

Как String стал неизменным?

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

Сдвиг ссылки не означает, что вы изменили ее значение. Было бы изменчиво, если вы можете обновить массив символов, который находится за сценой в классе String. Но в действительности этот массив будет инициализирован один раз, и во всей программе он останется прежним.

Почему StringBuffer изменчив?

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

Когда ты сказал str, вы должны быть осторожны, что вы имеете в виду:

  • Вы имеете в виду переменную str?

  • или вы имеете в виду объект, на который ссылается str?

В вашем StringBuffer Например, вы не меняете значение strи в вашем String Например, вы не изменяете состояние String объект.

Самый острый способ почувствовать разницу будет примерно так:

static void change(String in) { 
  in = in + " changed";
}

static void change(StringBuffer in) {
  in.append(" changed");
}

public static void main(String[] args) {
   StringBuffer sb = new StringBuffer("value");
   String str = "value";
   change(sb);
   change(str);
   System.out.println("StringBuffer: "+sb);
   System.out.println("String: "+str);
}

В Java все строки являются неизменяемыми (невозможно изменить). Когда вы пытаетесь изменить строку, вы действительно создаете новую.

Следующими способами мы можем создать строковый объект

  1. Использование строкового литерала

    Strung str="java";

  2. Используя новое ключевое слово

    Strung str = new String("java");

  3. Использование массива символов

    char[] helloArray = { 'h', 'e', ​​'l', 'l', 'o', '.' };

    String helloString = new String (helloArray);

приходя к неизменности String, просто означает неизменяемый или неизменяемый

Давайте возьмем один пример

Я инициализирую значение строкового литерала с

String s="kumar";

Ниже я собираюсь отобразить десятичное представление адреса местоположения, используя hashcode()

System.out.println(s.hashCode());

Простая печать значения строки

System.out.println("value "+s);

Хорошо, на этот раз я инициализирую значение "kumar" для s1

String s1="kumar";   // what you think is this line, takes new location in the memory ??? 

Хорошо, давайте проверим, отобразив хеш-код объекта s1, который мы создали

System.out.println(s1.hashCode());

хорошо, давайте проверим код ниже

String s2=new String("Kumar");
    System.out.println(s2.hashCode());  // why this gives the different address ??

Хорошо, проверьте этот код ниже, наконец

String s3=new String("KUMAR");
    System.out.println(s3.hashCode());  // again different address ???

ДА, если вы видите, что строки 's' и 's1' имеют одинаковый хеш-код, потому что значения, удерживаемые с помощью 's' и 's1', совпадают с 'kumar'

Давайте рассмотрим String 's2' и 's3', эти два хеш-кода Strings кажутся разными в том смысле, что они оба хранятся в разных местах, потому что вы видите, что их значения различны.

поскольку хэш-код s и s1 одинаков, поскольку эти значения одинаковы и хранятся в одном и том же месте.

Пример 1: попробуйте код ниже и анализируйте построчно

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

    String s="java";
    System.out.println(s.hashCode());
    String s1="javA";
    System.out.println(s1.hashCode());
    String s2=new String("Java");
    System.out.println(s2.hashCode());
    String s3=new String("JAVA");
    System.out.println(s3.hashCode());
}
}

Пример 2: попробуйте код ниже и анализируйте построчно

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

        String s="java";
        s.concat(" programming");  // s can not be changed "immutablity"
        System.out.println("value of s "+s);
        System.out.println(" hashcode of s "+s.hashCode());

        String s1="java";
        String s2=s.concat(" programming");   // s1 can not be changed "immutablity" rather creates object s2
        System.out.println("value of s1 "+s1);
        System.out.println(" hashcode of s1 "+s1.hashCode());  

        System.out.println("value of s2 "+s2);
        System.out.println(" hashcode of s2 "+s2.hashCode());

    }
}

Хорошо, давайте посмотрим, в чем разница между изменяемым и неизменным.

изменяемый (он изменяется) и неизменный (он не может измениться)

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


        // it demonstrates immutable concept
        String s="java";
        s.concat(" programming");  // s can not be changed (immutablity)
        System.out.println("value of s ==  "+s); 
        System.out.println(" hashcode of s == "+s.hashCode()+"\n\n");


        // it demonstrates mutable concept
        StringBuffer s1= new StringBuffer("java");
        s1.append(" programming");  // s can be changed (mutablity)
        System.out.println("value of s1 ==  "+s1); 
        System.out.println(" hashcode of s1 == "+s1.hashCode());


    }
}

Есть еще вопросы? пожалуйста, напишите на...

Его очень легко объяснить в этой связи с классом setter и getter, который является изменяемым, в то время как класс только с getter является неизменным. Вот подробности. http://latest-tutorial.com/2014/11/14/difference-mutable-immutable-objects-java/

Изменяемые объекты: если у вас есть ссылка на экземпляр объекта, содержимое этого экземпляра может быть изменено

Неизменяемые объекты: если у вас есть ссылка на экземпляр объекта, содержимое этого экземпляра не может быть изменено

Давайте разберемся с этим на примере:

String myString = new String( "old String" );
System.out.println( myString );
myString = new String( "new String" );
System.out.println( myString );

Выход из этого:

old String
new String

Теперь мы обнаруживаем, что значение, отображаемое переменной myString, изменилось. Мы определили неизменные объекты как неспособные изменить стоимость, так что же происходит? Давайте еще раз расширим пример, чтобы посмотреть ближе к переменной myString.

String myString = new String( "old String" );
String myCache = myString;
System.out.println( "equal: " + myString.equals( myCache ) );
System.out.println( "same:  " + ( myString == myCache ) );
myString = "not " + myString;
System.out.println( "equal: " + myString.equals( myCache ) );
System.out.println( "same:  " + ( myString == myCache ) );

Результат выполнения этого:

equal: true
same:  true
equal: false
same:  false

Это показывает, что переменная myString ссылается на новый экземпляр класса String. Содержимое объекта не изменилось; мы отказались от экземпляра и изменили нашу ссылку на новую с новым содержанием.

Изменяемая переменная - это переменная, значение которой может измениться на месте, тогда как в неизменяемой переменной изменение значения не произойдет. Изменение неизменяемой переменной перестроит ту же переменную.

Изменяемый означает, что вы сохраните ту же ссылку на переменную и измените ее содержимое, но неизменяемой вы не можете изменить содержимое, но вы объявите, что новая ссылка содержит новое и старое значение переменной

Бывшийнеизменный -> Строка

String x = "value0ne";// adresse one x += "valueTwo"; //an other adresse {adresse two}адрес на куче памяти меняется.

Изменяемый -> StringBuffer - StringBuilderStringBuilder sb = new StringBuilder(); sb.append("valueOne"); // adresse One sb.append("valueTwo"); // adresse One

СБ все еще в том же адресе, я надеюсь, что этот комментарий поможет

Я изменил код Уильям с выходными комментариями для лучшего понимания

   static void changeStr(String in) { 
      in = in+" changed";
      System.out.println("fun:"+in); //value changed 
    }
    static void changeStrBuf(StringBuffer in) {
      in.append(" changed");   //value changed
    }

    public static void main(String[] args) {
       StringBuffer sb = new StringBuffer("value");
       String str = "value";
       changeStrBuf(sb);
       changeStr(str);
       System.out.println("StringBuffer: "+sb); //value changed
       System.out.println("String: "+str);       // value 
    }

В приведенном выше коде посмотрите на значение str в main() и changeStr(), хотя при изменении значения str в changeStr () оно влияет только на эту функцию, но в основной функции значение не изменяется, но это не в случае StringBuffer..

В StringBuffer измененное значение влияет как глобальное.

следовательно, String неизменен, а StringBuffer изменчив...

В Простом все, что вы изменили на String Object, повлияет только на эту функцию, перейдя в String Pool. но не изменилось...

Другие вопросы по тегам