I tried to move codebase to Kotlin from Java. But I found strange behavior in String.format.
I have both same codes (and feature, also) in Kotlin and Java.
fun callScriptMethod(methodName: String, vararg args: Any): String {
var format = methodName
if (!format.contains("javascript:")) {
format = String.format("javascript:%s", format)
}
val objects = mutableListOf<Any>()
for (arg in args) objects.add(arg)
if (!objects.isEmpty()) {
format += "("
var i = 0
val icnt = objects.size
while (i < icnt) {
format += "\'%s\'"
if (i != icnt - 1) {
format += ", "
}
i++
}
format += ")"
} else {
format += "()"
}
val message = String.format(Locale.getDefault(), format, args)
return message
}
public static String callScriptMethod(String methodName, Object... args) {
String format = methodName;
if (!format.contains("javascript:")) {
format = String.format("javascript:%s", format);
}
List<Object> objects = Arrays.asList(args);
if (!objects.isEmpty()) {
format += "(";
for (int i = 0, icnt = objects.size(); i < icnt; i++) {
format += "\'%s\'";
if (i != icnt - 1) {
format += ", ";
}
}
format += ")";
} else {
format += "()";
}
String message = String.format(format, args);
return message;
}
and some test code.
fun main() {
val result = Java.callScriptMethod("nativeCallback", "1", "d8d8441n24n134n",
"dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas", "0")
println(result)
val result2 = Kotlin.callScriptMethod("nativeCallback", "1", "d8d8441n24n134n",
"dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas", "0")
println(result2)
}
I can expect result is javascript:nativeCallback('1', 'd8d8441n24n134n', 'dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas', '0')
.
But the version of Kotlin has exception MissingFormatArgumentException
.
So, I tried to debug these codes to know the format is generated successfully.
Java: javascript:nativeCallback('%s', '%s', '%s', '%s')
Kotlin: javascript:nativeCallback('%s', '%s', '%s', '%s')
Both are the same result and have same args
but has a different result.
javascript:nativeCallback('1', 'd8d8441n24n134n', 'dasqhjidhkdhaskjdfhawoiudnqwaidnqwioldjnqawskld:djoashdojashdlkjasdjhas', '0')
Exception in thread "main" java.util.MissingFormatArgumentException: Format specifier '%s'
at java.util.Formatter.format(Formatter.java:2519)
at java.util.Formatter.format(Formatter.java:2455)
at java.lang.String.format(String.java:2981)
at Kotlin.callScriptMethod(Kotlin.kt:31)
at TestKt.main(test.kt:11)
at TestKt.main(test.kt)
So, I want to know what is the problem. How can i do?
As vararg becomes an array once entering the function body, you have to use the spread operator in order to pass it as vararg. https://kotlinlang.org/docs/reference/functions.html#variable-number-of-arguments-varargs
When we call a vararg-function, we can pass arguments one-by-one, e.g. asList(1, 2, 3), or, if we already have an array and want to pass its contents to the function, we use the spread operator (prefix the array with *):
val message = String.format( format, *args)
The difference with Java is that Java actually allows passing an array as vararg directly, see this SO post: Can I pass an array as arguments to a method with variable arguments in Java?
i.e. Object...
in Java is technically identical to Object[]
, there are no "real" vararg things in Java, while vararg
is a real different thing in Kotlin.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With