Java中的Var关键字

du7egjpx  于 2023-01-01  发布在  Java
关注(0)|答案(5)|浏览(223)

在Java10或+中,我们可以使用var关键字进行声明。在初始化时,编译器将推断出类型。
当我示例化类并赋给用var声明的变量时,会发生什么,是接口的实现吗?它将被推断为哪种类型,接口还是实现?

mum43rcc

mum43rcc1#

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

  1. var不是Java关键字。它是保留的类型名。看起来差别不大,但实际上,它是:
var var = 0;

这里var也是一个变量名,所以var可以用作类型名,但没有像正则关键字那样的限制(即我们也可以有一个名为var的变量)。
1.变量的实际类型是由Java编译器在编译时声明变量的那一行决定的,但类型实际上并不是你在表达式右边使用的实现。

var i = true ? Integer.valueOf(1) : "ABC";

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

6uxekuva

6uxekuva2#

回答您的问题:

当我示例化类并赋给用var声明的变量时会发生什么,是接口的实现吗?它会被推断出哪种类型,接口还是实现?
变量的推断类型将与类完全相同,引用示例,将其赋值给用var声明的变量。
此外,如果你的类实现了两个或更多的接口,你认为会发生什么?你认为Java应该如何决定推断变量类型呢?所以,这是不可能的,即使我们的判断纯粹基于一个简单的逻辑-将不存在"真理的来源",Java将能够决定这一点。

* 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注入,等等)并且在字节码处,不可能针对每个不同的情况动态地更改字段类型。

n9vozmp4

n9vozmp43#

到目前为止,其他的答案没有强调一个重要的点,即编译时可推导类型和运行时示例类之间的区别。
假设我们有

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

然后,编译器可以看到Collections.singleton("test")被声明为返回Set<String>。因此data实际上被声明为Set<String>(而不是Collection<String>ObjectCollections.SingletonSet)。Set<String>是编译器可以找到的最具体的信息。
当运行时,data中引用的示例将是由Collections.singleton()方法决定的某个实现类(例如Collections.SingletonSet),这意味着data.getClass()将不返回Set类,而是实现Set接口的不同类,例如Collections.SingletonSet
所以我们要考虑三种类型:
1.示例的运行时类,它被赋值给变量(例如Collections.SingletonSet)。当然,这总是与(2)和(3)兼容,并且在编译时无法知道。
1.分配给变量的表达式的编译时类型(例如Set<String>)。
1.变量声明的类型。通常情况下,你会在变量名的左边找到它,当使用var关键字时,编译器会将其视为声明了(2)中的类型(即Set<String>)。

vsikbqxv

vsikbqxv4#

“官方的”局部变量类型推理风格指南(https://openjdk.java.net/projects/amber/LVTIstyle.html)提出了这个问题,但指出:
这里必须重申,var只能用于局部变量。它不能用于推断字段类型、方法参数类型和方法返回类型。在这些上下文中,“编程到接口”的原则仍然像以前一样重要。
以及
如果按照准则G2中的建议,局部变量的范围很小,则可能影响后续代码的具体实现的“泄漏”风险有限。

0kjbasz6

0kjbasz65#

类型将与变量被赋给的值完全相同。
如果您更关心接口而不是实现思想:你可以创建一个函数,它返回接口类型,但是在里面创建一个特定的实现示例。

相关问题