【问题标题】:Can someone explain why applying map like this in Scala throws and IllegalArgumentException?有人可以解释为什么在 Scala 中应用这样的地图会抛出和 IllegalArgumentException 吗?
【发布时间】:2011-08-08 09:54:40
【问题描述】:

这是解释器命令的副本:

scala>val myTable = Array(Array(1))
res30: Array[Array[Int]] = Array(Array(1))

scala> myTable.map(_.map(_.toString))
res31: Array[Array[java.lang.String]] = Array(Array(1))

scala> var result = 0
result: Int = 0

scala> myTable.head
res32: Array[Int] = Array(1)

//note how applying this works
scala> res32.map(elem => if(3> result) result = 3)
res34: Array[Unit] = Array(())

scala> result
res35: Int = 3

//this also works
scala> myTable.map(_.map(_.toString))
res31: Array[Array[java.lang.String]] = Array(Array(1))

//when you combine the double map application and the anonymous function from earlier:
scala> myTable.map(_.map(elem => if(3 > result) result = 3))
java.lang.IllegalArgumentException
    at java.lang.reflect.Array.newArray(Native Method)
    at java.lang.reflect.Array.newInstance(Array.java:52)
    at scala.reflect.ClassManifest$class.arrayClass(ClassManifest.scala:107)
    at scala.reflect.Manifest$$anon$9.arrayClass(Manifest.scala:152)
    at scala.reflect.Manifest$class.arrayManifest(Manifest.scala:46)
    at scala.reflect.Manifest$$anon$9.arrayManifest(Manifest.scala:152)
    at scala.reflect.Manifest$$anon$9.arrayManifest(Manifest.scala:152)
    at scala.reflect.ClassManifest$.arrayType(ClassManifest.scala:205)
    at .<init>(<console>:45)
    at .<clinit>(<console>)
at .<init>(<console>:11)
at .<clinit>(<console>)
at $export(<console>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:592)
at scala.tools.nsc.interpreter.IMain$Request$$anonfun$10.apply(IMain.scala:828)
at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
at scala.tools.nsc.io.package$$anon$2.run(package.scala:31)
at java.lang.Thread.run(Thread.java:662)

这是预期的行为吗?

【问题讨论】:

    标签: scala map illegalargumentexception


    【解决方案1】:

    首先,您应该使用 foreach,而不是 map,但您已经知道 :-)

    您正在尝试创建 Unit 数组的数组,该数组在 java 中被转换为 Void.TYPE。这会导致 IllegalArgumentException。

    【讨论】:

      【解决方案2】:

      Scala 在调用map 时使用java.lang.reflect.Array.newInstance 动态创建数组。 这个方法,does not accept a size of zero。因为,你的 lambda 返回一个 Array[Unit] 类型的空数组,它的大小为零,在调用外部映射时会出现异常。

      顺便说一下,在这个例子中,你真的应该使用foreach,因为你不是试图将数组映射到另一个数组,而是使用副作用:

      scala> myTable.foreach(_.foreach(elem => if(3 > result) result = 3))
      
      scala> result
      res21: Int = 3
      

      编辑:我误解了这个问题(请参阅 MatthieuF 答案)。问题不在于数组的大小,而在于类型。只需:

      scala> java.lang.reflect.Array.newInstance(classOf[Unit], 1)
      java.lang.IllegalArgumentException
      at java.lang.reflect.Array.newArray(Native Method)
      at java.lang.reflect.Array.newInstance(Array.java:52)
      at .<init>(<console>:8)
      ...
      

      【讨论】:

      • 是的(接受零大小)。使用的方法是:public static Object newInstance(Class> componentType, int length) throws NegativeArraySizeException。不是另一个
      • 尝试以下操作:java.lang.reflect.Array.newInstance(int.class, 0)
      猜你喜欢
      • 2012-01-14
      • 1970-01-01
      • 1970-01-01
      • 2022-01-10
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      • 2016-06-01
      • 1970-01-01
      相关资源
      最近更新 更多