В чем разница между неизменяемым и окончательным в java?

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

Например

Конечный и неизменный:

final String name = "John";

если я сейчас напишу

name = "Sam";

Я получу ошибку компилятора

Неизменный:

String name = "John";
name = "Sam"; 

оно работает.

Я думаю, это объясняет его часть в приложении. Но могу ли я получить хорошее, легко понятное объяснение по обеим темам?

Ответ 1

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

Что касается второй части вашего вопроса (неотменяемости), компилятор создает новый объект String со значением "Sam" и указывает на него ссылку на name.

Ответ 2

final убедитесь, что адрес объекта остается неизменным. Где, как Immutable предполагает, что мы не можем изменить состояние объекта после его создания.

final - это просто ключевое слово, в то время как Immutable - образец.

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

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

Ответ 3

окончательный

Объект нельзя изменить.

final String s = "Hello";
// Not allowed.
s = "Bye";

неизменный

Содержимое объекта не может быть изменено.

BigInteger one = BigInteger.ONE;
// Does not change 'one' or 'BigInteger.ONE'.
one.add(BigInteger.ONE);
// Have to do it this way.
BigInteger two = one.add(one);

Ответ 4

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

если объект не является immutable, методы на нем могут быть использованы для изменения самого объекта - это тот же объект, но его свойства были изменены.

Ответ 5

Неизменяемость: http://www.programcreek.com/2009/02/diagram-to-show-java-strings-immutability/

при изменении String создайте новый объект String ('abcdef') и измените ссылку с 'abce' на 'abcdef'. Но вы не можете удалить 'abcd'. Только измените ссылку. Это непреложно.

окончательный:

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

Ответ 6

Когда вы используете ключевое слово "final", это означает, что вы не можете изменить ссылку объекта, на который указывает переменная. Таким образом, в этом случае переменная "name" не может быть указана на другой строковый объект. Однако обратите внимание, что мы можем изменить содержимое объекта, так как мы используем окончательную ссылку. Также строки в java по своей сути неизменяемы. т.е. вы не можете изменить его содержимое. Итак, в вашем случае окончательный окончательный ссылка на строковый объект. и поскольку вы не можете изменить переменную, чтобы указать на другой объект строки, код не работает.

См. Код ниже, чтобы понять работу конечной переменной.

public class test {

public static void main(String[] args) {
    final A aObject = new A();
    System.out.println("Old value :" + aObject.a);
    aObject.a = 2;
    System.out.println("New value :" + aObject.a);
}} 

class A {
public int a = 1;}

Ответ 7

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

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

например

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.

final - зарезервированное ключевое слово в Java для ограничения пользователя и его можно применять к переменным-членам, методам, классам и локальным переменным. Заключительные переменные часто объявляются с ключевым словом static в Java и рассматриваются как константы. Например:

public static final String hello = "Hello"; Когда мы используем ключевое слово final с объявлением переменной, значение, хранящееся внутри этой переменной, не может быть изменено последним.

Например:

public class ClassDemo {
  private final int var1 = 3;
  public ClassDemo() {
    ...
  }
}

Примечание. Класс, объявленный как final, не может быть расширен или унаследован (т.е. Не может быть подкласса суперкласса). Также полезно отметить, что методы, объявленные как final, не могут быть переопределены подклассами.

Преимущества использования ключевого слова final рассматриваются в этом потоке

Ответ 8

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

String s1 = new String("cant't change");

Финал: когда мы создаем ссылку на String

Final String s2 = "cant't change";

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

Ссылка s теперь всегда указывает на значение объекта, которое не может быть изменено. Эта ссылка не может быть изменена.

Ответ 9

final String name = "John";

Когда вы пишете выше, ваш код сообщает компилятору, что name ссылки всегда будет указывать на одно и то же место в памяти. Теперь, почему я говорю "расположение в памяти", потому что может случиться так, что объект, на который указывает ссылка, изменчив, как массив или список целых чисел. Так что, если я скажу final int[] arr = {5,6,1}; Я могу сделать arr[2] = 3; но я не могу сделать arr = {3,4,5} потому что вы будете пытаться назначить новую переменную int[] для конечной переменной arr которая является новой ячейкой памяти, и если этот компилятор покажет ошибку.

String name = "John";
name = "Sam"; 

Над name переменная типа String является неизменяемой, потому что String в java является immutable что означает, что вы не можете изменить состояние объекта, на которое указывает ссылочное name после его создания, и даже если вы измените его на Sam это теперь другой объект, на который указывает ссылочное name и предыдущий объект John будет иметь ссылки и может быть собран сборщиком мусора всякий раз, когда он запускается, если у него нет других ссылок, указывающих на него.