2013-05-20 5 views
2

Я хотел бы создать несколько неизменяемых объектов для моей кодовой базы. Каков наилучший способ действительно доставить сообщение, что данный класс предназначен для неизменяемости? Должен ли я сделать все мои поля окончательными и инициализировать во время построения объекта? (Это кажется действительно неудобным ...) Должен ли я создать какой-то неизменяемый интерфейс и реализовать его объекты? (Поскольку у Java нет стандартного интерфейса, я думал, что у них есть другой способ справиться с этим.) Каков стандартный способ, с которым это связано? (Если это просто сделать, добавив кучу комментариев вокруг поля восклицая, что они не должны быть изменены после инициализации, это тоже хорошо.)Создание неизменяемых объектов в Java

+1

Что именно вас беспокоит? Разве ваши коллеги не поймут и изменят ваш класс, чтобы сделать его изменчивым? –

+0

да, точно. Я боюсь, что люди, которые видят код в будущем, не будут в полной мере осознавать тот факт, что дизайн класса был тем, что он неизменен, и они могут создавать сеттеры для будущего и т. Д. – Sal

ответ

7

Должен ли я сделать все мои полей конечных и инициализировать в процессе строительства объекта ?

Да. И убедитесь, что эти типы сами по себе являются неизменными или что вы создаете копии, когда возвращаете значения из методов getter. И сделайте сам класс окончательным. (В противном случае ваш класс сам по себе может быть неизменен, но это не означает, что любой экземпляр вашего класса будет неизменен. - потому что это может быть экземпляром изменяемого подкласса)

(Это, кажется, очень неудобно ...)

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

Foo foo = Foo.newBuilder() 
    .setName("asd") 
    .setPoints(10) 
    .setOtherThings("whatever") 
    .build(); 
+2

+1 для 'И убедитесь, что эти типы сами по себе неизменяемы'. Что вы скажете об неизменяемом интерфейсе или аннотации в метаданных, похожих на интерфейс Serializable? – Craig

+1

@ Craig, о котором вы думаете [это] (http://jsr-305.googlecode.com/svn/trunk/javadoc/javax/annotation/concurrent/Immutable.html). –

+0

Спасибо, Джон, это ответ на мой вопрос. Чтобы ответить на ваш вопрос, я просто нашел, что каждое поле окончательно неловко, потому что я обычно не вижу этого в коде, который я видел до сих пор. – Sal

5

Да и нет. Создание всех полей в финале не является гарантией само по себе. Если вы хотите получить подробную информацию об этом, в главе «Эффективная Ява» Джошуа Блоха есть ряд глав, посвященных неизменности и соображениям. Пункт 15 в «Эффективной Java» охватывает основную часть и ссылается на другие элементы, о которых идет речь.

Он предлагает пять шагов:

  1. Не предоставляют каких-либо методов, которые изменяют состояние объекта (известный как muta- ров).

  2. Убедитесь, что класс не может быть расширен.

  3. Сделать все поля окончательными.

  4. Сделать все поля частными.

  5. Обеспечить эксклюзивный доступ к любым изменяемым компонентам.

Один из способов узнать, как сделать все это, чтобы увидеть, как разработчики языка делают классы неизменные, просмотрев исходный код для классов, как String, которые являются неизменяемыми (например, см http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/String.java).

+1

Что означает эта пятая маркерная точка? –

+1

Вот что написал Джошуа Блох в «Эффективной Java» о пятой марке: «Если ваш класс имеет любые поля , относящиеся к изменяемым объектам, убедитесь, что клиенты класса не могут получить ссылки на эти объекты. Никогда не инициализируйте такое поле объекту, предоставленному клиентом , ссылку или возврат ссылки на объект от аксессуара. – andreih

+1

Это также известно как создание * защитных копий *. –

1

Напишите единичный тест, который потерпит неудачу, если ваши коллеги сделают класс изменчивым.

Используя Mutability Detector, вы можете написать тест, как это:

import static org.mutabilitydetector.unittesting.MutabilityAssert.assertImmutable; 

@Test public void isImmutable() { 
    assertImmutable(MyImmutableThing.class) 
} 

Если Коллега приходит, и, например, добавляет метод установки в класс, тест проваливается. Ваш прецедент является одной из основных целей детектора Mutability Detector.

Отказ от ответственности: Я написал его.

Смежные вопросы