Разрешает ли установщик Java bean вернуть это?
Я могу определить метод установки, чтобы вернуть это, а не void?
Подобно:
ClassA setItem1() {
return this;
}
ClassA setItem2() {
return this;
}
тогда я могу использовать новый ClassA().setItem1().setItem2()
10 ответов
Существует много недоразумений о спецификации JavaBeans.
Основной причиной его существования является унифицированная модель Java "компонент". Это способ программно взаимодействовать с Java-объектом, используя Reflection. Сам API называется JavaBeans Introspection. Пожалуйста, взгляните на примеры использования, и вы узнаете намного больше, чем обычный программист на Java.
API самоанализа можно использовать для унифицированного управления элементами графического интерфейса. Ваш компонент предоставляет свои свойства в виде пары методов получения и установки, чтобы их можно было обнаружить и манипулировать во время выполнения на странице свойств компоновщика GUI.
Таким образом, смешивать API и JavaBeans Spec на мой взгляд не стоит. Это две совершенно не связанные между собой концепции, которые могут нарушать друг друга. Самоанализ JavaBeans может не работать, если сигнатура метода отличается (тип возвращаемого значения).
Взгляните на этот пример (взят из связанного урока):
public class SimpleBean
{
private final String name = "SimpleBean";
private int size;
public String getName()
{
return this.name;
}
public int getSize()
{
return this.size;
}
public void setSize( int size )
{
this.size = size;
}
public static void main( String[] args )
throws IntrospectionException
{
BeanInfo info = Introspector.getBeanInfo( SimpleBean.class );
for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
System.out.println( pd.getName() );
}
}
В этом примере создается невизуальный компонент и отображаются следующие свойства, полученные из объекта BeanInfo:
- учебный класс
- название
- размер
Возможно, вы захотите увидеть, что происходит, когда вы меняете void
тип возврата к чему-либо еще. Я так и сделал, и результат тот же. Так значит ли это, что это разрешено?
Боюсь нет. Спецификация JavaBeans довольно строга в отношении этих сигнатур методов. Просто так получилось, что реализация прощает. Тем не менее, я бы не советовал смешивать свободный интерфейс с JavaBeans. Вы не можете действительно полагаться на это, если открытие работает сейчас, оно также будет в будущем.
Но, с другой стороны - похоже, вы не используете JavaBeans в полной мере. Только пара методов получения / установки. Вам решать, как Вы реализуете и разрабатываете свои API.
Спецификация JavaBeans описывает JavaBean как:
Java Bean - это программный компонент многократного использования, которым можно визуально манипулировать в инструменте разработчика
Они обязаны обеспечивать самоанализ, настройку, события и постоянство среди других свойств (Раздел 2.1: Что такое бин?)
Обычно Java Bean вызывается для простого старого объекта Java с методами доступа, следуя спецификации JavaBeans (раздел 7.1 и 8.3). Правда состоит в том, что такой объект все еще может быть далеко не соответствующим всем требованиям.
Если объект, который вы определяете в этом классе, на самом деле является JavaBean, то ваш метод должен вернуть void в соответствии со спецификацией JavaBean, раздел 7.1, где методы доступа описаны следующим образом:
void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter
Раздел 8.3 назвал разработанные шаблоны для свойств говорит:
По умолчанию мы используем шаблоны проектирования для поиска свойств путем поиска методов формы:
public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);
Кроме того, для логических свойств мы разрешаем методу getter соответствовать шаблону:
public boolean is<PropertyName>();
Однако, если ваш класс - просто POJO, то нет ничего плохого в использовании стратегии цепочки методов, поскольку вам разрешено отклоняться от спецификации, поскольку вы на самом деле не строите JavaBean. В конце концов, не все классы, которые вы определяете, должны быть JavaBeans, верно?
Возможно, вы захотите взглянуть на учебник по Oracle JavaBeans.
Нет причин, по которым ты не мог этого сделать. Лично, если сеттеры используются во время создания объекта, я бы назвал их с помощью Item1() и withItem2().
ClassA obj = new ClassA().withItem1(item1).withItem2(item2);
Делает это немного более ясным (для меня так или иначе), каково назначение методов.
После проверки страниц Oracle JavaBean я не нашел ничего, что бы явно указывало на то, что сеттеры должны быть недействительными. Тем не менее, все примеры имеют void set-методы.
PropertyDescriptor в Java API поддерживает не-пустые установщики, поэтому я думаю, что это должно быть довольно безопасно, чтобы ваши установщики возвращали это. Чтобы быть в безопасности, вы, вероятно, должны проверить, использует ли фреймворк, который вы собираетесь использовать, отражение. Например, Spring не поддерживал не пустые сеттеры в конфигурации xml до версии 3.1.
Я предполагаю, что это не является нарушением спецификации JavaBean, хотя я не уверен в этом.
Посмотрите на следующий пример:
public class JavaBean {
private String value;
public String getValue() {
return value;
}
public JavaBean setValue(String value) {
this.value = value;
return this;
}
public static void main(String[] args) throws Exception {
JavaBean bean = new JavaBean();
JavaBean.class.getMethod("setValue", String.class).invoke(bean, "test");
System.out.println(bean.getValue());
}
}
Многие фреймворки получают доступ к JavaBeans с помощью API отражения. Как вы можете видеть выше, доступ к установщику, который возвращает 'this', не зависит от типа возвращаемого значения (тип возвращаемого значения не используется для определения местоположения метода посредством отражения). Это также имеет смысл, потому что вы не можете иметь два метода в одной области видимости, кроме их возвращаемого типа.
Просто добавлю, что для людей, использующих Spring 3.1+, это больше не проблема
см. http://static.springsource.org/spring/docs/3.1.0.M2/spring-framework-reference/html/new-in-3.1.html
Да. Это довольно распространенный метод, называемый "Метод цепочки", и его можно использовать для создания "свободного интерфейса".
Смотрите: http://en.wikipedia.org/wiki/Method_chaining, http://en.wikipedia.org/wiki/Fluent_interface
Абсолютно ничто не мешает вам делать это, но почему. Если вы хотите сделать это, создайте конструктор, который принимает аргументы. Не забывайте, что некоторые программы, использующие bean-компоненты, не будут ожидать возвращаемых значений и могут иметь неожиданные результаты.
Если вы просто хотите упростить инициализацию (возможно, для настройки тестов), вы можете использовать какой-то отличный код.
Ничто не мешает вам предоставлять методы установки, которые возвращают целевой объект как соглашение в вашем интерфейсе...
Однако вы также должны использовать каноническую сигнатуру для методов установки простого свойства Java Bean (например, void setProp(Type t)
) или свойство bean-компонента не будет признано доступным для записи другим программным обеспечением, которое ожидает эту подпись.
Шаблон Builder обычно используется для построения неизменяемых объектов. Хотя JavaBeans по своей природе не является неизменным, я часто использовал шаблон компоновщика на моих JavaBeans, потому что он обеспечивает свободный интерфейс, который я могу использовать в своих тестах. Оба легко совместимы друг с другом, не нарушая спецификацию JavaBean. Вы можете проверить это по переполнению стека в Pattern Builder в эффективной Java
Вам просто нужно убедиться, что вы включили конструктор по умолчанию, а также частный конструктор Builder, а затем поместили ваши стандартные методы получения и установки в объект JavaBean.
Это намного чище, чем построение цепочки, и легче читать.