具有和不具有类型归属的最终val的Scala不一致行为
发布时间:2020-12-16 09:54:47 所属栏目:安全 来源:网络整理
导读:我使用 scala 2.10.3,我注意到以下行为 object TestConstantScala { final val str1 : String = "foo:" + number1 final val number1 : Int = 123 final val number2 : Int = 123 final val str2 : String = "foo:" + number2 def main(args: Array[String])
我使用
scala 2.10.3,我注意到以下行为
object TestConstantScala { final val str1 : String = "foo:" + number1 final val number1 : Int = 123 final val number2 : Int = 123 final val str2 : String = "foo:" + number2 def main(args: Array[String]){ System.out.println(str1) System.out.println(str2) } } 输出: foo:0 foo:123 而我的问题是为什么订单有所作为.另外,如果我省略了Int定义,它返回的行为正常 解决方法
如果没有类型ascription(:Int),number1甚至不作为字段存在,因此不需要初始化.相反,编译器创建一个直接返回值123的访问器方法,并在构造函数中使用文字值123来初始化str1.
为什么在存在类型归属时会创建字段?在这种情况下它确实没有意义,但有时类型归属可能需要执行值转换的代码,例如装箱基元或应用隐式转换.由于语义原因(对象标识,隐式转换中的副作用)和效率,这些操作应该只进行一次.因此,结果必须存储在字段中. 因此,没有类型归属的行为是对初始化为常量值的最终基元字段的优化,并且编译器不够智能,无法在存在类型归属时应用优化. 这是一个更小的例子: object TestConstantScala { final val brokenStr: String = "foo:" + brokenNumber final val brokenNumber: Int = 123 final val workingStr: String = "foo:" + workingNumber final val workingNumber = 123 println(brokenStr) println(workingStr) } 这里是scalac -Xprint:constructors的输出,在将初始化移动到构造函数后立即显示AST: [[syntax trees at end of constructors]] // test18.scala package <empty> { object TestConstantScala extends Object { final private[this] val brokenStr: String = _; final <stable> <accessor> def brokenStr(): String = TestConstantScala.this.brokenStr; final private[this] val brokenNumber: Int = _; final <stable> <accessor> def brokenNumber(): Int = TestConstantScala.this.brokenNumber; final private[this] val workingStr: String = _; final <stable> <accessor> def workingStr(): String = TestConstantScala.this.workingStr; final <stable> <accessor> def workingNumber(): Int(123) = 123; def <init>(): TestConstantScala.type = { TestConstantScala.super.<init>(); TestConstantScala.this.brokenStr = "foo:".+(scala.Int.box(TestConstantScala.this.brokenNumber())); TestConstantScala.this.brokenNumber = 123; TestConstantScala.this.workingStr = "foo:".+(scala.Int.box(123)); scala.this.Predef.println(TestConstantScala.this.brokenStr()); scala.this.Predef.println(TestConstantScala.this.workingStr()); () } } } 注意workNumber没有字段,只有一个访问器,以及构造函数workStr如何用“foo:”初始化. (scala.Int.box(123)). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |