Разрешает ли Java bean setter вернуть это?

Можно ли определить метод setter, чтобы вернуть это вместо void?

Как

ClassA setItem1() {
      return this;
}

ClassA setItem2() {
      return this;
}

то я могу использовать новый ClassA(). setItem1(). setItem2()

Ответы

Ответ 1

Существует много недоразумений в отношении спецификации JavaBeans.

Основной причиной его существования является унифицированная Java-компонентная модель. Это способ интерактивного взаимодействия с Java-объектом с использованием Reflection. Сам API называется JavaBeans Introspection. Пожалуйста, посмотрите пример использования, и вы узнаете намного больше, чем средний программист Java.

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

Итак, смешивание бедных API-интерфейсов и JavaBeans Spec, на мой взгляд, является не-go. Это две совершенно несвязанные концепции и могут нарушать друг друга. Интроспекция 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() );
}
}

В этом примере создается невизуальный bean и отображаются следующие свойства, полученные из объекта BeanInfo:

  • класса
  • имя
  • размер

Возможно, вам захочется узнать, что произойдет, когда вы измените тип возвращаемого типа void на что-либо еще. Я сделал это, и результат тот же. Значит ли это, что это разрешено?

Боюсь, нет. Спецификация JavaBeans довольно строго связана с этими сигнатурами методов. Просто случилось, что реализация прощает. Тем не менее, я бы не уклонялся от смешения интерфейса с JavaBeans. Вы не можете действительно полагаться на это, если открытие работает сейчас, оно также будет и в будущем.

Но, с другой стороны - похоже, что вы не используете JavaBeans в полной мере. Только метод getters/seters метода. Это для вас, как вы реализуете и разрабатываете свои API.

Ответ 2

Спецификация JavaBeans описывает JavaBean как:

Java Bean - это многоразовое программное обеспечение компонент, который можно манипулировать визуально в инструменте построения

Они должны обеспечивать интроспекцию, настройку, события и настойчивость среди других свойств (раздел 2.1: что такое bean?)

Обычно принято называть "Java Bean" обычным старым Java-объектом с помощью методов доступа по спецификации JavaBeans (раздел 7.1 и 8.3). Правда в том, что такой объект все еще может быть далек от соответствия всем требованиям.

Если объект, который вы определяете в этом классе, на самом деле является JavaBean, тогда ваш метод должен возвращать void согласно спецификации JavaBean Specification, раздел 7.1, где методы доступа описаны следующим образом:

void setFoo(PropertyType value); // simple setter
PropertyType getFoo(); // simple getter

В разделе 8.3, названном шаблоном для свойств, сказано:

По умолчанию мы используем шаблоны проектирования для поиска свойств путем поиска методов формы:

public <PropertyType> get<PropertyName>();
public void set<PropertyName>(<PropertyType> a);

Кроме того, для булевых свойств мы позволяем методу геттера соответствовать шаблону:

public boolean is<PropertyName>();

Однако, если ваш класс является просто POJO, тогда нет ничего плохого в использовании стратегии цепочки методов, потому что вам разрешено отклоняться от спецификации, так как вы фактически не создаете JavaBean. Не все классы, которые вы определяете, должны быть JavaBeans в конце концов, правильно?

Возможно, вам понравится Учебник Oracle JavaBeans.

Ответ 3

Нет причин, по которым вы не могли этого сделать. Лично, если сеттеры используются во время создания объекта, я бы назвал их withItem1() и withItem2().

ClassA obj = new ClassA().withItem1(item1).withItem2(item2);

Делает это немного яснее (для меня в любом случае), каковы намерения методов.

Ответ 4

После проверки страниц Oracle JavaBean я не нашел ничего, что явно говорит вам, что сеттеры должны быть недействительными. Тем не менее, все примеры имеют недействительные set-методы.

PropertyDescriptor в API-интерфейсах API Java поддерживает не-void-сеттеры, поэтому я думаю, что должно быть довольно безопасно позволить вашим сеттерам вернуть это, Чтобы быть в безопасности, вы должны, вероятно, проверить, будут ли рамки, которые вы намереваетесь использовать, используя отражение. Например, Spring поддерживают не-void сеттеры в конфигурации xml до версии 3.1.

Ответ 5

Я бы предположил, что это не является нарушением спецификации 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', не зависит от типа возврата (тип возврата не используется для определения метода путем отражения). Это также имеет смысл, потому что вы не можете иметь два метода в одной области, которые идентичны, за исключением возвращаемого типа.

Ответ 7

Абсолютно ничего, чтобы остановить вас, но почему. Если вы хотите сделать это, создайте конструктор, который принимает аргументы. Заметим, что некоторое программное обеспечение, использующее beans, не будет ожидать возвращаемых значений и может иметь некоторые неожиданные результаты

Если вы просто хотите упростить инициализацию (возможно, для настройки тестов), вы можете использовать код groovy.

Ответ 9

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

Однако вы также должны использовать каноническую подпись для методов Java Bean Simple Property (например, void setProp(Type t)) или Bean свойство не будет распознаваться как записываемое другим программным обеспечением, которое ожидает эту подпись.

Ответ 10

Шаблон Builder обычно используется для построения неизменяемых объектов. Несмотря на то, что JavaBeans по своей природе не являются неизменными, я часто использовал шаблон построителя на своих JavaBeans, потому что он обеспечивает свободный интерфейс, который я могу использовать в своих тестах. Эти два легко совместимы друг с другом, не нарушая спецификации JavaBean. Вы можете проверить это на Qaru в Шаблон Builder в Эффективной Java.

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

Это намного чище, чем цепочка конструкторов, и легче читать.