Перейти к основному содержимому

Объявление переменных Val и Var в Ломбоке

· 6 мин. чтения

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 .