Weekend with Kotlin: Everything you need to know to get started with Kotlin — Part I of III

Faheem un nisa
BYJU’S Exam Prep Engineering
9 min readApr 1, 2019

This series of three articles assumes that you have absolutely no idea of whatsoever-in-God’s-name Kotlin is, and it shall see to it that, by the end of these articles, you are equipped well enough to dive head first into the awesome universe of Kotlin! For all those Java bros out there, we will also come across some Java v/s Kotlin face-offs to see how concise yet powerful Kotlin is in comparison to dear old Java.

What is Kotlin ?

Kotlin is an Android-compatible language that is concise, expressive, and designed to be type- and null- safe. In more relatable words, it is the modern day, uber-cool programming language that requires you to write less, much less code and leaves lesser scope for bugs!

Why Kotlin ?

  • Open source
    Kotlin is distributed under Apache License, Version 2.0. The Kompiler (Kotlin compiler), IntelliJ IDEA plugin, enhancements to basic Java libraries and build tools all are open source.
  • Interoperable with Java and Android
    It is 100% interoperable with Java and Android. Porting an existing java based project to Kotlin is easy as Kotlin is extremely flexible and interoperable; you can keep your existing code, continue to use the various Android libraries, and incrementally add Kotlin code to your project. Kotlin can be used bi-directionally — you can call into the Java language from Kotlin, and you can call into Kotlin from the Java language and can mix java and kotlin in your project with ease! How awesome is that?
  • Concise and Expressive …………………………………………………… It’s easy to write code that both humans and compilers can understand with ease. Estimation indicates that using Kotlin allows you to cut off the lines of code by approximately 40% (when compared to Java). You have to write less code and eventually you make lesser bugs!
  • Easy to Learn
    It is influenced by Java, Scala, Groovy, C#, JavaScript and Gosu. Learning Kotlin is easy if you know any of these programming languages. It is particularly easy to learn if you know Java.
  • Tool-friendly
    Kotlin is developed by JetBrains, a company renowned for creating development tools for professionals. No wonder, it is tool-friendly. You can choose any Java IDE to run Kotlin or build it from the command line.
  • Safe
    It is aimed at removing dangers of null references from the code (a big headache in Java) and is super efficient in overcoming NPE problem. Kotlin compiler comes with in built mechanism to handle null data via auto-cast mistake feature. In Kotlin, all the variables are non-null by default which automatically stamps out the chances of occurrence of NullPointerException since it won’t be compiled in the first place!

I know, right?!

The Present

  • Many companies like Netflix, Uber, Trello, Pinterest, Corda, etc. are using Kotlin (along with other programming languages) to create applications.
  • The number of lines of code increased from 2.1 million to 10 million in an interval of year from 2016 to 2017.
  • At recent Google I/O held on 17 May, 2017, Android team announced Kotlin as an official language for Android app development.
  • Though the majority of progress has been made on Java and Android, it’s not a Java/Android language. It can compile many Kotlin projects to JS. Similarly, Kotlin/Native is under progress that compiles Kotlin directly to machine code.

The Future

The future plans include the concept of common module in Kotlin. It allows you to develop platform specific functionality for multiplatform development. In future, you will be able to write platform specific code in Kotlin for Android and iOS app in the implementation module.

Getting started

1. Variables:

Variables that can be reassigned use the var keyword

var x:Int = 5
var x = 5 // `Int` type is inferred

Read-only local variables are defined using the keyword val

val a: Int = 1 // immediate assignment
val b = 2 // `Int` type is inferred
val c: Int // Type required when no initializer is provided
c = 3 // deferred assignment

2. Ranges

Range expressions are formed with rangeTo functions that have the operator form .. which is complemented by in and !in. Range is defined for any comparable type, but for integral primitive types it has an optimised implementation.

if (i in 1..10) { // equivalent of 1 <= i && i <= 10
println(i)
}

To iterate over numbers in reverse order, you can use the downTo() function defined in the standard library:

for (i in 4 downTo 1) 
print(i)

To iterate over numbers with arbitrary step, not equal to 1

for (i in 1..4 step 2) print(i)

for (i in 4 downTo 1 step 2) print(i)

To create a range which does not include its end element, you can use the until function:

for (i in 1 until 10) {// i in [1, 10), 10 is excludedprintln(i)}

3. Switch statement & loops

Kotlin replaces “switch” functionality with “when” expression

when (x) { //switch changes to when (x)
1 -> print(“x == 1”) //case 1 : changes to only 1
2 -> print(“x == 2”)
else -> { // Note the block // default changes to else
print(“x is neither 1 nor 2”)
}
}

“when” matches its argument against all branches sequentially until some branch condition is satisfied. If many cases should be handled in the same way, the branch conditions may be combined with a comma:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

You can also call a function in a condition

when (x) {
parseInt(s) -> print(“s encodes x”)
else -> print(“s does not encode x”)
}

“when” can also be used as a replacement for an if-else if chain. If no argument is supplied, the branch conditions are simply boolean expressions, and a branch is executed when its condition is true:

when {x.isOdd() -> print("x is odd")x.isEven() -> print("x is even")else -> print("x is funny")}

else clause is compulsory in a when block unless the compiler can prove that all possible cases are covered with branch conditions.

For Loops
for loop iterates through anything that provides an iterator.

for (item in collection) print(item)//orfor (item: Int in ints) {
// ...
}

To iterate over a range of numbers, use a range expression:

