[原创] 问个关于调用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在编译期间做了隐式转换。


感谢解答,我回家后就试试
Global site tag (gtag.js) - Google Analytics