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

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

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

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

Комментарии к вопросу (5)
Решение

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

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

например

class Foo
{
     private final String myvar;

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

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

Фу не'т придется беспокоиться, что абонент `и getValue () может менять текст в строке.

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

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

Комментарии (13)

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

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

Производительность: выполнить следующие работы:

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, были изменяемы (персонажей можно поменять позже), то вам придется скопировать все символы, в противном случае изменения символов в подстроке будут отражены в другой строке позже.

Параллелизм: если внутренняя структура неизменный объект является действующим, он всегда будет действителен. Там's нет шансов, что разные потоки могут создавать недопустимое состояние этого объекта. Таким образом, неизменяемые объекты потокобезопасным.

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

Однако, есть и минусы в неизменности:

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

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

Две линии как заменить четвертый символ с буквой "А". Не только вторая часть код более читабельным, это's быстрее. Смотреть на то, как вы должны сделать основной код для Foo. Подстроки легко, но сейчас, потому что там's уже персонажа в пространстве пяти и что-то еще может быть привязка Фу, Вы можете'т сделать это, вам нужно скопировать всю строку (конечно, некоторые из этих функций отводится в функциями в реальный базовый 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->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();
}

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

Комментарии (5)

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

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

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

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

Комментарии (2)

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

Просто чтобы прояснить, однако, то StringBuilder на самом деле является изменяемый объект, не является неизменным одно. Обычное Java строка является неизменным (т. е. как только он'был создан вы не сможете изменить основные строки без изменения объекта).

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

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

Затем вы ожидаете строку, чтобы всегда быть quot&; Синий и". Однако, если другой поток, ухватился за этот экземпляр и называется

blueString.setColor("Red");

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

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

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

Строки S1 = "Старый строку на";

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

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

Строка С2 = С1;

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

С1 = "в новую строку и";

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

исходную строку 'на память' Я'т изменение, но ссылка на переменную был изменен так, что он ссылается на новую строку. И если мы не'т иметь С2, "Старый строку" и остались бы в памяти, но мы'll быть не в состоянии получить доступ к его...

Комментарии (0)

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


String foo = "Hello";
foo.substring(3);
Комментарии (0)

и Java.время

Это может быть немного поздно, но для того, чтобы понять, что неизменяемый объект, рассмотрим следующий пример из новой Java 8 дата и время API (Ява.время). Как вы, наверное, знаете все объекты Date в 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);

дата.метод toString()... 2014-03-18

dateAfterTwoYears.метод toString()... 2016-03-18

Комментарии (0)

Мне очень нравится объяснение от [SCJP, сертифицированный Sun программист для изучения языка Java 5 руководство][1].

Чтобы сделать эффективную Java больше памяти, то JVM выделяет специальную область памяти называют "строковую константу бассейн." когда компилятор обнаруживает строковый литерал, он проверяет бассейн, чтобы увидеть, если идентичная строка уже существует. Если совпадение найдено, ссылка на новый литерал направлено на существующую строку, а не создается новый строковый литерал объекта.

[1]: http://www.amazon.com/Certified-Programmer-310-055-Certification-Guides/dp/0072253606/ref=pd_bbs_sr_2?ie=UTF8&s=books&=&amp 1226363595 qid;sr=8-2

Комментарии (1)

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

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

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

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

Комментарии (0)

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

Комментарии (0)
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

С1=С"Привет" в : объект С1 был создан с "Привет" и значение в нем.

С2=С1 : объект С2 создается со ссылкой на объект С1.

С1=С"До свидания" в : предыдущий С1 объект's стоимостью не't изменить, потому что С1 имеет тип String и тип String-это неизменяемый тип, вместо компилятора создайте новый строковый объект с "прощай" в значении и С1 обратилась к нему. вот когда мы печатаем С2 значение, результат будет "Привет и" не то "До свидания" и потому что С2 ссылается на предыдущие С1 объект, который был когда-то "Привет" и значение.

Комментарии (1)

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

Рассмотрим пример ниже,

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

Позвольте'ы вам идея, учитывая схему ниже,

На этой диаграмме можно увидеть созданный новый объект как "Мир будущего" и. Но не менять "на будущее" и.Потому что string является неизменяемым``. С, до сих пор ссылаются на "Будущее" по. Если вам нужно называют "Мир будущего" и,

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

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

потому что Java использует понятие строкового литерала. Предположим, есть 5 ссылочные переменные, все относится к одному объекту "в будущем" по.Если ссылочная переменная изменяет значение объекта, он будет влиять на все ссылочные переменные. Вот почему строковые объекты являются неизменными в Java.

Комментарии (0)

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

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

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

Комментарии (0)

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

Комментарии (0)

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

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

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

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

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

Источник

Комментарии (0)

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

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

[1]: http://dobbscodetalk.com/index.php?option=com_myblog&показать=инвариант-струны.HTML-код&атрибут Itemid=29

Комментарии (1)