Статья была первоначально опубликована по адресу Карлос chac.in
Смотрите также:
🎩 Неизменяемость на Java 🔥 Упрощено
Карлос Чачин ☕ 👽 – 12 апреля – 10 минут читать
В этой статье мы собираемся сравнить некоторые особенности Immutables.org библиотека, Автоматическое значение Google и Проект Ломбок :
- Сгенерировал шаблон
Builder
по умолчанию? - Сгенерированные вспомогательные методы для, т. е.
Необязательно
иСписок
? - Количество строк кода для написания?
- Необходимые плагины IDE?
- Являются ли объекты неизменяемыми?
Три библиотеки основаны на процессоре аннотаций для генерации/изменения кода для нас:
- Неизменяемые классы
равно
,Хэш-код
иtoString
методы- другие коммунальные услуги
ПРИМЕЧАНИЕ: Неизменяемый
и Автоматическое значение
генерирует новые классы с помощью процессора, и Ломбок
изменяет байт-код исходного класса.
Обзор 💡
Неизменяемый Процессоры аннотаций Java для создания простых, безопасных и согласованных объектов значений. Не повторяйтесь, попробуйте Неизменяемый, самый полный инструмент в этой области!
AutoValue обеспечивает более простой способ создания неизменяемых классов значений с гораздо меньшим количеством кода и меньшим количеством возможностей для ошибок, не ограничивая при этом вашу свободу кодировать практически любой аспект вашего класса именно так, как вы этого хотите.
Project Lombok – это библиотека java, которая автоматически подключается к вашему редактору и инструментам сборки, улучшая вашу java. Никогда больше не пишите другой метод getter или equals, с одной аннотацией ваш класс имеет полнофункциональный конструктор, автоматизирует ваши переменные ведения журнала и многое другое.
📇 Модель
Мы собираемся создать класс, используя три библиотеки, чтобы иметь возможность создавать представление объекта со следующими полями.
OptionalmyOptional; String myString; List myList;
🔩 Создание модели с автоматическим значением
package autovalue; import com.google.auto.value.AutoValue; import java.util.List; import java.util.Optional; @AutoValue public abstract class MyModel { public abstract OptionalmyOptional(); public abstract String myString(); public abstract List myList(); // Builder not generated by default // We have to write this boilerplate code @AutoValue.Builder public abstract static class Builder { public abstract Builder setMyOptional(Optional myOptional); public abstract Builder setMyString(String myString); public abstract Builder setMyList(List myList); public abstract MyModel build(); } }
- Сгенерировал шаблон
Builder
по умолчанию? 🔴 - Сгенерированные вспомогательные методы для, т. е.
Необязательно
иСписок
? 🔴 Давайте посмотрим в следующем разделе - Количество строк кода для написания? 28 проверка
- Для этого требуется плагин IDE 🔴
- Являются ли объекты неизменяемыми? 🔴 Давайте посмотрим в следующем разделе
🔩 Создание модели с помощью Ломбока
package lombok; import java.util.List; import java.util.Optional; @Value @Builder public class MyModel { OptionalmyOptional; String myString; List myList; }
- Сгенерировал шаблон
Builder
по умолчанию? 🔴 - Сгенерированные вспомогательные методы для, т. е.
Необязательно
иСписок
? 🔴 Давайте посмотрим в следующем разделе - Количество строк кода для написания? 14 проверка
- Для этого требуются плагины IDE 🔴
- Являются ли объекты неизменяемыми? 🔴 Давайте посмотрим в следующем разделе
🔩 Создание модели с неизменяемым
package immutables; import org.immutables.value.Value; import java.util.List; import java.util.Optional; @Value.Immutable public interface MyModel { OptionalmyOptional(); String myString(); List myList(); }
- Сгенерировал шаблон
Builder
по умолчанию? ✅ - Сгенерированные вспомогательные методы для, т. е.
Необязательно
иСписок
? ✅ , Давайте посмотрим в следующем разделе - Количество строк кода для написания? 15 проверка
- Для этого не требуется плагин IDE ✅
- Являются ли объекты неизменяемыми? ✅ , Давайте посмотрим в следующем разделе
🌵 Тесты
Давайте проверим какой-нибудь псевдокод:
Мы собираемся создать два идентичных списка с одним и тем же элементом внутри:
list1=List.of("OneValue") list2=List.of("OneValue")
Мы собираемся создать два идентичных объекта ценности, подобных этому:
MyModel1: ( myOptional=Optional.of(1) myString="Hello" myList=list1 // Using list 1 ) MyModel2: ( myOptional=Optional.of(1) myString="Hello" myList=list2 // Using list 2 )
Даже при использовании разных ссылок для списков объекты должны быть равны по значению.
model1 == model2 // TRUE
После изменения одного из списков сравнение объектов должно быть одинаковым
list1.add("AnotherValue") model1 == model2 // TRUE
🍭 Проверка Автоматического значения
@Test void immutability() { // Create 2 lists containing the same element var myList1 = new ArrayList(); myList1.add("OneValue"); var myList2 = List.of("OneValue"); // Create model 1, assigning the list1 var myModel1 = new AutoValue_MyModel.Builder() .setMyOptional(Optional.of(1)) // 😥 🔴 No helper for Optional .setMyString("Hello") .setMyList(myList1) // 😥 🔴 No helper for List .build(); // Create model 2, assigning the list2 var myModel2 = new AutoValue_MyModel.Builder() // 😥 🔴 No helper for copying .setMyOptional(Optional.of(1)) .setMyString("Hello") .setMyList(myList2) .build(); // Compare the 2 objects // Test passes since the fields contain the same values assertThat(myModel1).isEqualTo(myModel2); // Mutate the list used on Model 1 myList1.add("AnotherValue"); // Compare the 2 objects: // - PASSES objects are NOT equal for AutoValue 😮 🔴 assertThat(myModel1).isNotEqualTo(myModel2); }
🍭 Тестирование Ломбока
@Test void immutability() { // Create a mutable list with 1 element var myList1 = new ArrayList(); myList1.add("OneValue"); var myList2 = List.of("OneValue"); // Create model 1, assigning the list1 var myModel1 = MyModel.builder() .myOptional(Optional.of(1)) // 😥 🔴 No helper for Optional .myString("Hello") .myList(myList1) // 😥 🔴 No helper for List .build(); // Create model 2, assigning the list2 var myModel2 = MyModel.builder() 😥 🔴 // No helper for copying .myOptional(Optional.of(1)) .myString("Hello") .myList(myList2) .build(); // Compare the 2 objects // Test passes since the fields contain the same values assertThat(myModel1).isEqualTo(myModel2); // Mutate the list used on Model 1 myList1.add("AnotherValue"); // Compare the 2 objects: // - PASSES objects are NOT equal for Lombok 😮 🔴 assertThat(myModel1).isNotEqualTo(myModel2); }
🍭 Тестирование неизменяемых
@Test void immutability() { // Create a mutable list with 1 element var myList1 = new ArrayList(); myList1.add("OneValue"); var myList2 = List.of("OneValue"); // Create model 1, assigning the list1 var myModel1 = ImmutableMyModel.builder() .myOptional(1) // 🎩 ✅ Helper for Optional .myString("Hello") .myList(myList1) .build(); // Create model 2, assigning the list2 var myModel2 = ImmutableMyModel.builder() .from(myModel1) // 🎩 ✅ Helper for copying .addMyList("OneValue") // 🎩 ✅ Helper for List .build(); // Compare the 2 objects // Test passes since the fields contain the same values assertThat(myModel1).isEqualTo(myModel2); // Mutate the list used on Model 1 myList1.add("AnotherValue"); // Compare the 2 objects: // - Test PASSES objects ARE EQUAL for Immutables 🎩 ✅ assertThat(myModel1).isEqualTo(myModel2); }
📈 Результаты
14 | 28 | 15 | Строка кода для написания/ поддерживать |
🔴 | 🔴 | ✅ | Конструктор (по умолчанию) |
🔴 | ✅ | ✅ | Необходимый плагин IDE |
🔴 | 🔴 | ✅ | Неизменность |
🔴 | 🔴 | ✅ | Помощник для дополнительного |
🔴 | 🔴 | ✅ | Помощник для коллекций |
🔴 | 🔴 | ✅ | Помощник для копирования |
Код и тесты для приведенных выше примеров доступны на GitHub:
cchacin/неизменяемые – автоматическое значение -ломбок
Горячий напиток Неизменяемый/Автоматическое значение/Ломбок 🔥 какой?
Запись в блоге: https://dev.to/cchacin/immutables-autovalue-lombok-which-one-2j33
Выводы 🔆
Даже когда три библиотеки проделывают большую работу, чтобы избежать шаблонного кода, я лично использую
Неизменяемая
библиотека в большинстве проектов из-за безопасных значений по умолчанию.Справедливости ради, оба
Ломбок
иАвтоматическое значение
может также обеспечить неизменность но это требует большего внимания при создании классов, и это может вызвать проблемы.Одним из основных преимуществ
автоматического значения
является то, что он генерирует меньше кода, и это было бы удобно, если вы разрабатываете/дляAndroid
.Параметры конфигурации для
Автоматического значения
иЛомбок
довольно ограничены по сравнению сНеизменяемый
но эта тема не была затронута в этой статье.Для Lombok требуется плагин, если вы хотите видеть все измененные/добавленные методы в байт-код.
Оригинал: “https://dev.to/cchacin/immutables-autovalue-lombok-which-one-2j33”