В чем преимущество POJO?

В моем проекте есть небольшая структура данных Key.

public class Key implements Serializable {

  private static final long serialVersionUID = 1L;

  public String db;
  public String ref;
  public Object id;

  protected Key() {
  }

  public Key(String db, String ref, Object id) {
    this.db = db;
    this.ref = ref;
    this.id = id;
  }
}

Да, этот класс прост, и каждое поле общедоступно.

Но кто-то предложил мне вместо этого использовать классы стиля POJO, но когда я спросил, почему они не могут мне сказать.

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

Так почему я должен использовать стиль программирования POJO?


person jackalope    schedule 05.01.2013    source источник
comment
вызов метода получения и установки работает медленнее, чем поле прямого доступа. неверная информация. Непосредственное манипулирование переменными - очень плохая идея. Представьте, что в коде можно установить age = -11111; что плохо. Если у вас есть геттер / сеттер, вы можете проверить недопустимые значения перед установкой значения в поля.   -  person Pradeep Simha    schedule 05.01.2013
comment
если значения неизменяемы, вы можете сделать их final, чтобы предотвратить установку недопустимых значений.   -  person jlordo    schedule 05.01.2013
comment
@PradeepSimha Вы правы, финальные поля могут быть хорошей идеей. Я думаю, что нужно платить за каждую плохую вещь, которую они сделали, например, установили недопустимое значение в каком-либо поле. Я также могу написать валидатор, чтобы убедиться, что Key действителен.   -  person jackalope    schedule 05.01.2013
comment
IMHO, POJO лучше всего сравнивать с фреймворком, таким как EJB, который заставляет класс реализовывать определенные интерфейсы и т. Д. Ваш вопрос больше связан с инкапсуляцией?   -  person Jayan    schedule 05.01.2013
comment
@Jayan Да, я верю в этот случай, если бы я превратил каждое поле в final, тогда мне не нужно было бы оборачивать этот класс для получения стиля POJO   -  person jackalope    schedule 05.01.2013
comment
@ jackalope: Вы нашли еще документацию по «этому» стилю POJO? Кстати, вы только что реализовали шаблон неизменяемого объекта, что, как правило, полезно!   -  person Jayan    schedule 05.01.2013
comment
То, что вы закодировали выше, технически является POJO.   -  person Hot Licks    schedule 05.01.2013
comment
@HotLicks, тогда как называется тот объект, у которого каждое поле является частным и имеет сеттер / получатель?   -  person jackalope    schedule 05.01.2013
comment
Я видел термин «непрозрачный», хотя и не с таким же значением, поскольку не все поля считаются доступными для непрозрачного объекта.   -  person Hot Licks    schedule 05.01.2013
comment
Я удивлен, почему никто не упомянул, что ответ @pradeep simha касается очень простой вещи oop. инкапсуляция !!!   -  person Anil Sharma    schedule 05.07.2013


Ответы (5)


Взято из Википедии:

POJO - это аббревиатура от Plain Old Java Object. Имя используется, чтобы подчеркнуть, что данный объект является обычным Java-объектом, а не специальным объектом.

POJO обычно прост, поэтому не зависит от других библиотек, интерфейсов или аннотаций. Это увеличивает вероятность того, что его можно будет повторно использовать в нескольких типах проектов (веб, настольный компьютер, консоль и т. Д.).

Как кто-то уже указывал в комментариях, ваш объект технически уже является POJO, однако вы специально спрашивали о геттерах и сеттерах, которые больше похожи на JavaBeans.

