2016-09-16 32 views
0

在下面的代碼中,我嘗試調用具有Int參數的對象的方法(將其值設爲3)。這返回一個錯誤,Int3是不兼容的類型。使用Int參數的斯卡拉反射

//Using scala's Int does not work! 
object MyObject{ 
    def handleInt(id:Int) : Boolean = { 
    true 
    } 
} 

object testApp extends App { 
    val obj = MyObject.getClass 
    val method = obj.getDeclaredMethod("handleInt", classOf[Int]) //Int.getClass shows the same behavior 
    val rsp = method.invoke(obj, 3) 
} 

Error:(106, 41) the result type of an implicit conversion must be more specific than AnyRef

val rsp = method.invoke(obj, 3) 

Error:(106, 41) type mismatch; found : Int(3) required: Object

val rsp = method.invoke(obj, 3) 

我想在這裏改變了很多東西,只是這可能是工作的方式是改變所有簽名Java的Integer。該代碼將是這樣的:

//This works with Java's Integer 
object MyObject{ 
    def handleInt(id:Integer) : Boolean = { 
    true 
    } 
} 

object testApp extends App { 
    val obj = MyObject.getClass 
    val method = obj.getDeclaredMethod("handleInt", classOf[Integer]) 
    val rsp = method.invoke(obj, 3) 
} 

我的問題(S)是:

  1. 有人可以解釋爲什麼出現這種情況?我認爲斯卡拉的Int包裝Java的原始int(這就是爲什麼這不被認爲是對象),但我不知道。
  2. 有沒有一種方法可以使用Scala的Int類型實現這個功能?
  3. 像這樣混合scala和java類型是可以接受的嗎?這是一個好習慣嗎?

回答

0

不,我們不能使用Scala類型。

它可以混合使用Java和Scala類型。

由於反射涉及運行時讀取類字節碼。在字節碼級別,只有可見的類型是Java類型,因爲所有的scala類型都歸結爲Java類型。

1

第一個問題是你調用方法對不對象:obj沒有handleInt方法,MyObject沒有。第二種是一種邊緣情況:invoke需要Object...可變參數和斯卡拉不會自動將Int直接轉換爲Object,因爲這不是您通常想要做的。您可以使用類型歸屬來說「將此Int裝入Integer」,然後Scala將自動將其上傳到Object

因此,結合這2個修復:你不需要改變handleIntval method,只是

val rsp = method.invoke(MyObject, 3: Integer) 

要回答你的最後一個問題:使用的Integerjava.lang.Double等,不應該在普通Scala代碼,但它並沒有特別的問題。反思是您可能必須使用它們的領域之一。