Kotlin vs. Java: All-purpose Uses and Android Apps
Kotlin and Java are two powerful general-purpose languages popular for Android and beyond. We’ll discuss their top features and differences, then focus on how to smoothly transition between the two.
authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
Kotlin and Java are two powerful general-purpose languages popular for Android and beyond. We’ll discuss their top features and differences, then focus on how to smoothly transition between the two.
authors are vetted experts in their fields and write on topics in which they have demonstrated experience. All of our content is peer reviewed and validated by Toptal experts in the same field.
By Gabriel Gircenko
Verified Expert in Engineering
Gabriel is a senior Android engineer with eight years of experience building apps from scratch in Kotlin and Java, and facilitating conversions between the two languages. Gabriel has worked on multimillion-dollar apps and has industry experience at companies like HBO and Yahoo.
Expertise
Previous Role
Senior Android Engineer
Years of Experience
Previously At
It’s true that Java lost the Android battle to Kotlin, which is now Google’s preferred language and therefore better suited to new mobile apps. But both Kotlin and Java offer many strengths as general-purpose languages, and it’s important for developers to understand the language differences, for purposes such as migrating from Java to Kotlin. In this article, we will break down Kotlin’s and Java’s differences and similarities so you can make informed decisions and move seamlessly between the two.
Are Kotlin and Java Similar?
Indeed, the two languages have a lot in common from a high-level perspective. Both Kotlin and Java run on the Java Virtual Machine (JVM) instead of building directly to native code. And the two languages can call into each other easily: You can call Java code from Kotlin and Kotlin code from Java. Java can be used in server-side applications, databases, web front-end applications, embedded systems and enterprise applications, mobile, and more. Kotlin is similarly versatile: It targets the JVM , Android, JavaScript, and Kotlin/Native, and can also be used for server-side, web, and desktop development.
Java is a much more mature language than Kotlin, with its first release in 1996. Though Kotlin 1.0 was introduced much later, in 2016, Kotlin quickly became the official preferred language for Android development in 2019. Outside of Android, however, there is no recommendation to replace Java with Kotlin.
Year
Java
Kotlin
JDK Beta, JDK 1.0, JDK 1.1, J2SE 1.2, J2SE 1.3, J2SE 1.4, J2SE 5.0, Java SE 6
Project Loom first commit
Kotlin development started
Kotlin project announced
Kotlin open sourced
Java SE 8 (LTS)
Kotlin 1.2; Kotlin support for Android announced
Java SE 10, Java SE 11 (LTS)
Kotlin 1.3 (coroutines)
Java SE 12, Java SE 13
Kotlin 1.4 (interoperability for Objective-C and Swift); Kotlin announced as Google’s preferred language for developers
Java SE 14, Java SE 15
Java SE 16, Java SE 17 (LTS)
Kotlin 1.5, Kotlin 1.6
Java SE 18, JDK 19
Kotlin 1.7 (alpha version of Kotlin K2 compiler), Kotlin 1.8
Java SE 20, Java SE 21, JDK 20, JDK 21
Java SE 22 (scheduled)
Kotlin vs. Java: Performance and Memory
Before detailing Kotlin’s and Java’s features, we’ll examine their performance and memory consumption as these factors are generally important considerations for developers and clients.
Kotlin, Java, and the other JVM languages, although not equal, are fairly similar in terms of performance, at least when compared to languages in other compiler families like GCC or Clang. The JVM was initially designed to target embedded systems with limited resources in the 1990s. The related environmental requirements led to two main constraints:
- Simple JVM bytecode: The current version of JVM, in which both Kotlin and Java are compiled, has only 205 instructions. In comparison, a modern x64 processor can easily support over 6,000 encoded instructions, depending on the counting method.
- Runtime (versus compile-time) operations: The multiplatform approach (“Write once and run anywhere”) encourages runtime (instead of compile-time) optimizations. In other words, the JVM translates the bulk of its bytecode into instructions at runtime. However, to improve performance, you may use open-source implementations of the JVM, such as HotSpot, which pre-compiles the bytecode to run faster through the interpreter.
With similar compilation processes and runtime environments, Kotlin and Java have only minor performance differences resulting from their distinct features. For example:
- Kotlin’s inline functions avoid a function call, improving performance, whereas Java invokes additional overhead memory.
- Kotlin’s higher-order functions avoid Java lambda’s special call to InvokeDynamic , improving performance.
- Kotlin’s generated bytecode contains assertions for nullity checks when using external dependencies, slowing performance compared to Java.
Now let’s turn to memory. It is true in theory that the use of objects for base types (i.e., Kotlin’s implementation) requires more allocation than primitive data types (i.e., Java’s implementation). However, in practice, Java’s bytecode uses autoboxing and unboxing calls to work with objects, which can add computational overhead when used in excess. For example, Java’s String.format method only takes objects as input, so formatting a Java int will box it in an Integer object before the call to String.format .
On the whole, there are no significant Java and Kotlin differences related to performance and memory. You may examine online benchmarks which show minor differences in micro-benchmarks, but these cannot be generalized to the scale of a full production application.
Unique Feature Comparison
Kotlin and Java have core similarities, but each language offers different, unique features. Since Kotlin became Google’s preferred language for Android development, I’ve found extension functions and explicit nullability to be the most useful features. On the other hand, when using Kotlin, the Java features that I miss the most are the protected keyword and the ternary operator.

