簡體   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