Project lombok генерирует не только геттеры и сеттеры, но и конструкторы и свойства полей класса.
Модификаторы полей.
В первую очередь избавимся от вечноповторяющихся private и final. Аннотация @FieldDefaults, применённая на класс, позволяет задать всем поля класса уровень доступа по умолчанию или сделать все поля final по умолчанию. В случае, если требуется исключение, можно использовать аннотацию @NonFinal , чтобы убрать final с конкретного поля. Аннотация @PackagePrivate аналогичным образом работает для уровня доступа — значение из @FieldDefaults игнорируется.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** * Sample user entity */ @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @NoArgsConstructor(force = true) @RequiredArgsConstructor public class User { /** * Id. */ @Getter private Long id; /** * User name. */ @Getter @NonNull private String name; /** * Some value, that you can set. */ @Getter @Setter @NonFinal BigDecimal value; } |
Конструкторы
Аннотация @NoArgsConstructor создаёт конструктор по умолчанию. В случае, если в классе есть final поля, такой конструктор сгенерирован не будет. Но, если очень сильно попросить, передав в @NoArgsConstructor параметр force = true, то конструктор будет сгенерирован, а final поля будут инициализированы пустыми значениями. В том числе пустые значения будут присвоены полям с аннотацией @NonNull.
@RequiredArgsConstructor генерирует конструктор, принимающий значения для каждого final поля или поля с аннотацией @NonNull Аргументы конструктора будут сгенерированы в том порядке, в котором поля перечислены в классе. Для @NonNull полей конструктор так же будет проверять, чтобы в него не передали значение null.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | @Test public void testConstructor() { User testedObject = new User(1L, "TEST"); assertThat(testedObject.getId(), is(1L)); assertThat(testedObject.getName(), is("TEST")); } @Test(expected = NullPointerException.class) public void testNullName() { new User(1L, null); } @Test public void testDefaultConstructor() { User testedObject = new User(); assertNull(testedObject.getId()); assertNull(testedObject.getName()); assertNull(testedObject.getValue()); } |
Все три аннотации принимают аргумент staticName, который позволяет создать статическую обёртку вокруг конструктора, с заданным именем и использовать её:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** * Sample account entity. */ @FieldDefaults(level = AccessLevel.PRIVATE) @AllArgsConstructor(staticName = "create") public class Account { /** * Id. */ @Getter @Setter Long id; /** * Account owner. */ @NonNull @Getter @Setter User owner; /** * Account's value. */ @Getter @Setter BigDecimal amount; } |
1 2 3 4 5 6 7 8 9 10 11 12 | public class AccountTest { @Test public void testChainedSetters() { User user = new User(1L, "TEST"); Account testedObject = Account.create(1L, user, BigDecimal.ONE); assertThat(testedObject.getId(), is(1L)); assertThat(testedObject.getOwner(), is(user)); assertThat(testedObject.getAmount(), is(BigDecimal.ONE)); } } |
Код примера доступен на github.