[英]Using java formatter in scala
我正在将别人的java代码转换为scala(对于好奇,这是这里的示例)我在下面遇到了编译器错误(有些简化):
var out = new Formatter(new StringBuilder(), Locale.US)
out.format("%s-%d ", someObject, someInteger);
这是我收到的错误消息:
[error] (java.util.Locale,java.lang.String,<repeated...>
[java.lang.Object])java.util.Formatter <and>
[error] (java.lang.String,<repeated...>[java.lang.Object])java.util.Formatter
[error] cannot be applied to (java.lang.String, java.lang.Object, Int)
...
[error] one error found
如果我将第二行更改为:
out.format("%s-%d ", someObject, someInteger.asInstanceOf[Object]);
有人可以解释为什么会这样吗?
这是否意味着在java中传递整数可以预期对象参数但在scala中没有?
其他答案都添加了一些内容,但我不确定他们会解释问题所在。
这一切都归结为Int
是Scala中的一个类,而int
是Java中的一个原语。 因此,在Java中,当你编写一个方法需要一个Object
,并且你传递一个int
,Java会在java.lang.Integer
自动将它包装起来。
现在,Scala中Java的java.lang.Object
等价物是AnyRef
,但Int
不是 AnyRef
的子类。 有一个适当的类型: Any
。 Any
可以包含java.lang.Object
子类以及Java中的原语。 如果你说一个方法需要Any
并传递一个Int
,那么它将被自动装箱,但不是AnyRef
。
因此,每当您与Java接口并且方法希望您传递盒装基元时,您将不得不自己强制进行装箱。 您可以在Scala中创建一个期望Any
的方法,然后将其转换为AnyRef
并调用Java等效项,以便在您打算调用该方法时更容易。
您没有指定someInteger
的定义方式,但我假设您尝试执行以下操作:
val someObject: Object = "this"
val someInteger = 3
var out = new Formatter(new StringBuilder(), Locale.US)
out.format("%s-%d ", someObject, someInteger);
问题是当你在Scala中说someInteger = 3
时,变量是Scala的Int
而不是Java的int
,而Java的Formatter
不知道如何处理它。
如果您将声明更改为使用Java可以理解的整数类型,那么它可以正常工作。 例如:
import java.lang.Integer
val someInteger = new Integer(3)
至于为什么丑陋的asInstanceOf
版本有效? 快速检查REPL将显示正在发生的事情:
scala> 3.asInstanceOf[java.lang.Object].getClass
res0: java.lang.Class[_ <: java.lang.Object] = class java.lang.Integer
因此,当您在Int
上调用.asInstanceOf[java.lang.Object]
时,Scala会返回一个java.lang.Integer
。
但实际上,您应该以更加Scala-ish的方式重写代码。 如果你这样做,安德鲁麦卡勒姆会更开心。
java和scala中的类层次结构不同。 java.lang.Object
位于java中层次结构的根。 在scala中, Any
类型位于根目录中。 因此,任何东西都可以传递给一个带有Any
类型参数的函数。 但是,只能将java.lang.Object
子类型传递给采用java.lang.Object
类型参数的函数。
更糟糕的是,有两种类型的整数。 有scala的Int类型和java.lang.Integer。 前者是您在scala中将某些内容设置为数字时通常会得到的。 后者是你用new Integer(3)
或3.asInstanceOf[Integer]
。 事实证明,scala Int不继承自java.lang.Object,但java.lang.Integer继承。 因此,您无法将scala Int作为期望java.lang.Object的参数传递。 这就是为什么这在scala中不起作用的原因。
Java的故事有点奇怪。 在过去,曾经有过java int
s无法在期望对象的地方传递; 您需要将它们显式转换为java.lang.Integer
。 但是,最新的更改(版本5)会自动为您执行此操作。 这称为自动装箱或拆箱,具体取决于转换的方式。 这就是为什么它在java中工作的原因。
正如dhg所说,scala编译器将Scala int类型视为与Java int类型不同。 您可以尝试导入JavaConversions
隐含,看看是否有帮助。 我不太明白确切的区别(我本以为它会对待它们一样)。
或者,您可以使用Scala格式设置工具:
val someObject: Object = "this"
val someInteger = 3
val out = "%s-%d ".format(someObject, someInteger)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.