我想在 Scala 中的运行时创建一个类。现在,只考虑一个简单的例子,我想用一些属性来构造一个 java bean,我只在运行时知道这些属性。
如何创建scala类?我愿意从scala源文件创建,如果有一种方法来编译它并在运行时加载它,我可能想要因为我有时有一些复杂的功能,我想添加到类。 我该怎么做?
我担心我读到的scala解释器是对它加载的解释代码进行沙盒化,以便托管解释器的一般应用程序无法使用它?如果是这种情况,那么我将无法使用动态加载的scala类。
无论如何,问题是,如何在运行时动态创建一个scala类并在我的应用程序中使用它,最好的情况是在运行时从scala源文件加载它,如interpreterSource("file.scala")
和它加载到我当前的运行时,第二个最好的情况是通过调用方法即 createClass(...)
来创建它在运行时创建它。
谢谢,菲尔
答案 0 :(得分:7)
没有足够的信息来了解最佳答案,但请记住您在JVM上运行,因此任何适用于Java的技术或字节码工程库在此都应该有效。
您可能会使用数百种技术,但最佳选择完全取决于您的确切用例,因为许多技术不是通用的。这里有几个想法:
对于一个简单的bean,你也可以 只需使用地图,或查看 来自apache commons的DynaBean课程。
您可以获得更高级的行为 显式调用编译器 然后获取生成的.class文件 通过类加载器(这主要是 JSP如何做到这一点)
解析器和自定义DSL非常适合 一些案例。和豆壳一样 脚本。
点击此处查看ScalaDays视频:http://days2010.scala-lang.org/node/138/146 它演示了如何使用Scala作为符合JSR-223的脚本语言。 这应该涵盖您希望在运行时评估Scala的大多数场景。
您还需要查看此处的电子邮件主题:http://scala-programming-language.1934581.n4.nabble.com/Compiler-API-td1992165.html#a1992165
这包含以下示例代码:
// We currently call the compiler directly
// To reduce coupling, we could instead use ant and the scalac ant task
import scala.tools.nsc.{Global, Settings}
import scala.tools.nsc.reporters.ConsoleReporter
{
// called in the event of a compilation error
def error(message: String): Nothing = ...
val settings = new Settings(error)
settings.outdir.value = classesDir.getPath
settings.deprecation.value = true // enable detailed deprecation warnings
settings.unchecked.value = true // enable detailed unchecked warnings
val reporter = new ConsoleReporter(settings)
val compiler = new Global(settings, reporter)
(new compiler.Run).compile(filenames)
reporter.printSummary
if (reporter.hasErrors || reporter.WARNING.count > 0)
{
...
}
}
val mainMethod: Method = {
val urls = Array[URL]( classesDir.toURL )
val loader = new URLClassLoader(urls)
try {
val clazz: Class = loader.loadClass(...)
val method: Method = clazz.getMethod("main", Array[Class]( classOf[Array[String]] ))
if (Modifier.isStatic(method.getModifiers)) {
method
} else {
...
}
} catch {
case cnf: ClassNotFoundException => ...
case nsm: NoSuchMethodException => ...
}
}
mainMethod.invoke(null, Array[Object]( args ))