开发者

Scala - how to explicitly choose which overloaded method to use when one arg must be null?

All,

I'm doing some image manipulation in Scala by making use of BufferedImages and Raster objects. I am attempting to get all the pixels in the buffered image with the following code.

val raster = f.getRaster()

// Preallocating the array causes ArrayIndexOutOfBoundsException .. http://forums.sun.com/thread.jspa?threadID=5297789
// RGB channels;
val pixelBuffer = new Array[Int](width*height*3)
val pixels = raster.getPixels(0,0,width,height,pixelBuffer)

Now, when I read in relatively large files, this wor开发者_高级运维ks fine. When I read in 20x20 PNG files, I get an ArrayIndexOutOfBoundsException:

java.lang.ArrayIndexOutOfBoundsException: 1200
at sun.awt.image.ByteInterleavedRaster.getPixels(ByteInterleavedRaster.java:1050)

I've read online that the way around this problem is to NOT preallocate the pixelBuffer, but instead to pass in a null value and use the one returned by the Raster.getPixels method.

Here's my problem. When I do the naive approach and just pass Nil as the last argument:

val pixels = raster.getPixels(0,0,width,height,Nil)

I get the error

error: overloaded method value getPixels with alternatives (Int,Int,Int,Int,Array[Double])Array[Double] <and> (Int,Int,Int,Int,Array[Float])Array[Float] <and> (Int,Int,Int,Int,Array[Int])Array[Int] cannot be applied to (Int,Int,Int,Int,Nil.type)
val pixels = raster.getPixels(0,0,width,height,Nil)

So obviously the compiler cannot determine which of the two methods I'm trying to call; it's ambiguous. If I were using Java, I would cast the null to make my intent explicit. I can't quite figure out how to get the same effect in Scala. Things I've tried:

 val pixelBuffer:Array[Int] = Nil // Cannot instantiate an Array to Nil for some reason
 Nil.asInstanceOf(Array[Int]) // asInstanceOf is not a member of Nil

Any idea how to tell the compiler explicitly that I want the method with the Int array as last parameter rather than a Float array?

EDIT: As an answer points out, I was getting Nil mixed up with null. Nil is an empty list. See the following blog post

Also, I should point out that the array out of bounds exception was my fault (as these things often are). The problem was I was assuming that the raster had 3 channels, but my image had 4 channels, since I had created it that way. I instead preallocate the array as follows:

val numChannels = raster.getNumBands() 

val pixelBuffer = new Array[Int](width*height*numChannels)
val pixels = raster.getPixels(minX,minY,width,height,pixelBuffer)

Thanks for the help


(Assuming you want the question of how to resolve overloads when you need to pass a null):

Just as you would in Java, by ascribing the type corresponding to the overload you wish to invoke (in Java you'd cast, but it amounts to the same thing: an assertion of the static type to assign to the null):

scala> object O { def m(i: Int, s: String): String = s * i; def m(i: Int, l: List[String]): String = l.mkString(":") * i }
defined module O

scala> O.m(23, null)
<console>:7: error: ambiguous reference to overloaded definition,
both method m in object O of type (i: Int,l: List[String])String
and  method m in object O of type (i: Int,s: String)String
match argument types (Int,Null)
       O.m(23, null)
         ^

scala> O.m(23, null: String)
res4: String = nullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnullnull

scala> O.m(23, null: List[String])
java.lang.NullPointerException
        at O$.m(<console>:5)
        at .<init>(<console>:7)
        at .<clinit>(<console>)
        at RequestResult$.<init>(<console>:9)
        at RequestResult$.<clinit>(<console>)
        at RequestResult$scala_repl_result(<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$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
        at scala.tools.nsc.Interpreter$Request$$anonfun$loadAndRun$1$$anonfun$apply$18.apply(Interpreter.scala:981)
        at scala.util.control.Exception$Catch.apply(Exception.scala:7...
scala>


You confused Nil with null.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