The Bad

Although Kotlin is great, it’s not perfect. Here are a few aspects of the language that I’m not in love with.

No namespaces

Kotlin allows you to define functions and properties at the top level of your files. That’s a great feature, but it can cause some confusion when combined with the fact that all top level declarations are referenced unqualified from Kotlin. This can sometimes make it difficult to tell what a function is when reading one of its usages.

For example, if you define a top level function:

fun foo() {...}

You will call that function as foo(). If you have a function with the same name in a different package, it’s not obvious from looking at the call site which function is being called. You can fully qualify the name of the function with the entire name of the package that it’s defined in, but given Java’s convention of very deep package names, that’s not ideal.

One workaround is to approximate a namespace by using with a singleton object class.

object FooActions {

fun foo() {...}

}

That allows you to refer to the function as FooActions.foo() if you’re only calling the functions from Kotlin, but it’s not as pretty if you have Java code that needs to call that function. From Java, you have to refer to the function as FooActions.INSTANCE.foo(), which is certainly not ideal. You can avoid the INSTANCE step by annotating your function with @JvmStatic, which is about the best you can do currently. That’s not a big deal, but it’s some boilerplate that wouldn’t be necessary if Kotlin had namespaces.

No static modifier

Following on the previous point, Kotlin has unusual handling of static function and property declarations that are called from Java. It’s not bad, but it feels dirtier than necessary. For example, the Android View class defines some static constants like View.VISIBLE and static methods like View.inflate:

public class View {

public static final int VISIBLE = 0x00000000;

public static final int INVISIBLE = 0x00000004;

public static View inflate(Context context, int resource) {...}

}

The declaration is simple. In contrast, here’s the equivalent Kotlin:

class View {

companion object {

@JvmField

val VISIBLE: Int = 0x00000000

@JvmField

val INVISIBLE: Int = 0x00000004

@JvmStatic

fun inflate(context: Context, resource: Int) {...}

}

}

Although the Kotlin version isn’t terrible, it’s more verbose than I would normally expect from the language. If you skip the annotations, then Java code will have to use awful syntax to refer to your fields:

// With annotations:

View.VISIBLE; //Without annotations:

View.Companion.getVISIBLE();

It feels odd that there are no better ways to create static functions and properties. I know that companion objects are real objects and can do stuff like implement interfaces, but that doesn’t feel like a compelling enough use case to completely replace normal static declarations.

Automatic conversion of Java to Kotlin

This was the first topic in the list of things I like about Kotlin, and it works well. But because it work so well 80% of the time, many of the cases where it fails can be frustrating.

Javadocs are often mangled, especially any paragraphs the wrap lines. Static fields and methods are converted to plain declarations on the companion object, which breaks any Java code that previously called them unless you manually add @JvmField or @JvmStatic, respectively.

All of these problems will certainly get fixed as the Kotlin team has more time to work on the converter, so I’m optimistic in this case.

Required property accessor syntax

Kotlin has the great syntactic sugar called “property accessor syntax” that allows you to call JavaBeans-style getters and setters as if they were a Kotlin property. So for example, you can call the Activity.getContext() method by writing activity.context instead of writing the whole method name. If you use the actual method call in Kotlin, you will get a lint warning telling you to use the property syntax instead.

That’s definitely a nice feature, but there are a few cases where method names start with the word “get”, but you don’t want to use the property syntax. One common case is with Java’s atomic classes. If you have a val i = AtomicInteger(), you might want to call i.getAndIncrement(). But Kotlin wants you to call i.andIncrement. That’s clearly not an improvement.

You can annotate every call site with @Suppress(“UsePropertyAccessSyntax”), but that’s ugly. It would be much better if there was a way to annotate functions you write with a similar annotation that would tell the linter that the function shouldn’t be treated like a property.

Method count

Writing code in Kotlin will certainly reduce the number of lines of code in your project. But it will also probably increase the method count of the compiled code, which is of course a drawback if you’re using Android. There are a number of reasons for that, but one of the larger contributors is the way Kotlin implements properties.

Unlike Java, the Kotlin language doesn’t provide any way to define a bare field. All val and var declarations instead create a property. This has the advantage of allowing you to add a get or set definition to a property whenever you want without breaking code that references the property. That’s a great feature that removes the need to write defensive getters and setters in the way that you often do in Java.

That feature comes at a cost, though. Every public val causes Kotlin to generate both a backing field and a getter function that can be called from Java [4]. Every public var will cause both a getter and setter to be generated. Fortunately, private properties with default getters and setters are generated as fields and don’t cause getters or setters to be generated. If you were previously exposing a lot of public fields in Java (which is a common practice for constants), you can end up with a surprising increase in method count.

If you are close to the method limit in your android app, I recommend using the workaround of applying the @JvmField annotation on public constants for which you don’t expect to need a custom getter for in the future. This will prevent the getters from being generated, and can cut down on your method count. [Update: Kirill Rakhman pointed out in the comments that you could use the const modifier instead of @JvmField for a similar effect, although it can only be applied to primitive types and strings.]

It’s not all bad, though. As I discussed in my article on converting an app to 100% Kotlin, the Kotlin standard library is small and can replace a number of common Java libraries that are much larger once you don’t need them in Java any more. Thanks to the standard library, the method count in that app decreased after converting it to Kotlin. So as long as you avoid the big areas that can increase your method count, you may end up ahead in the end.