为了账号安全,请及时绑定邮箱和手机立即绑定

为什么JAVA 10中的var无法初始化为null?

为什么JAVA 10中的var无法初始化为null?

慕勒3428872 2021-04-09 22:19:50
我正在尝试在JAVA 10中引入的新功能,在其中发现了一个非常有趣的事实,即您不能使用null声明变量。在您编写以下代码后,var a = null;它抛出一个错误:变量初始值设定项为null现在,众所周知,我们不能将原始类型声明为null,因此下面的语句没有任何意义。int a  = null;这意味着,如果开发人员正在使用null初始化var,则它肯定要在其中放置一个Object,而不是文字val。如果是这样,我的问题是为什么编译器不将其视为Object var而是抛出错误。另一方面,如果您编写以下语句,则可以很好地工作:var a = (Object)null;用null声明var的原因是什么考虑以下情况,我想初始化var并想在条件块外使用它:var a = null;if(some condition) Initialize with some argumentselse Initialize with some other arguments//Use a variable here因此,在这种情况下,由于我们希望a的范围在条件块之外,因此我们有必要初始化它,如果if块,则它将为null,这在使用var时是不可能的。
查看完整描述

3 回答

?
噜噜哒

TA贡献1784条经验 获得超7个赞

编译器可以应用于(至少)三种可能的类型推断策略var o = null

  • 挑选 Void

  • 挑选 Object

  • 寻找稍后的初始化并选择该类型

所有这些在技术上都是可行的,因此出现了一个问题,这对开发人员来说最有意义。

显然,这Void是毫无用处的,我认为这Object也没有太大用处。尽管正确,但选择其中任何一种类型都不太可能帮助开发人员编写更好和更具可读性的代码。

避免初始化的最后一个选项不是为了避免所谓的“远距离动作”错误而特意采用的:


var parent = null;

// imagine some recursion or loop structure, so this makes more sense

processNode(parent); // expects a parameter of type `Node`

parent = determineParent(); // returns a parameter of type `Node`

如果编译器推断Node为parent,因为determineParent()回报它,这将汇编。但是代码很脆弱,因为更改最后一行可能会导致在第一行中选择不同的类型,从而在第二行中编译错误。这不好!


我们已经习惯了这样的事实,即更改类型的声明可能会导致错误,但在此更改(第3行),其效果(第1行)和随之而来的错误(第2行)可能相距甚远,这使得对于开发人员来说,了解或更好地预测会发生什么事情要复杂得多。


通过保持简单的类型推断规则,开发人员可以更轻松地形成一个简单但正确的思维模式。


附录

令人怀疑的是,从以后的初始化中推断类型的选项3在技术上是否确实可行。我的看法是基于对JEP 286的理解,尤其是:


另一方面,我们可以将该功能扩展为包括“空白”末尾的局部等效项(即,不需要初始化程序,而是依赖于明确的赋值分析。)我们选择了“仅具有初始化程序的变量”的限制覆盖了很大一部分候选对象,同时保持了功能的简单性并减少了“远距离操作”错误。


同样,在推断类型时,我们也可以考虑所有分配,而不仅仅是初始化程序。虽然这将进一步增加可利用此功能的本地人的比例,但也会增加“远距离行动”错误的风险。


查看完整回答
反对 回复 2021-04-18
?
元芳怎么了

TA贡献1798条经验 获得超7个赞

我要问的是,在这种情况下,我们如何扩大范围。因此,例如,如果我想在条件块内初始化变量,但又想扩展范围,以便可以在块外使用相同的变量,那么在var情况下可以做什么。


答案是您可以使用:


var a = (RealType) null;

或(对此很明智)使用常规的类型声明:


RealType a = null;

的var形式仅仅是语法糖:一个方便,以避免不必编写特定的类型。当您使用初始化时,它根本不起作用null。推断Object的类型a是没有用的行为在绝大多数情况下。


例如,如果(假设)为avar分配了null:


    var a = null;            

    if (something) {

        a = someMethodReturningRealType();

    }

    a.someRealTypeMethod();  // Compilation error ... because the inferred

                             // type is java.lang.Object.  Oops!!

这是编写代码的正确方法:


    RealType a = null;       // Just use a classic variable declaration

    if (something) {

        a = someMethodReturningRealType();

    }

    a.someRealTypeMethod();

我的示例只是分享我们可能需要将var声明为null的所有地方。似乎没有明确的方法可以做到这一点。


不。您不需要这样做。您想这样做...但是“想要”和“需要”不是同一回事。


而且,这是一个非常基本的问题,好像我们可以做到Object x = null;为什么我们不能做到var x = null;


因为JLS禁止这样做。就是这样。故事结局。


如果您不喜欢它,那很好。但这不是讨论论坛。无论如何,我们不是需要说服的人。


查看完整回答
反对 回复 2021-04-18
?
慕神8447489

TA贡献1780条经验 获得超1个赞

从Oracle JDK 10页面:


您不能只使用var语法来声明没有值的变量,也不能将var变量初始化为null。实际上,尚不清楚类型应该是什么,因为它可能打算用于后期初始化。


因此,基本上,您必须具体确定所需的数据类型,编译器不能仅仅假定您想要的数据类型Object或任何其他类型。


因此,以下所有操作均会导致编译失败:


var x;


var x = null;


var x = () -> {}


查看完整回答
反对 回复 2021-04-18
  • 3 回答
  • 0 关注
  • 198 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信