I was writing some Scala StringBuilder code like this today:
val sb = new StringBuilder
for (b: Byte <- mdOut.digest) {
val hexString: String = String.format("%02x", b)
sb.append(hexString)
}
sb.toString
and encountered this error message:
Error:(40, 44) overloaded method value format with alternatives:
(x$1: java.util.Locale,x$2: String,x$3: Object*)String <and>
(x$1: String,x$2: Object*)String
cannot be applied to (String, Byte)
val hexString: String = String.format("%02x", b)
The problem
In short, it turns out that the problem is that the Byte
value I’m using here is the scala.Byte value, which is a wrapper around the primitive byte
in Java and a descendant of scala.AnyValue. Because Scala.byte is not a descendant of the Java Object
class, the second (overloaded) method signature doesn’t apply to what I’m trying to do. In Scala terms, here’s what that second String.format
method signature expects:
(x1: String, x2: java.lang.Object*): String
---------------------
And this is what I’m trying to pass into it:
(x1: String, x2: scala.Byte): String
--------------
The solution
The solution to the problem is to “box” the byte value. This converts the scala.Byte value into a Java Byte
object that I can pass into String.format
. When working with a Scala Byte
value you do this with the Byte.box()
method (a box
method on the Scala Byte
object). Here’s the solution:
val sb = new StringBuilder
for (b: Byte <- mdOut.digest) {
val hexString: String = String.format("%02x", Byte.box(b)) //notice Byte.box
sb.append(hexString)
}
sb.toString
When you compile that code you’ll see that it works without any errors; problem solved.
Discussion: Scala boxing methods
The Byte class scaladoc states that the box
method “Transforms a value type into a boxed reference type,” and further states the box
method return type is a java.lang.Byte.
To further understand the problem, if you look at the scala.Byte scaladoc, you’ll find its description as follows: “Byte
, an 8-bit signed integer (equivalent to Java’s byte primitive type) is a subtype of scala.AnyVal. Instances of Byte
are not represented by an object in the underlying runtime system.”
If you run into this error message with other Scala data types, you’ll find that they all offer box
methods to convert them into descendants of the Java Object
class. For instance, you’ll find box
methods on each of these scaladoc pages:
- scala-lang.org/api/current/scala/Double$.html
- scala-lang.org/api/current/scala/Float$.html
- scala-lang.org/api/current/scala/Int$.html
In summary, if you run into this “overloaded method value format with alternatives” error message when using String.format, I hope this information is helpful.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |