# Why is Kotlin's cast more weakly typed than Java's?

**URL:** <https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595>\
**Category:** Language Design\
**Created:** [January 19, 2021, 7:50pm UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595 "2021-01-19T19:50:58Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![darag](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@darag](https://discuss.kotlinlang.org/u/darag)\
**Post date:** [January 19, 2021, 7:50pm UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/1 "2021-01-19T19:50:59Z")

</div>

With Java the following fails to compile:

```auto
    String s = "abc"; 
    Integer i = (Integer) s; // fails to compile - "Inconvertable types" error

```

But Kotlin’s cast does not cause a compile error when used in this way:

```auto
    val s: String = "abc" 
    val i: Int = s as Int // compiler is happy with this but guaranteed to fail at runtime

```

Java’s casting mechanism seems superior - more errors are caught at runtime. I’m curious why Kotlin weakened the type of the “as” operator here?

---

<div class="post-metadata">

**Author:** ![madmax1028](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/madmax1028/32/3335_2.png) [@madmax1028](https://discuss.kotlinlang.org/u/madmax1028)\
**Post date:** [January 19, 2021, 8:06pm UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/2 "2021-01-19T20:06:00Z")

</div>

It seems like it shows a warning, but I would also prefer compilation errors in such oblivious cases.

---

<div class="post-metadata">

**Author:** ![luhtonen](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/luhtonen/32/6825_2.png) [@luhtonen](https://discuss.kotlinlang.org/u/luhtonen)\
**Post date:** [January 24, 2021, 10:39am UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/3 "2021-01-24T10:39:43Z")

</div>

In general type casting is one of the most dangerous operations in any programming language and in real life nobody will cast `String` to `Integer` in Java.  
When we’ll change slightly Java example:

```java
String s = "123";
Integer i = (Integer) s;

```

Compiler will still not compile it just simply because `String` is different type than `Integer`. Even though for human this is obvious that content of this string is an integer number, for compiler this doesn’t really matter.

But even in Java compiler is not that smart all the time. Here’s more realistic example (though it is an example of bad code practice):

```java
public class Main {
    enum ResultType {
        STRING_ABC,
        STRING_123,
        INTEGER
    }

    static Object getResult(ResultType type) {
        return switch (type) {
            case STRING_ABC -> "abc";
            case STRING_123 -> "123";
            case INTEGER -> 123;
        };
    }

    public static void main(String[] args) {
        Object result1 = getResult(ResultType.STRING_ABC);
        Integer i1 = (Integer) result1; // class cast exception

        Object result2 = getResult(ResultType.STRING_123);
        Integer i2 = (Integer) result2; // class cast exception

        Object result3 = getResult(ResultType.INTEGER);
        Integer i3 = (Integer) result3; // Ok
    }
}

```

Imagine we have some external service, which returns a result of `Object` type, which maybe of several types. This code will compile without errors, but will fail in 2 out of 3 cases. Type case is unsafe operation and should be used with caution.

In Kotlin `as` operator is _“Unsafe” cast operator_. It will try to cast object into denoted type but this cast is not guaranteed and it will throw an exception in case of failure.

In Java is `instanceof` operator which can be used for safe type cast, in Kotlin there is `is` operator.

---

<div class="post-metadata">

**Author:** ![darag](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@darag](https://discuss.kotlinlang.org/u/darag)\
**Post date:** [January 24, 2021, 6:01pm UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/4 "2021-01-24T18:01:16Z")

</div>

Hi luhtonen. I may not have expressed myself clearly.

This isn’t about parsing integers from strings or about runtime class cast exceptions - it’s about compile time type safety.

More abstractly, in Java the following

```auto
    X x = ...;
    Y y = (Y) x;

```

will only be accepted by the compiler if Y is the same type as X or a sub-class of X (or visa versa although “casting” from a sub-class to a super-class does nothing). This makes sense because if Y is NOT a sub-class of X, then obviously you know at compile time that the cast will always fail at runtime regardless of the actual type of x.

The Kotlin equivalent:

```auto
    var x: X = ...
    var y = x as Y

```

is not flagged as a compile time error even if X and Y have no sub/super class relationship. By not catching this at compile time, makes Kotlin less safe than Java in the sense that more errors are caught at runtime rather than compile time.

What’s weird is that Kotlin’s type system is easily capable of capturing this constraint. For example I can define a better cast operation:

```auto
fun <X, Y: X>stricterCast(x: X) = x as Y

fun bar() {
   foo(12.34d)
}

fun foo(a: Number) {
    val b = stricterCast<Number, Double>(a) // compiles and succeeds at runtime
    val c = stricterCast<Number, Int>(a) // compiles but throws runtime class cast exception
    val d = stricterCast<Number, String>(a) // does not compile
}

```

I’m curious why Kotlin’s behaviour is a regression in terms of (static) type safety compared to Java’s in this regard.

---

<div class="post-metadata">

**Author:** ![josephroffey](https://avatars.discourse-cdn.com/v4/letter/j/58f4c7/32.png) [@josephroffey](https://discuss.kotlinlang.org/u/josephroffey)\
**Post date:** [January 25, 2021, 2:14am UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/5 "2021-01-25T02:14:15Z")

</div>

Hi @darag,

First I’d like to point out that I’m no expert, but I can offer my two cents as to why I think this might be preferable in a language like Kotlin.

TL;DR: I expect it’s because of smart casting and a preference for as?

Whereas in Java, there is only one method of casting `(Class) myObj`, in Kotlin there are explicitly two ways `myObj as Class` and `myObj as? Class`.

Whilst it might be intuitive to imagine that the “unsafe cast” `as` which is regularly treated as equivalent to the previous cast in Java might be expected to be used in the same ways, it might actually be used in very different ways.

Whereas in Java you may well have code that you do not want to throw an `InvalidCastException` that performs an unsafe cast, in Kotlin, if you are using `as` instead of `as?` you are almost invariably choosing to accept and handle any `TypeCastException` that might be thrown either by accepting responsibility for any that occur at runtime or because they might be explicitly preferred in your code for whatever reason.

Further, if Kotlin were to function as you suggest, you might get some irregularities in code due to “smart casting” objects where objects are of a stricter type than you expect, so for example if you were writing a function that purported to take an “Any” and you decided that the best way would be to handle all types the same way by performing a cast and handling any `TypeCastException`…

```
@Throws(TypeCastException::Class)
fun castingExperiment(a: Any) {
    ...
    return a as TargetClass
    ...
    return a as TargetClass
}

```

Now, if the compiler initially allowed one of these, but then either

- code was introduced that allowed the compiler to judge that `a` at the second return was never of `TargetClass` or
- updates to Kotlin led to improvements to smart casting leading to `as TargetClass` not compiling

Then you might end up having to change that code to throw a `TypeCastException`. And importantly, you might not throw it yourself in the same way as the previous call to `a as TargetClass` might’ve been doing — leading to slightly different behaviour further down the line.

Also, it might be worth noting that Java code that has something like

```
if (a instanceof NotTargetClass) {
    ...
    (TargetClass) a
}

```

Without `as` would not be easily portable into Kotlin because of smart casting as it would have to work out to convert it to:

```
if (a is NotTargetClass) {
    ...
    throw TypeCastException(...)
}

```

which might both be a large ask on the conversion process and not the code that the programmer was expecting or wanting.

Those are just my thoughts, I’d love to hear what other people might think or if they think that Kotlin would be better with refusing to compile in the case of any such cases.

Thanks.

---

<div class="post-metadata">

**Author:** ![darag](https://avatars.discourse-cdn.com/v4/letter/d/ba8739/32.png) [@darag](https://discuss.kotlinlang.org/u/darag)\
**Post date:** [January 27, 2021, 8:11am UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/6 "2021-01-27T08:11:54Z")

</div>

Thanks josephroffey - lots to think about in what you wrote. I suspect you’re on the right track that it has something to do with smart casting or some other Kotlin feature (but I will need to think about it).

Your message provoked me to try the experiment with the “is” operator:

```auto
sealed class Foo

fun bar(x: Foo) {
    val b = x is String // compilation error - "incompatible types"
    val c = x as String // no compilation error
}

```

This for me is even odder - if I had been asked to guess I would have assumed that “is” would be more loosely typed than “as” but it seems the other way around. While in Java, both “(String) x” and “x instanceof String” in the above context result in “incompatible type” compile errors.

---

<div class="post-metadata">

**Author:** ![elizarov](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.kotlinlang.org/elizarov/32/2164_2.png) [@elizarov](https://discuss.kotlinlang.org/u/elizarov)\
**Post date:** [January 27, 2021, 9:38am UTC](https://discuss.kotlinlang.org/t/why-is-kotlins-cast-more-weakly-typed-than-javas/20595/7 "2021-01-27T09:38:46Z")

</div>

It is hard to track why it is exactly so, but we can change it if we’ll find no compelling reason to keep it this way. I’ve created the corresponding YT issue: [https://youtrack.jetbrains.com/issue/KT-44569](https://youtrack.jetbrains.com/issue/KT-44569)
