1. Введение
Project Lombok помогает уменьшить многословие Java для повторяющихся задач в нашем исходном коде. В этом руководстве мы объясним, как выводить типы, объявляя локальные переменные val
и var
в Lombok.
2. Объявление переменных val
и var
в Lombok
Lombok предоставляет интеллектуальные возможности для обхода стандартного кода . Например, он скрывает геттеры и сеттеры от объектов модели предметной области. Аннотации Builder — еще одна интересная функция, помогающая правильно реализовать шаблон Builder .
В следующих разделах мы сосредоточимся на функции Lombok для определения локальных переменных без указания типа . Мы будем использовать типы Lombok val
и var
для объявления переменных и избежания лишних строк в нашем исходном коде.
val
` был представлен в версии 0.10. При использовании
val Lombok объявляет переменную как
final` и автоматически определяет тип после ее инициализации. Таким образом, инициализирующее выражение является обязательным.
var
был представлен в версии 1.16.20. Как и в случае с val
, он также выводит тип из инициализирующего выражения с той большой разницей, что переменная не объявляется как final
. Поэтому допускаются дальнейшие присваивания, но они должны соответствовать типу, указанному при объявлении переменной.
3. Реализация примеров val
и var
на Ломбоке
3.1. Зависимости
Чтобы реализовать примеры, мы просто добавим зависимость Lombok в наш pom.xml
:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
Мы можем проверить самую последнюю доступную версию здесь .
3.2. Объявление переменной val
Во-первых, мы импортируем тип val
из Ломбока:
import lombok.val;
Во-вторых, мы объявим разные локальные переменные, используя val
. Например, мы можем начать с простой строки
:
public Class name() {
val name = "name";
System.out.println("Name: " + name);
return name.getClass();
}
Lombok автоматически генерирует следующую ванильную Java:
final java.lang.String name = "name";
Затем давайте создадим Integer
:
public Class age() {
val age = Integer.valueOf(30);
System.out.println("Age: " + age);
return age.getClass();
}
Как мы видим, Lombok генерирует правильный тип:
final java.lang.Integer age = Integer.valueOf(30);
Мы также можем объявить List
:
public Class listOf() {
val agenda = new ArrayList<String>();
agenda.add("Day 1");
System.out.println("Agenda: " + agenda);
return agenda.getClass();
}
Ломбок выводит не только список
, но и тип внутри него:
final java.util.ArrayList<java.lang.String> agenda = new ArrayList<String>();
Теперь давайте создадим карту
:
public Class mapOf() {
val books = new HashMap<Integer, String>();
books.put(1, "Book 1");
books.put(2, "Book 2");
System.out.println("Books:");
for (val entry : books.entrySet()) {
System.out.printf("- %d. %s\n", entry.getKey(), entry.getValue());
}
return books.getClass();
}
Опять же, правильные типы выводятся:
final java.util.HashMap<java.lang.Integer, java.lang.String> books = new HashMap<Integer, String>();
// ...
for (final java.util.Map.Entry<java.lang.Integer, java.lang.String> entry : books.entrySet()) {
// ...
}
Мы видим, что Lombok объявляет правильные типы как final
. Итак, если мы попытаемся изменить имя, сборка завершится ошибкой из-за окончательной природы val
:
name = "newName";
[12,9] cannot assign a value to final variable name
Затем мы запустим несколько тестов, чтобы убедиться, что Lombok генерирует правильные типы:
ValExample val = new ValExample();
assertThat(val.name()).isEqualTo(String.class);
assertThat(val.age()).isEqualTo(Integer.class);
assertThat(val.listOf()).isEqualTo(ArrayList.class);
assertThat(val.mapOf()).isEqualTo(HashMap.class);
Наконец, мы можем увидеть в консоли вывод объектов с определенными типами:
Name: name
Age: 30
Agenda: [Day 1]
Books:
- 1. Book 1
- 2. Book 2
3.3. Объявление переменной var
Объявление var
очень похоже на val
с тем отличием, что переменная не является final
:
import lombok.var;
var name = "name";
name = "newName";
var age = Integer.valueOf(30);
age = 35;
var agenda = new ArrayList<String>();
agenda.add("Day 1");
agenda = new ArrayList<String>(Arrays.asList("Day 2"));
var books = new HashMap<Integer, String>();
books.put(1, "Book 1");
books.put(2, "Book 2");
books = new HashMap<Integer, String>();
books.put(3, "Book 3");
books.put(4, "Book 4");
Давайте посмотрим на сгенерированную ванильную Java:
var name = "name";
var age = Integer.valueOf(30);
var agenda = new ArrayList<String>();
var books = new HashMap<Integer, String>();
Это связано с тем, что Java 10 поддерживает объявление var
для вывода типов локальных переменных с использованием выражения инициализатора. Однако при его использовании нам необходимо учитывать некоторые ограничения .
Поскольку объявленная переменная не является final
, мы можем выполнять дальнейшие присваивания. Тем не менее, объекты должны соответствовать соответствующему типу, выведенному из выражения инициализатора .
Если мы попытаемся присвоить другой тип, то получим ошибку при компиляции:
books = new ArrayList<String>();
[37,17] incompatible types: java.util.ArrayList<java.lang.String> cannot be converted to java.util.HashMap<java.lang.Integer,java.lang.String>
Немного изменим тесты и проверим новые задания:
VarExample varExample = new VarExample();
assertThat(varExample.name()).isEqualTo("newName");
assertThat(varExample.age()).isEqualTo(35);
assertThat("Day 2").isIn(varExample.listOf());
assertThat(varExample.mapOf()).containsValue("Book 3");
И, наконец, вывод консоли также отличается от предыдущего раздела:
Name: newName
Age: 35
Agenda: [Day 2]
Books:
- 3. Book 3
- 4. Book 4
4. Составные типы
Есть случаи, когда нам нужно использовать составные типы в качестве выражения инициализатора:
val compound = isArray ? new ArrayList<String>() : new HashSet<String>();
В приведенном выше фрагменте назначение зависит от логического значения, `` и выводится наиболее распространенный суперкласс.
Lombok присваивает AbstractCollection
как тип, как показывает ванильный код:
final java.util.AbstractCollection<java.lang.String> compound = isArray ? new ArrayList<String>() : new HashSet<String>();
В неоднозначных случаях, например с нулевыми
значениями, выводится класс Object .
5. Ключи конфигурации
Lombok позволяет настраивать функции в одном файле для всего проекта. Таким образом, можно включать директивы и настройки для проекта, расположенные в одном месте.
Иногда, в рамках обеспечения соблюдения стандартов разработки в нашем проекте, мы можем захотеть ограничить использование var
и val
Lombok . И, если кто-то использует их непреднамеренно, мы можем захотеть сгенерировать предупреждение во время компиляции.
В этих случаях мы можем пометить любое использование var
или val
как предупреждение или ошибку, включив в файл lombok.config следующее
:
lombok.var.flagUsage = error
lombok.val.flagUsage = warning
Мы получим ошибку о незаконном использовании var
в проекте:
[12,13] Use of var is flagged according to lombok configuration.
Точно так же мы получим предупреждающее сообщение об использовании val
:
ValExample.java:18: warning: Use of val is flagged according to lombok configuration.
val age = Integer.valueOf(30);
6. Заключение
В этой статье мы показали, как использовать Lombok для определения локальных переменных без указания типа. Кроме того, мы изучили тонкости объявления переменных val
и var .
Мы также продемонстрировали, как универсальное объявление локальных переменных работает с составными типами.
Как всегда, код доступен на GitHub .