Why I abandoned Java in favour of Kotlin
I’ve always been a huge fan of Java. I started my career as a PHP developer and soon after that I was forced to work in perl in another project. With PHP’s consistent brokenness throughout the language and perl’s (alphabet-soup-puke)-like-syntax, getting into Python two years later was a huge improvement. However, certain things still irked me (which at that time I just couldn’t put into words), but it was there, like a splinter in my hand that would not go away.
Eight months into the Python project, I had to build a system in Java for a freelance project. I had no idea about how to get started, but the more I started messing around with it, the more I loved it. It was like watching poetry unfold and an orchestra perform a software ritual right in front of my eyes. As an ex-Delphi developer, who became accustomed to code that reads almost like English, the ceremony Java provided was beautiful and I was hooked.
Source : Feast of Music, Flickr
Let’s say you are an opera singer performing the same play every day and every night, after some time, you get tired of performing the same ceremony every day and just want to get down to performing - screw the announcements, screw the pre-show drinks, screw the credits, screw the standing ovations you just want to sing, enjoy the singing and not get bogged down by everything else.
For me, the case with Java, was similar. I enjoyed writing code in Java, but all the boilerplate bothered me. You'll see in the next few sections — how then, my intro to Kotlin was a breath of fresh air.
It was quite strange back in the days when Java introduced a 4 letter extension,
.java
, when every other file-extension at the time was only 3 letters long.
Kotlin cuts it down to two letters, .kt
, almost as if they're making a statement saying,
"we're tired of boilerplate".
Now let's check out some interesting use cases where Kotlin outperforms Java.
Main method
Look at all the ceremony Java gives you before you get to write a single line of code whereas Kotlin gets straight to the performance!
Java:
public class MyClass {
public static void main(String... args) {
// code goes here;
}
}
Kotlin (doesn't even require that main method be in a class):
fun main(args: Array<String>) {
// code goes here
}
Declaring variables and constants
Java:
private String s1 = "my string 1";
private final String s2 = "my string 2";
private static final String s3 = "my string 3";
Kotlin:
var s1 = "my string 1"
val s2 = "my string 2"
val s3 = """my string 3""" // requires companion object
Also note the lack of semicolons in Kotlin! Semicolons are optional in Kotlin and can be used if you want to write two lines of code on the same line, otherwise you can just ignore it.
Unlike Java which forces you to use double-quotes everywhere, you can use triple quotes in Kotlin! Triple quotes allow you to put anything in there without having to escape strings, let me demonstrate …
Java:
String html = "<div class=\"text\">" + s2 + "</div>";
Kotlin:
val html = """<div class=”text”>$s2</div>"""
Note the $s2
, this allows you to place any Kotlin / Java value directly in your String without
having to break the string and without having to plus parts of strings, this is really awesome!
Alternatively, you can also use ${}
which allows you to do things to that value inline, like
${s2.trim()}
.
Getters and Setters
Java forces you to use getters and setters everywhere to encapsulate private variables; in Kotlin, anything that is not private, will automatically be exposed via properties making your code more concise and readable - this feature alone got me to try out Kotlin. Furthermore, the null-safety in Kotlin is beyond awesome. If you’re a Java developer, you’ll probably be familiar with endless null-pointer exceptions in your logs or bloated code that does endless null-checks, let me demonstrate with an imaginary HTML class.
Java:
HTML html = myHelperClass.getHtml();
String text = "";
if (html != null){
Body body = html.getBody();
if (body != null){
Div div = body.getDiv();
if (div.getText() != null){
text = div.getText();
}
}
}
System.out.println(text);
Kotlin:
val html = myHelperClass.html
val text = html?.body?.div?.text ?: ""
println(text)
Or in short, in a single line:
println(myHelperClass.html?.body?.div?.text ?: "")
Notice the lack of getters in Kotlin (getting the job done without the ceremony),
the ?
does the null check for you and returns null
at any point the ?
encounters a null and the elvis operator, ?:
, checks if the result is null
and if so, offers a default value.
Null checking in Kotlin is just sooooo much better than Java.
Method extensions
It really closed the deal for me, in Java you have gazillions of helper classes, just think Apache Commons for example or java.utils.Collections, let me give a simple example ...
Java:
public class Helper {
public static String stripUnwantedSlashes(final String input) {
if (input == null){
return null;
}
if (input.isEmpty()){
return "";
}
String s = input.replaceAll("\\\\'", "'").replaceAll("\\\\\"", "\"").replaceAll("\\\\`", "`");
if (s.length() != input.length()){
return stripUnwantedSlashes(s);
}
return s;
}
}
Now every time you want to make use of this helper function, you have to do use the Helper
class which bloats your code pretty quickly.
System.out.println(Helper.stripUnwantedSlashes(text));
Kotlin fixes this by allowing you to extend the String class injecting your own method.
Note that I don’t need to do a null check on input, by defining it as type String
,
the compiler won't allow it to be null; it won't even compile if it can be null.
If you want to allow null, you need to define the type as String?
instead and handle
the null, otherwise, once again, it won’t even compile.
Kotlin:
fun String.stripUnwantedSlashes() : String {
if (this.isEmpty()){
return ""
}
val s = this.replace("\\\\'".toRegex(), "'").replace(("\\\\\"").toRegex(), "\"").replace(("\\\\`").toRegex(), "`")
if (s.length != this.length){
return s.stripUnwantedSlashes()
}
return s
}
See the difference, no Helper.
bloat:
println(text?.stripUnwantedSlashes() ?: "");
So instead of doing Collections.sort(mylist);
, you can get straight down to business and just do mylist.sort()
Instead of bloating your code with Integer.parseInt("1")
, get straight down to business and do "1".toInt()
Smart casting in Kotlin
This is another awesome feature that you don’t get in Java!
Following is a Java class that we'll extend, and use in both Java and Kotlin:
public abstract class Param<T> {
private T value;
public Param(T value) {
this.value = value;
}
public T getValue() {
return value;
}
}
public class Password extends Param<String> {
public Password(String value) {
super(value);
}
public String getMaskedValue() {
// code that masks password and returns it
}
}
public class Username extends Param<String> {
public Username(String value) {
super(value);
}
}
Java:
List<Param> params = Arrays.asList(new Password("password1"), new Password("password2"), new Username("dude"));
params.forEach((param) -> {
if (param instanceof Password){
System.out.println("Password=" + ((Password) param).getMaskedValue());
} else if (param instanceof Username){
System.out.println("Username=" + ((Username) param).getValue());
}
});
Kotlin:
val params = mutableListOf(Password("password1"), Password("password2"), Username("dude"))
params.forEach { param ->
if (param is Password){
println("Password=${param.maskedValue}")
} else if (param is Username){
println("Username=${param.value}")
}
}
Notice how in the Java code, you need to cast your param every time you want to use it! Kotlin on the other hand, once you've confirmed param's type, you're free to use it as if it is of that type!
Kotlin also allows you to tell it what type param is in which case you can also just use it
as if it is of that type. Example, let's assume that list only contained Password
objects
Kotlin:
params.forEach { param ->
param as Password
println(param.maskedValue)
println(param.maskedValue)
println(param.maskedValue)
}
Primary Constructors and named arguments
Another awesome feature I wish Java had, is the way you can more precisely call methods and constructors with named arguments.
Java:
Java, defining a class, typically looks like this:
public class User {
private String firstName;
private String lastName;
private String email;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
To make use of this class in Java, you'll typically write this boilerplate:
User user = new User();
user.setFirstName("Graham");
user.setLastName("Spencer");
Kotlin:
Kotlin allows you to firstly get rid of the getters and setters, but also allows you to set variables in your class directly from the constructor
class User(
var firstName: String = "",
var lastName: String = "",
var email: String = "") {
override fun toString(): String {
return "FirstName=${firstName}, LastName=${lastName}, Email=${email}"
}
}
To make use of this class in Kotlin, you can either do what Java did and set the variables individually, or you can passs the variables into the constructor or you can make use of named parameters (the one which I prefer most)
Kotlin (option1):
val user1 = User()
user1.firstName = "Graham"
user1.lastName = "Spencer"
Kotlin (option2) (notice that we can skip the last parameter since it has a default value):
val user2 = User("Graham", "Spencer")
Kotlin (option3) (notice that we can now pass in the parameters in any order):
var user3 = User(lastName = "Spencer", firstName = "Graham")
Methods in Kotlin also allows you to either call them via sequential arguments, or named arguments. The latter is great for when you want to make a method call much more readable, example, which looks better?
findUser("Graham", "Spencer", "0841234567", 33, 40, "Mr.")
or
findUser(
title = "Mr", firstName = "Graham", lastName = "Spencer",
phoneNumber = "0841234567", minAge = 33, maxAge = 40)
Using named parameters, you can even omit parameters that does not make sense to provide (assuming you provide default values for them in the method declaration) instead of providing empty strings or null. How many times have you seen long strings of null being sent into a method and not even knowing if the method will handle it correctly?
Java:
findUser(null, null, null, 33, 40, "Mr");
Kotlin:
findUser(title="Mr", minAge=33, maxAge=40)
Operator overloading
This is something Kotlin has which Java does not! There’s been many attempts to get operator overloading into Java, but the founders seems to kick back against it. Operator overloading is a feature I enjoyed very much in Python and I’m happy to see that Kotlin has it as well.
Instead of writing a.contains(b)
in Java, you can overload the contains
method or use method extensions to inject a contains method which will
allow you to write Kotlin a in b
And this can be done for any operator that you can apply on an integer, like +
, -
, ++
, etc
Kotlin:
Let's override the compareTo
operator in User:
operator fun compareTo(user: User): Int {
return firstName.compareTo(user.firstName)
}
Now which one reads easier?
if (user1.compareTo(user2) > 0)
or
if (user1 > user2)
Better Switch Case
Haven't you always wished for a switch case that is a little more powerful?
Java’s switch case is really simplistic, Kotlin gives you when
which allows
you to do anything an if-else can do, without the boilerplate.
Kotlin:
when (x) {
1 -> println("x == 1")
2 -> println("x == 2")
3,4 -> {
println("x == 3")
println("x == 4")
}
in 5..10 -> println("x >= 5 and x <= 10")
is String -> println("x is actually a string")
else -> {
println("this is the else block")
}
}
The first question I asked on Kotlin's Slack channel (which is very active by the way) was
about whether Kotlin offered something similar to Dart's double-dot operator and some
guy told me that I can use DSLs to write my own ..
syntax, but he would suggest
I stick to with
. With allows you to switch the scope, let me demonstrate.
with (user1){
firstName = "Graham"
lastName = "Spencer"
println("First=${firstName}, Last=${lastName}")
if (this > user2){
println("user1 > user2")
}
}
Without with
, you'd have to type user1 out every time and if you had nested properties,
you'd have to chain user1.a.b.c.d.e
them which reads very hard when you're integrating
into complex APIs with many levels of nested objects.
user1.firstName = "Graham"
user1.lastName = "Spencer"
println("First=${user1.firstName}, Last=${user1.lastName}")
if (user1 > user2){
println("user1 > user2")
}
Getting rid of equals()
I think the biggest win for Kotlin is getting rid of having to use equals
everywhere!!!
In Java, when using ==
on objects (even String
s), you are comparing pointers,
something which I've never seen anyone use in any real-world code and instead you are forced to
write string1.equals(string2)
everywhere.
Kotlin decided that since hardly anyone ever wants to compare pointers, why not make ==
actually compare values and instead, if you REALLY want to compare pointers, use ===
.
So instead of user1.firstName.equals(user2.firstName)
, you can write user1.firstName == user2.firstName
.
To existing Kotlin users, I know I know, I'm just shaving the tip of the iceberg here. There's plenty more to cover, but to cut a long story short, if you're already a Scala developer and are liking it, you'll probably not find many new things in Kotlin that you don't have already (except for the zero-overhead null-safety). But if you're a Java developer and are tired of the boilerplate and all the ceremonies before you get to do any real work, then Kotlin is for you.
Kotlin is literally a better Java and I've already said goodbye to Java many months ago, not writing any new code in Java. For existing Java projects, I simply continue writing all new code in Kotlin while keeping the old code in Java, and keeping them both in the same project.
Cheers to the Kotlin team for making Java better!
3.4K+ developers have started their personal blogs on Hashnode in the last one month.
Write in Markdown · Publish articles on custom domain · Gain readership on day zero · Automatic GitHub backup and more
Fullstack Developer.
Finally! Kudos for the effort and time to compile this HNO.
I'm currently looking into Kotlin and my plan to ditch Java is getting delayed. But with more and more I read about Kotlin, I grow more and more into it. As I mentioned before, it wouldn't be long before I left Java for Kotlin, and thanks for putting out all information which I needed.
The most interesting thing is, how quick I can write the same code in Kotlin with far more less code. And this is what I was looking for. Another good thing is, it is coming under JVM family IIRC!
Once again, thank you for writing this, so that people like me, who thought Java was the end of the world can get more idea about this Insane language!
Kotlin + Spring is also doable, you just have to lateinit
your @Autowired
dependencies, or autowire them via the constructor, although I've abandoned Spring as well rather going for VertX as a replacement for SpringMVC and when I really need dependency injection, which is almost never, I use Guice. Kodein and Dagger seems like good options as well which I haven't had time to investigate yet.
FullStack Software Engineer
That was awesome, although i am not a java developer, i am going to give Kotlin a try.
full-stack developer
Triple double quotes??? This is not VB is it?
That would work as well, but if you wanted to do it over multiple lines:
val html = """
<div class="text">
<p>${s2}</p>
</div>
"""
tripled quotes would be needed since single quotes can't go across multiple lines.
"Smart casting in Kotlin" is biased. In Java there's no need to cast objects to Password nor to Username since getValue method is declared in the base class. In order to improve the example, some methods specific to Password and Username should be added.
Can you "invent" some method for Username as well?
getValue()
can easily be replaced with getMaskedValue()
to make the example more clear. Updated :-)
Full Stack Developer
I used to code in Java for a couple years and really never had any love for it. I did find JavaScript to be much more fun for me, although it is lacking in many aspects as a robust language. Python was something that really had my attention but still to me was not complete when comparing to Java. Kotlin really caught my eye and actually got me back into the Java realm.
Great article about some of the many questions I have been looking up answers for.
I am really starting to like kotlin. I did have one quesion. Does it use the Java API? So I could import any Java API library and use it in my Kotlin program or does Kotlin use its own API?
Kotlin is 100% compatible with Java with Java's standard classes heavily extended via the Standard Library to give you more functionality.
Example, in Java you can do "blah".isEmpty()
, in Kotlin you can do that as well, but also do "blah".isNotEmpty()
since the standard lib extends the String class via method extensions.
So everything Java is available to you in Kotlin, plus the Kotlin add-ons.
Full-stack developer specializing in healthcare IT
Interesting. Reminds me of some of the similar reasons Groovy was created.
When I was using Groovy, it wasn't functional, and while it didn't require variables to be strongly typed, they certainly could be. I typically did because that's what I was used to in the Java world.
Interesting, sounds like Groovy is optionally typed like Dart is. Sounds like a great language for frontend development.
What material would you suggest for learning?
I believe there's some good tutorials on YouTube, but haven't seen anything yet on the online university-type sites
In addition to several youtube-based Kotlin courses, there are at least 5 others university-style:
probably you have an error here ;)
if (user1.compareTo(user2) > 1)
Indeed, that should be > 0
. If it was Kotlin, I would not have made that mistake.
Programmer
Method Extension is what I've always demanded as a facility to help you follow OOD concept better.
Apart from this, 11 years ago I learned OOP/OOD with Java & I owe Java cultivating my mind as a modern software programmer. But this is the nature of things, always new stuff has the opportunity to be better than the legacy one, because it had chance & time to see drawbacks of the old one which bothers its users! Lets put this tragic story aside :-))
Jan Vladimir Mostert it was a wonderful intro to Kotlin. You could announce them to use it as a helper document to convince the resisting users! IMO you could name it Kotlin Crash Course! Well done
Behrad Khodayar thanks for the kind words! This article is actually close to a year old by now and barely scratches the surface. I've since upped my Kotlin skills by a lot and should be able to write an article on the more advance features as well when I eventually get time again.
Jetbrains actually shared this article, see the screenshot: imgur.com/cMCGuXT
Executive Product Leader & Mentor for High-End Influencers and Brands @ mevrael.com
Have you tried Swift 3? It also has elegant syntax. 1st time I'm hearing about Kotlin... What is it used for and why was it invented? How easy is it to get started and build 1st business production app without installing over 9000 packages or VMs? Java sucks, it's true.
Kotlin has everything Swift has plus some more as well as the awesome ecosystem that comes with working on the JVM whereas Swift has some catching up to do if you want to use it server-side. Await Async is coming soon under Co-routines, so for now that's one thing Swift has that Kotlin doesn't yet have.
Kotlin is using Type Inference whereas Swift is a little more flexible in this regard.
Kotlin can be used everywhere where Java is being used, so Android, Serverside, compiled to JS, etc. The Java ecosystem is still an awesome ecosystem, the language itself is just showing its age, this is where Kotlin comes to the rescue.
How complicated you want to go is up to you, use Maven, Gradle, Ant, straight Kotlin compiler, Eclipse, IntelliJ, etc. Here's a simple hello world example that gets compiled to JavaScript: http://try.kotlinlang.org/#/Examples/Hello,%20world!/Simplest%20version/Simplest%20version.kt
Comments (33)