for (i in 1..3) {
println(i)
}
for (i in 6 downTo 0 step 2) {
println(i)
}

While Loops
while and do..while work as usual

while (x > 0) {
x —
}

do {
val y = retrieveData()
} while (y != null) // y is visible here!

…and without further delay, let’s introduce

4. Null Checks

One of the most common pitfalls in many programming languages, including Java, is that accessing a member of a null reference will result in a null reference exception. Kotlin’s type system is aimed to eliminate NullPointerException's from our code. In Kotlin, the type system distinguishes between references that can hold null (nullable references) and those that can not (non-null references). For example, a regular variable of type String can not hold null:

var a: String = "abc"a = null // compilation error

To allow nulls, we can declare a variable as nullable string, written String?:

var b: String? = "abc"b = null // okprint(b)

Now, if you call a method or access a property on a, it's guaranteed not to cause an NPE, so you can safely say:

val l = a.length

But if you want to access the same property on b, that would not be safe, and the compiler reports an error:

val l = b.length // error: variable 'b' can be null

But if you still need to access that property, there are a few ways of doing that.

  • Checking for null in conditions: First, you can explicitly check if b is null, and handle the two options separately:
val l = if (b != null) b.length else -1
  • Safe Calls: Your second option is the safe call operator, written ?.:
val a = "Kotlin"val b: String? = nullprintln(b?.length)println(a?.length) // Unnecessary safe call

This returns b.length if b is not null, and null otherwise. The type of this expression is Int?.

Safe calls are useful in chains.

bob?.department?.head?.name

Such a chain returns null if any of the properties in it is null.

To perform a certain operation only for non-null values, you can use the safe call operator together with let:

val listWithNulls: List<String?> = listOf("Kotlin", null)for (item in listWithNulls) {item?.let { println(it) } // prints Kotlin and ignores null}

Elvis Operator

When we have a nullable reference r, we can say "if r is not null, use it, otherwise use some non-null value x":

val l: Int = if (b != null) b.length else -1

Along with the complete if-expression, this can be expressed with the Elvis operator, written ?::

val l = b?.length ?: -1
  • The !! Operator

The not-null assertion operator (!!) converts any value to a non-null type and throws an exception if the value is null. We can write b!!, and this will return a non-null value of b(e.g., a String in our example) or throw an NPE if b is null:

val l = b!!.length

Thus, if you want an NPE, you can have it, but you have to ask for it explicitly, and it does not appear out of the blue.

Collections of Nullable Type: If you have a collection of elements of a nullable type and want to filter non-null elements, you can do so by using filterNotNull:

val nullableList: List<Int?> = listOf(1, 2, null, 4)val intList: List<Int> = nullableList.filterNotNull()

5. Type checks and Smart Casts

is and !is Operators:

We can check whether an object conforms to a given type at runtime by using the is operator or its negated form !is:

if (obj is String) {print(obj.length)}if (obj !is String) { // same as !(obj is String)print("Not a String")}

Smart Casts

In many cases, one does not need to use explicit cast operators in Kotlin, because the compiler tracks theis-checks and explicit casts for immutable values and inserts (safe) casts automatically when needed:

fun demo(x: Any) {if (x is String) {print(x.length) // x is automatically cast to String}}

The compiler is smart enough to know a cast to be safe if a negative check leads to a return:

if (x !is String) returnprint(x.length) // x is automatically cast to String

or in the right-hand side of && and ||:

// x is automatically cast to string on the right-hand side of `||`if (x !is String || x.length == 0) return// x is automatically cast to string on the right-hand side of `&&`if (x is String && x.length > 0) {print(x.length) // x is automatically cast to String}

Such smart casts work for when-expressions and while-loops as well:

when (x) {is Int -> print(x + 1)is String -> print(x.length + 1)is IntArray -> print(x.sum())}

Smart casts do not work when the compiler cannot guarantee that the variable cannot change between the check and the usage. More specifically, smart casts are applicable according to the following rules:

  • val local variables: always except for local delegated properties;
  • val properties: if the property is private or internal or the check is performed in the same module where the property is declared. Smart casts aren’t applicable to open properties or properties that have custom getters;
  • var local variables: if the variable is not modified between the check and the usage, is not captured in a lambda that modifies it, and is not a local delegated property;
  • var properties: never (because the variable can be modified at any time by other code).

“Unsafe” cast operator

Usually, the cast operator throws an exception if the cast is not possible. Thus, we call it unsafe. The unsafe cast in Kotlin is done by the infix operator as (see operator precedence):

val x: String = y as String

“Safe” (nullable) cast operator

To avoid an exception being thrown, one can use a safe cast operator as? that returns null on failure:

val x: String? = y as? String

Note that despite the fact that the right-hand side of as? is a non-null type String the result of the cast is nullable.

Java v/s Kotlin Face-Off

Java

public int getObjectLength(Object myObject){

if(myObject instanceof String){
String newString=(String)myObject;
return newString.length();
}else if(myObject instanceof List){
List newList = (List) myObject;
return newList.size();
}
return -1;
}

Kotlin

fun getObjectLength(myObject:Any):Int->{
when (myObject) {
is String -> return myObject.length
is List -> return myObject.size()
else -> -1
}

For details, please refer to https://kotlinlang.org/docs/reference/.

That brings us to the end of part I. I know you aren’t done yet; I amn’t either! Let’s meet in to the second part of the series:

--

--