Может ли класс (экземпляр класса), содержащий переменную объекта Random, быть неизменным? - PullRequest
4 голосов
/ 08 августа 2011

Определение неизменяемости гласит, что состояние объекта (его данных) не может быть изменено после построения.

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

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

Скажите, если это правильно:

final class Obj1 {
 private final  int i; 
 private final  Random rnd = new Random();
 private int j = rnd.nextInt(1000);
 public Obj1(int i) {
   this.i = i;
  }  
 public getI() {
  j = rnd.nextInt(1000);
  return i;
 }
}

Экземпляр Obj1 является неизменным объектом.

final class Obj2 {
 private final int i; 
 private final Random rnd = new Random();
 private int j = rnd.nextInt(1000);
 public Obj1(int i) {
   this.i = i;
 }  
 public getI() {
   return i;
 }
 public getJ() {
   return j;
 }
}

Является ли экземпляр Obj2 изменяемым или неизменным объектоми почему?Что если мы получим следующий объект Random в теле getJ каждый раз, когда вызывается геттер?

А что насчет такого класса?Изменчивый / неизменный и почему?

final class Obj3 {
 private final  Random rnd = new Random();
 private int j = rnd.nextInt(1000);
 public Obj1() {
  }  
 public getJ() {
   return j;
 }
}

А как насчет этого?Изменчивый / неизменный и почему?

final class Obj4 {
 private final Random rnd = new Random();
 public Obj1() {
  }  
 public getRnd() {
   return rnd.nextInt(1000);
 }
}

Ответы [ 3 ]

7 голосов
/ 08 августа 2011

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

Очень хорошим примером является java.lang.String, который часто цитируется как канонический пример для неизменного класса. У него есть одно не final поле, которое hash. hash содержит хэш-код, но по умолчанию 0. Хэш-код вычисляется лениво при первом вызове и кэшировании hashCode() в этом поле. Таким образом, внутреннее состояние объекта String может измениться, но состояние наблюдаемое никогда не изменится (потому что hashCode() всегда возвращает одно и то же значение, независимо от того, вычислено ли оно или просто возвращает кэшированное значение).

Это означает, что первые три предоставленных вами сэмпла (Obj1, Obj2, Obj3) являются неизменяемыми: у них нет установщика, и ничто иное не может изменить значение, возвращаемое их методами после построения (это будет хорошая идея объявить поля final, но это не является обязательным требованием для неизменности). Также обратите внимание, что вы также можете полностью исключить поле Random в этих классах, так как оно все равно не используется после построения.

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

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

0 голосов
/ 14 августа 2012

Совершенно законно, что неизменяемый объект может содержать и даже предоставлять ссылки на объекты произвольного типа, если ссылки распознаются как , идентифицирующие , а не , содержащие , объекты обсуждаемый. Например, рассмотрите ссылку на объект как аналог VIN (идентификационный номер транспортного средства - буквенно-цифровую строку, которая однозначно идентифицирует транспортное средство, по крайней мере, произведенное в США или импортированное в США), и представьте, что ремонтная мастерская может сохранить список VIN-адресов автомобилей, которые он обслуживал. Сами автомобили вряд ли можно отнести к неизменным объектам, но в списке не будет машин - он будет идентифицировать автомобилей. Нельзя было смотреть на VIN и знать, какого цвета была машина, когда ее обслуживали, но когда машина заходит в магазин, можно использовать список VIN, чтобы определить, посещал ли автомобиль раньше.

0 голосов
/ 08 августа 2011

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

  • Вы можете передать их по ссылке и быть уверенным, что никто не изменит их состояние;
  • Вам не нужно думать о синхронизации;
  • Более безопасно использовать в качестве ключей в хэш-картах.

Я бы не объявил объект неизменным, если он меняет свое состояние после построения, даже если ему нужны сеттеры.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...