Java中的var关键字

Posted

技术标签:

【中文标题】Java中的var关键字【英文标题】:Var keyword in Java 【发布时间】:2020-11-14 07:04:48 【问题描述】:

在 Java 10 或 + 中,我们可以使用 var 关键字进行声明。在初始化时,编译器会推断出一个类型。

当我实例化的类并分配给用var声明的变量时,会发生什么,是接口的实现吗?会推断出哪种类型,接口还是实现?

【问题讨论】:

它将是实际类型,即。 e.实施。 (一个类可以实现多个接口。) 在此处查看 G5:openjdk.java.net/projects/amber/LVTIstyle.html “编程到接口”的建议对于局部变量来说有些宽松。 @user7655213 不是真的,请查看我的示例代码 【参考方案1】:

我的 2 美分来纠正问题和答案:

    var 不是 Java 关键字。这是一个保留类型名称。看起来差别不大,但实际上是这样的:
var var = 0;

这里var也是一个变量名,所以var可以用作类型名,但没有常规关键字的限制(即我们也可以有一个名为var的变量)。

    变量的实际类型是由 Java 编译器在编译时在声明变量的行上决定的,但该类型实际上并不是您在表达式右侧使用的确切实现。请参阅此代码:
var i = true ? Integer.valueOf(1) : "ABC";

Java 编译器需要为变量i 选择一个满足两个分支的类型。它可以是 a) Object,b) Serializable,c) Comparable,或组合,或三者兼有。我们不在乎也不知道。

【讨论】:

【参考方案2】:

到目前为止,其他答案并未强调一个重点,即编译时可推导类型和运行时实例类之间的区别。

假设我们有

var data = Collections.singleton("test");

然后,编译器可以看到Collections.singleton("test") 被声明为返回Set<String>。所以data 实际上被声明为Set<String>(不是例如Collection<String> 也不是Object 也不是Collections.SingletonSet)。 Set<String> 是编译器能找到的最具体的信息。

在运行时,data 中引用的实例将属于某个实现类(例如Collections.SingletonSet),由Collections.singleton() 方法决定,这意味着data.getClass() 不会返回Set 类,而是实现Set 接口的不同的东西,即Collections.SingletonSet

所以我们要考虑三种类型:

    分配给变量的实例的运行时类(例如Collections.SingletonSet)。当然,这将始终与 (2) 和 (3) 兼容,并且在编译时无法知道。 分配给变量的表达式的编译时类型(例如Set<String>)。 变量的声明类型。传统上,您会发现变量名显式左侧,当使用 var 关键字时,编译器会将其视为使用 (2) 中的类型声明(即 Set<String>)。

【讨论】:

【参考方案3】:

“官方”局部变量类型推断风格指南 (https://openjdk.java.net/projects/amber/LVTIstyle.html) 提出了这种担忧,但表示:

"这里必须重申一下,var只能用于local 变量。不能用于推断字段类型、方法参数 类型和方法返回类型。 “编程”的原则 接口”在这些情况下仍然像以往一样重要。”

"如果按照指南 G2 的建议,局部变量的范围 小,具体实施的“泄露”风险 能影响后续代码的都是有限的。”

【讨论】:

【参考方案4】:

回答您的问题

变量的类型将与您分配给使用var 声明的变量的类、实例完全相同。


var 关键字的

动机

请记住,根据语言的设计(自 JDK 10+ 起),使用 var 的唯一目的是美化代码并使其更具可读性。

例如这段代码:

URL url = new URL("http://www.oracle.com/"); 
URLConnection conn = url.openConnection(); 
Reader reader = new BufferedReader(
new InputStreamReader(conn.getInputStream()));

读起来不太清楚,那么:

var url = new URL("http://www.oracle.com/"); 
var conn = url.openConnection(); 
var reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));

实施

var 仅服务于更简洁的代码和更好的可读性目的,它不会修改 Java 语言的类型系统。这就是为什么,你不能在类级别使用它(对于静态或实例字段),因为字段可能与多态一起使用,可能由 IoC 注入等,并且在字节码中,不可能动态更改每种不同情况的字段类型。

【讨论】:

对我来说 var 使代码更难阅读,因为它隐藏了变量的类型。当我阅读代码时,我喜欢清楚地看到变量类型并明确声明,无论变量是否是本地的。【参考方案5】:

类型将与分配给变量的值完全相同。

如果您更关心接口而不是实现思想:您可以创建返回接口类型但在内部创建特定实现实例的函数。

【讨论】:

关于你的第二段:或者简单地用接口类型声明变量而不是使用var关键字。

以上是关于Java中的var关键字的主要内容,如果未能解决你的问题,请参考以下文章

Java 10 和 kotlin 中的“var”

Java 10 var关键字详解和示例教程

java 10 中 var关键字用法

java有没有goto?保留字与关键字

C# 中的var关键字

如何用“let”和“const”替换此代码中的“var”关键字?