繁体   English   中英

在scala中使用java格式化程序

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM