Что подразумевается под неизменным?

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

  1. Может кто-нибудь уточнить, что подразумевается под неизменный?
  2. Почему String неизменяемый?
  3. Каковы преимущества / недостатки неизменяемых объектов?
  4. Почему изменяемый объект, такой как StringBuilder, должен быть предпочтительнее String и наоборот?

Мы будем очень признательны за хороший пример (на Java).

Понимаете, это был не такой уж и глупый вопрос. Рад, что ты спросил!

DOK 11.11.2008 02:14

Кстати, я не думаю, что это самый тупой вопрос :) Я думаю, что это довольно важная концепция, которую нужно понять.

Jason Coco 11.11.2008 02:38

Когда вы сказали StringBuilder, разве вы не имели в виду изменяемый класс StringBuffer? String и StringBuffer более похожи по функциям, чем String и StringBuilder. StringBuffer фактически является изменяемой строкой.

Derek Mahar 09.12.2009 18:30

Могу я предложить добавить к этому вопросу тег «новичок», чтобы программисты, не знакомые с Java, могли найти его при поиске других вводных вопросов?

Derek Mahar 09.12.2009 18:31
stackoverflow.com/questions/2971315/…
Rajavel D 14.08.2014 10:02
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
406
5
181 594
17
Перейти к ответу Данный вопрос помечен как решенный

Ответы 17

После создания не может быть изменен. Рассмотрим класс, экземпляр которого может использоваться в качестве ключа для хеш-таблицы или подобного. Ознакомьтесь с лучшими практиками Java.

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

String s1 = "  abc  ";
String s2 = s1.trim();

В приведенном выше коде строка s1 не изменилась, другой объект (s2) был создан с помощью s1.

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

String foo = "Hello";
foo.substring(3);
<-- foo here still has the same value "Hello"

Чтобы сохранить изменения, вы должны сделать что-то вроде этого foo = foo.sustring (3);

Неизменяемые и изменяемые могут быть забавными, когда вы работаете с коллекциями. Подумайте, что произойдет, если вы используете изменяемый объект в качестве ключа для карты, а затем измените значение (совет: подумайте о equals и hashCode).

Одно значение связано с тем, как значение хранится в компьютере. Например, для строки .Net это означает, что строку в памяти нельзя изменить. Когда вы думаете, что меняете ее, вы фактически создаете новую строку. строка в памяти и указание существующей переменной (которая является просто указателем на фактический набор символов в другом месте) на новую строку.

Ответ принят как подходящий

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

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

например

class Foo
{
     private final String myvar;

     public Foo(final String initialValue)
     {
         this.myvar = initialValue;
     }

     public String getValue()
     {
         return this.myvar;
     }
}

Foo не должен беспокоиться о том, что вызывающий getValue() может изменить текст в строке.

Если вы представите себе класс, аналогичный Foo, но с StringBuilder, а не с String в качестве члена, вы увидите, что вызывающий getValue() сможет изменить атрибут StringBuilder экземпляра Foo.

Также остерегайтесь различных видов неизменяемости, которые вы можете найти: Эрик Липперт написал об этом статья в блоге. В основном у вас могут быть объекты, интерфейс которых неизменяем, но за кулисами фактическое изменяемое частное состояние (и, следовательно, не может безопасно совместно использоваться между потоками).

Я думаю, вам следует добавить конструктор с одним аргументом, чтобы присвоить значение хотя бы один раз. Смысл текущего кода не ясен, так как на самом деле нет смысла менять :).

Georgy Bolyuba 11.11.2008 02:21

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

JaredPar 11.11.2008 03:15

Это хороший ответ. Но чтобы уточнить, это не означает, что вы не можете установить свою переменную в другой экземпляр неизменяемого типа (a-la const). Это просто означает, что сам экземпляр не может быть изменен.

OJ. 11.11.2008 05:03

Член myVar должен быть окончательным, чтобы он был действительно неизменяемым.

laz 10.01.2009 00:16

