在您给出的简单示例中,生成的字节码没有区别,因此性能没有区别。它也不会对编译速度产生明显影响。
在更复杂的代码(可能涉及隐式)中,您可能会遇到通过指定某些类型会显着提高编译类型性能的情况。但是,我会完全忽略这一点,除非您遇到它——出于其他更好的原因指定类型或不指定类型。
更符合您的问题,在一个非常重要的情况下,最好指定类型以确保良好的运行时性能。考虑这段代码:
val x = new AnyRef { def sayHi() = println("Howdy!") }
x.sayHi
该代码使用反射来调用 sayHi,这对性能造成了巨大的影响。出于这个原因,最新版本的 Scala 会警告您此代码,除非您已为其启用语言功能:
warning: reflective access of structural type member method sayHi should be enabled
by making the implicit value scala.language.reflectiveCalls visible.
This can be achieved by adding the import clause 'import scala.language.reflectiveCalls'
or by setting the compiler option -language:reflectiveCalls.
See the Scala docs for value scala.language.reflectiveCalls for a discussion
why the feature should be explicitly enabled.
然后您可以将代码更改为不使用反射的代码:
trait Talkative extends AnyRef { def sayHi(): Unit }
val x = new Talkative { def sayHi() = println("Howdy!") }
x.sayHi
因此,您通常希望在以这种方式定义类时指定变量的类型;这样,如果您无意中添加了一个需要反射才能调用的方法,您将得到一个编译错误——该方法不会为变量的类型定义。因此,虽然指定类型不会使代码运行得更快,但 如果代码会很慢,指定类型会导致编译失败。
val x: AnyRef = new AnyRef { def sayHi() = println("Howdy!") }
x.sayHi // ERROR: sayHi is not defined on AnyRef
当然还有其他原因可能会导致您想要指定类型。它们是方法/函数的形式参数以及递归或重载方法的返回类型所必需的。
此外,您应该始终为公共 API 中的方法指定返回类型(除非它们非常明显),否则您最终可能会得到与您预期不同的方法签名,然后冒着破坏 API 现有客户端的风险修复签名。
你当然可能想故意扩大一个类型,以便以后可以将其他类型的东西分配给一个变量,例如
var shape: Shape = new Circle(1.0)
shape = new Square(1.0)
但在这些情况下,不会影响性能。
指定类型也有可能导致转换,当然这会对转换产生的任何性能影响产生影响。