Be careful with Kotlin type inference while dealing with Java types

Daniil Popov
2 min readNov 2, 2020

If your codebase is 100% written in Kotlin then you have nothing to worry about. Keep going! You’re awesome and could boldly close this post.

But if you mix Kotlin and Java code then you should pay attention to some type inference nuances.

Let’s say you have two Java classes: A and B. They inherit the same base Java class called Base. Then suppose you have some Kotlin code like the following:

val aOrB = if (Random.nextBoolean()) A() else B()

Type inference is one of the things that makes Kotlin a very concise programming language. Obviously aOrB variable is of type Base. This code would compile successfully and would work like a charm.

Some days later your teammate decides to make class Base to be a package-private. Maybe he or she is finishing up a great refactoring incapsulating some logic like class Base in a separate project module or package. Now they prefer not to expose Base outside of the package/module. And then troubles begin.

The piece of Kotlin code from above is still compiled successfully but now the compiler produces a warning saying class Base is inaccessible in that context. It’s easy to miss it, especially when you’ve changed another code in another package or module but it leads your app to a runtime crash with IllegalAccessError.

If you develop Android applications here is an example from a real application that shows the problem from above:

val interpolator = 
if (linear) FastOutLinearInInterpolator()
else FastOutSlowInInterpolator()

And this code will also compile successfully although with a warning but it definitely will fail at runtime because the base class for those two interpolators is LookupTableInterpolator which is a package-private one.

As a result, I would suggest you explicitly specify the type in such situations particularly when Java classes are involved in if or when statements. In the presented Android example you can define interpolator as a variable of type Interpolator. Interpolator is public and is a base class for package-private LookupTableInterpolator.

Also, I should mention that in pure Kotlin described problem does not exist at all because you cannot derive from a class with a more restricted access modifier. In other words, a public class cannot inherit an internal or protected class because otherwise it would have to expose its super-class to the public. Thanks to Kotlin compiler for not allowing us to do that.

Happy coding and safe type inference!

--

--