Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Why Kotlin Language, Android? Why Did Google Choose Kotlin?

DZone's Guide to

Why Kotlin Language, Android? Why Did Google Choose Kotlin?

Kotlin is gaining fame for being supported by Google and simplifying Android development. See how it solves many of the pain points with Java.

· Mobile Zone
Free Resource

Why Kotlin?

If I was asked today about the characteristics that distinguish the development of Android applications from other fields, I would not hesitate to answer that the possibility of executing the same application on devices with different hardware in a native way is one of them; but…how is this possible? I would like to start my series of Kotlin language articles by explaining the language and the benefits of it. 

At this point, no one is surprised to see the same web application running on any device and on any platform (Android, iOS, Windows, MacOS…). We all know that these applications are slower and more unstable than any native application, but in exchange, we only have to develop one application for all platforms. A similar problem would arise when talking about the number of different devices on which Android works right now, and I say would if it weren't for Java. The power of Java and the fact that it is used in billions of devices today, it’s ability to work on any device regardless of its hardware and software, as long as it has an interpreter of the pseudo-compiled code generated by the Java compiler (the official Java interpreter is the Java Virtual Machine, although on Android Dalvik was used in the first versions and ART today).

Does this mean that Java is the solution to all evils? Unfortunately, nothing is further from the truth. Although Java solves the problem of interoperability between devices, it opens a new range of headaches that we would like to be able to remove from the equation. Here are some of them*:

*Note: Many of these problems, although resolved in Java 8 and 9, are not available in the Android SDK below API 24, which makes them practically unusable.

  • There is no native support for optionals (although we do have it for immutable collections). Although there is the Optional <T> class, its use implies the generation of a large amount of boilerplate code, which we could save if the support for the options was built within the language itself and not as an extension of it.
  • There is no native support for functional programming: in Java, there is the Stream API (once again, it only has support in Android starting from API 24), but its integration in the language is similar to the one of Optional; it exists poorly in the objects associated with primitive types (IntStream, DoubleStream …), and through a Stream class <T> for all other objects.
  • Support for anonymous functions (Lambdas). Although Java 8 incorporates support for Lambda functions, these are not first-class citizens; this means that, although we can use lambdas to implement anonymously interfaces with a single method, Java does not support passing functions as arguments to a method. In addition, the lack of type inference makes the statement of Lambdas quite uncomfortable, especially in the attempt to simulate functions such as composition of functions or currying, due to the lack of support for them in the language.
  • Type nullability: Although this can be included within the section referring to the optional, the dimension of this problem deserves a special mention. How many Java programmers didn’t fill their code with if (foo! = Null) to try to fight the dreaded NullPointerException?(actually, it’s creator apologized for what he calls a “billion-dollar mistake”) And how many of those check-ups are more than patches to avoid a crash in our application?
  • Binding of manual views: Although this problem is specific to Android as a platform, and not Java as a language, it is also worth pointing out the amount of boilerplate code needed to obtain a reference to an Android view. Although we have managed to eliminate the hated findViewById (int id) thanks to dataBinding, we still have to store a reference to that binding.
  • It is more general, but not less important; Java is a very verbose language, it requires writing a large amount of code for any operation, as well as generating a large number of files (one per class). The first problem can lead us to code that is more expensive to maintain and more prone to errors. The second is a problem of class proliferation. 

Why Kotlin Breaks With All This

It is for all these reasons that, today, Java is considered as a language that, at least in Android development, does not evolve at the speed that the industry does. As time passes, the need to have a language with real and native support for everything mentioned above becomes more imperative, as well as maintaining the main features of Android explained at the beginning of this article: its ability of writing and compiling a single application makes it work on any device and version.

In this direction, many possibilities have been explored, some of them being the use of Swift or Scala, although none has been very promising. All this changed with the appearance of the Kotlin language. Kotlin is a language designed and developed by Jetbrains, focused on being a modern language, in constant evolution and, above all, that can be executed on the JVM. This makes it a perfect candidate to be used on Android.

To begin to demonstrate it, we can list all the cons we face with Java and how Kotlin acts in front of them:

  • Optionals: They’re built into Kotlin; all you have to do is declare the type of a variable ending in a question mark so it becomes an optional type. Kotlin also provides the possibility of safely unwrapping those optionals listener?.onSuccess() without checking if there’s a value for this optional, and also provides the Elvis Operator
  • Functional programming: In Kotlin, we find native support to work with collections and datasets like Streams. We can directly call .flatMap {} in a collection, as well as .filter {}, .map {}, and many more. The inference of types makes the use of Lambdas especially manageable.
  • Lambdas and high order functions: The previous point is completed with the fact that in Kotlin, the functions are first-class citizens. We can define functions that receive other functions as parameters. An example of this is the definition of the map function itself:
inline fun <T, R> Iterable.map(transform: (T) -> R): List (source)

Although at first sight, this code may seem a bit chaotic, the part that interests us is transform: (T) -> RThis means the map function has a parameter called transform, which is itself a function that has an input parameter of type T and returns an object of type R.

Thanks to this native support for lambdas, in Kotlin, we can use the map function such that:

collection.map { item -> aTransformation(item) }

This code snippet will return a collection of elements of the type returned by aTransformation.

  • Type nullability: In Kotlin, since there is integrated support for optionals, we should have the minimum possible number of nullables in our code. But even so, if it exists, Kotlin offers us tools to deal with them more easily than in Java. For example, we have the operator safe call (?) to avoid NullPointerException when accessing an optional, or with the operator safe cast to protect us in case we want to perform a casting. The compiler of Kotlin, in addition, forces control of the types that could have a null value, and even introduces runtime checks in case of compatibility with Java code.
  • Binding of views: This being a specific Android problem, Jetbrains offers us Kotlin Android Extensions; an official support library to simplify this problem (and some others) through a gradle plugin.

Java:

public interface Listener {
  void success(int result);
  void error(Exception ex);
}

public void someMethod(Listener listener) {
  int rand = new Random().nextInt();
  if(listener != null) {
    if (rand <= 0) {
      listener.onError(new ValueNotSupportedException());
    }
    else {
      listener.success(rand);
    }
  }
}

public void fun(Type1 param1) {
  param1.someMethod(new Listener() {
    @Override
    public void success(int result) {
      println(“Success” + result);
    }

    @Override
    public void error(Exception ex) {
      ex.printStackTrace();
    }
  }
}

Kotlin:

fun someMethod(success: (Int) -> Unit, error: (Exception) -> Unit) {
    val rand = Random().nextInt()
    if (rand <= 0) {
        error(ValueNotSupportedException())
    }
    else {
      success(rand)
    }
}

fun (param1: Type1) {
    param1.someMethod( {
        println(“Success” + it);
    }, {
        it.printStackTrace();
    })
}

Or even, using expressions: 

fun someMethod(success: (Int) -> Unit, error: (Exception) -> Unit) {
    val rand = Random().nextInt()
    if (rand <= 0) error(ValueNotSupportedException()) else success(rand)
}

fun (param1: Type1) {
    param1.someMethod( {
        println(“Success” + it);
    }, {
        it.printStackTrace();
    })
}

It is up to the reader to decide which of the two snippets is easier to write and interpret.

All we've discussed, along with a large number of features that did not fit in this article or that were not the ones that really matter to us, shows us that Kotlin seems the most promising bet for the next few years in the world of mobile development. In my next articles, we will study more in detail what benefits we get by using Kotlin in Android development and its impact on the industry.

Topics:
kotlin ,android ,mobile ,mobile app development ,cross platform

Published at DZone with permission of Diego Ojeda. See the original article here.

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}