gpt4 book ai didi

scala - 上下文绑定(bind) [T : Manifest] -> Nothing

转载 作者:行者123 更新时间:2023-12-01 14:15:32 24 4
gpt4 key购买 nike

我使用 Jackson Scala 模块。

我创建了一个小的序列化工具来处理 Play2 框架接收到的 json 负载。

  def unserializePayloadAs[T](implicit requestContext: RequestContext[JsValue]): T = {
val json: String = Json.stringify(requestContext.request.body)
unserialize(json)
}

def unserialize[T](json: String): T = {
objectMapper.readValue(json)
}

Jackson Scala 模块的 readValue 具有签名:

  def readValue[T: Manifest](content: String): T = {
readValue(content, constructType[T])
}

当尝试使用我的反序列化代码时,我有一个堆栈。

Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate abstract type [simple type, class scala.runtime.Nothing$] (need to add/enable type information?)
at [Source: java.io.StringReader@7bb78579; line: 1, column: 2]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:164) ~[jackson-databind-2.2.0.jar:2.2.0]
at com.fasterxml.jackson.databind.deser.std.ThrowableDeserializer.deserializeFromObject(ThrowableDeserializer.java:77) ~[jackson-databind-2.2.0.jar:2.2.0]
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:121) ~[jackson-databind-2.2.0.jar:2.2.0]
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:2888) ~[jackson-databind-2.2.0.jar:2.2.0]
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2041) ~[jackson-databind-2.2.0.jar:2.2.0]
at com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper$class.readValue(ScalaObjectMapper.scala:157) ~[jackson-module-scala_2.10-2.2.0.jar:2.2.0]
at utils.CustomSerializer$$anon$1.readValue(CustomSerializer.scala:17) ~[na:na]
at utils.CustomSerializer$.unserialize(CustomSerializer.scala:39) ~[na:na]
at utils.CustomSerializer$.unserializePayloadAs(CustomSerializer.scala:35) ~[na:na]

正如预期的那样,当我在我的代码中添加 list 时它工作正常:

  def unserializePayloadAs[T: Manifest](implicit requestContext: RequestContext[JsValue]): T = {
val json: String = Json.stringify(requestContext.request.body)
unserialize(json)
}

def unserialize[T: Manifest](json: String): T = {
objectMapper.readValue(json)
}

有人能解释一下那里发生了什么吗?当我们调用一个带有 Manifest 上下文绑定(bind)的方法时,使用一个没有 Manifest 的参数化方法,然后 Nothing 的 Manifest 被提供给第一个方法?

我本以为会出现某种编译错误,告诉我我正在使用没有 Manifest 或类似内容的参数化类型调用 readValue,这似乎更快失败。

最佳答案

举一个稍微简单一点的例子:

def getManifest[A: Manifest] = implicitly[Manifest[A]]

或等效的脱糖版本:

def getManifest[A](implicit whatever: Manifest[A]) = whatever

然后:

scala> def getIt[T]: Manifest[T] = getManifest
<console>:8: error: type mismatch;
found : Manifest[Nothing]
required: Manifest[T]
Note: Nothing <: T, but trait Manifest is invariant in type T.
You may wish to investigate a wildcard type such as `_ <: T`. (SLS 3.2.10)
def getIt[T]: Manifest[T] = getManifest
^

发生的事情是,当编译器尝试为 getManifest 推断类型参数时,有很多类型在范围内具有 Manifest 实例,它没有办法在它们之间进行选择,因此它使用默认选择 Nothing

(您在运行时而不是编译时看到此错误,因为这就是您使用基于反射的序列化方法时发生的情况。)

我们可以添加一个上下文绑定(bind):

def getIt[T: Manifest]: Manifest[T] = getManifest

或者,等价地:

def getIt[T](implicit whatever: Manifest[T]): Manifest[T] = getManifest

现在一切都很好——范围内有一个最精确的 Manifest 实例,因此编译器可以(适本地)将 getManifest 的类型参数解析为 T

您可以在以下示例中更加生动地看到这一点:

scala> trait Foo[A]
defined trait Foo

scala> def getFoo[A: Foo] = implicitly[Foo[A]]
getFoo: [A](implicit evidence$1: Foo[A])Foo[A]

scala> implicit object stringFoo extends Foo[String]
defined module stringFoo

scala> def getIt[T]: Foo[T] = getFoo
<console>:10: error: type mismatch;
found : Foo[String]
required: Foo[T]
def getIt[T]: Foo[T] = getFoo
^

由于范围内只有一个 Foo 实例(对于 String),编译器可以在解析 getFoo 的类型参数时选择它,我们最终会遇到不同的类型不匹配。

关于scala - 上下文绑定(bind) [T : Manifest] -> Nothing,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17651530/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com