Reputation: 1773
I have the following program:
fun main(args: Array<String>) {
var a: Int
var b = 23.5
a = b as Int
println(a)
}
If I run it, the program throws a java.lang.ClassCastException
exception.
Since the data types used in Kotlin are represented as objects, I can understand why it is not possible to frivolously cast them like I have, and instead should use the built-in conversion methods associated with each type or the "safe" as?
operator -- but then this brings the question: when can (or should) you use the as
operator?
Upvotes: 0
Views: 91
Reputation: 18617
In your example, b
is a Double
floating-point value, not an Int
. (As other answers have pointed out.) To convert it, you'd need to use something like b.toInt()
.
Your program doesn't convert it, because Kotlin's as
operator doesn't change the value into a new type; instead it tells the compiler that the value is already of the required type. That's called a cast.
So for example, if I have:
val n: Number = 4
Then the type of n
is Number
. Its current value is actually an Int
(which is a subclass of Number
). So in this case I can cast it to Int
, e.g.:
val i = n as Int
after which the compiler will treat it like an Int
.
(This particular case is a down-cast, because Int
is below Number
in the class hierarchy. In general, up-casts are safe but down-casts and others aren't. If you had initialised n
with a floating-point number instead, then its value would be of type Double
, which is another subclass of Number
, and not an Int
; the program would fail at run-time and throw a ClassCastException
, as you saw. That's why Kotlin also has a safe-cast operator, as?
, which gives null instead of the exception.)
The Kotlin compiler is very smart, and most of the time it already knows what type a value can be, so casting isn't needed very often. There can still be occasions when you know something the compiler doesn't, and a cast is appropriate; but too many of them can be a ‘code smell’ indicating that there may be a better approach.
Upvotes: 1
Reputation: 40228
Kotlin compiler's smart casts are pretty smart, so in most cases you don't need explicit casting. This code in Java:
Object foo = "foo";
if (foo instanceof String) {
String fooString = (String) foo;
System.out.println(fooString.length);
}
would translate to this Kotlin code:
val foo: Any = "foo"
if (foo is String) {
println(foo.length)
}
However, as
and as?
are still relevant, e.g.:
fun test(foo: Any) {
val fooString = foo as? String ?: throw IllegalArgumentException()
...
}
Overall, rely on smart casts as much as you can and leave as
and as?
for specific cases.
Upvotes: 1