【发布时间】:2022-12-31 00:24:42
【问题描述】:
使用 Java 10 或 +,我们可以使用 var 关键字进行声明。在初始化时,编译器将推断出一个类型。
当我实例化并分配给用var声明的变量的类是接口的实现时会发生什么?将推断出哪种类型,接口还是实现?
【问题讨论】:
-
它将是实际类型,我。 e.实施。 (一个类可以实现多个接口。)
-
“编程到接口”的推荐对于局部变量有些宽松。
-
@user7655213 不是真的,请检查我的示例代码
使用 Java 10 或 +,我们可以使用 var 关键字进行声明。在初始化时,编译器将推断出一个类型。
当我实例化并分配给用var声明的变量的类是接口的实现时会发生什么?将推断出哪种类型,接口还是实现?
【问题讨论】:
我的 2 美分来纠正问题和答案:
var 是不是 Java 关键字.它是保留类型名称.这似乎没有太大区别,但实际上,它是:
var var = 0;
这里var也是一个变量名,所以var可以用作类型名,但没有像常规关键字那样的限制(即我们也可以有一个名为var的变量)。
var i = true ? Integer.valueOf(1) : "ABC";
Java 编译器需要为变量 i 选择一个类型,它会满足两个分支。它可以是 a) Object,b) Serializable,c) Comparable,或组合,或三者兼而有之。我们不在乎,也不知道。
【讨论】:
ContextualKeyword 仅在 Java 17 JLS 中添加,而我的回答(和问题也是)日期早于 Java 17 发布。
回答你的问题:
变量的类型将与您分配给用 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 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>)。
【讨论】:
“官方”局部变量类型推断风格指南 (https://openjdk.java.net/projects/amber/LVTIstyle.html) 提出了这个问题,但说:
"这里必须重申,var只能用于本地 变量。它不能用于推断字段类型、方法参数 类型和方法返回类型。 “编程的原则 在这些情况下,界面”仍然和以往一样重要。”
和
“如果按照指南 G2 中的建议,局部变量的范围 小,具体实施的“泄漏”风险 对后续代码的影响有限。”
【讨论】:
该类型将与变量分配给的值完全相同。
如果您更关心接口而不是实现思想:您可以创建返回接口类型但在内部创建特定实现实例的函数。
【讨论】:
var 关键字。