Kotlin vs Java 7 – Brevity

October 26, 2016

For those unaware, Kotlin is a language developed, released, and maintained by Jetbrains. It compiles to Java bytecode and Javascript, and can be used to replace or add on to existing Java files in an Android project.

It has been in development for years and I have been using it for the last year; the end result for me is that Java is downright painful to use. Kotlin makes me feel like a ninja and enables code that would be unfeasible or impossible to write in Java (at least Java 7).

So, some examples? Let’s take a look.

Filtering a list

/** Returns a subset of {@code list} containing only the items where {@code someBool == true} */
public final List<MyClass> filterList(List<MyClass> list) {
  List<MyClass> ret = new List<>(list.size());
  
  for(MyClass item : list) { 
    if(item.someBool) {
        ret.add(item);
      }
    }
    
  return ret;
}

This straightforward method should look familiar, because you’ve probably written some variation of it many, many times before.

Nine lines, excluding whitespace and comments. And the same code in Kotlin?

/** Returns a subset of `list` containing only the items where `someBool == true` */
fun filterList(items:List) = items.filter { item -> item.someBool } // or { it.someBool }

One line. Also note the difference in comments; you can use ticks to designate code, as in markdown.

Let’s break it down quickly. fun defines a function. You’ll notice that a variable’s type is declared after the name, instead of before. And what’s up with the =? This is shorthand for { return }. It looks like a variable declaration, but it uses a parameter like a method. Also notice that the compiler automagically figures out the function return type and it isn’t declared.

Lastly, the beautiful .filter method and lambda. If you have used C#, Java 8, or another modern language, this will be familiar. Rather than give a full explanation here, let’s just admire its conciseness and move on.

Getting a value (or null if missing)

/** Gets the second character in a string or, if not possible, returns some default value (which may be {@code null}) */
@Nullable
public final String getSecondCharOrDefault(@NonNull String str, @Nullable String defaultVal) {
  return str.length() > 2 ? str.get(1) : defaultVal;
}

@Nullable and @NonNull are awesome annotations for Java that will save you from NullPointExceptions if used properly. They work by giving your IDE the information it needs to warn you when something could be null - but they aren’t actually supported directly by Java and are instead something that works on top.

/** Gets the second character in a string or, if not possible, returns some default value (which may be `null`) */
fun getSecondCharOrDefault(str: String, defaultVal: String?) = if(str.length > 2) str[1] else defaultVal

Kotlin, by comparison, has these built directly into the language. All variables are, by default, not allowed to be null. Appending a ? indicates that null is an acceptable value. Kotlin will, in fact, fail to compile if you violate these rules.

We again use the shorthand function declaration, which is allowed because if statements can return values (in lieu of the standard ternary (? :) operator).

RxJava

Two more examples. First, some RxJava code. Naturally ugly in Java 7, better in Java 8, and glorious in Kotlin.

/** First prints "one dish", then "two dish" */
public final void printRxJavaStuff() {
  Observable.from(Arrays.asList("one fish", "two fish", "red fish", "blue fish"))
  .filter(new Func1<String, Boolean>() {
      @Override
      public Boolean call(String s) {
          return s.contains("one") || s.contains("two");
      }
  })
  .map(new Func1<String, String>() {
      @Override
      public String call(String s) {
          return s.replace("fish", "dish");
      }
      })
  .subscribe(new Action1<String>() {
      @Override
      public void call(String s) {
          Timber.v(s);
      }
  });
}

21 lines.

/** First prints "one dish", then "two dish" */
fun printRxJavaStuff() {
  Observable.from(asList("one fish", "two fish", "red fish", "blue fish"))
  .filter { it.contains("one") || it.contains("two") }
  .map { it.replace("fish", "dish") }
  .subscribe( { Timber.v(s) } )
}

Six lines. And far more readable. The it keyword stands for “the temporary variable in scope for this expression”. For example, in a standard foreach loop for(String str : strings), it would be the same as str.

Declaring a data class

Let’s wrap this up with a class declaration.

Java:

/** Example of a {@link Class} declaration */
class MyClass {
  private boolean someBool;
  
  public MyClass() {
  }
  
  public MyClass(boolean someBool) {
    this.someBool = someBool;
  }
  
  public boolean getSomeBool() {
    return someBool;
  }
  
  protected void setSomeBool(@NonNull boolean value) {
    someBool = value;
  }
  
  @Override
  public String toString() {
    return "someBool:" + someBool;
  }
  
  // not shown: .copy override
  // not shown: .hashcode override
  // not shown: .equals override
}

Kotlin:

/** Example of a [Class] declaration. */
data class MyClass(var someBool: Boolean = false)

Yep. Those are the same thing. You can declare a constructor with the class declaration and if you use var or val (val = final), then it will keep it as a field. The getter and setter is auto-generated, as with C#. It handles toString, too, if you mark it as a data class.

Finally, note the [Class] syntax, compared to Java’s {@link Class} syntax.

And that’s it. You can try Kotlin for yourself here: http://try.kotlinlang.org/

You can drop it into an existing Android project and it has full interopt with Java; that is, you can write one class in Kotlin, another in Java, and they can both use each other without issues. Happy coding!

Last note: Java 8 has, to an extent, hugely improved on Java 7 and Kotlin doesn’t have as many advantages over Java 8. However, using Java 8 on Android remains problematic because of performance issues with Jack and it being only natively supported on Nougat and up. Kotlin is just as fast as Java 7 (compiled and compiling) and works on any version of Android you’d want to support.

All code samples can be found here: https://gist.github.com/davidwhitman/5d7bde79a3967b27d9e25a74bccfdad7


Follow @davidwhitman    Star    Issue

Android Dev Kotlin