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()));
5条答案
按热度按时间mum43rcc1#
我的2美分纠正问题和答案:
var
是不是Java关键字。它是保留的类型名。看起来差别不大,但实际上,它是:这里
var
也是一个变量名,所以var
可以用作类型名,但没有像正则关键字那样的限制(即我们也可以有一个名为var
的变量)。1.变量的实际类型是由Java编译器在编译时声明变量的那一行决定的,但类型实际上并不是你在表达式右边使用的实现。
Java编译器需要为变量
i
选择一个类型,它可以满足两个分支,它可以是a)Object
,b)Serializable
,c)Comparable
,或者combinatioin,或者三者都有,我们不关心也不知道。6uxekuva2#
回答您的问题:
当我示例化类并赋给用var声明的变量时会发生什么,是接口的实现吗?它会被推断出哪种类型,接口还是实现?
变量的推断类型将与类完全相同,引用示例,将其赋值给用
var
声明的变量。此外,如果你的类实现了两个或更多的接口,你认为会发生什么?你认为Java应该如何决定推断变量类型呢?所以,这是不可能的,即使我们的判断纯粹基于一个简单的逻辑-将不存在"真理的来源",Java将能够决定这一点。
* var * 关键字的动机:
请记住,根据语言的设计(从JDK 10+开始),使用
var
的唯一目的是美化代码,使其更具可读性。例如,以下代码:
阅读起来不如:
实施细节:
var
只用于 * 更清晰/更好的可读性 * 目的,它不会修改Java语言的类型系统,这就是为什么不能在类级别使用它(对于静态或示例)字段,因为字段可能与多态一起使用(可以接收不同的实现类型,可以由IoC注入,等等)并且在字节码处,不可能针对每个不同的情况动态地更改字段类型。n9vozmp43#
到目前为止,其他的答案没有强调一个重要的点,即编译时可推导类型和运行时示例类之间的区别。
假设我们有
然后,编译器可以看到
Collections.singleton("test")
被声明为返回Set<String>
。因此data
实际上被声明为Set<String>
(而不是Collection<String>
、Object
或Collections.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>
)。vsikbqxv4#
“官方的”局部变量类型推理风格指南(https://openjdk.java.net/projects/amber/LVTIstyle.html)提出了这个问题,但指出:
这里必须重申,var只能用于局部变量。它不能用于推断字段类型、方法参数类型和方法返回类型。在这些上下文中,“编程到接口”的原则仍然像以前一样重要。
以及
如果按照准则G2中的建议,局部变量的范围很小,则可能影响后续代码的具体实现的“泄漏”风险有限。
0kjbasz65#
类型将与变量被赋给的值完全相同。
如果您更关心接口而不是实现思想:你可以创建一个函数,它返回接口类型,但是在里面创建一个特定的实现示例。