Я не думаю, что final на самом деле что-то добавляет - извне класса (даже подклассов) myVar не может указывать на другую строку, а сама строка неизменна.

Douglas Leeder 10.01.2009 12:47

Вы правы, что myVar недоступен за пределами Foo. Однако наличие final указывает любому, кто может изменять класс в будущем, что его значение не должно изменяться. Я предпочитаю быть максимально откровенным в таких обстоятельствах.

laz 13.01.2009 00:41

IIRC, использующий final, также имеет некоторые преимущества в модели памяти Java (хотя у меня сейчас нет источника для этого).

Grundlefleck 09.01.2010 15:46

Как насчет «Ссылочные типы нельзя сделать неизменяемыми с помощью ключевого слова final. Final предотвращает только переназначение». от en.wikipedia.org/wiki/Immutable_object

Yousha Aleayoub 17.04.2015 20:08

ИМО, подход, подобный const, мог бы быть более надежным

peterchaula 02.01.2017 18:36

@DouglasLeeder, что произойдет, если я сделаю myvar.toUpperCase();, создаст ли он новый объект для myvar с новым значением или изменит существующий объект myvar в памяти кучи.

KingKongCoder 07.09.2017 09:42

@randomaspirer Строки неизменяемы, поэтому он вернет новую строку. docs.oracle.com/javase/7/docs/api/java/lang/… явно не говорит, но он может возвращать ту же строку или совместно использовать буфер в случае, когда ему не нужно изменять какие-либо символы.

Douglas Leeder 08.09.2017 12:20

класс также должен быть final, или вы можете создать подкласс и переопределить метод getValue()

Danny Dan 14.05.2019 12:30

Неизменяемые объекты - это объекты, которые нельзя изменить программно. Они особенно хороши для многопоточных сред или других сред, где несколько процессов могут изменять (мутировать) значения в объекте.

Однако, чтобы прояснить, StringBuilder на самом деле является изменяемым объектом, а не неизменяемым. Обычная строка java неизменяема (это означает, что после ее создания вы не можете изменить базовую строку без изменения объекта).

Например, предположим, что у меня есть класс ColoredString, который имеет значение String и цвет String:

public class ColoredString {

    private String color;
    private String string;

    public ColoredString(String color, String string) {
        this.color  = color;
        this.string = string;
    }

    public String getColor()  { return this.color;  }
    public String getString() { return this.string; }

    public void setColor(String newColor) {
        this.color = newColor;
    }

}

В этом примере ColoredString называется изменяемым, потому что вы можете изменить (видоизменить) одно из его ключевых свойств, не создавая новый класс ColoredString. Причина, по которой это может быть плохо, заключается, например, в том, что у вас есть приложение с графическим интерфейсом, которое имеет несколько потоков, и вы используете ColoredStrings для печати данных в окне. Если у вас есть экземпляр ColoredString, созданный как

new ColoredString("Blue", "This is a blue string!");

Тогда вы ожидаете, что строка всегда будет «синей». Однако, если другой поток захватил этот экземпляр и вызвал

blueString.setColor("Red");

У вас внезапно и, вероятно, неожиданно появится «красная» струна, когда вы захотите «синюю». Из-за этого неизменяемые объекты почти всегда предпочтительнее при передаче экземпляров объектов. Когда у вас есть случай, когда изменяемые объекты действительно необходимы, вы обычно должны защищать объект, передавая копии только из вашего конкретного поля управления.

Напомним, что в Java java.lang.String является неизменяемым объектом (не могу может быть изменен после его создания), а java.lang.StringBuilder - изменяемый объект, поскольку его можно изменить без создания нового экземпляра.

Вы должны сделать поля доступными только для чтения. Прямо сейчас ваш класс неизменен по соглашению. Для будущих разработчиков нет никаких указаний на то, что неизменяемость является преднамеренной. Если вы сделаете поля только для чтения, это поможет прояснить ваши намерения будущему разработчику.

