Java may be the first programming language that springs to mind when you think about Android, but you don’t have to use Java for Android development. You can write Android apps in a number of different programming languages, including C#, Lua, C/C++, JavaScript, Scala, and Clojure, but there’s one alternative programming language in particular that’s been getting a ton of attention since this year’s Google I/O.
During the I/O keynote, Google announced that they were making Kotlin an officially supported language for Android development. As of the 3.0 Preview, Android Studio ships with Kotlin support built-in, so creating an Android project that understands Kotlin code is now as easy as selecting a checkbox in Android Studio’s project creation wizard.
This news has generated plenty of buzz, and has also sparked a bit of a Kotlin vs Java debate. Chances are you’ve been reading lots of positive things about Kotlin recently, but if you do make the switch from Java to Kotlin, then what exactly are you gaining? What features does Kotlin have, that Java doesn’t, and vice versa?
In this article, we’re going to be looking at all the major differences between Kotlin vs Java, including a few features that you’ll be sacrificing if you do make the move to Kotlin.
Kotlin vs Java, the later offers more succinct code – with no findViewByIds
If you compare a Kotlin class and a Java class that are performing the same work, then the Kotlin class will generally be much more concise, but there’s one area in particular where Kotlin can seriously reduce the amount of boilerplate code you need to write: findViewByIds.
Kotlin Android Extensions allow you to import a reference to a View into your Activity file, at which point you’ll be able to work with that View as though it was part of the Activity. The result? You’ll never have to write another findViewById method again!
Before you can use these extensions, you’ll need to add an extra plugin to your module-level build.gradle file (apply plugin: ‘kotlin-android-extensions’) but after that you’re ready to start importing Views, for example if your activity_main.xml file contained a TextView with the ID textView, then you’d add the following to your Activity:
import kotlinx.android.synthetic.main.activity_main.textView
You can then access this TextView using just its ID:
textView.setText("Hello World")
This is much more succinct than the Java equivalent:
TextView text = (TextView) findViewById(R.id.textView); text.setText("Hello World");
Kotlin is null safe by default
NullPointerExceptions are a huge source of frustration for Java developers. Java allows you to assign null to any variable, but if you try to use an object reference that has a null value, then brace yourself to encounter a NullPointerException!
In Kotlin, all types are non-nullable (unable to hold a null value) by default. If you try to assign or return null in your Kotlin code, then it’ll fail at compile-time, so neither of the following lines will compile:
val name: String = null
fun getName() : String = null
If you really want to assign a null value to a variable in Kotlin, then you’ll need to explicitly mark that variable as nullable, by adding a question mark after the type:
val number: Int? = null
This makes it almost impossible to encounter NullPointerExceptions in Kotlin – in fact, if you do encounter this exception, then chances are it’s because you explicitly asked Kotlin to throw one, or the NullPointerException is originating from external Java code.
Extension functions
Kotlin gives developers the ability to extend a class with new functionality, which is ideal if there’s a class that you always felt was missing an important method!
These ‘extension functions’ aren’t available in Java, although they are available in other programming languages that you can use for Android development, such as C#.
You create an extension function by prefixing the name of the class you want to extend (such as ‘String’) to the name of the function you’re creating (‘styleString’) for example:
fun String.styleString(): String { // Style the string and then return it// }
You can then call this function on instances of the extended class, via the . notation, as if it were part of that class:
myString.styleString()
Coroutines are first-class citizens
Whenever you initiate a long-running operation, such as network I/O or CPU-intensive work, the calling thread is blocked until the operation completes. Since Android is single-threaded by default, as soon as you block the main thread your app’s UI is going to freeze, and it’ll remain unresponsive until the operation completes.
In Java, the solution has traditionally been to create a background thread where you can perform this intensive or long-running work, but managing multiple threads can lead to complex, error-prone code, and creating a new thread is an expensive operation.
While you can create additional threads in Kotlin, you can also use coroutines. Coroutines perform long-running and intensive tasks by suspending execution at a certain point without blocking the thread, and then resuming this function at a later point, possibly on another thread. This allows you to create non-blocking asynchronous code that looks synchronous, and is therefore more clear, concise and human-readable. Coroutines are also stackless, so they have a lower memory usage compared to threads, and they open the door to additional styles of asynchronous non-blocking programming, such as async/await.
There are no checked exceptions
Kotlin does not have checked exceptions, so you don’t need to catch or declare any exceptions.
Whether this is something that draws you to Kotlin, or makes you want to stick with Java will depend on your opinion of checked exceptions, as this is a feature that divides the developer community. If you’re sick of try/catch blocks cluttering up your Java code, then you’re going to be happy with this omission, however if you find that checked exceptions encourage you to think about error recovery and ultimately push you towards creating more robust code, then you’re more likely to see this as an area where Java has the edge over Kotlin.
Native support for delegation
Kotlin, unlike Java, supports the ‘composition over inheritance’ design pattern, via first-class delegation (sometimes known as implicit delegation). Delegation is where a receiving object delegates operations to a second delegate object, which is a helper object with the original context.
Kotlin’s class delegation is an alternative to inheritance that makes it possible to use multiple inheritance. Meanwhile, Kotlin’s delegated properties help prevent the duplication of code, for example if you need to reuse the same code for multiple properties’ getters and setters, then you can extract this code into a delegated property. The property delegate needs to define the getValue operator function and, optionally, the setValue operator:
class Delegate { operator fun getValue(...) ... ... ... } operator fun setValue(...) ... ... ... } }
Then, when you’re creating a property you can declare that the getter and setter functions for this particular property are handled by another class:
class MyClass { var property: String by Delegate() }
Data classes
It’s not unusual for a project to have multiple classes that do nothing but hold data. In Java, you’ll find yourself writing lots of boilerplate code for these classes, even though the classes themselves have very little functionality. Typically, you’ll need to define a constructor, fields to store the data, getter and setter functions for each field, plus hashCode(), equals() and toString() functions.
In Kotlin, if you include the ‘data’ keyword in your class definition, then the compiler will perform all of this work for you, including generating all the necessary getters and setters:
data class Date(var month:String, var day: Int)
Smart casts
In Java, you often have to check type and then cast an object in situations where it’s already clear that the object can be cast.
Kotlin’s smart casts can handle these redundant casts for you, so you don’t need to cast inside a statement if you’ve already checked it with Kotlin’s ‘is’ operator. For example, the compiler knows that the following cast is safe:
if (hello is String) { printString(hello) }
Support for constructors
Unlike Java, a Kotlin class can have a primary constructor and one or more secondary constructors, which you create by including them in your class declaration:
class MainActivity constructor(firstName: String) { }
No support for implicit widening conversions
Kotlin doesn’t support implicit widening conversions for numbers, so smaller types aren’t implicitly converted to bigger types. In Kotlin, if you want to assign a value of type Byte to an Int variable, then you’ll need to perform an explicit conversion, whereas Java has support for implicit conversions.
Annotation processing libraries with Kotlin
Kotlin supports all existing Java frameworks and libraries, including advanced frameworks that rely on annotation processing, although some Java libraries are already providing Kotlin extensions, such as RxKotlin.
If you do want to use a Java library that relies on annotation processing, then adding it to your Kotlin project is slightly different as you’ll need to specify the dependency using the kotlin-kapt plugin, and then use the Kotlin Annotation processing tool (kapt) instead of annotationProcessor. For example:
//Apply the plugin// apply plugin: 'kotlin-kapt' //Add the respective dependencies using the kapt configuration// dependencies { kapt "com.google.dagger:dagger-compiler:$dagger-version" ... ... ... }
Interchangeability with Java
When debating whether to use Kotlin or Java for Android development, you should be aware that there’s a third option: use both. Despite all the differences between the two languages, Java and Kotlin are 100% interoperable. You can call Kotlin code from Java, and you can call Java code from Kotlin, so it’s possible to have Kotlin and Java classes side-by-side within the same project, and everything will still compile.
This flexibility to move between the two languages is useful when you’re getting started with Kotlin as it allows you to introduce Kotlin into an existing project incrementally, but you may also prefer to use both languages on a permanent basis. For example, there may be certain features that you prefer to write in Kotlin, and certain features that you find easier to write in Java. Since Kotlin and Java both compile to bytecode, your end-users won’t be able to tell where your Java code ends, and the Kotlin code begins, so there’s no reason why you can’t release an app that consists of Java and Kotlin code.
If you do want to try Kotlin for yourself, then as long as you have Android Studio 3.0 Preview or higher installed, there’s a few ways that you can get started:
- Create a new Android Studio project. The easiest method is to create a new project and select the ‘Include Kotlin support’ checkbox from the project creation wizard.
- Add a Kotlin class to an existing directory. Control-click the directory in question, then select ‘File > New > Kotlin File/Class.’ Android Studio will display a banner asking you to configure your project to support Kotlin; click the ‘Configure’ link and follow the onscreen instructions.
- Convert existing Java files to Kotlin. You can run any Java file through a Kotlin converter, by Control-clicking the file and selecting ‘Code > Convert Java File to Kotlin File.’
Wrapping up
As you can see there are lots of good reasons to prefer Kotlin to Java, however there are a couple of areas where Java has the upper hand. Likely the Kotlin vs Java debate won’t settle anytime soon, with both having their own merits. So, are you going to be making the switch to Kotlin, or do you feel that Java is still the best option for Android development? Let us know in the comments!