2013-06-24 79 views
2

我想要做的就是這個代碼轉換爲斯卡拉:無法Java代碼轉換爲斯卡拉一個

Object[] method1(Object obj) { 
    if (obj instanceof int[]) { 
    int sourceArr[] = (int[]) obj; 
    Integer[] res = new Integer[sourceArr.length]; 
    for (int i = 0; i < sourceArr.length; i++) 
     res[i] = sourceArr[i]; 

    return res; 
    } 
    else if // and so on for double, int, boolean ... 

    else if (obj instanceof Object[]) { 
     return (Object[]) obj; 
    } else { 
     return new Object[] { obj }; 
    } 
    } 

這裏是我的嘗試:

def method1(obj: Any): Array[Any] = obj match { 
    case x: Array[AnyRef] => x 
    case x: Array[Int] => x 
    // and so on for Double, Boolean, Char, Byte, Long.... 
    case _ => new Array[Any]() 
    } 

而且錯誤:

1) overloaded method constructor Array with alternatives: 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int,dim5: Int,dim6: Int,dim7: Int,dim8: Int,dim9: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int,dim5: Int,dim6: Int,dim7: Int,dim8: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int,dim5: Int,dim6: Int,dim7: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int,dim5: Int,dim6: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int,dim5: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int,dim4: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int,dim3: Int)Array[Any] <and> 
[error] (dim1: Int,dim2: Int)Array[Any] <and> 
[error] (_length: Int)Array[Any] 
[error] cannot be applied to() 
[error]  case _ => new Array[Any]() 

2) type mismatch; 
[error] found : Array[Short] 
[error] required: Array[Any] 
[error] Note: Short <: Any, but class Array is invariant in type T. 
[error] You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10) 
[error]  case x: Array[Short] => x 

3) type mismatch; 
[error] found : Array[Long] 
[error] required: Array[Any] 
[error] Note: Long <: Any, but class Array is invariant in type T. 
[error] You may wish to investigate a wildcard type such as `_ <: Any`. (SLS 3.2.10) 
[error]  case x: Array[Long] => x 

// and so on for each type I have -- Double, Boolean, Char, Byte, Long.... 

我該如何解決這個問題?在Scala中有更合理的方法嗎? 請注意,我無法更改Java代碼。

+0

Java代碼是錯誤的。 'float []'不是'Object []'。你的意思是'Object [] res = ...'? –

+0

@RexKerr,對不起,我沒有看到Java代碼有什麼問題。不過,我編輯它以使其更精確。 –

+0

@Rew Kerr:儘管它是錯誤的,但它是(可悲的)有效的java代碼,並且潛在的不一致性在運行時處理(請參見http://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)#Covariant_arrays_in_Java_and_C.23) 。 –

回答

3

您可以刪除最後一種情況:由於其他情況已經涵蓋了所有可能性(Any只能是AnyValAnyRef),因此無法確定。 接下來,你應該改變的返回類型,因爲Array是不變的,因此事實上,Int <: Any(舉例)並不意味着Array[Int] <: Array[Any]

def method1(obj: Any): Array[_] = obj match { 
    case x: Array[AnyRef] => x 
    case x: Array[Int] => x 
    // and so on for Double, Boolean, Char, Byte, Long.... 
} 

這將編譯。但是,這可能還不是你的意思。您的原始Java版本爲原始數組執行輸入數組的副本,如果數組是引用數組,則返回數組,如果最初不是數組,則最終將輸入封裝到單個元素數組中。你的Scala版本沒有做到這一點。 所以我認爲你想要的只是這個:

def method1(obj: Any): Array[_] = obj match { 
    case x: Array[AnyRef] => x 
    case x: Array[_] => x.clone() 
    case x => Array(x) 
} 
+0

這是偉大的,它編譯。你爲什麼用'case x => Array(x)'?不要'case x:Array [AnyRef] => x'和'case x:Array [_] => x.clone()'涵蓋所有可能的情況嗎? –

+0

以及爲什麼'def method1(obj:Any):Array [_]'而不是'def method1(obj:Any):Array [Any]'? –

+0

「......涵蓋所有可能的情況?」。我只是遵循你原來的代碼做了什麼。它對應於你的java代碼中的最後一種情況('return new Object [] {obj};')。 「爲什麼def method1(obj:Any):Array [_]而不是def method1(obj:Any):Array [Any]」。因爲'Array'是不變的,所以(引用自己)Int <:Any(通過示例)並不意味着Array [Int] <:Array [Any]。這是您的類型不匹配錯誤的原因(通過示例Array [Short]不可轉換爲Array [Any])。只是因爲java類型系統中存在漏洞,等價的java代碼纔會編譯好。 –

4

在Java代碼中,你必須重新包裝陣列,所以你必須做相同的斯卡拉也(雖然它很容易與map):

case x: Array[Int] => x.map(_.asInstanceOf[Any]) 

(哦,既然你回來AnyAnyRef,但兩者實際上是一樣的事情到JVM,只是看你想返回一個不如此。

case x: Array[AnyRef] => x.asInstanceOf[Array[Any]] 

但:

case x: Array[Any] = x 

而你混了構造函數調用到Array,可呈現帶一個參數,它是長度 - 與apply方法Array對象,它可以讓你指定的內容。你可能意味着

case _ => Array[Any]() 

或者,如果你真的想換行對象的Java代碼,

case x => Array(x) 
+0

它似乎是正確的,但我真的沒有得到你的意思。特別是,**所以不是:case x:Array [AnyRef] => x.asInstanceOf [Array [Any]] ** - >我沒有這個。 **但是case x:Array [Any] = x ** - >這就是我所擁有的,然而,你爲什麼說「but」?你能解釋一下,我該如何改變我的代碼? –

+0

@Grienders - 在你的問題中,你有** case x:Array [AnyRef] => x **這是** NOT **相同​​。一個輸入爲'Any',另一個輸入'AnyRef'。 –

2

嘗試new Array[AnyRef]()代替。 ObjectAnyRef而不是Any

無論如何,你必須投下結果,如果.asInstanceOf[Array[Any]]。 Java將數組視爲協變,而Scala將它們視爲不變。

+0

最重要的一點是澄清:Java的對象是Scala的任何,對嗎?由於Java中的所有類型(包括Integer,Boolean和所有引用類型)都是從Object繼承的,所以類似於Scala - 來自任何 –

+0

@Grienders否,Java的Object是Scala的AnyRef,因爲Java類型爲int, boolean','double','float','char'和'short'不會從Object繼承,並且'void'甚至不是Java中的一種類型。當您說「所有參考類型」時,您觸及了這一點。 AnyRef是任何引用類型,而Any是任何類型,包括值類型。 –