JaredPar 11.11.2008 03:16

@JaredPar - На самом деле класс вообще не является неизменяемым ... это пример изменяемого класса, чтобы продемонстрировать, почему это может быть проблемой.

Jason Coco 11.11.2008 04:04

@JaredPar - О, это совершенно нормально :) Я собирался немного переписать его, чтобы было понятнее, но Дуглас уже хорошо написан и кажется фаворитом, поэтому я просто оставлю свой в качестве другого примера; но кто-то на самом деле отредактировал его, чтобы сделать свойства окончательными, что мне показалось забавным :)

Jason Coco 11.11.2008 05:52

Мне очень нравится объяснение от SCJP Sun Certified Programmer for Java 5 Study Guide.

To make Java more memory efficient, the JVM sets aside a special area of memory called the "String constant pool." When the compiler encounters a String literal, it checks the pool to see if an identical String already exists. If a match is found, the reference to the new literal is directed to the existing String, and no new String literal object is created.

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

Zan Lynx 11.11.2008 06:00

Неизменяемый объект - это объект, который нельзя изменить после его создания. Типичный пример - строковые литералы.

В языке программирования D, который становится все более популярным, есть понятие «неизменяемость» через ключевое слово «инвариант». Посмотрите статью об этом доктора Добба - http://dobbscodetalk.com/index.php?option=com_myblog&show=Invariant-Strings.html&Itemid=29. Это прекрасно объясняет проблему.

Я действительно считаю, что с D 2.020 ключевое слово было изменено с неизменного на неизменяемое. Я не вижу в этом смысла, но там сказано: «Сейчас реализовано неизменное». digitalmars.com/d/2.0/changelog.html#new2_020

he_the_great 11.11.2008 03:50

Состояние неизменяемых объектов не может быть изменено после создания.

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

  • Намного легче понять, как работает ваша программа, если вы знаете, что состояние объекта не может быть изменено другим методом.
  • Неизменяемые объекты автоматически являются потокобезопасными (при условии, что они опубликованы безопасно), поэтому никогда не будут причиной этих труднопоказываемых ошибок многопоточности.
  • Неизменяемые объекты всегда будут иметь один и тот же хэш-код, поэтому их можно использовать в качестве ключей в HashMap (или аналогичном). Если бы хэш-код элемента в хеш-таблице должен был измениться, запись в таблице была бы потеряна, поскольку попытки найти ее в таблице будут искать не в том месте. Это основная причина того, что объекты String неизменяемы - они часто используются в качестве ключей HashMap.

Есть также некоторые другие оптимизации, которые вы могли бы сделать в коде, когда знаете, что состояние объекта неизменяемо - например, кэширование вычисленного хэша - но это оптимизации и, следовательно, не так уж и интересны.

На самом деле String не является неизменным, если вы используете определение из Википедии, предложенное выше.

Состояние строки меняет конструкцию поста. Взгляните на метод hashcode (). String кэширует значение хэш-кода в локальном поле, но не вычисляет его до первого вызова hashcode (). Эта ленивая оценка хэш-кода помещает String в интересное положение как неизменяемый объект, состояние которого изменяется, но его нельзя наблюдать без использования отражения.

Так что, возможно, определение неизменяемого должно быть объектом, изменение которого невозможно наблюдать.

Если состояние неизменяемого объекта изменяется после его создания, но никто не может его увидеть (без отражения), остается ли объект неизменным?

Хорошая идея - объект, который нельзя увидеть как изменившийся, а также невозможно изменить его извне. Частное поле для hashCode () - это внутреннее изменение, которое не является существенным для внешнего видимого состояния объекта.

mparaz 22.02.2009 18:55

На самом деле следует заметить, что может изменился, если вы используете отражение. См. Больше на сайте Sedgewick's Строки изменяемы, если вы разрешаете отражение.

Miguel 04.07.2013 12:42

