Вопрос

Являются ли все конечные классы в Java неизменяемыми.String и Integer оба являются конечными классами, и я полагаю, что оба они неизменяемы.

Это было полезно?

Решение

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

public final class FinalMutable {
  int value;
  public void setValue(int v) { value=v; }
  public int getValue() { return value; }
}

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

Нет, final означает, что класс не может быть расширен. Это ничего не говорит о изменчивости. Например:

final class MutInt {
   public int modifyMe;
}

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

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

Самое запутанное заключается вот в чем:Ключевое слово final имеет разные значения при использовании в классе, чем при использовании в поле / переменной.Первое означает "этот класс не может быть расширен".Второе означает "эта переменная (или ссылка) не может быть изменена".

В дополнение к другим ответам, если вы посмотрите на код для java.lang.String , вы увидите, что он содержит поле: hash , которое является mutable и фактически вычисляется и сохраняется при первом вызове hashCode () .

Однако класс по-прежнему неизменен : поле hash не может быть доступно напрямую или изменено за пределами класса.

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

private final List<String> values;

public List<? get String> getValues() {
  return Collections.unmodifiableList(values);
}

Как уже было сказано другими ранее final не делает класс imuutable в Java, хотя он играет определенную роль в стратегии неизменяемости.Чтобы получить неизменяемость, вы должны следовать общим рекомендациям:

  • убедитесь, что класс не может быть переопределен - создайте класс final, или используйте статические фабрики и сохраняйте конструкторы закрытыми
  • создавать поля private и final
  • заставлять вызывающих создавать объект полностью за один шаг, вместо использования конструктора без аргументов в сочетании с последующими вызовами setXXX методы (то есть избегайте соглашения Java Beans)
  • не предоставляйте никаких методов, которые могут каким-либо образом изменить состояние объекта - не только setXXX методы, но любой метод, который может изменять состояние
  • если в классе есть какие-либо изменяемые поля объекта, то они должны быть скопированы в целях защиты при передаче между классом и его вызывающим объектом

Закрытое поле не может быть доступно переопределенным методам подкласса ... Так что методы подкласса не могут изменить закрытое поле суперкласса ... Тогда какой смысл делать неизменяемый класс финальным

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

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

// a class not intended to be mutated 
public class GoodClass{

   private String name;

   public GoodClass() {
       this.name = "Good Class Neme";
   }

   public String getName() {
       return name;
   }
}

public class BadClass extends GoodClass {

   private String name;

   public String getName() {
       return name;
   }

   // mutating state
   public void setName(String name) {
       this.name = name;
   }
}



Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top