id = "124"
让我们从后文找出引入 var 类型推断的的原因,以及它是如何影响代码可读性的,为什么 val 与 let 没有随之一起引入.如果你还是对其他细节颇有兴趣,可以参照官方 JEP 286, var FAQ 问题解答,或者是 Amber 项目的邮件列表.
But why?!
Java 的语法历来以冗长著称,尤其是对比一些年轻的语言,这以及成为开发者最大的痛点之一,你往往会听到一些初学者与高级开发者的诟病与抱怨.Project Amber, var 的原始项目, 致力于孵化出一种 "体积更小,面向生产效率" 的 Java 新语言特性,减少一些以往过于累赘的语法规则.
如此,局部变量类型推断机制(Local-variable type inference)便应运而生了.在编写代码的时候,可以很明显地使变量的声明变得简洁,虽然到目前为止我仍认为它与 IDE 的自动生成功能相比是喜忧参半的,比如在重写过程中,或者写一个构造方法,抑或是为方法的返回值声明一个类型.
var 的好处除了使局部变量的声明更加简便之外,还能使代码相得益彰,why?如果你曾经或现在致力于过企业级开发,你会觉得那些命名相当丑陋.下面就是一个典型栗子:
InternationalCustomerOrderProcessor<AnonymousCustomer, SimpleOrder<Book>> orderProcessor = createInternationalOrderProcessor(customer, order);
它就像王大娘的裹脚一般,又臭又长,一个很简单的功能要写到吐血,中间还夹叙夹议才能保证语义明确,避免后期维护的时候看不懂写的什么.
var orderProcessor = createInternationalOrderProcessor(customer, order);
以往声明中间变量的爱恨纠葛,在引入了 var 之后可以彻底地冰释前嫌了,现在你在方法体内可以什么也不管,一路 var 下去,特别是一些嵌套的或者连锁表达式,它的好处也更加显而易见.
简而言之,var 就是减少 Java 累赘语法的一颗语法糖,谁先尝到谁先甜到忧伤.
And What About 可读性?
现在来看看可读性的影响.毫无疑问,使用 var 势必会引起变量类型可视化缺失, 这会伤害一部分的可读性,特别是当你想要知道一些代码的运行逻辑的时候,能够目所能及地看到变量类型显得格外重要,尽管将来的 IDE 可能会智能显示所有推断类型,这是当前唯一可能会受到批评的地方.
针对可读性缺失,var 从其他地方来弥补,其中一种方式就是使变量名称对其(呵呵 00 好像是好看了一些):
// with explicit types
No no = new No();
AmountIncrease < BigDecimal > more = new BigDecimalAmountIncrease();
HorizontalConnection < LinePosition,
LinePosition > jumping = new HorizontalLinePositionConnection();
Variable variable = new Constant(5);
List < String > names = List.of("Max", "Maria");
// with inferred types
var no = new No();
var more = new BigDecimalAmountIncrease();
var jumping = new HorizontalLinePositionConnection();
var variable = new Constant(5);
var names = List.of("Max", "Maria");
变量类型固然重要,但是变量名称才是决定性因素.类型描述了 Java 整个生态系统(JDK),通用用例(库或框架),以及业务领域(应用程序). 但一个又一个渺小的变量名称才是串起这一些的枢纽.就像 JS 那样,不也风靡世界吗?
使用 var 的时候,变量名可以忽略类型名近乎以顶格的方式存在,特别是当你双击选中其中一个变量名的时候,不同以往的满天星的呈现,如今可以排列地整整齐齐.Kotlin 的这一点不也广受欢迎?
如上所述,舍弃掉变量类型显示声明,换来了另一种方式的可读性,我们要做的就是适应.
Finding A Style
当然,使用 var 固然容易,但是我们需要在可读性和简洁性之间取得平衡.甲骨文的 Java 语言架构师,负责 Amber 项目的 Brian Goetz 给了我们启示:
当我们需要使代码更清晰,更简洁的同时不会丢失掉一些重要信息,那就使用 var.
为什么不用 val/let?
许多使用 var 为主变量的语言会为不可变变量提供一个额外的关键字,通常是 val 或者 let,但是我们在 Java 10 将会使用 final var,促成这个结果的原因有以下几点:
不可变变量比局部变量更加重要.
从 Java 8 开始,我们 Effectively final 的概念(局部内部类和匿名内部类访问的局部变量必须由 final 修饰,java8 开始,可以不加 final 修饰符,由系统默认添加.java 将这个功能称为:Effectively final 功能)
引入 var 的赞扬度很高 (74% 强烈支持, 12% 中度支持) 反观 var/ val 与 var/ let 的组合则含糊不清.
这个结果其实有些令人失望的,让 val 或者 let 替代 final var 不是也挺好的吗?
Well, maybe in the future... until then we have to use final var.
总结
在 Java 10 之后你在声明局部变量类型的时候可以使用 var 来告知编译器进行类型推断,取代之前的类名或接口名.这仅仅发生在变量初始化的阶段,就像 var s = ""; 这样. 此外,for 循环中的索引变量类型也可以使用 var.它由编译器推断类型,然后将推断出的类型写入字节码中,也就是说它对运行时并没有任何影响,仅仅是一个语法糖,Java 仍然是一种静态语言.
除了局部变量之外,另外在属性和方法返回值类型中,不能使用 var. 这样做是为了避免引起一些无法预知的错误,使用的时候尽量使需要推断的变量靠近它声明的地方,从而缓解可读性问题.
尽管引入 var 变量会使代码可读性变得更糟,但此次的新特性为开发者提供了一种在编写复杂表达式的时候寻求了一个新的契机.
略有改动 原文参考
来源: https://juejin.im/post/5a61758c51882573443cc265