Неизменяемый объект - это объект, внутренние поля которого (или, по крайней мере, все внутренние поля, влияющие на его внешнее поведение) не могут быть изменены.

У неизменяемых строк есть много преимуществ:

Представление: Выполните следующую операцию:

String substring = fullstring.substring(x,y);

Базовый C для метода substring (), вероятно, выглядит примерно так:

// Assume string is stored like this:
struct String { char* characters; unsigned int length; };

// Passing pointers because Java is pass-by-reference
struct String* substring(struct String* in, unsigned int begin, unsigned int end)
{
    struct String* out = malloc(sizeof(struct String));
    out->characters = in->characters + begin;
    out->length = end - begin;
    return out;
}

Обратите внимание, что ни один из символов не должен копироваться! Если бы объект String был изменяемым (символы могли измениться позже), вам пришлось бы скопировать все символы, иначе изменения символов в подстроке будут отражены в другой строке позже.

Параллелизм: Если внутренняя структура неизменяемого объекта действительна, она всегда будет действительной. Нет никаких шансов, что разные потоки могут создать недопустимое состояние внутри этого объекта. Следовательно, неизменяемые объекты - это Поток Безопасный.

Вывоз мусора: Сборщику мусора намного проще принимать логические решения относительно неизменяемых объектов.

Однако у неизменяемости есть и обратные стороны:

Представление: Подождите, я думал, вы сказали, что производительность - это преимущество неизменности! Иногда бывает, но не всегда. Возьмите следующий код:

foo = foo.substring(0,4) + "a" + foo.substring(5);  // foo is a String
bar.replace(4,5,"a"); // bar is a StringBuilder

В обеих строках четвертый символ заменяется буквой «а». Второй фрагмент кода не только читабельнее, но и быстрее. Посмотрите, как вам нужно сделать базовый код для foo. Подстроки просты, но теперь, поскольку уже есть символ в пятом месте и что-то еще может ссылаться на foo, вы не можете просто изменить его; вам нужно скопировать всю строку (конечно, некоторые из этих функций абстрагируются в функции в реальном базовом C, но суть здесь в том, чтобы показать код, который выполняется в одном месте).

struct String* concatenate(struct String* first, struct String* second)
{
    struct String* new = malloc(sizeof(struct String));
    new->length = first->length + second->length;

    new->characters = malloc(new->length);

    int i;

    for(i = 0; i < first->length; i++)
        new->characters[i] = first->characters[i];

    for(; i - first->length < second->length; i++)
        new->characters[i] = second->characters[i - first->length];

    return new;
}

// The code that executes
struct String* astring;
char a = 'a';
astring->characters = &a;
astring->length = 1;
foo = concatenate(concatenate(slice(foo,0,4),astring),slice(foo,5,foo->length));

Обратите внимание, что объединение называется дважды, что означает, что вся строка должна быть пропущена по циклу! Сравните это с кодом C для операции bar:

bar->characters[4] = 'a';

Операция с изменяемой строкой, очевидно, намного быстрее.

В заключение: В большинстве случаев вам нужна неизменяемая строка. Но если вам нужно много добавлять и вставлять в строку, вам нужна изменчивость для скорости. Если вам нужны преимущества безопасности параллелизма и сборки мусора, ключевым моментом является сохранение ваших изменяемых объектов локальными по отношению к методу:

// This will have awful performance if you don't use mutable strings
String join(String[] strings, String separator)
{
    StringBuilder mutable;
    boolean first = true;

    for(int i = 0; i < strings.length; i++)
    {
        if (!first) first = false;
        else mutable.append(separator);

        mutable.append(strings[i]);
    }

    return mutable.toString();
}

Поскольку объект mutable является локальной ссылкой, вам не нужно беспокоиться о безопасности параллелизма (только один поток когда-либо касается его). И поскольку на него больше нигде нет ссылок, он выделяется только в стеке, поэтому он освобождается, как только вызов функции завершается (вам не нужно беспокоиться о сборке мусора). И вы получаете все преимущества в производительности как изменчивости, так и неизменяемости.

