vals的初始化顺序

vals的初始化顺序

本文介绍了Scala - vals的初始化顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个代码从文件加载属性:

I have this piece of code that loads Properties from a file:

class Config {
  val properties: Properties = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
  }

  val forumId = properties.get("forum_id")
}

似乎工作正常。

我已经尝试将属性的初始化移动到另一个val, loadedProperties ,像这样:

I have tried moving the initialization of properties into another val, loadedProperties, like this:

class Config {
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")

  private val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
   }

}

但它不工作! (属性 properties.get(forum_id))中为空。

But it doesn't work! (properties is null in properties.get("forum_id") ).

为什么会这样?当属性引用时,不是 loadedProps

Why would that be? Isn't loadedProps evaluated when referenced by properties?

其次,这是一个很好的方法来初始化需要非平凡处理的变量吗?在Java中,我将声明它们 final 字段,并在构造函数中进行初始化相关的操作。

Secondly, is this a good way to initialize variables that require non-trivial processing? In Java, I would declare them final fields, and do the initialization-related operations in the constructor.

在Scala中有这种情况的模式吗?

Is there a pattern for this scenario in Scala?

谢谢!

推荐答案

Vals会按照(正确地,非惰性 vals),因此属性 loadedProps 。或者换句话说,当属性时, loadedProps 仍然是 null 正在初始化。
这里最简单的解决方案是在属性之前定义 loadedProps

Vals are initialized in the order they are declared (well, precisely, non-lazy vals are), so properties is getting initialized before loadedProps. Or in other words, loadedProps is still null when propertiesis getting initialized.The simplest solution here is to define loadedProps before properties:

class Config {
  private val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
  }
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")
}

您也可以使 loadedProps 它将在其第一次访问时被初始化:

You could also make loadedProps lazy, meaning that it will be initialized on its first access:

class Config {
  val properties: Properties = loadedProps
  val forumId = properties.get("forum_id")

  private lazy val loadedProps = {
    val p = new Properties()
    p.load(Thread.currentThread().getContextClassLoader.getResourceAsStream("props"))
    p
  }
}

使用lazy val有一个优点,你的代码更强大的重构,因为只是改变你的vals的声明顺序不会破坏你的代码。

Using lazy val has the advantage that your code is more robust to refactoring, as merely changing the declaration order of your vals won't break your code.

在这种情况下,你只需将 loadedProps 转换为 def (由@NIA建议)仍然使用一次。

Also in this particular occurence, you can just turn loadedProps into a def (as suggested by @NIA) as it is only used once anyway.

这篇关于Scala - vals的初始化顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-28 08:10