无法将Java代码转换为Scala代码

时间:2013-06-24 15:06:59

标签: java scala

我想要做的是将此代码转换为Scala:

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代码。

3 个答案:

答案 0 :(得分:3)

在Java代码中,你必须重新打包数组,所以你必须在Scala中也这样做(尽管map很容易):

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

(哦,既然你正在返回Any而不是AnyRef,但两者对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)

答案 1 :(得分:2)

您可以删除最后一个案例:它是未确定的,因为其他案例已涵盖所有可能性(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 )
}

答案 2 :(得分:1)

请尝试使用new Array[AnyRef]()ObjectAnyRef而不是Any

无论如何,如果.asInstanceOf[Array[Any]],您必须投射结果。 Java将数组视为协变,而Scala将它们视为不变量。