daedsidog
daedsidog

Reputation: 1773

When can you use the 'as' operator?

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

Answers (2)

gidds
gidds

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

Egor
Egor

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

Related Questions