[原创] 问个关于调用java里有Object[]参数的方法时发生的问题
davepkxxx
2012-01-15
如果一个方法的参数是Object,当然能够被识别为Any。 但是如果参数为Object[]时,就无法识别为Array[Any]了。
public class JavaTest { public void test(Object[] objs) { } } class ScalaTest { def test(objs : Array[Any]) { new JavaTest test objs } } 错误提示如下:
type mismatch; found : Array[Any] required: Array[java.lang.Object] Note: Any >: java.lang.Object, but class Array is invariant in type T. You may wish to investigate a wildcard type such as `_ >: java.lang.Object`. (SLS 3.2.10)
经试验被识别为Array[AnyRef],但是这样Array[AnyVal]就被抛弃了。
求解决方案。
|
|
Eastsun
2012-01-15
这个是Scala的优点。
数组在Java中是协变的,也就是你可以把一个String[] arr传给一个Object[] arr,然后你再在里面存入一个Integer,这样异常就出现了。 而Scala中数组是非协变的,这样就防止了上面情况的出现。 |
|
davepkxxx
2012-01-16
Eastsun 写道 这个是Scala的优点。
数组在Java中是协变的,也就是你可以把一个String[] arr传给一个Object[] arr,然后你再在里面存入一个Integer,这样异常就出现了。 而Scala中数组是非协变的,这样就防止了上面情况的出现。 注意,我写的是Array[Any],不是Array[_ <: Any]。 所以不会出现把Int放到Array[String]里的情况。 |
|
Eastsun
2012-01-16
davepkxxx 写道 Eastsun 写道 这个是Scala的优点。
数组在Java中是协变的,也就是你可以把一个String[] arr传给一个Object[] arr,然后你再在里面存入一个Integer,这样异常就出现了。 而Scala中数组是非协变的,这样就防止了上面情况的出现。 注意,我写的是Array[Any],不是Array[_ <: Any]。 所以不会出现把Int放到Array[String]里的情况。 那你的疑问在哪里? 在Scala中与Java中的Object对等的就是AnyRef,一切都很正常啊。 而Scala中Array[_<:AnyVal]和Java中的int[],double[],...等对应, 即便是在Java中,应该也是无法将一个int[]传给object[]的吧。 所以虽然“Array[AnyVal]就被抛弃了”,但你并没有丢掉任何东西。 当然有时你希望将一个Scala中Array[Int]之类的传入这个方法,这时你必须将相应的array先转转换为Array[AnyRef],具体来说: array.map{_.asInstanceOf[AnyRef]} |
|
davepkxxx
2012-01-16
Eastsun 写道 davepkxxx 写道 Eastsun 写道 这个是Scala的优点。
数组在Java中是协变的,也就是你可以把一个String[] arr传给一个Object[] arr,然后你再在里面存入一个Integer,这样异常就出现了。 而Scala中数组是非协变的,这样就防止了上面情况的出现。 注意,我写的是Array[Any],不是Array[_ <: Any]。 所以不会出现把Int放到Array[String]里的情况。 那你的疑问在哪里? 在Scala中与Java中的Object对等的就是AnyRef,一切都很正常啊。 而Scala中Array[_<:AnyVal]和Java中的int[],double[],...等对应, 即便是在Java中,应该也是无法将一个int[]传给object[]的吧。 所以虽然“Array[AnyVal]就被抛弃了”,但你并没有丢掉任何东西。 当然有时你希望将一个Scala中Array[Int]之类的传入这个方法,这时你必须将相应的array先转转换为Array[AnyRef],具体来说: array.map{_.asInstanceOf[AnyRef]} 最明显的就是Object...不能转换为Any*,只能变为AnyRef*,那么就不能放AnyVal进去了。比如method.invoke(obj, 1, 2, 3)就会报错,在java中是没有问题的。 而且java有Integer[]、Double[],可以当做Object[],scala有么? |
|
Eastsun
2012-01-17
davepkxxx 写道 最明显的就是Object...不能转换为Any*,只能变为AnyRef*,那么就不能放AnyVal进去了。比如method.invoke(obj, 1, 2, 3)就会报错,在java中是没有问题的。 我上面说过,遇到这种情况必须先将Array[AnyVal]转换为Array[AnyRef], 比如你有一个 val intArray = Array(1,2,3) 想调用method.invoke方法,可以这样: method.invoke(obj, intArray.map(_.asInstanceOf[AnyRef]) :_*) davepkxxx 写道 而且java有Integer[]、Double[],可以当做Object[],scala有么?
有的,和Java中一样: scala> val integerArray = Array[Integer](0,1,2) integerArray: Array[Integer] = Array(0, 1, 2) 要注意的是,上面的 val intArray = Array(1,2,3) 和 scala> val integerArray = Array[Integer](0,1,2) integerArray: Array[Integer] = Array(0, 1, 2) 是不一样的,一个是基本数组,一个是Integer数组,第二个因为指定了类型,Scala在编译期间做了隐式转换。 |
|
davepkxxx
2012-01-17
Eastsun 写道 davepkxxx 写道 最明显的就是Object...不能转换为Any*,只能变为AnyRef*,那么就不能放AnyVal进去了。比如method.invoke(obj, 1, 2, 3)就会报错,在java中是没有问题的。 我上面说过,遇到这种情况必须先将Array[AnyVal]转换为Array[AnyRef], 比如你有一个 val intArray = Array(1,2,3) 想调用method.invoke方法,可以这样: method.invoke(obj, intArray.map(_.asInstanceOf[AnyRef]) :_*) davepkxxx 写道 而且java有Integer[]、Double[],可以当做Object[],scala有么?
有的,和Java中一样: scala> val integerArray = Array[Integer](0,1,2) integerArray: Array[Integer] = Array(0, 1, 2) 要注意的是,上面的 val intArray = Array(1,2,3) 和 scala> val integerArray = Array[Integer](0,1,2) integerArray: Array[Integer] = Array(0, 1, 2) 是不一样的,一个是基本数组,一个是Integer数组,第二个因为指定了类型,Scala在编译期间做了隐式转换。 感谢解答,我回家后就试试 |