2017-02-23 73 views
1

Рассматривают следующий кодс StringBuffer, как достичь 100% неизменности. Я хочу сделать это только с помощью stringbuffer. ни один другой тип данных

final class immudemo 
{ 
     private static final StringBuffer bf = new StringBuffer("Yaxita"); 
     public StringBuffer getter() 
     { 
      return bf; 
     } 
} 

public class HelloWorld{ 

    public static void main (String args[]) 
    { 
     immudemo obj1 = new immudemo(); 
     StringBuffer bf2 = obj1.getter(); 
     bf2.append("Shah"); 
     System.out.println(obj1); 
    } 
} 

в коде выше, даже если StringBuffer объявлен как окончательный я могу изменить его. Может ли кто-нибудь помочь мне, как достичь 100% неизменности?

P.S. : Я хочу достичь этого с помощью StringBuffer только. Если вы предоставите что-либо, пожалуйста, проверьте, что он должен быть связан только с StringBuffer.

+2

Erm, используйте String, а не Stringbuffer? Я имею в виду, что это точка Stringbuffer, что она изменена в отличие от обычных строк. Изменить: кроме этого, нет операции, чтобы сделать изменяемый класс неизменным. Если вы хотите, чтобы класс был неизменным, он должен быть запрограммирован именно так. Но я до сих пор не понимаю, какова точка неизменяемого StringBuffer. –

+0

это правильно .. но меня попросили сделать это только с StringBuffer. Вопросник хотел знать, как я могу создать пользовательский класс, который на 100% неизменен. –

+1

@YaxitaShah, как вы упомянули в своем комментарии. «Вопросник хотел знать, как я могу создать определенный пользователем класс, который на 100% неизменен». Он хотел знать, как создать собственный класс с такой же функциональностью, как и для класса String, и как вы достигнете непреложности в нем. –

ответ

2

С окончательным вы определяете, что вы не можете установить другой объект в "bf". Статус самого объекта по-прежнему можно изменить, если он изменен. Это относится к StringBuffer. И поскольку вы отпустите его снаружи «getter», ваш класс «immudemo» также изменен.

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

Поэтому ваш класс «immudemo» будет неизменен, если вы возвращаете тип String, вместо StringBuffer вашего метода «геттер».

class immudemo 
{ 
     private static final StringBuffer bf = new StringBuffer("Yaxita"); 
     public String getter(){ 
      return bf.toString(); 
     } 
} 

public class HelloWorld{ 

    public static void main (String args[]) 
    { 
     immudemo obj1 = new immudemo(); 
     String bf2 = obj1.getter(); 
     bf2.append("Shah"); // does not work anymore 
     System.out.println(obj1); 
    } 
} 

Дополнительно: Следуйте эту стратегию, чтобы определить неизменные объекты сам: https://docs.oracle.com/javase/tutorial/essential/concurrency/imstrat.html

+0

В этой ссылке нет ничего о stringbuffer –

+0

Нет, потому что StringBuffer не является неизменным. Это общая стратегия. Посмотрите на мой ответ еще раз. Я добавил возможное исправление внизу. – cybi

+1

Но что вы имеете в виду под "StringBuffer only"? Если у вас есть изменяемый объект внутри другого объекта, а внешний объект публикует изменяемый объект методом, вы не можете достичь 100% неизменности. Чтобы достичь 100% неизменности, вам нужно вернуть неизменяемый объект, даже если ваши внутренние объекты изменяемы. Поэтому самым простым решением было бы вернуть String «getter». – cybi

2

YaxitaShah, в этом случае, StringBuffer объявлен как окончательные, но ссылки StringBuffer проходит через метод получения в классе immudemo;

может быть, вы можете:

final class immudemo 
 
{ 
 
     private static final StringBuffer bf = new StringBuffer("Yaxita"); 
 
     public StringBuffer getter(){ 
 
      return new StringBuffer(bf); 
 
     } 
 
     
 
     public String toString() { 
 
    \t return bf.toString(); 
 
     } 
 
} 
 

 
public class HelloWorld{ 
 

 
    public static void main (String args[]) 
 
    { 
 
     immudemo obj1 = new immudemo(); 
 
     StringBuffer bf2 = obj1.getter(); 
 
     bf2.append("Shah"); 
 
     System.out.println(obj1); 
 
    } 
 
}

1

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

Нет, append() не создает новый объект вашего Stringbuffer, просто изменив значение одного и того же упомянутого объекта.

Смотрите Java ИЕ final variable, который говорит,

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

Таким образом, Неизменный класс может быть с помощью,

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