示例:
scala> String.format("%d", 2)
<console>:8: error: overloaded method value format with alternatives:
(java.util.Locale,java.lang.String,<repeated...>[java.lang.Object])java.lang.String <and>
(java.lang.String,<repeated...>[java.lang.Object])java.lang.String
cannot be applied to (java.lang.String, Int)
String.format("%d", 2)
^
为什么 Scala 不能处理 String
类的重载format
方法?
使用:Windows 7 64 位上的 Scala 2.9.2。
请改用这个:
"%d".format(2)
String.format
方法是一个 Java 的东西,所以它需要输入参数是 java.lang.Object
的子类型。 Scala的Int
不是java.lang.Object
:
scala> val i: java.lang.Object = 2
<console>:7: error: type mismatch;
found : Int(2)
required: java.lang.Object
Note: an implicit exists from scala.Int => java.lang.Integer, but
methods inherited from Object are rendered ambiguous. This is to avoid
a blanket implicit which would convert any scala.Int to any AnyRef.
You may wish to use a type ascription: `x: java.lang.Integer`.
val i: java.lang.Object = 2
^
要了解更多信息,您应该阅读 Scala 对 AnyVal
和AnyRef
类型的区别。 Java在效率方面区分了对象(如Integer
)和原语(如int
)。 Scala也有类似的区别。 所有类型都从Any
扩展,但"值类型"(基本上对应于基元)从AnyVal
扩展,其他所有内容都从AnyRef
扩展(基本上是java.lang.Object
)。 在此处阅读更多内容。
因此,要使用String.format
,您必须将其替换为Java Integer
,这是一个Object
:
String.format("%d", new java.lang.Integer(2))
但不要这样做;只需以Scala的方式使用它,如上所述。
第一个重载定义无法匹配,因为第一个参数是 Locale
,而您提供了一个 String。
备选方案无法匹配,因为第二个参数是 Object
的 vararg 参数,但您提供了Int
。 Int
不是Object
的子类型(在Scala中称为AnyRef
)。Java通过自动装箱"修复"它,但在Scala类型系统中,没有从原始类型Int
到java.lang.Integer
的自动转换。
如果 Java 定义是泛型的,比如 format[T](f: String, args: T*)
,Scala 将允许你调用,因为 Scala 中的无界类型参数也超过了基元类型。