Kotlin vs. Java Comparison: Introductory Differences

Mark Foley
5 min readJan 31, 2021

Starting out in the Android development space you’ll hear about two languages: Java and Kotlin. The former is a venerable language with broad application outside Android development but if you’re new to Android you may not be familiar with Kotlin. What is it exactly?

Kotlin is Google’s chosen successor to Java for Android app development. Built to be fully interoperable with Java to facilitate industry-wide adoption and easy, gradual migration, Kotlin is able to coexist in a previously monolithic Java environment. New code is typically written in Kotlin alongside legacy code maintained in Java, necessitating that an Android developer be well-versed in both at the present time. Over the next decade this is likely to change as the old paradigm is gradually phased out and Kotlin comes into full prominence.

Informally described as a “modernized Java,” Kotlin features much functionality absent in Java but which will be familiar to someone with a background in other modern languages, for example ES6 JavaScript. We’ll get into some examples of what that means in detail below. I say “informally” because an appeal — arguably the main appeal — of Kotlin to Google is that unlike Java it is not licensed by hostile big tech competitor Oracle, with whom Google has been embroiled in a decade-long legal battle over the seminal role of unlicensed Java APIs in the development of Android OS.

Rather than give a sweeping, high-level look at how Kotlin compares to its predecessor I think it’s more enlightening to take a look at specific modern programming concepts it introduces. I find this gives a better gist of the language and more convincingly communicates how it represents an advancement over Java than open-ended statements like “it’s a safer, more concise language.”

  • Default parameter values. This affords a single Kotlin constructor the flexibility to handle a variety of inputs when creating an object — no need for Java’s workaround solutions such as multiple constructors or using the Builder pattern to circumvent these constructor limitations entirely. The syntax will be familiar to any JavaScript or Ruby developer.
  • Type inference. Perhaps the most immediately recognizable difference is that Kotlin supports type inference — no explicit declaration of a variable’s data type is necessary as in Java. This places Kotlin alongside JavaScript and Ruby in the family of languages which use implicit typing of variables. However, unlike JavaScript it does not support implicit type conversion; it is akin to Java (and Ruby) in this regard.
  • Implicit getters and setters for each property of an object. In Kotlin there is no need to explicitly write out standard getters and setters as in Java unless they need to be customized from their default functionality. Of course Kotlin supports their customization with an override, but the vast majority of the time this is unnecessary and these implicit getters and setters represent a significant quality of life improvement for the developer. This will be intuitive to JavaScript developers and may be understood from a Ruby perspective as akin to Ruby’s attribute accessor macros.
  • Single expression functions: implicit return from one line functions. Unlike in Java, when a single line function’s curly brackets are omitted that function will automatically, or implicitly, return its single line expression. This is identical to JavaScript (including omission of curly brackets) and familiar to Ruby.
  • String interpolation. Whereas in Java your options are limited to the concatenation operator + or relying on helper methods to interpolate a String, Kotlin supports direct interpolation using the interpolation operator $. The Kotlin syntax is reminiscent of JavaScript in its use of the $ symbol to interpolate a variable and identical to it when interpolating an expression (other than not requiring backticks):
"$kotlin ${kotlin.expression}"
`${javascript} ${javascript.expression}`
"#{ruby} #{ruby.expression}"
  • Async/await. Parallel to async/await in JavaScript, Kotlin features the modern concept of coroutines, greatly simplifying common processes such as fetch calls to an API. Java depends on libraries like Retrofit for this functionality and still async/await is much more streamlined than Retrofit’s Call > enqueue > nested response/failure process.
  • With. Kotlin provides syntactic sugar to avoid the need for repeated explicit getter/setter calls for each property of an object. Keyword with scopes to an object, avoiding the repetition that can plague Java when accessing multiple properties of an object.
  • Synthetic imports. Particular to Android development, Kotlin has direct access to views in the layout XML through synthetic imports whereas in Java you’d need to “findViewById” to access each individual element. I find this very reminiscent of the jump from vanilla JS to React: React allows for direct access to other React components through imports, largely avoiding the need to use “querySelector” or “getElementById” which are ubiquitous in vanilla JS DOM manipulation.
  • Using if as an expression. In Kotlin you can assign a variable to the output of an entire if statement, treating the if as an expression rather than a statement. You can do this in Ruby as well, however it is familiar to JavaScript only in the form of a ternary assignment.
  • Classes are not open by default. In Kotlin there can be no inheritance unless the parent class is explicitly defined as open.
  • Spread operator (*). Unlike Java, Kotlin can for example spread the contents of an array into an indefinite number of arguments on a function call like so: functionCalled(*array). This parallels the JavaScript spread operator ... and the Ruby splat operator *. The spread operator allows for great flexibility such as combining some fixed values with the contents of an array as arguments, something Java does not support.
  • Objects are non-nullable by default. This is commonly mentioned as a difference between Kotlin and Java and is cited as justification for the characterization of Kotlin as a “safer” language than Java — safe in this sense from a NullPointerException. This can be overridden when declaring a variable with a ?, for example:
val a = "Safe; non-nullable by default"
val b: String? = "Unsafe; nullable"
  • Extensions. Reminiscent of, yet safer than, monkey patching a new method into an existing class in Ruby and JavaScript, Kotlin shares with C# the ability to create extensions (called extension methods in C#) which allow you to safely add new functions to an existing class. Unlike monkey patching, extensions do not modify the original class — they even must be imported separately, making them safe to use.
  • Object destructuring. Unsupported in Java yet familiar to Ruby and especially JavaScript, object destructuring allows for convenient assignment of an object’s properties (or an array’s contents) to newly-defined individual variables.

On the whole I find Kotlin to be wonderfully familiar and a welcome addition to, rather than a deviation from, the family of modern software development languages. I welcome and anticipate its rise over the next decade — for more people worship the rising than the setting sun.

--

--