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关键字的主要内容,如果未能解决你的问题,请参考以下文章