Mic*_*ill 32 program-entry-point scala traits
我刚刚开始学习Scala,我正在遵循的许多教程都使用了一种main方法的不同表示形式的组合.除了熟悉的主要方法; 还有使用特征App或Application.它似乎Application已被弃用,不推荐使用,但我找不到任何有关这些定义入口点的方法的信息.
所以,我想知道是否有人可以向我解释:
App和Application工作如何?Application不再推荐这个App特性,这个特性有什么不同呢?App来启动我的程序?这两种方法有什么区别?Raf*_*ter 28
特征的问题Application实际上在其文档中描述:
(1)引用该对象的线程代码将阻塞,直到静态初始化完成.但是,因为扩展Application的对象的整个执行发生在静态初始化期间,所以如果并发代码必须与封闭对象同步,则它们将始终死锁.
这是一个棘手的问题.如果扩展Application特征,基本上就是创建一个Java类:
class MyApplication implements Application {
static {
// All code goes in here
}
}
Run Code Online (Sandbox Code Playgroud)
JVM运行上面隐式在MyApplication类上同步的类初始化程序.这样,可以确保MyApplication在初始化类之前不会创建任何实例.如果从应用程序生成一个再次需要访问其实例的线程,则应用MyApplication程序将无法锁定,因为类初始化仅在整个程序执行完毕后才完成.这意味着一个矛盾,因为只要您的程序正在运行,就不能创建任何实例.
(2)如上所述,无法获取命令行参数,因为扩展Application的对象体中的所有代码都是作为静态初始化的一部分运行的,这是在Application的main方法甚至开始执行之前发生的.
类初始值设定项不接受任何参数.此外,它首先运行,然后可以将任何值传递给类,因为在您甚至可以分配静态字段值之前需要执行类初始化程序.因此,args您通常在main方法上收到的内容将丢失.
(3)静态初始化程序在程序执行期间只运行一次,而JVM作者通常认为它们的执行时间相对较短.因此,某些JVM配置可能会变得混乱,或者只是无法优化或JIT扩展Application的对象体中的代码.这可能导致显着的性能下降.
JVM优化了经常运行的代码.这样,它确保不会浪费任何不是性能瓶颈的方法的运行时间.但是,它安全地假定static方法只执行一次,因为它们无法手动调用.因此,它不会优化从类初始化程序运行的main代码,如果您正在使用该Application特征,则该类初始化程序是应用程序的方法代码.
该App特征通过扩展来解决所有这些问题DelayedInit.Scala编译器明确知道此特征,因此初始化代码不是从类初始化程序运行,而是从另一个方法运行.请注意名称引用是特征的唯一方法:
trait Helper extends DelayedInit {
def delayedInit(body: => Unit) = {
println("dummy text, printed before initialization of C")
body
}
}
Run Code Online (Sandbox Code Playgroud)
实现时DelayedInit,Scala编译器将其实现类或对象的任何初始化代码包装到for name函数中,然后传递给该delayedInit方法.不直接执行初始化代码.这样,您还可以在运行初始化程序之前运行代码,这样可以让Scala将应用程序的运行时指标打印到控制台,该控制台包含在程序的入口点和退出处.不过,也有这种做法的一些注意事项和使用DelayedInit,因此不推荐使用.你应该真正只依赖于App解决特质所带来的问题的Application特性.你不应该DelayedInit直接实施.
main如果你愿意,你仍然可以定义一个方法,只要你在一个方法中定义它object.这主要是风格问题:
object HelloWorld {
def main(args: Array[String]) {
println("Hello, world!")
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10950 次 |
| 最近记录: |