Java 10局部变量类型推断的优势是什么?

5

我正在尝试理解Java 10本地变量类型推断。我似乎理解了它是什么,但我没有看到任何优势。所以我想知道引入这个功能的背后意图是什么。以下是我的一些观察,请纠正我是否有误。

  1. For example, (unlike other languages) I can not just declare a variable like this

    var abc;
    

    I need to initialize it(But cannot initialize to null). So I don't really see any advantage whatsoever.

  2. One of the other arguments I saw is that previously we had to declare a variable like this with its explicit types.

    Map<User, String> userChannels = new HashMap<>();
    

    Now I can do it like this

    var userChannels = new HashMap<User, String>();
    

随着现代IDE(如IntelliJ IDEA)的支持代码自动补全功能,我无法想象这给上述情况带来了任何额外的优势。

我读到的其他一些观点是:

多态代码与var不兼容。
而且我不能将var用于非可指定类型,例如匿名类。

考虑到所有这些,为什么要引入这个功能呢?请有人能否澄清一下,如果我漏掉了什么。


6
  1. IDE不是浏览器。
  2. 列举优点不在这里的讨论范围内。
  3. 这里是JEP https://openjdk.java.net/jeps/286,用于解释其背后的动机和目标。
- Naman
2
这并非必须的。但是像 Properties properties = new Properties() ; 这样的变量声明现在可以用 var properties = new Properties(); 来声明,有些人更喜欢这种方式。 - NielsNet
3
问题仍然不符合主题。请阅读JEP(Java增强提案)中关于优势、动机和目标的内容,并具体说明在使用或比较该功能时可能遇到的任何问题/疑虑。请注意,翻译后的内容要保持原意并尽量通俗易懂。 - Naman
1
@pvpkiran 如果我不用IntelliJ,用其他什么阅读你的代码呢? - Arthur Attout
3
对我来说,使用此方法的好处是减少了冗余的文本,使代码更加清晰简洁,易于阅读。减少打字量这一事实,无论使用还是不使用IDE,都是额外的小福利。在多个变量一起初始化的情况下,它还可以更好地对齐变量名。 - Slaw
显示剩余11条评论
2个回答

10

其中一个原因是使你的代码更短,更易读。考虑以下示例,在声明后仅使用变量一次或两次。

ReallyLongClassNameBecauseBigEnterpriseProject reallyLongClassAbv = new ReallyLongClassNameBecauseBigEnterpriseProject(foo);
OtherAnnoyingLongClassName otherAnnoyingLongClassName = reallyLongClassAbv.getOtherAnnoyingLongClassName();

如果变量名与类名相同(或者因为可以通过上下文或构造函数推断出类名而缩短了名称),那么类名并没有添加太多的信息。但是,如果您写出{{className.variableName}},那么代码可读性将会更高。
var reallyLongClassAbv = new ReallyLongClassNameBecauseBigEnterpriseProject(foo);
var otherAnnoyingLongClassName = reallyLongClassAbv.getOtherAnnoyingLongClassName();

阅读起来已经更加流畅和快速了,而且由于你已经有了类名,不会失去任何信息。另外,额外的好处是,你的变量名称甚至对齐了!你可能认为这并没有太大的区别,但根据我的经验,在我参与的一些项目中充满了这些语句,我真的希望我不必在每个声明中多次阅读两到三次类名。使用var关键字可以增加信息/文本比率,使代码更简洁。
注意:要明确的是,即使使用var,你仍应避免给你的类赋予无用的长名称,但有时你没有选择或者它来自另一个库。

如评论所述,您可以查看JEP以获得更完整的答案,以及由Stuart Marks撰写的局部变量类型推断的样式指南


开个玩笑:你可以在这里查看如何将你的Java类名企业化的讽刺文章,或者像InstantiationAwareBeanPostProcessorAdapter这样的真实例子。


我没有编辑过以适应屏幕,只是我记得在我的项目中有时变量名没有完整的类名。即使变量名相同,它已经删除了长类名的一个无用出现。你确实可以说人们必须使用更短的类名,但有时在项目中你并不总是有选择的机会,特别是如果它们来自外部库。 - Ricola
2
一个例子是:AbstractSingletonProxyFactoryBean,如果我想把我的变量命名为 bean,因为我只使用它一两次,在上下文中不需要完整的名称,该怎么办? - Ricola
1
撤销了投票,以便分享经验。尽管这主要是一种看法,据说在SO上是不相关的。无论如何,对于那些专注于使用LVTI的人来说,更好的方法是遵循Stuart Marks的风格指南-http://openjdk.java.net/projects/amber/LVTIstyle.html - Naman
只有一个人给你的回答点了踩!虽然不是我,但你被点踩的可能原因之一是你在回答一个(依我看)与 Stack Overflow 不相关的问题。 - skomisa

8

优点:代码更短

StringBuilder buffer = new StringBuilder();  // traditional
var buffer = new StringBuilder();            // new

缺点:在某些情况下不够清晰

Person theFirst = phoneRegister.values().iterator.next();   // At least you know it's a Person
var theFirst = phoneRegister.values().iterator.next();      // Quite a task to find out the type.

希望在任何生产代码中都不会出现这样的一行代码,即使是第一次编写。

缺点:实现类型而非接口

Map<User, String> userChannels = new HashMap<>();   // interface type
var userChannels = new HashMap<User, String>();     // this gives a HashMap variable

使用 "var" 版本,您将获得声明为 HashMap 的变量,而不是 Map,这样可以默默地让您使用 HashMap 类中实现的所有附加方法,而不仅仅是 Map 接口中的方法。因此,如果您以后想要使用不同的实现类,则需要更加努力。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接