Java 10 中的 var 是什么,可与 JavaScript 相媲美?

Esh*_*shu 2 java java-10

我正在阅读 Java 10 中发布的新功能,我发现了这一点:

Java 10var作为保留类型名称引入以减少冗长。它可以用作变量、方法和包名,但我们不能将其用作类或接口名。

是否var类似于varJavaScript 中的关键字?Javavar和 JavaScript之间究竟有何异同var

Mic*_*ael 13

var 两种语言在概念上都有相似的用途,但存在重要差异。

JavaScript 是一种动态类型语言。变量没有类型信息。它对可以包含的内容没有限制。它只是一个值的持有者,该值可以是任何类型。

Java 是一种静态类型语言,所有这些语句的情况恰恰相反。程序员必须预先说明他们的变量可以容纳什么类型。它们可能像Object(每个类都Object隐式扩展)或像FieldTagTestsVisitorComparator.

Object objectVariable = "hello";
FieldTagTestsVisitorComparator enterpriseVariable = new FieldTagTestsVisitorComparator();
Run Code Online (Sandbox Code Playgroud)

在 JavaScript 中,我可以非常简洁地编写

var age = 10;
Run Code Online (Sandbox Code Playgroud)

我有一个地方可以存储一个我可以稍后读取或操作的值。

如果我稍后在我的代码中决定要为这个变量重新分配其他东西,那么我可以这样做。

age = {years: 10, months: 4, days: 5};
Run Code Online (Sandbox Code Playgroud)

您可以清楚地看到哪些声明更适合使用。人们经常抱怨 Java 的冗长。在上面的示例中,我FieldTagTestsVisitorComparator在同一行上声明了两次。这增加了什么价值?我刚刚重复了自己。

var在 Java 中寻求减少重复声明的数量。就像之前的菱形运算符一样,语言设计者正在努力改进 Java 编译器,使其足够聪明,可以推断出程序员的意图。如果某事可以是隐式的,为什么要显式呢?

这在实践中意味着赋值左侧的变量类型是从右侧推导出来的。

如果我用Java编写以下内容

var foo = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

那么 Java 10+ 编译器足够聪明,可以识别右侧的字符串构建器并自动为变量提供foo适当的类型。

这与 JavaScript 有着根本的不同,因为虽然我没有指定类型,但类型仍然存在。我不能随后为它分配任何我喜欢的东西:

foo = 3; // fails to compile, foo is of type StringBuilder
Run Code Online (Sandbox Code Playgroud)

var纯粹在编译时使用。编译器计算出类型,替换它,字节码就像从未使用过一样。之间没有功能差异

var foo = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

StringBuilder foo = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

这纯粹是一种表面差异,使语言更具表现力。


有关的注意事项var中的地位

Java 语言设计者在添加新特性时总是非常小心,以免破坏向后兼容性,因此var具有某种特殊的地位。它不是关键字,因为具有关键字状态会过于严格。例如,关键字不能用作标识符;我不能调用方法,if因为if是关键字。

var正如您的引用所述,是“保留类型名称”。这乍一听很复杂,但实际上非常描述了var的状态。它是 Java 保留的类型的名称。您不能命名您的类型 - 类、接口、枚举 - var,因为这会引入歧义。

您仍然可以在所有其他上下文中自由使用“var”一词 - 方法名称、变量标识符等。

通过拥有这种状态,设计人员最大限度地向后兼容(根本不添加功能!)。除非你有一个叫做小写的类var——首先你在做什么选择这些可怕的名字,其次你为什么不至少遵循命名约定并调用它Var?-- 然后您就可以免受任何重大更改的影响。

这里有一个完整的问题:Java 10 中的“var”究竟是什么类型的令牌?


功能不错吧?这绝对是,但重要的是不要仅仅因为可以就开始在任何地方使用它。Stuart Marks 是 JDK 开发人员之一,他有一些出色的样式指南,我建议您阅读这些指南

我的经验法则是,如果类型未在同一行中指定(如上述示例中所示),则我不使用var. 编译器足够聪明,可以从任何有效表达式的结果中推断出类型,因此以下内容完全有效:

var foo = bar();
Run Code Online (Sandbox Code Playgroud)

但是,如果不查看方法签名,则推断出变量的类型并不是很明显。编译器没有歧义,但阅读它的人不太清楚。在这种情况下,我们为了简洁而牺牲了可读性。


进一步阅读