Let’s examine a more detailed breakdown of features available in Kotlin versus Java. You may follow along with my examples using the Kotlin Playground or a Java compiler for a more hands-on learning approach.
Feature
Kotlin
Java
Description
Extension functions
Allows you to extend a class or an interface with new functionalities such as added properties or methods without having to create a new class:
class Example <> // extension function declaration fun Example.printHelloWorld() < println("Hello World!") >// extension function usage Example().printHelloWorld()
Smart casts
Keeps track of conditions inside if statements, safe casting automatically:
fun example(a: Any) < if (a is String) < println(a.length) // automatic cast to String >>
Kotlin also provides safe and unsafe cast operators:
// unsafe "as" cast throws exceptions val a: String = b as String // safe "as?" cast returns null on failure val c: String? = d as? String
Inline functions
Reduces overhead memory costs and improves speed by inlining function code (copying it to the call site): inline fun example() .
Native support for delegation
Supports the delegation design pattern natively with the use of the by keyword: class Derived(b: Base) : Base by b .
Type aliases
Provides shortened or custom names for existing types, including functions and inner or nested classes: typealias ShortName = LongNameExistingType .
Non-private fields
Offers protected and default (also known as package-private ) modifiers, in addition to public and private modifiers. Java has all four access modifiers, while Kotlin is missing protected and the default modifier.
Ternary operator
Replaces an if/else statement with simpler and more readable code:
if (firstExpression) < // if/else variable = secondExpression; >else < variable = thirdExpression; >// ternary operator variable = (firstExpression) ? secondExpression : thirdExpression;
Implicit widening conversions
Allows for automatic conversion from a smaller data type to a larger data type:
int i = 10; long l = i; // first widening conversion: int to long float f = l; // second widening conversion: long to float
Checked exceptions
Requires, at compile time, a method to catch exceptions with the throws keyword or handles exceptions with a try-catch block.
Note: Checked exceptions were intended to encourage developers to design robust software. However, they can create boilerplate code, make refactoring difficult, and lead to poor error handling when misused. Whether this feature is a pro or con depends on developer preference.
There is one topic I’ve intentionally excluded from this table: null safety in Kotlin versus Java. This topic warrants a more detailed Kotlin to Java comparison.
Kotlin vs. Java: Null Safety
In my opinion, non-nullability is one of the greatest Kotlin features. This feature saves time because developers don’t have to handle NullPointerException s (which are RuntimeException s).
In Java, by default, you can assign a null value to any variable:
String x = null; // Running this code throws a NullPointerException try < System.out.println("First character: " + x.charAt(0)); >catch (NullPointerException e)
In Kotlin, on the other hand, we have two options, making a variable nullable or non-nullable:
var nonNullableNumber: Int = 1 // This line throws a compile-time error because you can't assign a null value nonNullableNumber = null var nullableNumber: Int? = 2 // This line does not throw an error since we used a nullable variable nullableNumber = null
I use non-nullable variables by default, and minimize the use of nullable variables for best practices; these Kotlin versus Java examples are meant to demonstrate differences in the languages. Kotlin beginners should avoid the trap of setting variables to be nullable without a purpose (this can also happen when you convert Java code to Kotlin).
However, there are a few cases where you would use nullable variables in Kotlin:
Scenario
Example
You are searching for an item in a list that is not there (usually when dealing with the data layer).
val list: List = listOf(1,2,3) val searchResultItem = list.firstOrNull < it == 0 >searchResultItem?.let < // Item found, do something >?: run < // Item not found, do something >
You want to initialize a variable during runtime, using lateinit .
lateinit var text: String fun runtimeFunction() < // e.g., Android onCreate text = "First text set" // After this, the variable can be used >
I was guilty of overusing lateinit variables when I first got started with Kotlin. Eventually, I stopped using them almost completely, except when defining view bindings and variable injections in Android:
@Inject // With the Hilt library, this is initialized automatically lateinit var manager: SomeManager lateinit var viewBinding: ViewBinding fun onCreate() < // i.e., Android onCreate binding = ActivityMainBinding.inflate(layoutInflater, parentView, true) // . >
On the whole, null safety in Kotlin provides added flexibility and an improved developer experience compared to Java.
Shared Feature Differences: Moving Between Java and Kotlin
While each language has unique features, Kotlin and Java share many features too, and it is necessary to understand their peculiarities in order to transition between the two languages. Let’s examine four common concepts that operate differently in Kotlin and Java:
Feature
Java
Kotlin
Data transfer objects (DTOs)
Java records, which hold information about data or state and include toString , equals , and hashCode methods by default, have been available since Java SE 15:
public record Employee( int id, String firstName, String lastName )
Kotlin data classes function similarly to Java records, with toString , equals , and copy methods available:
data class Employee( val id: Int, val firstName: String, val lastName: String )
Lambda expressions
Java lambda expressions (available since Java 8) follow a simple parameter -> expression syntax, with parentheses used for multiple parameters: (parameter1, parameter2) -> < code >:
ArrayList ints = new ArrayList<>(); ints.add(5); ints.add(9); ints.forEach( (i) -> < System.out.println(i); >);
Kotlin lambda expressions follow the syntax < parameter1, parameter2 ->code > and are always surrounded by curly braces:
var p: List = listOf("firstPhrase", "secondPhrase") val isShorter = < s1: String, s2: String ->s1.length < s2.length >println(isShorter(p.first(), p.last()))
Java threads make concurrency possible, and the java.util.concurrency package allows for easy multithreading through its utility classes. The Executor and ExecutorService classes are especially beneficial for concurrency. (Project Loom also offers lightweight threads.)
Kotlin coroutines, from the kotlinx.coroutines library, facilitate concurrency and include a separate library branch for multithreading. The memory manager in Kotlin 1.7.20 and later versions reduces previous limitations on concurrency and multithreading for developers moving between iOS and Android.
Static behavior in classes
Java static members facilitate the sharing of code among class instances and ensure that only a single copy of an item is created. The static keyword can be applied to variables, functions, blocks, and more:
class Example < static void f()*. */> >
Kotlin companion objects offer static behavior in classes, but the syntax is not as straightforward:
class Example < companion object < fun f()*. */> > >
Of course, Kotlin and Java also have varying syntaxes. Discussing every syntax difference is beyond our scope, but a consideration of loops should give you an idea of the overall situation:
Loop Type
Java
Kotlin
for , using in
for (int i=0; i
for (i in 0..5)
for , using until
for (int i=0; i
for (i in 0 until 5)
List list = Arrays.asList("first", "second"); for (String value: list)
var list: List = listOf("first", "second") list.forEach
int i = 5; while (i > 0)
var i = 5 while (i > 0)
An in-depth understanding of Kotlin features will assist in transitions between Kotlin and Java.
Android Project Planning: Additional Considerations
We’ve examined many important factors to think about when deciding between Kotlin and Java in a general-purpose context. However, no Kotlin versus Java analysis is complete without addressing the elephant in the room: Android. Are you making an Android application from scratch and wondering if you should use Java or Kotlin? Choose Kotlin, Google’s preferred Android language, without a doubt.
However, this question is moot for existing Android applications. In my experience across a wide range of clients, the two more important questions are: How are you treating tech debt? and How are you taking care of your developer experience (DX)?
So, how are you treating tech debt? If your Android app is using Java in 2023, your company is likely pushing for new features instead of dealing with tech debt. It’s understandable. The market is competitive and demands a fast turnaround cycle for app updates. But tech debt has a hidden effect: It causes increased costs with each update because engineers have to work around unstable code that is challenging to refactor. Companies can easily enter a never-ending cycle of tech debt and cost. It may be worth pausing and investing in long-term solutions, even if this means large-scale code refactors or updating your codebase to use a modern language like Kotlin.
And how are you taking care of your developers through DX? Developers require support across all levels of their careers:
- Junior developers benefit from proper resources.
- Mid-level developers grow through opportunities to lead and teach.
- Senior developers require the power to architect and implement beautiful code.
Attention to DX for senior developers is especially important since their expertise trickles down and affects all engineers. Senior developers love to learn and experiment with the latest technologies. Keeping up with newer trends and language releases will allow your team members to reach their greatest potential. This is important regardless of the team’s language choice, though different languages have varying timelines: With young languages like Kotlin, an engineer working on legacy code can fall behind trends in less than one year; with mature languages like Java, it will take longer.
Kotlin and Java: Two Powerful Languages
While Java has a wide range of applications, Kotlin has undeniably stolen its thunder as the preferred language for the development of new Android apps. Google has put all of its efforts into Kotlin, and its new technologies are Kotlin-first. Developers of existing apps might consider integrating Kotlin into any new code—IntelliJ comes with an automatic Java to Kotlin tool—and should examine factors that reach beyond our initial question of language choice.
The editorial team of the Toptal Engineering Blog extends its gratitude to Thomas Wuillemin for reviewing the code samples and other technical content presented in this article.
Further Reading on the Toptal Blog:
- Tips and Tools for Optimizing Android Apps
- Buggy Java Code: The Top 10 Most Common Mistakes That Java Developers Make
- Introduction to Kotlin: Android Programming for Humans
- Hunting Java Memory Leaks
- An In-depth Look at C++ vs. Java
В чем заключается отличие Kotlin от Java?
Java – один из старейших и востребованных языков программирования. Но вот уже несколько лет он делит популярность с Kotlin. Это более новый язык, не менее популярный у разработчиков, особенно работающих в сфере мобильных приложений. Сегодня мы расскажем о разнице между Java и Kotlin, их плюсах и минусах для программистов разного уровня.
Что такое Kotlin?
Java не нуждается в представлении, а с Kotlin знакомы не все. Поэтому мы начнем обзор с представления этого языка.
Изначально он представлял собой клон Java. Его авторы хотели улучшить типобезопасность в сравнении с исходником и сделать язык проще, чем Scala. Именно благодаря этим плюсам Kotlin обрел огромную популярность. Google сообщает, что 700 из 1000 лучших приложений в Play Store написаны на этом языке.
Сегодня Kotlin является предпочтительным для разработчиков на Android, но и забывать про Java рано. Нельзя сказать, что «новичок» лучше «предшественника». Оба языка обладают своими преимуществами и недостатками, и выбор зависит от предпочтений и опыта разработчика. На последнем пункте остановимся подробнее.
Новички и языки программирования
Начинающим важны низкий порог вхождения в язык, простота его использования, быстрота обучения и общность технологической базы. И это то, в чем Kotlin лучше Java. Например, чтобы написать на Kotlin приложение и backend server, к которому оно будет обращаться, в дополнение к общему стеку потребуется изучить только фреймворк Ktor. При работе с Java понадобятся минимум Spring Boot и Retrofit. Кроме того, синтаксис «старшего» языка строже, одна пропущенная запятая – приложение станет нерабочим.
Так что для новичков Kotlin предпочтительнее из-за:
- менее строгого синтаксиса;
- лаконичности и простой читаемости;
- высокой консистентности;
- кроссплатформенности.
Опытные разработчики и языки программирования
Для программистов с опытом важны такие критерии, как возможности синтаксиса и скорость выполнения кода. Имеет значение и актуализация версий: при регулярных обновлениях функциональность расширяется, а баги оперативно устраняются. И здесь однозначного лидера нет, так как оба языка отвечают требованиям. При выборе оптимального варианта придется опираться на другие нюансы.
С одной стороны, Kotlin гарантирует большую безопасность, но это молодой язык, не лишенный «детских болезней».
Java хорошо изучен, недочеты устранены, у него есть сильное сообщество. Однако он требует больше памяти, и это нужно учитывать.
Что касается быстродействия, раньше на стороне Java был перевес в 12–15 %, но сейчас разницы между ним и Kotlin нет.
Плюсы и минусы Kotlin и Java для бизнеса
Отдельно стоит сказать о преимуществах и недочетах каждого языка в контексте их использования в бизнес-процессах. Для предпринимателей важна в первую очередь скорость разработки и внедрения решения, а также универсальность языка, чтобы можно было разработать и мобильное приложение, и десктопную программу.
В принципе, оба языка соответствуют этим критериям. У Kotlin также есть полезные языковые фичи в IDE экосистемы JetBrains. Кроме того, может автоматически конвертироваться в Java и обратно, так что можно начать работу с него, а при необходимости перейти на другой язык.
Но есть и минус: соискателей, работающих с Kotlin, существенно меньше, чем разработчиков на Java. Также мало языков и курсов, так что у IT-сотрудника могут возникнуть проблемы с самообразованием.
Найти программиста на Java гораздо легче, как и подобрать решение возникшей при работе проблемы. К минусам можно отнести то, что с 11 версии придется приобрести коммерческую лицензию.
Если вы все еще выбираете между двумя вариантами, специалисты компании Garpix помогут вам. Мы проконсультируем по вопросам разработки приложения и подскажем, какой язык оптимален в вашем случае. Напишите нам!
Есть ли отличие Kotlin от Java?


Всем привет. Хочу рассказать немного базовых вещей о языке Kotlin, что будет полезно новичкам. Так уж сложилось, что сейчас попасть в android-разработку только с одним языком будет сложно — большинство новых проектов начинают писать на Kotlin, большинство готовых проектов написаны на Java. На данный момент у меня на работе 4 проекта: два на Kotlin и два на Java (один большой основной и три маленьких, для внутреннего пользования). Когда компанией было принято решение писать новые проекты на Kotlin, для меня это решение казалось странным. Зачем мешать разные языки? Пусть себе кто-то другой пишет на Kotlin, нам оно зачем? Но выхода не было, потому решил опробовать новый язык и начал его изучать. Первый код, естественно, был полностью написан в стиле Java, что еще больше добавляло непонимания: зачем мне новый язык? Но по мере его использования я всё больше находил преимуществ и сейчас (уже почти 2 года пишу на Kotlin) могу сказать, что в андроид-разработке Kotlin удобнее. Хочу показать некоторые нюансы, которые будут неочевидны для того, кто решил начать изучать Kotlin после Java. Также напомню, что в андроиде используется Java 8, при нынешней актуальной версии 14. Итак, первое — Переменные: Java:
Int a = 1; String s = "test";
val a = 1 var b = 2 val c: Int val d = "test"
В Kotlin переменные двух типов: val (только для чтения) и var (для чтения и записи). Рекомендуется использовать val везде, где это возможно. Объявлять тип переменной не обязательно, если переменная уже инициализирована. Второе — выражения if/else, switch: Как часто вы используете в Java такую цепочку операторов:
if (вариант 1) else if (вариант 2) . else
switch(выражениеДляВыбора)
В Kotlin используется для таких выражений оператор when (хотя if/else тоже можно использовать):
val x = 5 val result = when(x) < 0, 1 ->"cool" 2 -> "bad" 5 -> "normal" else -> "error" > System.out.println(result)
Здесь мы не просто прошлись по цепочке условий, а еще и всё выражение сразу присвоили в переменную result, что сократило нам немало строк кода. Но всё же если у вас только два варианта в ветвлении, рекомендую использовать обычный if..else. Конструкция when будет короче только от трех вариантов. Идем дальше — Конструкторы. Здесь вообще сказка. Просто сравните код в Java и Kotlin. Java:
public class Person < private String firstName; private String lastName; private int age; public Person(String firstName, String lastName, int age) < this.firstName = firstName; this.lastName = lastName; this.age = age; >public String getFirstName() < return firstName; >public String getLastName() < return lastName; >public int getAge() < return age; >public void setAge(int age) < this.age = age; >>
class Person(private val firstName: String, private val lastName: String, private var age: Int)
Может показаться, что в коде на котлине что-то не дописали. Но нет, это два идентичных кода на разных языках. Давайте немного разберемся. В Kotlin конструктор можно прописывать прямо в теле названия класса (но если хочется, то можно и по старинке, как в Java). Итак, мы прописали три переменные, в Java создали конструктор, геттеры и один сеттер для переменной age. В Kotlin, как мы помним, переменная val только для чтения, а потому сеттер для этих переменных недоступен (геттеры-сеттеры котлин реализует под капотом сам). Переменная var дает возможность использовать сеттер. В итоге практически одной строкой мы написали то же самое, что на Java заняло больше десятка строк. Здесь рекомендую еще почитать про data class в Kotlin. Но это еще не всё, в чем хороши конструкторы в Kotlin. А что, если вам надо два конструктора? А если три? В Java это будет выглядеть так:
public Person(String firstName, String lastName, int age) < this.firstName = firstName; this.lastName = lastName; this.age = age; >public Person(String firstName, String lastName) < this.firstName = firstName; this.lastName = lastName; >public Person(String firstName)
Ничего сложного, сколько надо конструкторов, столько и сделали. В Kotlin можно обойтись одним конструктором. Как? Всё просто — значения по умолчанию.
class Person(private val firstName: String, private val lastName: String? = null, private var age: Int = 5)
Мы в конструкторе присвоили значения по умолчанию и теперь вызов их будет выглядеть так:
Person(firstName = "Elon", lastName = "Mask", age = 45) Person(firstName = "Elon", age = 45) Person(firstName = "Elon", lastName = "Mask")
Тут может возникнуть вопрос: что это такое:
private val lastName: String? = null
Что еще за знаки вопроса? Да, если значение может быть null, то ставится ? .Также есть вариант вот такой — !! (если переменная не может принимать null). Об этом уже сами почитайте, там всё просто. А мы идем к следующему пункту. Extensions. Это очень крутой инструмент в Kotlin, которого нету в Java. Иногда мы в проекте используем шаблонные методы, которые повторяются во многих классах. Например, так:
Toast.makeText(this, "hello world :)", Toast.LENGTH_SHORT).show();
В Kotlin мы можем сделать расширение для класса:
fun Context.toast(message: CharSequence) = Toast.makeText(this, message, Toast.LENGTH_SHORT).show()
И дальше по всему проекту использовать это вот так:
context?.toast("hello world")
Мы сделали расширение для класса Context. И теперь везде, где доступен context, будет доступен его новый метод toast. Это можно сделать для любого класса: String, Fragment, ваши кастомные классы, ограничений нет. И последний пункт, который разберем — Работа со строками. Тут всё просто. В Java это пишется так:
String s = "friends"; int a = 5; System.out.println("I have" + a + s + "!");
В Kotlin проще:
val s = "friends" val a = 5 println("I have $a $s!")
Kotlin is *Way* More Than Just Android
Justin Lee goes over a number of frameworks and libraries available for Kotlin development and not once have to touch the Android emulator.
Bio
Justin Lee is a Java Champion and Kotlin fanatic. He has been programming in Java since 1996 and has worked on virtually every level of the application stack. A long time advocate of Java and Kotlin, he has spoken at conferences and user groups all across the US and Europe. He is currently a Principal Software Engineer at Red Hat working on QuarkusIO.
About the conference
QCon Plus is a virtual conference for senior software engineers and architects that covers the trends, best practices, and solutions leveraged by the world’s most innovative software organizations.
Transcript
Lee: Welcome to Kotlin: More than Just Android. My name is Justin Lee. I’m a developer at Red Hat. I work on the Quarkus microservice MicroProfile based framework. I’m also a huge Kotlin fan. I’ve been a fan of Kotlin for many years now. I’m really excited to see how big it’s growing and continues to evolve in some really amazing spaces. Kotlin, was really the very first language that enticed me away from writing in Java. I’m a Java champion. I’ve been doing Java since 1996. For me, Kotlin was the first language that felt really good enough to migrate all my stuff to. I did that several years ago. I moved my first big project over to Kotlin in 2015. I’ve been trying to do as much as I can with it ever since. I’m one of the co-leaders at the New York City Kotlin meetup. Many of the Kotlin devs I talk to only do Android. They’ve never really written any backend applications. The thought of writing non-Android applications in Kotlin just hasn’t occurred to a lot of them, because why would they. That’s a little frustrating for me, a little disappointing, because I personally love Kotlin, obviously, but I’ve never written a single Android app. There’s so much that Kotlin has to offer on the backend, but never really gets considered for a lot of people.
Outline
What I want to do is I want to showcase some of the more prominent non-Android options for Kotlin on the backend. I just want to go through a quick whirlwind tour of some of the bigger players, to give you an idea of what’s out there. We can talk some options there. The beautiful thing about Kotlin is it was designed to interoperate with Java as seamlessly as possible. Virtually, any Java library out there, whether it’s a framework or a library or whatever it might be, you can use it in Kotlin with very little problems. You can pretty much use any framework you want to write Kotlin on the backend, but these options give specific Kotlin goodness to the mix and make it a little bit simpler to use on the backend. We’ll look at some of that stuff. What I’m hoping to do is to whet your appetite for Kotlin on the backend, if you haven’t considered it yet, because it is a great option. What I really hope to do is to inspire you just to write Kotlin everywhere you can. Because there’s really no technical reason you shouldn’t. It’s a great choice for whatever your computing needs might happen to be.
I wanted to go through a series of options you have for running stuff on the backend. Primarily, we’re going to look at web microservice frameworks, because it’s typically at least the entry point on the backend when you want to start talking about this or that. That’s what we’re going to look at. Then we’ll look at some desktop stuff, then maybe take a brief peek at some of the things.
Web Frameworks — Ktor
Let’s start talking web frameworks. I would be remiss if I didn’t start with the most Kotlin-y version of that answer. The definitive answer there seems to be this library called Ktor, which started off as an early DSL experiment for this or that, and has evolved into a super feature rich framework. It had probably more features than I can process at this moment. If you want something like purely Kotlin and written for Kotlin by Kotlin people, then Ktor is where you want to go. You can find it at ktor.io. Because it’s written in Kotlin and for Kotlin and by Kotlin people, all the rich Kotlin goodness comes out in how the language plays into the library.
The Simplest Ktor Application
For example, if you want to do, as the website says, the simplest Ktor application, in this case we’re going to do, fun main, which is the equivalent of public static void main, from the Java world. In Kotlin, you just need, fun main. You can take an array of string as arguments if you want, or not. Most people I think don’t probably use those arguments overly much. Regardless, this is the simplest way that you can start a Ktor application. In this case, they’re defining an embedded server, they’re using Netty, running on port 8000. As you can see here, they’re parsing a lambda to this embedded server. In here, what they’re defining is the routing, so all of your route endpoints. If you’re coming from the JAX-RS world, this would be like your @Path. You’re going to have @GET, @PUT, @POST, whatever. Ktor defines a very handy DSL to do this. There’s the starting point here. We’re defining the routing for this embedded server, and we’re parsing in yet another lambda. We’re going to define a get endpoint on the route, and all it does is it returns the response text of Hello, World. There’s some internal stuff here, where a call comes from everything. This is what a very basic Ktor application looks like.
Define Multiple Route Handlers
You can get a little bit more complicated in your routing, if you so choose. Here, for example, there are multiple endpoints, a get on /customer with an ID as URL parameters that can be used inside the function body there. There’s a post on the /customer endpoint, and then it gets again, an order instead of ID. You can define them like this. Also, if you want to, you can group them together. We’re going to define a route on /customer with a get endpoint and a post endpoint. You can put your various handling logic in those particular functions, depending on what the incoming HTTP verb looks like. You can nest them, of course, if you wanted to do so. Then you can use extension functions if you want. You can define your functions elsewhere. If you had everything defined in one giant routing block, your simple application suddenly becomes very large just to do the starting point. You can map all those out into separate functions and separate classes, if you like.
Building Web Applications with Spring Boot and Kotlin
If you’ve done Java backend development, then you’ve probably used Spring Boot. If you haven’t, you know someone who has. This is the obvious second step, because it is the biggest player probably in the Java world, at least in the microservices universe. Spring Boot added Kotlin support, two or three years now. They have some rather robust options for you. If you’ve used Spring Boot, this should all look very familiar to you. They have their Spring Initializr. You can come in, define whichever options you want, you need Gradle or Maven. You can use Kotlin, you can use Java. We’re here to learn Kotlin, so why wouldn’t we? Just like every other Spring Boot application, just choose which modules you want, which extensions, and then generate. It will generate a whole new package for you. You load it up, run it, and suddenly you’re running Kotlin on the web. Super handy. If you’re fiddling with Spring Boot, it’s definitely a great place to start.
Quarkus — Creating Your First Application
Next is Quarkus, which is near and dear to my heart. I happen to work on the Quarkus team. I do want to mention Quarkus, because it also has Kotlin support, part of my job is to enhance and render out the Kotlin support inside Quarkus. If you’re not too keen on getting tied up into the Spring ecosystem, which some people are for various reasons, then Quarkus is a great option. It uses RESTEasy and Hibernate. If you’re familiar with CDI for MicroProfile, it all uses standard Jakarta EE and MicroProfile, so it’s a library. It should all be very familiar to you. Even though most of it is not written in Kotlin, as is the case with Spring Boot as well, because Kotlin is designed to interop with Java, it’s very natural to use Java libraries from Kotlin for the most part. Both Spring Boot and Quarkus do provide a number of Kotlin idiomatic ways to interact with the system. Those of course will increase and improve over time. Quarkus is a great choice.
Micronaut
Another one is Micronaut, which is also quite popular. A lot of people like to use that if they’re not on Spring Boot or Quarkus. They have rather robust Kotlin support as well. They also have support for Ktor. If you’d rather use Ktor as the underlying transport layer instead of, I believe it uses Netty by default, you can actually use Ktor and wire in that way. If you’re familiar with Micronaut, and all of its injections and annotations, and lifecycle support and everything, you can still use all that on top of Ktor. Which has some interesting multi-threaded concurrency capabilities that you don’t necessarily see as a developer, but you will definitely experience them on the Ops side, because it’s quite nice.
If I had to pick the top three or four web frameworks, that’s what I would look to, for Kotlin. There are dozens of more niche or boutique frameworks. I don’t say that to denigrate any of them. There’s some amazing work going on in terms of like pushing the boundaries with Kotlin and DSLs, and such. They’re just not as popular, so finding support or someone who also knows those libraries might be a little bit harder, but it might be worth it to try some of those smaller ones as well because they might really scratch your particular itch.
JavaFX and TornadoFX
Moving away from the web to the desktop. If you’ve ever talked about Java in the desktop, of course, it was Swing for a long time, but the new hotness is JavaFX. I’ve seen some amazing JavaFX applications written doing some pretty stellar work in aerospace work. For example, putting things in orbit around Jupiter. That’s not an exaggeration, it’s pretty stellar. However, there is a library called TornadoFX, which provides a number of Kotlin extension functions and DSLs and convenience methods for building your JavaFX applications in a much more idiomatic, Kotlin way, that helps reduce the boilerplate needed to build out such an application. The documentation is fairly extensive. You have to build your layout, for example. It might look like this, which is a nice little DSL, creating your virtual box and button. You can define the action on it. It pops out like this. These are all basic examples, of course. It really leverages the power of Kotlin to reduce the amount of code you have to write in order to build your JavaFX applications.
Jetpack Compose for Desktop
One I wanted to mention, even though I’m skirting dangerously close to Android, is this thing from JetBrains called Jetpack Compose. It originally, as I understand it, started off as an Android application framework for building Android applications for Android devices. It has since expanded to the desktop, which is now in alpha, according to the website. I thought it was beyond that. The website still says alpha at least. It provides fast reactive desktop UIs for Kotlin. It’s based on some stuff from Google and JetBrains. As I understand it, they’re working together to build this framework for building applications. What makes this really stellar and what might make it interesting to those of you who write desktop applications is that you can use much of the same code base for the desktop version of the application and the mobile application version of it. You can share a whole lot of the code in between each module. Then there’s also a third component of this which is not as far along, as the mobile device and the desktop. There’s also work being done for web. You can actually build the same application for desktop for Android and for the web. Even though, obviously, some of the UI components won’t necessarily carry over much of the logic, and the wiring behind the scenes can be reused. Then you just have to swap out perhaps certain UI elements to make something a little bit more natural for whichever platform you’re building on. Then you can share all the rest of the code in between the projects in one code base. That’s Jetpack Compose.
Resources
This website is called Awesome Kotlin, and it has a number of links and resources off to everything. Just the base, awesome tab has courses and books. You scroll down, and you see all these libraries and frameworks. Here’s Ktor, of course. Here’s http4k which has 1700 stars on GitHub, which is nothing to laugh at. A lot of work is being done with Kotlin in data science, which makes me happy. If you’re not a huge fan of Python, for example, you can actually use Kotlin with Jupyter Notebooks with Kotlin Jupyter. There’s work being done there. There are some specific testing frameworks you can use to make it a little bit more Kotlin friendly inside your test. There’s some database specific, and JetBrains exposed as a nice typesafe DSL over SQL queries in Kotlin, which is very interesting. Some custom dependency injection, this and that. The list just goes on. If you click under resources, you can get the latest hotness, depending on what you’re looking for in resources and courses.
I also wanted to point out this last tab, especially. I just wanted to show you all the user groups around. Hopefully, there’s one near you wherever you happen to live. In the time of COVID, most of them are online in here. A lot of them are online. They have the resources to do that. Please do find a meetup user group somewhere nearby and just hang out and see what the vibe is, and learn. You don’t have to actually write Kotlin code. You don’t have to commit to it. Join a group. You can just join one and see what’s happening.
I want to leave a couple of resources. Kotlinlang.org is the primary website. All the official documentation is there, tutorials. It’s all there, all you could ever want. There’s also play.kotlinlang.org, where you can actually run code in your browser, so you can experiment with Kotlin code without having to install anything. If you would like to use Slack, there’s a Slack workspace for Kotlin that has over 30,000 people in various channels. It is a great resource. There’s dozens of different topics you can follow and create your own. If you’re more of the IRC type like myself, there is #Kotlin on FreeNode, where you will find me hanging out most days. Of course, Awesome Kotlin with all those links. There’s a ton of information there.
Questions and Answers
Ruiz: Kotlin 1.5 was just released, May 5. What can you tell us about the new release? What is exciting for you?
Lee: One of the things that I’ve been looking forward to, is they actually rewrote the entire compiler, and that doesn’t really necessarily affect developers as such. I’ve been eyeballing it, because one of the things that I do on Quarkus, which is one of the reasons I brought up in the talk, was I’m the guy adding support for Kotlin-y sorts of things inside Quarkus. We do a lot of bytecode manipulation. I was a little worried that they would change how that bytecode gets generated, and it would just completely mangle everything I work on, but so far, so good. I’m in the process of actually now trying to port it over, and tests are failing weirdly, so who knows. I haven’t actually gone over the list of things to look at, because I don’t get to write Kotlin that much in my day job just yet. I do try to do in my side projects, and I have some open source stuff that I’m going to migrate to that.
Ruiz: Actually about that, what about Morphia and Kotlin, tell me.
Lee: I used to work for MongoDB, and there was this layer called Morphia. I like to describe it as Hibernate but for Mongo, so you annotate all your Java objects, and Morphia shells it back and forth just like Hibernate would do. There is support in Morphia for Kotlin, actually, in this upcoming release that hopefully will be out in the next week or two. There’s a specific module for supporting data classes inside Morphia, because those are slightly different from a reflection standpoint. I’m adding more support. At some point, I’m going to port all of Morphia probably to Kotlin, because I like writing in it. I’m trying not to leave anyone behind. Kotlin is really great. It is designed to interop with Java. If you’re not careful, you can expose the fact that it’s a Kotlin library to your Java developers, because there’s a certain way that Kotlin does the magic, especially around like generics that can sometimes leak out, if you’re not careful.
Scala is really bad about that. One of the questions was, why Kotlin over Scala? Scala is a fine language. I’ve tried to use it, and I’ve tried to like it, but it’s never been a professional thing for me. If you’ve ever tried to use a Scala library from Java, it’s very obvious that the library was not written in Java. It’s really hard to use. Whereas Kotlin, that’s not the case. You can run it from Java, you’d see something like, what is that? It’s usually generally good about creating Java friendly APIs. One of the things that Kotlin has, and I really liked it, I hope Java gets someday, but probably won’t, is named parameters and default parameters. When you define a function, you can define default values for a parameter. If you don’t parse an argument for that when you call it, the compiler will inject it for you. You could default all your parameters away in your declaration. When you call it, you can just call it with no parameters, because the compiler will insert things for you when it builds. From Java, that gets weird, because there’s just the one method that takes all the parameters, and so you lose some of that defaulted parameters. There’s an annotation you can use that Kotlin will actually generate multiple overloads. It’ll start from the very right-hand side and start peeling off the defaulted parameters, so that if there are four parameters with defaults, you get four or five methods. One that takes all the parameters, and then one that takes three, then two, then one, and nothing. You get that same feeling from Java.
Ruiz: Actually, Marc is telling us some bytecode changed indeed, they had to do some adjustment for JaCoCo to support Kotlin 1.5. There is something that changed already.
Lee: I have some tests that are failing because a method that I should have overwritten as part of my bytecode stuff wasn’t for whatever reason, so I’m going to have to dig into that and just see what’s going on.
Ruiz: From people moving from Java to Kotlin, any advice on how to avoid bad practices from the Java world, example, handling nulls?
Lee: How to avoid them? I mentioned this project that I switched over in 2015. It’s a large-ish project. It’s an IRC bot, so no money was riding on this particular conversion. IntelliJ IDEA has an option, you can go in and say convert this Java class to Kotlin, and it will just blast it out for you automatically. It gets you like 98% of the way there. What I found was there’s a whole lot of places in there where I was exposed to a null pointer exception, because I wasn’t checking for it. I had to go back and fix all those. I would start with, you put a question mark on a type that can be null, or a question mark on the type for a field that can be null. I would start without those. In that way, you’re essentially telling the compiler, nothing in my application can be null. Your code will break. It won’t compile or whatever. You’ll start to see those places where a null may or may not creep in. Then you can evaluate those situations. You’re like, no, actually, I never want a null there, so let’s leave the question mark off. There’s someplace that is perfectly valid, so you can put a question mark in. You can start to backfill in some of the nullability. That’s probably simpler than just marking everything as nullable, because then everywhere you use any of those fields, there are certain things you have to do. There’s a number of different ways you can check for null. It’s more work to go and add those everywhere than it is to just figure out where do we really want to allow nulls, and then fix those places. Because, generally, we don’t want nulls.
Ruiz: Why Kotlin and the leads that you show will not be the new Groovy plus Grails, what’s the big difference for you?
Lee: What’s to stop Kotlin from becoming Groovy, essentially? Grails is basically Rails but with Groovy. I think there’s a couple differences. Groovy never really had much backing, corporately speaking. I have a lot of friends that are very into Groovy, so I have to be delicate in how I talk about it, because I have stuck my foot in my mouth a few times. It never had much corporate backing. It never had a whole lot of developer buy-in. People who did use it were very passionate about it, and they loved it. I think one of the thing that turned me off about Groovy personally was it was a dynamically typed language, which I’ve never liked. I’ve been doing Java since 1996, since there was a Java basically. Being able to reason about types and validate things, that was like very important to me, and Groovy broke that contract. Even though the other language had some nice features, it was harder to reason about. Kotlin is not that. It does a lot of type inference, which I think is amazing. Also, the types are fixed and they’re known. That’s a big difference between Kotlin and Ruby. Also, Google is all in on Kotlin. It’s the preferred recommended language for Android, for example. I think it’s going to be around for a while, for that, if no other reason. Kotlin has a lot more corporate backing than Groovy did.
Ruiz: That’s true. IntelliJ, yes, it is investing a lot.
Just curious if there is anything with a more idiomatic Kotlin API.
Lee: Idiomatic for what, in what context?
Ruiz: What’s the use case for Kotlin? What are the pros and cons? Where does Kotlin shine, amazingly?
Lee: Where does it shine? For me, one of the bigger things is, I think the syntax is a lot sleeker. Java has come on quite a ways. I think the value add for Kotlin is somewhat less now than it used to be. Certainly, like in the Java 6 days when Kotlin was really starting to rise to prominence, you could do all these amazing modern lambdas, and type inferences, and all those sorts of thing on a Java 6 JVM. Which was still 40 years before Java actually adopted some of those features. It’s I think why it took off on Android, it really gave a modern language on an older JVM. That’s changed a little bit. I still think the syntax is sleeker. When you talk about Java’s concepts versus Kotlin, I think the syntax is nicer in Kotlin for that. There are certainly more functions available to you to process your data stream. There’s that.
Kotlin has coroutines, which is an implementation of what’s called structured concurrency, which I only know because I’ve been reading about Kotlin coroutines. It doesn’t mean a whole lot to me otherwise, but for the CS nerds out there. It basically lets you write concurrent code, like it’s imperative. C# has its async, await. There’s like all these reactive APIs where you subscribe to this, and on callback this. You can get concurrent code with reactive messaging, or asynchronous code with reactive whatever, but it’s a massive buy-in to a really awkward, terrible API. With Kotlin coroutines, for example, you have to launch it in a certain way, because it needs a certain context. Then you just write your code, foo this, bar that, and the Kotlin compiler will actually build in all the stuff necessary to say, fire off this request off in a thread somewhere. You take care of that, I’m going to go work on this, and I will come back ready. Your code just looks like normal imperative code, but it’s actually highly scalable, like millions of coroutines running on a single machine. As opposed to Java threads, once you get past certainly 100,000 threads and you will turn your laptop into slug. Coroutines are great.
Project Loom is coming up, and so that will be an interesting competitor to coroutines. It’s not going to be in Java 17, it might be in 18. I don’t know when it’s going to land. It’ll be years before that becomes a common thing in the Java world, unless it’s so compelling that everyone immediately says we should upgrade to Java 19 today, which would be amazing. I’d love it. Java updates typically has lagged quite a bit.
Ruiz: After Java 17 LTS is out, what features are still lacking that you like in Kotlin? New features in Java, for instance in Project Loom and Virtual Threads, could this close the gap in functionality between languages and keep Kotlin? They are thinking like, Java, it’s picking up.
Lee: I think once Loom lands, it gets really interesting. Virtual Threads will be interesting. I’m old enough to remember Green Threads back in the early JVM days. It feels like we’re veering back into that era again, although I think it’s slightly different than the original Green Threads. Certainly that gap is closing, I think. The nice thing still with Kotlin is they’ve been able to push the boundaries for what you can do in the JVM without requiring JVM updates. Some of the stuff that’s coming in Java necessitates updates to this VM itself, which is fine, which is great. It’s a slower process. I think Kotlin will probably still outpace Java, in that respect. At some point, as much as I love Kotlin, and I absolutely love Java as well, I think the value proposition for, «Rewrite your entire application in Kotlin,» becomes less at some point, because the gap will be smaller for things that most people care about.
Ruiz: Do you have any advice for developers either in Java or in C#, moving to Kotlin?
Lee: Some of it is just stock advice, but we’ll see if something interesting comes out of it. One of the things that I’ve always learned or heard for years now, is the JVM is so great, because there’s literally hundreds of languages that run on the JVM. Everyone was like, if you want a new language, write your test in it first. You’re not necessarily betting the company on a test. You kind of are, but it’s a little bit more indirect. If your test doesn’t work, then suddenly you’ve just cost the company a billion dollars. You can start with writing small tests, for example, and just get a feel for the language. It can be pretty bite sized. Setting up multi-language projects is not difficult. If you go to the Kotlin website, there’s instructions for both Maven and Gradle, depending on what your preference is. The Kotlin world seems to favor Gradle. I think that’s driven more by Android than anything else, because Android builds on Gradle, and not Maven. I would start there and just start writing some tests.
What I’ve actually done, because building Quarkus can be complicated, there’s almost 900 modules inside Quarkus [inaudible 00:36:06] to help aid in my development. I originally had Bash scripts, which was fine, because I’m a Linux nerd for decades now. I actually went back and rewrote all those Bash scripts using Kotlin and Quarkus CLI. It’s what I work on, so I thought, I might try this out. I wrote all these dev scripts in Kotlin, so they’re all running on a JVM. They run so fast, it’s like running a Bash script. I never noticed the difference. You can write fairly complex scripts that way in Kotlin, and then run them. Then you really are outside risking the actual product whatever your development scripts might happen to be. Rewrite them in Kotlin and see how it feels. Some things are going to be more awkward, because interacting with the OS from the JVM, execing things out is not so great. You can play with the language, at least in a way that doesn’t threaten anything.
