Java 10引入了一个新功能:局部变量类型推断(LVTI)。对于局部变量,可以使用 “var” 代替实际类型,也就是像js一样,可以通过 var 定义变量。那么 var 是新增加的关键字吗?
答案是否定的,标识符var不是一个关键字,而是一个保留类型名。那么你还记得啥是保留类型名吗?
如果你也想对这块基础知识进行一次查漏补缺,那么咱们就开始吧!
@[toc]
一、前言
事情的起因是在无意间看到一个java基础知识的题,其中有一段 var a = 10;这样的代码 ,我感觉很纳闷,这不是js里定义变量的方法吗?
后来查看解析才发现,自Java10开始,增加了局部变量类型推断的功能,就已经支持 var 定义变量。
说来惭愧,之前项目中还一直沿用的Java8,对后续版本的变动确实不敏感。深感愧疚,遂决定开始查漏补缺。
二、局部变量类型推断(var)究竟是什么?
2.1 概念理解
首先,先上官方文档:JEP 286: Local-Variable Type Inference (openjdk.org)。
大家可以先大致过一下官方文档,以防我的理解偏差误导了大家。
Java局部变量类型推断(LVTI),简称var类型,Java 10中通过 JEP 286 添加进来。(Java 10 发布时间为 2018.03)。
其允许开发人员省略通常不必要的局部变量类型的声明。这种处理将仅限于具有初始值设定项的局部变量,增强型 -循环中的索引以及在传统 -循环中声明的局部变量;它不适用于方法形式,构造函数形式,方法返回类型,字段,捕获形式或任何其他类型的变量声明。
作为100%编译特征,它不会影响字节码,运行时或者性能。在编译时,编译器会检查赋值语句右侧代码,从而推断出具体类型。它查看声明的右侧,如果这是一个初始化语句,它会用那个类型取代var。
另外,它非常有助于减少冗余代码和样板代码。它还只在旨在编写代码时所涉及的仪式。
2.2 实际应用
// java10 之前
int a = 1;
String b = "string";
double c = 1.1;
boolean d = true;
ArrayList<String> e = new ArrayList<String>();
// java10 之后可以使用var
var a = 1;
var b = "string";
var c = 1.1;
var d = true;
var e = new ArrayList<String>();
1
2
3
4
5
6
7
8
9
10
11
12
13
2.3 简单总结
var 的使用是有要求的:
(1)只能用于局部变量上;
(2)声明时必须初始化;
(3)不能用作方法参数
var 是100%编译特征,它不会影响字节码,运行时或者性能。
var 应有节制地使用,否则会降低代码的可读性。
三、var 是新的关键字吗?
在搜索相关资料的时候,发现很多文章标题直接就是 Java10 var 关键字。
那么 var 究竟是不是关键字呢?
3.1 官方描述:不是
JEP 286:局部变量类型推断 (openjdk.org)
The identifier is not a keyword; instead it is a reserved type name. This means that code that uses as a variable, method, or package name will not be affected; code that uses as a class or interface name will be affected (but these names are rare in practice, since they violate usual naming conventions).
翻译一下:
标识符不是关键字;相反,它是一个保留类型名。这意味着用作变量、方法或包名的代码不会受到影响;用作类或接口名称的代码将会受到影响(但这些名称在实践中很少见,因为它们违反了通常的命名约定)
官网说的很清楚,var 是保留类型名,那你还记得啥是保留类型名吗?
3.2 保留类型名是什么
关键字: 被Java语言赋予了特殊含义,用作专门用途的字符串。关键字不能作为包名、类名、方法名、变量名。
保留类型名: 现有的Java版本尚未使用,但以后版本可能作为关键字使用。保留类型名不能作为类名。
四、你还记得有哪些关键字吗?
这是 Java 中基础的知识点了。大家可以直接查看 javax.lang.model.SourceVersion 类 的isKeyword 方法。
// 我贴的这部分代码来自JDK17,其余版本可自行查看。
/**
* Returns whether or not {@code s} is a keyword, boolean literal,
* or null literal in the given source version.
* This method returns {@code false} for <i>restricted
* keywords</i> and <i>restricted identifiers</i>.
*
* @param s the string to check
* @param version the version to use
* @return {@code true} if {@code s} is a keyword, or boolean
* literal, or null literal, {@code false} otherwise.
* @jls 3.9 Keywords
* @jls 3.10.3 Boolean Literals
* @jls 3.10.8 The Null Literal
* @since 9
*/
public static boolean isKeyword(CharSequence s, SourceVersion version) {
String id = s.toString();
switch(id) {
// A trip through history
case "strictfp":
return version.compareTo(RELEASE_2) >= 0;
case "assert":
return version.compareTo(RELEASE_4) >= 0;
case "enum":
return version.compareTo(RELEASE_5) >= 0;
case "_":
return version.compareTo(RELEASE_9) >= 0;
// case "non-sealed": can be added once it is a keyword only
// dependent on release and not also preview features being
// enabled.
// Keywords common across versions
// Modifiers
case "public": case "protected": case "private":
case "abstract": case "static": case "final":
case "transient": case "volatile": case "synchronized":
case "native":
// Declarations
case "class": case "interface": case "extends":
case "package": case "throws": case "implements":
// Primitive types and void
case "boolean": case "byte": case "char":
case "short": case "int": case "long":
case "float": case "double":
case "void":
// Control flow
case "if": case "else":
case "try": case "catch": case "finally":
case "do": case "while":
case "for": case "continue":
case "switch": case "case": case "default":
case "break": case "throw": case "return":
// Other keywords
case "this": case "new": case "super":
case "import": case "instanceof":
// Forbidden!
case "goto": case "const":
// literals
case "null": case "true": case "false":
return true;
default:
return false;
}
}
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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
五、总结
如官网所言,var 是一个保留类型名,不能作为类名使用。但可以用作变量、方法或包名以及包名(不推荐)。var 是100%编译特征,其使用有一定限制,但应有节制地使用,否则会降低代码的可读性。