val,lazy val和def的神秘行为,在我的scala应用程序中隐式转换

时间:2013-05-20 14:49:11

标签: java scala implicit-conversion playframework-2.1

我已经测试了相同代码的三种变体,我让它工作得很好。我想知道为什么会有不同的行为。

所以我有这个工作代码,它将长时间戳转换为ECMA日期标准格式的字符串:

  lazy val dateFormat = new java.text.SimpleDateFormat("yyyy-MM-DD'T'HH:mm:ss.sssZ")

  implicit def dateToECMAFormat(time: Long) = new {
    def asECMADateString: String = {
      dateFormat.format(new java.util.Date(time))
    }
  }

其他有效的变体:

  implicit def dateToECMAFormat(time: Long) = new {
    val dateFormat = new java.text.SimpleDateFormat("yyyy-MM-DD'T'HH:mm:ss.sssZ")

    def asECMADateString: String = {
      dateFormat.format(new java.util.Date(time))
    }
  }

但我不希望SimpleDateFormat一直重新安装。所以我优先考虑第一个。但现在真正的谜团:

  val dateFormat = new java.text.SimpleDateFormat("yyyy-MM-DD'T'HH:mm:ss.sssZ")

  implicit def dateToECMAFormat(time: Long) = new {
    def asECMADateString: String = {
      dateFormat.format(new java.util.Date(time))
    }
  }

最后一段代码编译但在运行时抛出异常;我没有设法从play框架获取堆栈跟踪。我只知道我的控制器在播放框架2.1中返回500(内部服务器错误)而没有任何更多信息(其他控制器工作但主要服务仍在运行)。

在每种情况下,通话都是这样的:100000L.asECMADateString

有人可以向我解释不同的行为,为什么最后一行不起作用?虽然我很好地理解了val,lazy val和def之间的区别,但现在我觉得我错过了一些东西。

更新

代码在这样的对象中调用:

object MyController extends Controller{

  implicit val myExecutionContext = getMyExecutionContext

  lazy val dateFormat = new java.text.SimpleDateFormat("yyyy-MM-DD'T'HH:mm:ss.sssZ")

  implicit def dateToECMAFormat(time: Long) = new {
    def asECMADateString: String = {
      dateFormat.format(new java.util.Date(time))
    }
  }

  def myAction = Action {
    Async {
     future {
       blocking{
         //here get some result from a db
         val result = getStuffFromDb
         result.someLong.asECMADateString
       }
     } map { result => Ok(result) } recover { /* return some error code */ }
   }
  }
}

这是您的基本playframework异步动作调用。

1 个答案:

答案 0 :(得分:2)

由于第1个和第3个示例之间的差异是lazy val,因此我正在查看 您的呼叫(100000L.asECMADateString)的确切位置。 lazy val有助于纠正混合内容的某些“初始化顺序”问题,例如:请参阅this recent issue以查看它是否与您的相似。