Есть ряд причин, по которым я могу использовать геттеры и сеттеры:

  1. Возможно, вам понадобится получить только некоторые значения (например, значения только для чтения). С помощью полей клиенты могут как получать, так и устанавливать значения напрямую. Поля можно сделать доступными только для чтения, если они помечены как окончательные, хотя это не всегда гарантирует их неизменность (см. Пункт 9).
  2. Методы получения и установки позволяют изменять базовый тип данных без нарушения общедоступного интерфейса вашего класса, что делает его (и ваше приложение) более надежным и устойчивым к изменениям.
  3. Возможно, вы захотите вызвать какой-либо другой код, например, запросить уведомление, когда значение получено или изменено. Это невозможно с вашим текущим классом.
  4. Вы раскрываете реализацию своего класса, что в некоторых случаях может представлять угрозу безопасности.
  5. Java-бины разработаны на основе POJO, что означает, что если ваш класс не реализован как один, он не может использоваться некоторыми инструментами и библиотеками, которые ожидают, что ваш класс будет придерживаться этих устоявшихся принципов.
  6. Вы можете отображать значения, которые не поддерживаются полем I.E. вычисляемые значения, такие как getFullName(), которые являются конкатенацией getFirstName() и getLastName(), которые поддерживаются полями.
  7. Вы можете добавить проверку к своим методам установки, чтобы убедиться, что передаваемые значения верны. Это гарантирует, что ваш класс всегда находится в допустимом состоянии.
  8. Вы можете установить точку останова в ваших геттерах и установщиках, чтобы вы могли отлаживать свой код при получении или изменении значений.
  9. Если поле является объектом (т.е. не примитивным типом), тогда внутреннее состояние вашего класса может быть изменено другими объектами, что может привести к ошибкам или угрозам безопасности. Вы можете защитить от этого сценария в геттере вашего POJO, вернув копию объекта, чтобы клиенты могли работать с данными, не влияя на состояние вашего объекта. Обратите внимание, что наличие последнего поля не всегда защищает вас от такого рода атак, поскольку клиенты все еще могут вносить изменения в объект, на который ссылаются (при условии, что этот объект сам изменяемый), вы просто не может указывать поле на другую ссылку после того, как она была установлена.

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

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

В этом ответе на очень похожий вопрос подробно рассматриваются некоторые соображения при разработке класса, имеющего геттеры и сеттеры. Хотя предложения могут быть более уместными в зависимости от типа создаваемого вами класса, Э. класс, который составляет часть API в большой системе, а не простой объект передачи данных.

Также обратите внимание, что могут быть определенные сценарии, в которых класс с прямым полем может быть выгодным, например, когда скорость важна или память ограничена, хотя это следует учитывать только после профилирования вашего кода и обнаружения, что на самом деле это узкое место .

Также будьте осторожны, чтобы вы не просто оборачивали все свои поля в геттеры и сеттеры, так как это действительно упускает из виду точку инкапсуляции.

Этот ответ дает хорошее резюме причин выбора POJO вместо объекта стиля JavaBean с геттерами и сеттерами.

person Benjamin Gale    schedule 05.01.2013
comment
Код, который возвращает изменяемый тип объекта, имеет тенденцию быть уродливым и неоднозначным, поскольку редко бывает очевидно, прикреплен ли возвращаемый объект к чему-либо еще. Что вы думаете о том, чтобы вместо этого использовать метод, копирующий данные в изменяемый объект, предоставляемый вызывающей стороной? Поскольку вызывающий объект предоставил объект, не может быть путаницы относительно того, содержит ли что-либо еще ссылки на него и на него повлияют дальнейшие изменения. - person supercat; 06.12.2013

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

person someone    schedule 05.01.2013

Геттеры и сеттеры, особенно простейшие формы, будут просто встроены JIT-компилятором и, таким образом, удаляют накладные расходы на вызов метода. Это очень похоже на преждевременную оптимизацию. Если вы когда-нибудь столкнетесь с узким местом, профилируйте его и посмотрите, где оно возникает. Я почти уверен, что это будет не в доступе к собственности.

person Joey    schedule 05.01.2013
comment
@jackalope, это зависит от того, какую JVM вы используете. Android Dalvic может делать меньше или другие оптимизации, чем Oracle или IBM JVM. - person Thomas Jungblut; 05.01.2013
comment
@jackalope - Любой достаточно хороший JITC удалит вызовы геттеров / сеттеров в большинстве случаев. - person Hot Licks; 05.01.2013
comment
Томас, да ладно, Dalvik - это не JVM. - person Joey; 05.01.2013

Купите себе книгу "Эффективная Java".

  • Правило 14, в публичных классах используйте методы доступа, а не публичные поля.

В этом Джошуа Блох говорит, что нет ничего изначально неправильного в общедоступных полях в пакетных частных или вложенных классах, но настоятельно рекомендует не использовать общедоступные классы.

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

person weston    schedule 05.01.2013
comment
Если вы имеете в виду эффективную Java, то я согласен, что это отличная книга. - person Benjamin Gale; 05.01.2013
comment
@ Бенджамин Я продолжаю писать это! и это прямо передо мной. - person weston; 05.01.2013

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

person syed    schedule 02.03.2015