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