Слишком много шаблонных, как я могу уменьшить мои POJO строители?

у меня несколько разных POJO-объекты чтобы использовать шаблона, но после добавления построителя для каждого из них и генерации Object.toString, Object.hashCode и Object.equals, мои классы в конечном итоге составляют около 100 строк кода. Там должен быть лучший способ справиться с этим. Я думаю, что наличие какого-то рефлексивного строителя очень помогло бы, но я не уверен, что это будет хорошей практикой, и я также не уверен, как именно я это сделаю. Другими словами, есть ли способ реализовать такой конструктор?

простой POJO:

public class Foo {

    public int id;
    public String title;
    public boolean change;
    ...

}

затем какой-то отражающий строитель:

Foo = ReflectiveBuilder.from(Foo.class).id(1).title("title").change(false).build();

4 ответов


короткий ответ:нет. То, о чем вы просите, невозможно. Отражение смотрит на код во время выполнения и вызывает методы динамически, оно не может генерировать фактические методы.

то, что вы могли бы сделать, было бы:

Foo foo = ReflectiveBuilder.from(Foo.class).
              set("id", 1).
              set("title", "title").
              build();

это три огромные проблемы:

  1. поля Strings - опечатка вызывает ошибку времени выполнения, а не время компиляции,
  2. значения Objects-неправильный тип вызывает ошибку времени выполнения, а не компиляции, и
  3. это было бы намного медленнее, чем альтернатива, поскольку отражение очень медленное.

таким образом, решение на основе отражения, хотя это возможно (см. Apache Commons BeanUtils BeanMap) совсем не практично.

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

действительно волшебная вещь заключается в том, что все IDEs, ну, по крайней мере, big 3, понимают предварительную обработку аннотаций и завершение кода все равно будут работать правильно, хотя код не действительно.

в случае POJO С Builder можно использовать @Data и @Builder

@Data
@Builder
public class Foo {

    public int id;
    public String title;
    public boolean change;
    ...

}

на @Data аннотации создать:

  • обязательный конструктор аргументов (который принимает все final поля),
  • equals и hashCode методы, использующие все поля (можно настроить с помощью @EqualsAndHashCode аннотация)
  • a toString метод на всех полях (можно настроить с помощью @ToString аннотации и
  • public геттеры и сеттеры для всех полей (можно настроить с помощью @Getter / @Setter заметки на полях).

на @Builder аннотация создаст внутренний класс под названием Builder который может быть создан с помощью Foo.builder().

убедитесь, что вы настроить equals, hashCode и toString методы, как если бы у вас было два класса с Ломбоком, которые имеют ссылки друг на друга, то вы получите бесконечный цикл в случае по умолчанию, поскольку оба класса включают друг друга в эти методы.

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

new Foo().setId(3).setTitle("title)...

для другого подхода вы можете посмотреть на аспектно-ориентированное программирование (AOP) и в AspectJ. AOP позволяет нарезать классы на "аспекты", а затем склеить их вместе, используя определенные правила с помощью предварительного компилятора. Например, вы можете реализовать именно то, что Lombok делает, используя пользовательские аннотации и аспект. Это довольно продвинутая тема, однако, и вполне может быть излишним.


может быть Проект Lombok (да, сайт уродливый) - это вариант для вас. Lombok вводит код в ваши классы на основе аннотаций.

С Ломбок вы используете @Data аннотации к созданным геттеры, сеттеры, toString(), hashCode() и equals():

@Data
public class Foo {
    public int id;
    public String title;
    public boolean change;
}

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

Ломбок также предоставляет @Builder который генерирует конструктор для ваш класс. Но имейте в виду, что это экспериментальная функция:

@Builder
public class Foo {
    public int id;
    public String title;
    public boolean change;
}

теперь вы можете сделать:

Foo foo = Foo.builder()
  .id(123)
  .title("some title")
  .change(true)
  .build();

Я лично использую этой веб-сайт для создания всего кода шаблона для POJOs для меня. Все, что вам нужно сделать, это вставить JSON, который вы хотите обработать, и он будет генерировать классы для вас. Затем я просто использую Retrofit для выполнения запросов / кэширования / анализа информации. здесь является примером модернизации и POJOs в моей учетной записи Github. Надеюсь, это поможет!


Я создал небольшую библиотеку CakeMold для беглой инициализации POJOs. Он использует рефлексию, что, конечно, не быстро. Но может быть очень полезно, когда нужно писать тесты.

Person person = CakeMold.of(Person.class)
    .set("firstName", "Bob")
    .set("lastName", "SquarePants")
    .set("email", "sponge.bob@bikinibottom.io")
    .set("age", 22)
    .cook();