Отличное чтение! только одно, я думаю, это должно быть, если (во-первых), а не если (! во-первых)

Siddhartha 27.10.2012 08:50

Необходимо не то, чтобы поля были неизменяемыми, а скорее, чтобы определенное наблюдаемое состояние объекта было неизменным; объект, содержащий ссылку на другой объект как средство инкапсуляции состояния, содержащегося в нем, может быть неизменным только в том случае, если все инкапсулированные аспекты состояния, которые он предоставляет внешнему миру, также неизменны. Обратите внимание на то, что поля неизменяемых типов не являются ни обязательными, ни достаточными. Что важно, так это видимое состояние.

supercat 07.01.2014 01:19
Passing pointers because Java is pass-by-reference Разве java не является «передачей по значению»?
Cristian Gutu 02.10.2014 05:31

@CristianGutu, да, вы правы, JAVA - это "передача по значению", а не "передача по ССЫЛКЕ"

Arsh Kaushal 16.05.2017 10:15

Ссылка передается как значение !!

devv 15.01.2019 04:47
  1. В больших приложениях строковые литералы обычно занимают большие биты памяти. Таким образом, чтобы эффективно обрабатывать память, JVM выделяет область, называемую «Пул констант строк». (Обратите внимание, что в памяти даже строка без ссылки содержит char [], int для ее длины и еще один для своего hashCode. Для числа, напротив, требуется не более восьми непосредственных байтов.)
  2. Когда компилятор встречает строковый литерал, он проверяет пул, чтобы увидеть, есть ли уже идентичный литерал. И если он найден, ссылка на новый литерал направляется на существующую строку, и новый «объект строкового литерала» не создается (существующая строка просто получает дополнительную ссылку).
  3. Следовательно: Изменчивость строк экономит память ...
  4. Но когда какая-либо из переменных меняет значение, на самом деле - изменяется только их ссылка, а не значение в памяти (следовательно, это не повлияет на другие переменные, ссылающиеся на нее), как показано ниже ...

Строка s1 = «Старая строка»;

//s1 variable, refers to string in memory
        reference                 |     MEMORY       |
        variables                 |                  |

           [s1]   --------------->|   "Old String"   |

Строка s2 = s1;

//s2 refers to same string as s1
                                  |                  |
           [s1]   --------------->|   "Old String"   |
           [s2]   ------------------------^

s1 = «Новая строка»;

//s1 deletes reference to old string and points to the newly created one
           [s1]   -----|--------->|   "New String"   |
                       |          |                  |
                       |~~~~~~~~~X|   "Old String"   |
           [s2]   ------------------------^

The original string 'in memory' didn't change, but the reference variable was changed so that it refers to the new string. And if we didn't have s2, "Old String" would still be in the memory but we'll not be able to access it...

java.time

Возможно, это немного поздно, но чтобы понять, что такое неизменяемый объект, рассмотрим следующий пример из нового API даты и времени Java 8 (java.time). Как вы, наверное, знаете, все объекты даты из Java 8 - это неизменный, поэтому в следующем примере

LocalDate date = LocalDate.of(2014, 3, 18); 
date.plusYears(2);
System.out.println(date);

Выход:

2014-03-18

Это печатает тот же год, что и начальная дата, потому что plusYears(2) возвращает новый объект, поэтому старая дата остается неизменной, потому что это неизменяемый объект. После создания вы не можете вносить в него дальнейшие изменения, и переменная даты по-прежнему указывает на него.

Итак, этот пример кода должен захватывать и использовать новый объект, созданный и возвращенный этим вызовом plusYears.

LocalDate date = LocalDate.of(2014, 3, 18); 
LocalDate dateAfterTwoYears = date.plusYears(2);

date.toString()… 2014-03-18

dateAfterTwoYears.toString()… 2016-03-18

String s1 = "Hi";
String s2=s1;
s1 = "Bye";

