gpt4 book ai didi

scala - ClassCastException 当 asInstanceOf 用于理解时

转载 作者:行者123 更新时间:2023-12-03 18:37:33 24 4
gpt4 key购买 nike

在 PlayFramework 2.4 中,我尝试将所有 Controller 方法转换为 JavaScript 路由。

val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))

for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods
) yield method.invoke(controller).asInstanceOf[JavaScriptReverseRoute]

但是出现以下错误:
Error injecting constructor, java.lang.ClassCastException: java.lang.String cannot be cast to play.api.routing.JavaScriptReverseRoute 
at controllers.Application.<init>(Application.scala:21)
while locating controllers.Application
for parameter 1 at router.Routes.<init>(Routes.scala:35)
while locating router.Routes
while locating play.api.inject.RoutesProvider
while locating play.api.routing.Router

我添加了一些代码,但我认为这是不必要的代码。之后不会发生异常。
for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods;
action <- method.invoke(controller).toString
) yield method.invoke(controller).asInstanceOf[JavaScriptReverseRoute]

为什么错误发生在第一个代码示例而不是第二个?

最佳答案

让我们一步一步地看代码,看看每一行产生了什么。
我将您的代码转换为完整的示例代码,但我希望我捕获了您代码的精髓。

package controllers

import play.api._
import play.api.mvc._

class Sample extends Controller {
def hello(name: String) = Action {
implicit req =>
import routes.javascript._

val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))
val met = for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods
) yield method
Ok(met.mkString(", "))
}
}

执行此请求时,您将看到类似
public play.api.routing.JavaScriptReverseRoute controllers.javascript.ReverseSample.hello(), public java.lang.String controllers.javascript.ReverseSample._defaultPrefix()

你应该从你的路由中找到你所有的方法,但请注意还有 _defaultPrefix()返回类型为 String 的方法。

这就是您的第一个代码示例不起作用的原因。其中一种方法不返回 JavaScriptReverseRoute并因此引发异常。

这仍然不能解释为什么您的第二个代码示例不起作用。因此,让我们向示例 Controller 添加一些代码:
package controllers

import play.api._
import play.api.mvc._

class Sample extends Controller {
def hello(name: String) = Action {
implicit req =>
import routes.javascript._

val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))
val met = for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods
) yield method.invoke(controller)
Ok(met.mkString(", "))
}
}

请注意,我们还没有强制转换方法调用的结果,请求会产生如下结果:
JavaScriptReverseRoute(controllers.Sample.hello,
function(name) {
return _wA({method:"GET", url:"/" + (function(k,v) {return v})("name", encodeURIComponent(name))})
}
),

仔细看会发现有流氓 ,最后的意思是我们临时的值 val met在位置 0 是 JavaScriptReverseRoute,在位置 1 和空字符串。

因此,查看您的解决方法 action <- method.invoke(controller).toString一次是带有 javascript 的字符串,另一次是空字符串。由于我们处于 for comprehension 中,因此 String 会自动转换为字符数组,如果该数组为空,则不会执行 yield 块。

您的解决方法的问题在于,如果 _.defaultPrefix()一旦产生一个字符串,它将再次抛出一个类转换异常。

更好的解决方案是过滤每个没有异常(exception)结果类型的方法,如下所示:
package controllers

import play.api._
import play.api.mvc._

class Sample extends Controller {
def hello(name: String) = Action {
implicit req =>
import routes.javascript._

val jsRoutesClass = classOf[routes.javascript]
val controllers = jsRoutesClass.getFields.map(_.get(null))
val met = for (
controller <- controllers;
method <- controller.getClass.getDeclaredMethods if method.getReturnType() == classOf[play.api.routing.JavaScriptReverseRoute]
) yield method.invoke(controller).asInstanceOf[play.api.routing.JavaScriptReverseRoute]
Ok(met.mkString(", "))
}
}

这应该导致预期的行为。

关于scala - ClassCastException 当 asInstanceOf 用于理解时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30519754/

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