【问题标题】:Var keyword in JavaJava 中的 var 关键字
【发布时间】:2022-12-31 00:24:42
【问题描述】:

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

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

【问题讨论】:

  • 它将是实际类型,我。 e.实施。 (一个类可以实现多个接口。)
  • “编程到接口”的推荐对于局部变量有些宽松。
  • @user7655213 不是真的,请检查我的示例代码

标签: java var


【解决方案1】:

我的 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,或组合,或三者兼而有之。我们不在乎,也不知道。

【讨论】:

  • @trashgod 仅供参考,ContextualKeyword 仅在 Java 17 JLS 中添加,而我的回答(和问题也是)日期早于 Java 17 发布。
【解决方案2】:

回答你的问题:

变量的类型将与您分配给用 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 使代码更难阅读,因为它隐藏了变量的类型。当我阅读代码时,我喜欢清楚地看到变量类型并明确声明,无论变量是否是本地变量。
【解决方案3】:

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

假设我们有

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

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

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

所以我们必须考虑三种类型:

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

【讨论】:

    【解决方案4】:

    “官方”局部变量类型推断风格指南 (https://openjdk.java.net/projects/amber/LVTIstyle.html) 提出了这个问题,但说:

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

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

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

      • 关于你的第二段:或者简单地用接口类型声明变量而不是使用 var 关键字。
      猜你喜欢
      • 2020-11-14
      • 2015-04-02
      • 1970-01-01
      • 2011-03-27
      • 2011-04-03
      • 2010-11-11
      • 1970-01-01
      • 2011-04-11
      • 2011-09-30
      相关资源
      最近更新 更多