In my quest to find a decent language that runs on the JVM (and can thus be used on Android without worrying about native compilation) while not being as painfully awful as Java itself, I’ve gone through a number of possibilities. Groovy was an old one that seems to have fallen by the wayside, and it’s one of those that always rubbed me the wrong way. A bit like Ruby in that regard, and I think that was the point. Scala was another contender, and I still think it’s a great language. It’s a nice blend of functional and object-oriented programming, a true multi-paradigm language in the vein of C++, and it has a lot of interesting features that make coding in it both easier and simply more fun than Java.
Alas, Scala support is sketchy at best, at least once you leave the world of desktops and servers. (Maybe things have picked up there in the past year and a half. I haven’t checked.) And while the language is great, it’s not without its flaws. Compilation is fairly slow, reminding me the “joys” (note sarcasm) of template-heavy C++ code. All in all, Scala is the language I wish I could use more often.
A new challenger
Enter Kotlin. It’s been around for a few years, but I’ve only recently given it a look, and I’m surprised by what I found. First and foremost, Kotlin is a language developed by JetBrains, the same ones who make IntelliJ IDEA (which, in turn, is the basis for Android Studio). It’s open source under the Apache license, so you don’t have to worry about them pulling the rug out from under you. Also, Android Studio has support for the language built in, and Google even has a few samples using it. That’s already a good start, I’d say.
At the link above, you can find all the usual hallmarks of a “modern” programming language. You’ve got docs, tutorials, lots of press-type stuff, commercial and free support, etc. In that, it’s no different from, say, Typescript. Maybe there’s a bit more emphasis on using IDEA instead of Eclipse or Netbeans, but that’s no big deal. All in all, it’s nothing special…until you dig into the language itself.
Kotlin’s main mission, essentially, is to make a better Java than Java. Maybe not in the wholesale sense like C#, but that’s the general vibe I get. Java interop is an important part of the documentation, and that’s a good thing, because there’s a lot of Java code out there. Some of it is even good. It’d be a shame to throw it all away just to use what’s undoubtedly a better language.
But let’s talk about why Kotlin is better than Java. (Hint: because it’s not Java.) It borrows heavily from Scala, and this is both intentional and promising. Like Scala, there’s a heavy pressure on the programmer to use the immutable
val where possible, while reserving the mutable
var for those situations where it’s needed. Personally, I’m not a fan of the “all constant, all the time” approach of e.g., Haskell or Erlang, but the “default constant” style that Kotlin takes from Scala is a happy medium, in my opinion.
In addition, Kotlin makes a major distinction between nullable and non-nullable types. For instance, your basic
String type, which you’d normally use for, well, strings, can’t be assigned a value of
null. It’s a compile-time error. (If you need a nullable type, you have to ask for it:
String?.) Likewise, you have an assortment of “safe” syntax elements that check for null values. Compiler magic allows you to work with a nullable type without hassle, as long as the compiler can prove that you’ve checked for
null. That only works with immutable values, another instance where the language guides you onto the “right” path.
Those two alone, nullability and mutability, are already enough to eliminate some of the most common Java programming mistakes, and Kotlin should be lauded for that alone. But it also brings a lot of nifty features, mostly in the form of syntactic sugar to cut down on Java’s verbosity. Lambdas are always nice, of course. Smart casts (the same compiler trick that lets you dispense with some null checks) are intriguing, and one of those things that makes you wonder why they weren’t already there. And then you have all the little things: destructuring assignments, ranges, enum classes, and so on.
All told, Kotlin is a worthy entry in the “what Java should be” competition. It fits the mold of the “modern” language, taking bits and pieces from everywhere. But it puts those pieces together in a polished package, and that’s what’s important. This isn’t something that involves arcane command-line incantations or a leaning tower of 57 different build systems to get working. If you use IDEA, then it’s already there. If not, it’s not hard to get. Compared to the torture of getting Scala to work on Android (never did manage it, by the way), Kotlin is a breeze.
Yet no language is perfect, and this is no exception. Mostly, what I find to be Kotlin’s disadvantages are minor annoyances, silly limitations, and questionable choices. Some of these, however, give rise to bigger issues.
The heavy emphasis on tracking nullability is worthwhile, but the documentation especially turns it into something akin to religious dogma. That gets in the way of some things, and it can make others cumbersome. For example, although the language has type inference, you have to be careful when you cast. The basic
as cast operator doesn’t convert from nullable to non-nullable. That’s good in that you probably don’t want it to, but it does mean you sometimes have to write things in a roundabout way. (This is particularly the case when you’re taking data from Java code, where the null-checks are toned down.)
Interop, in fact, causes most of Kotlin’s problems. There’s no solving that, I suppose, short of dropping it altogether, but it is annoying. Generics, for instance, are just as confusing as ever, because they were bolted on after the JVM had gone through a few revisions, and they had to preserve backward compatibility.
Except for syntax choices, that’s my main complaint about Kotlin, and I recognize that there’s not a JVM language out there that can really fix it. Not if you want to work with legacy Java code, anyway. So let’s take a look at the syntax bits instead.
I can’t say I like the belt-and-suspenders need to have both classes and methods
final by default. I get the thinking behind it, but it feels like the same kind of pedantry that causes me to dislike Java in the first place.
Operator overloading exists, after a fashion. It’s about as limited as Python’s, and one of the few cases where I wish Kotlin had swiped more from Scala. Sure, you can make certain methods into infix pseudo-operators, but that’s not really anything more than dropping a dot and a pair of parentheses. You’re not making your own power operator here.
Really, I could go on, but I think you see the pattern. Kotlin has some good ideas, none of them really new or innovative by themselves, but all bringing a welcome bit of sanity to the Java world. The minor problems are just that: minor. In most cases, they’re a matter of personal opinion, and I’ll gladly admit that my opinion is in the minority when it comes to programming style.
On the whole, Kotlin is a good language. I don’t know if I’d call it great, but that’s largely because I don’t really know what would make a programming language great these days. I’m not even sure we need one that’s great. Just one that isn’t bad would be a start, if you ask me.
And that’s what we have here. If I get back into Android development in 2018, I’ll definitely be looking at Kotlin as my first choice in language. Anything is an improvement over Java, but this one’s the biggest improvement I’ve seen yet.