当前位置: 首页 > 知识库问答 >
问题:

将单例对象编码为惰性VAL

楚博雅
2023-03-14

我们正在为Scala程序开发一个静态验证器(本硕士论文中描述的早期工作),目前的重点是验证涉及延迟评估的Scala特性。我们主要感兴趣的是特征的语义(行为),而不是其他(尽管很重要)方面,如可理解性或简洁性。

为了简化事情,我们暂时忽略了单例对象可能具有的特殊角色。例如,有些是伴随对象(这可能与它们的懒惰性质正交),或者有些是包对象。

懒惰的瓦尔斯

假设一个懒惰的瓦尔

lazy val v = I

其中I是初始化块,即确定懒惰val值的代码。初始化块I在第一次取消引用懒惰valv时执行。

单例对象

假设一个单态对象

object Foo {
  C1

  val v1 = I1
  var v2 = I2
  lazy val v3 = I3
  def m() {C2}
}

其中,C1是构成对象Foo构造函数的代码,I1I3也是初始化器块,C2是方法m的主体。当第一次使用对象Foo时(取消引用或分配给变量/字段),然后执行C1、I1I2I3仅在Foo时执行。v3被解除引用(因为v3是一个惰性val),每当调用m时,就会执行C2

考虑这个版本的<代码> Foo,其中Stutelon对象已经被一个懒惰的VAR和一个匿名类编码:

// Should probably sit in a package object
lazy val Foo = new {
  C1

  val v1 = I1
  var v2 = I2
  lazy val v3 = I3
  def m() {C2}
}

有人能想出一个原因来解释为什么将单例对象Foo编码为懒惰val会显示出与原始单例对象不同的行为吗?也就是说,是否存在编码版本的语义与原始代码不同的情况?

共有1个答案

司寇书
2023-03-14

至少有一个主要的语义差异,我在下面解释了。我认为在多线程上下文中有一些角落情况,因为对象是在他们类的静态初始化器期间创建的,静态初始化器与锁有一种奇怪的交互。但是我不是JVM多线程专家,所以我不知道细节。

不管怎样,即使在单线程上下文中也会发生一些事情(至少在当前标准库中的Maniests,也许还有ClassTags的实现中使用)。

考虑以下两个对象:

object A {
  val other = B
}
object B {
  val other = A
}

这是有效的Scala代码,访问A.其他B.其他将正确返回另一个。这是因为A的"val"是在调用超级构造函数后初始化的。本质上,您可以以某种方式将上述对象翻译成这个"低级"代码

private var instanceA: AClass = null
def A(): AClass = {
  if (instanceA == null)
    new AClass
  instanceA
}
class AClass {
  def this() = {
    // reification of the constructor of A
    super()
    instanceA = this
    this.other = B()
  }
}

当然,B的翻译也是类似的。您可以看到,在调用B()初始化A.other时,全局变量instanceA已经初始化。因此,当创建B并访问A()以初始化B.other时,def A()将立即返回A的正确实例。

lazy vals没有这种早期初始化,因此将对象编码为简单的lazy vals不会飞行。访问任何一个对象都将“死锁”,只有线程在等待自己。

 类似资料:
  • 问题内容: 希望我不必在这里重新发明轮子,但是有人知道C#中是否有一个类似于Adobe为AS3提供的类,用于将通用对象转换为JSON字符串的类? 例如,当我编码一个对象数组时。 输出: 问题答案: 在C#中:

  • 问题内容: 是否有将JavaScript对象编码为JSON的好方法? 我有一个键值对列表…其中名称来自复选框,根据是否选中该框,值为true或false: 我想将这些值传递到JSON对象中,然后存储到cookie中以呈现表(将根据用户检查的内容添加列)。 有人知道解决方案吗? 问题答案: 我认为您可以使用JSON.stringify:

  • 问题内容: 我想将Javascript对象编码为JSON字符串,但遇到了很多困难。 对象看起来像这样 我想将其放入JSON字符串以将其放入ajax请求中。 你明白了。不管我做什么,都行不通。所有JSON编码器(如json2等)都会产生 好吧,那对我没有帮助。基本上我想拥有类似php 函数的功能。 问题答案: 除非定义了变量,否则可能是造成您麻烦的原因。这样的事情会做你想要的: 您也可以一次完成所有

  • 问题内容: 我有一个实体: 然后我有一个控制器,其目的是检索书籍,我的问题是,流派字段包含在控制器的json响应中。有什么办法可以排除杰克逊序列化对象时延迟加载的那些字段? 这是我的ObjectMapper的配置: 谢谢! 我无法将其标记为JsonIgnore,因为它将永远在序列化框中。有时候,我将需要随书一起检索体裁,到那时,我将在查询中使用“获取联接”,因此它不会为null。 问题答案: 你可

  • 我的理解是,默认情况下,Hibernate将所有关系类型的FetchType设置为lazy。 在我的例子中,我有一个双向的OneToMany-ManyToOne关系,如下所示: 另一个问题是我如何得到一个有特定名字的孩子?是否可以通过存储库进行操作?还是需要getChildren(parentId)并迭代直到找到以特定方式命名的那个? 编辑:在一些建议之后,我继续这样实现了我的ChildRepos

  • 问题内容: 我有一个对象。我使用将对象编码为json 。 我怎样才能测量json字符串的大小? 问题答案: 并且不公开也不维护写入字节数。 一种方法是先使用内置函数将其编入其长度来封送该值。您要查找的位数是长度乘以8(1字节为8位)。之后,您必须手动将字节片写入输出中。对于小型类型,这不是问题,但是对于大型结构/值,可能是不希望的。另外,也没有必要的工作将其编组,获取其长度并手动编写切片。 一种更