System.out.println(s2); //Hi  (if String was mutable output would be: Bye)
System.out.println(s1); //Bye

s1 = "Hi": был создан объект s1 со значением «Hi» в нем.

s2=s1: объект s2 создается со ссылкой на объект s1.

s1 = "Bye": значение предыдущего объекта s1 не изменяется, потому что s1 имеет тип String, а тип String является неизменяемым типом, вместо этого компилятор создает новый объект String со значением «Bye» и ссылкой на s1. здесь, когда мы печатаем значение s2, результатом будет «Hi», а не «Bye», потому что s2 ссылался на предыдущий объект s1, который имел значение «Hi».

не могли бы вы добавить небольшое пояснение?

minigeek 01.06.2017 10:44

Неизменяемые объекты

Объект считается неизменным, если его состояние не может измениться после создания. Максимальное использование неизменяемых объектов широко признано разумной стратегией создания простого и надежного кода.

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

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

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

Источник

Неизменяемые просто означают неизменяемые или неизменяемые. После создания строкового объекта его данные или состояние не могут быть изменены

Рассмотрим нижеприведенный пример.

class Testimmutablestring{  
  public static void main(String args[]){  
    String s = "Future";  
    s.concat(" World");//concat() method appends the string at the end  
    System.out.println(s);//will print Future because strings are immutable objects  
  }  
 }  

Давайте рассмотрим схему ниже,

На этой диаграмме вы можете увидеть новый объект, созданный как «Мир будущего». Но не меняем "Будущее" .Because String is immutable. s, до сих пор относятся к «Будущему». Если вам нужно вызвать в «Мир будущего»,

String s = "Future";  
s=s.concat(" World");  
System.out.println(s);//print Future World

Почему строковые объекты неизменяемы в Java?

Because Java uses the concept of string literal. Suppose there are 5 reference variables, all refers to one object "Future".If one reference variable changes the value of the object, it will be affected to all the reference variables. That is why string objects are immutable in java.

Поскольку принятый ответ отвечает не на все вопросы. Я вынужден дать ответ через 11 лет и 6 месяцев.

Can somebody clarify what is meant by immutable?

Надеюсь, вы имели в виду неизменный объект (потому что мы могли подумать о неизменная ссылка).

Объект - это неизменный: если однажды они были созданы, они всегда представляют одно и то же значение (не имеют метода, изменяющего значение).

Why is a String immutable?

Соблюдайте приведенное выше определение, которое можно проверить, просмотрев исходный код Sting.java.

What are the advantages/disadvantages of the immutable objects? immutable types are :

  • безопаснее от ошибок.

  • легче понять.

  • и многое другое готово к переменам.

Why should a mutable object such as StringBuilder be preferred over String and vice-verse?

Сужение вопроса Зачем нам в программировании нужен изменяемый StringBuilder? Обычно его используют для объединения большого количества строк, например:

String s = "";
for (int i = 0; i < n; ++i) {
    s = s + n;
}

При использовании неизменяемых строк создается множество временных копий - первое число строки («0») фактически копируется n раз в процессе построения последней строки, второе число копируется n-1 раз, и поэтому на. На самом деле просто копирование занимает O (n2) времени, хотя мы объединили только n элементов.

StringBuilder разработан, чтобы минимизировать это копирование. Он использует простую, но продуманную внутреннюю структуру данных, чтобы избежать копирования до самого конца, когда вы запрашиваете последнюю строку с помощью вызова toString ():

StringBuilder sb = new StringBuilder();
for (int i = 0; i < n; ++i) {
  sb.append(String.valueOf(n));
}
String s = sb.toString();

Хорошая производительность - одна из причин, по которой мы используем изменяемые объекты. Другой - удобный совместный доступ: две части вашей программы могут более удобно взаимодействовать, разделяя общую изменяемую структуру данных.

Больше можно найти здесь: https://web.mit.edu/6.005/www/fa15/classes/09-immutability/#useful_immutable_types

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