1. Introduction
1.绪论
Project Lombok helps to reduce Java’s verbosity for repetitive tasks in our source code. In this tutorial, we’ll explain how to infer types by declaring local val and var variables in Lombok.
Project Lombok有助于减少Java在我们的源代码中重复性任务的冗长性。在本教程中,我们将解释如何在Lombok中通过声明本地val和var变量来推断类型。
2. Declaring val and var Variables in Lombok
2.在Lombok中声明val和var变量
Lombok provides intelligent capabilities to avoid boilerplate code. For instance, it hides getters and setters from domain model objects. Builder annotation is another interesting feature that helps to implement the Builder pattern properly.
Lombok提供智能功能以避免模板代码。例如,它从领域模型对象中隐藏了getters和setters。Builder注解是另一个有趣的功能,它有助于正确实现Builderpattern。
In the following sections, we’ll focus on the Lombok feature to define local variables without specifying the type. We’ll use Lombok val and var types to declare the variables and avoid extra lines in our source code.
在下面的章节中,我们将重点讨论Lombok的功能,即定义局部变量而不指定类型。我们将使用Lombok的val和var类型来声明变量,避免在源代码中增加行数。
val was introduced in version 0.10. When using val, Lombok declares the variable as final and automatically infers the type after initializing it. Thus, the initializing expression is mandatory.
val是在0.10版本中引入。当使用val时,Lombok将变量声明为final,并在初始化后自动推断其类型。因此,初始化表达式是强制性的。
var was introduced in version 1.16.20. As with val, it also infers the type from the initializing expression with the big difference that the variable is not declared as final. Therefore, further assignments are allowed, but they should comply with the type specified when declaring the variable.
var是在1.16.20版本中引入的。和val一样,它也是从初始化表达式中推断出类型,但最大的区别是变量没有被声明为final。因此,进一步的赋值是允许的,但它们应该符合声明变量时指定的类型。
3. Implementing val and var Examples in Lombok
3.在Lombok中实现val和var示例
3.1. Dependencies
3.1. 依赖性
To implement the examples, we’ll simply add the Lombok dependency to our pom.xml:
为了实现这些例子,我们只需将Lombok依赖性添加到我们的pom.xml。
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
<scope>provided</scope>
</dependency>
We can check for the most recent available version here.
我们可以检查最新的可用版本这里。
3.2. val Variable Declaration
3.2.val变量声明
First, we’ll import the val type from Lombok:
首先,我们将从Lombok导入val类型。
import lombok.val;
Second, we’ll declare different local variables using val. For instance, we can start with a simple String:
其次,我们将使用val声明不同的局部变量。例如,我们可以从一个简单的String开始。
public Class name() {
val name = "name";
System.out.println("Name: " + name);
return name.getClass();
}
Lombok automatically generates the following vanilla Java:
Lombok自动生成了以下的vanilla Java。
final java.lang.String name = "name";
Then, let’s create an Integer:
然后,让我们创建一个Integer。
public Class age() {
val age = Integer.valueOf(30);
System.out.println("Age: " + age);
return age.getClass();
}
As we can see, Lombok generates the proper type:
我们可以看到,龙目岛产生了适当的类型。
final java.lang.Integer age = Integer.valueOf(30);
We can also declare a List:
我们也可以声明一个List。
public Class listOf() {
val agenda = new ArrayList<String>();
agenda.add("Day 1");
System.out.println("Agenda: " + agenda);
return agenda.getClass();
}
Lombok infers not only the List but also the type inside it:
Lombok不仅推断出List,还推断出它里面的类型。
final java.util.ArrayList<java.lang.String> agenda = new ArrayList<String>();
Now, let’s create a Map:
现在,让我们创建一个Map。
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();
}
Again, the proper types are inferred:
同样,适当的类型是推断出来的。
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()) {
// ...
}
We can see Lombok declares the proper types as final. So, if we try to modify the name, the build will fail due to the final nature of val:
我们可以看到Lombok将适当的类型声明为final。所以,如果我们试图修改这个名字,由于val的最终性质,构建将失败。
name = "newName";
[12,9] cannot assign a value to final variable name
Next, we’ll run some tests to verify Lombok generates the proper types:
接下来,我们将运行一些测试来验证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);
Finally, we can see in the console output the objects with specific types:
最后,我们可以在控制台输出中看到具有特定类型的对象。
Name: name
Age: 30
Agenda: [Day 1]
Books:
- 1. Book 1
- 2. Book 2
3.3. var Variable Declaration
3.3.var变量声明
var declaration is pretty similar to val with the particularity that the variable is not final:
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");
Let’s have a look at the vanilla Java generated:
让我们来看看生成的vanilla Java。
var name = "name";
var age = Integer.valueOf(30);
var agenda = new ArrayList<String>();
var books = new HashMap<Integer, String>();
This is because Java 10 supports var declaration to infer types of local variables using the initializer expression. However, we’ll need to take into account some constraints when using it.
这是因为Java 10支持var 声明来使用初始化器表达式推断局部变量的类型。然而,我们在使用它时需要考虑到一些限制条件。
As the declared variable is not final, we can do further assignments. Nevertheless, the objects must fit the appropriate inferred type from the initializer expression.
由于声明的变量不是final,我们可以做进一步的赋值。尽管如此,这些对象必须符合从初始化表达式中推断出的适当类型。
If we try to assign a different type, we’ll get an error during compilation:
如果我们试图分配一个不同的类型,我们会在编译时得到一个错误。
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>
Let’s change the tests slightly and check the new assignments:
让我们稍微改变一下测试,检查一下新的作业。
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");
And finally, the console output is also different from the previous section:
最后,控制台的输出也与上一节不同。
Name: newName
Age: 35
Agenda: [Day 2]
Books:
- 3. Book 3
- 4. Book 4
4. Compound Types
4.复合物类型
There are cases in which we’ll need to use compound types as the initializer expression:
在有些情况下,我们需要使用复合类型作为初始化表达式。
val compound = isArray ? new ArrayList<String>() : new HashSet<String>();
In the above snippet, the assignment depends on the boolean value, and the most common superclass is inferred.
在上面的片段中,赋值取决于布尔值, 并且推断出了最常见的超类。
Lombok assigns AbstractCollection as the type as the vanilla code shows:
Lombok将AbstractCollection指定为类型,正如vanilla代码所显示的那样。
final java.util.AbstractCollection<java.lang.String> compound = isArray ? new ArrayList<String>() : new HashSet<String>();
In ambiguous cases, such as with null values, the class Object is inferred.
在不明确的情况下,如null值,会推断出Object类。
5. Configuration Keys
5.配置键
Lombok allows configuring the features in one file across the entire project. Thus, it is possible to include directives and settings for the project located in one place.
Lombok允许在一个文件中配置整个项目的功能。因此,有可能在一个地方包括项目的指令和设置。
Sometimes, as part of enforcing development standards in our project, we may want to restrict the use of Lombok’s var and val. And, if someone does use them inadvertently, we may want to generate a warning during compilation.
有时,作为在我们项目中执行开发标准的一部分,我们可能想限制Lombok的var和val的使用。而且,如果有人无意中使用它们,我们可能想在编译过程中产生一个警告。
For those cases, we can flag any usage of var or val as a warning or error by including the following in the lombok.config file:
对于这些情况,我们可以通过在lombok.config文件中加入以下内容,将任何对var或val的使用标记为警告或错误。
lombok.var.flagUsage = error
lombok.val.flagUsage = warning
We’ll receive an error about the illegal use of var across the project:
我们会收到一个关于在整个项目中非法使用var的错误。
[12,13] Use of var is flagged according to lombok configuration.
In the same way, we’ll receive a warning message about the use of val:
以同样的方式,我们会收到关于使用val的警告信息。
ValExample.java:18: warning: Use of val is flagged according to lombok configuration.
val age = Integer.valueOf(30);
6. Conclusion
6.结语
In this article, we showed how to use Lombok to define local variables without specifying the type. Furthermore, we learned the intricacies of declaring val and var variables.
在这篇文章中,我们展示了如何使用Lombok来定义局部变量而不指定类型。此外,我们还学习了声明val和var变量的错综复杂的方法。
We also demonstrated how the generic declaration of local variables works with compound types.
我们还演示了局部变量的通用声明如何在复合类型中发挥作用。
As always, the code is available over on GitHub.
像往常一样,代码可在GitHub上获得。