Get Started with Kotlin — It is here to stay
Functional programming is the present & Its time Android developers experience the happiness of coding.
It’s been a while since Google extended its support to Kotlin and app developers have already started moving to Kotlin. But while we adopt modern programming, its also important that we have a look at why this change is so important and is widely accepted.
Having worked in Android for a year+ now, I would like to take you through this change right from the start to how it is seen from the Android perspective. Here we go!
Functional programming is the key for the change
Now, there has been a lot of complex definitions hanging around in the web defining it, but to put it in a clear and concise way:
A programming method where functions based on mathematics are the building blocks and the focus is more on what you want to achieve than how you achieve it.
That said, functional programming deals with immutable data i.e. it doesn’t change the value of the variable. All it does is, Receive->Compute->Return without changing values it receives or causing side effects like changing values elsewhere.
Avoiding side effects is an important aspect of functional programming as it makes debugging a trillion times easier, so that you don’t end up searching the whole program for a bug caused by a variable value.
Here is an example of adding 2 t0 an array of numbers:
Imperative type:
int[] nums=new int[]{1,2,3,4,5};
for(int i=0;i<nums.length;i++){
nums[i]=nums[i]+2;
}
return nums;
Functional type:
def addTwo(x):x+2
result=map([1,2,3,4,5],addTwo)
The functional example is also what we would call a Higher-Order Function, as map function takes another function(addTwo) as an argument.
Below is an example of Higher-Order Function that takes a Lambda function as an argument.
Higher-Order Function:
max(strings, { a, b -> a.length < b.length })
Lambda Function:
b -> a.length < b.length
A Lambda Function is a function that is not declared, but passed immediately as an expression.
Now that we know that functional programming is the key to avoid side effects and mutable data (common in imperative programming) and as it helps in writing concise code thereby improving code readability, it is why a step forward and is most adopted in modern programming languages.
Functional programming is sane, straightforward, efficient and beautiful.
Despite having around such a paradigm, questions pop up that why it hasn’t made the cut to Android yet and to know about that we have to dig deeper into the relationship of Java and Android.
Why is Android stuck at Java 6 despite Java 8 being functional?
Ever since Java 6 came into existence, it took two years for Android to support it and be born, but then it never got better and despite Java 7 in 2011 & Java 8 in 2014 coming into play, Android’s adoption is still fairly fragmented, and Java 7 is only supported for API 19 and up.
The reason why Android could never support Java fully is because,
For every new release of Java, the device needs to be updated to support the new features of Java, and it introduces new bytecodes, so a device that can’t be updated to the latest version of android can’t make use of the new bytecodes.
This, is exactly why Android is still stuck at Java 6, but then lets assume if Android could extend 100% Java 8 support to all its devices in the next 2 years from now, Why shouldn’t we wait for Java 8 as it supports functional programming?
The straight answer would be:
Java as a language itself has a lot of problems.
Following are few of the problems:
- Null references, coined by its inventor as a billion dollar mistake: You can code very defensively, but null pointer exceptions sneak into everyone’s code just because Java’s type system is not safe.
- Raw types:We’ve been stuck with raw types in order to stay backwards compatible.
List numbers=getNumberList();
int sum=0;
for(Object num : numbers){
sum+=(Integer)num; // Unchecked cast
}
- Covariant arrays: You can create a string array, and an object array and then assign that string array to that object array, but it’ll throw an exception if you try to assign a number to that array of strings.
String [] strings={"hello"};
Object[] objects=strings;
objects[0]=1; // java.lang.ArrayStoreException
- Java 8 has higher-order functions but they’re implemented with SAM types. SAM is single abstract method, every function type needs an interface correlated to it.
- Wildcards in generics, anything but non-trivial generics can get out of control and become hard to read, write and understand.
And with the confessions of a Java developer, took birth is a new language, Kotlin.
Statically typed programming language for modern multiplatform applications
But, lets see why would some one prefer Kotlin, when there are languages like Scala and Groovy already in the race.
Why Kotlin & Why Kotlin + Android?
Moving forward, its everything about Kotlin in Java vs Kotlin perspective, so be ready to be amazed.
#Kotlin puts properties at front
- A very good example of boilerplate code would be a Java Class, where everything except for the variable decalrations, seems like unwanted and excessive lines of code, this is where Kotlin comes into play.
- Kotlin eliminates the need to add & maintain lines of codes that take care of getting, setting and converting values of variable.
//Java//Declaring Classpublic class Person{//VariablesString name;
int age;//Constructorspublic Person(String name, int age){
this.name=name;
this.age=age;
}//Getters and Setterspublic String getName(){
return name;
}
public int getAge(){
return age;
}
public setName(String name){
this.name=name;
}
public setAge(int age){
this.age=age;
}
}//Kotlin Equivalentdata class person(val name:String val age:Int)// That's it?
Kotlin doesn’t have Getters and Setters , it has only properties.
#Kotlin is functional:
- Having said so much about functional programming, Kotlin indeed is functional and that is why it is elegant, concise, expressive , readable and understandable.
Kotlin is not 100% functional programming because immutability is optional, but thats a pro.
#Kotlin’s Syntax feels like family
- Kotlin’s syntax stays very close to its logical context.
- It cuts down lot of ceremonial boilerplate codes seen in Object Oriented Programming languages.
- Easily understandable by novice developers and is also simple and short.
//Javaint num=0;
String str="Kotlin"; // Both are mutable and has side effects of being changed anywhere in the code.//Kotlinval str="Kotlin" // Type is optional & can be explicitly defined.
val str: String = "Kotlin" //val is immutable & remains unchanged.
var num: Int = 0 // var is mutable & can be changed anytime.
Property of Immutability is controlled by two variables, var & val, its type is inferred by itself.
#Kotlin is in terms with Java
- Kotlin is 100% interoperable with Java, allowing it not only to convert to and from Java but also to work with Java, so that one can access, modify and use Java and Kotlin alongside in the same project.
May it be accessing a Java class or a Kotlin data class, all the conversion is handled for you by Kotlin.
#Kotlin redefines the way functions are written
- Function overloading is no longer a mess and redundant: Function overloading has remained the same throughout the evolution of programming, but its also important to notice the redundant amount of code that it brings in, increasing confusion to the developer. Kotlin has a very straight forward approach in this case.
- Named arguments doesn’t follow order: Named arguments allow complete control over what value is passed to which variable and comes handy while dealing with booleans as seen below.
//Javavoid check(boolean isAlpha, boolean isNum){ //function definition
}
check(true,false);//function call//Kotlinfun check(isAlpha:Boolean,isNum:Boolean=false) {
//function definition
}
//function call
check(true)// Gets isAlpha as true & gets isNum default value false
check(true,true)// Overrides isNum with true//Named Argumentscheck(isAlpha=true,isNum=false)// Same as below
check(isNum=false,isAlpha=true)// Same as above
There is no more different functions for different number of argument or type of arguments. It’s all one and the same but adapts with the values we pass.
- Functions prefer to be single: Single-line expressions is the first step in improving code readability.
//Javaint sum(int x, int y){ //Return type has to be declared.
x=x+y; //value of x is changed and is a side effect.
return x;
}//Kotlinfun sum(x : Int, y : Int) = x+y // Perfect.
Functions should be bound to the logical context and doesn’t need to do more than what is required from it, and Kotlin handles that for you.
#Kotlin says No to Null
- Assigning a null: Anyone searching for Null on web will land up on Java Null Pointer Exception, it has been one of the long standing problems of Java, and that is why Kotlin puts Null safety at the top. Kotlin allows null only if ‘?’ operator is used while assigning as shown below.
//Java
String text1=null // Oops! Exception//Kotlin
var text1: String = "Kotlin" // Yay..Works
var text2: String = null // Oops!
var text2:String?=null// Now it Works
- Checking a null: Unlike Java, you never really have to make a null check before performing an action worrying about Null exception. Kotlin ensures this using safe call with “?.” operator.
//Java
if(a!=null){
int x=a.length();
}//Kotlin
val x=a?.length //Compiles only if a is not null
- The Elvis operator: There are cases where we might want to return a value for functions that deal with null instead of skipping it. In that cases the Elvis(?:) operator is used in combination with safe call, so that null is never a possibility.
val x =b?.length ?: 0 // x will have length of b or 0(if b is null)val x = b?.length ?: throw NullPointerException()
val x = b!!.length // same as above
There is Never a Null unless desired
#Lamda further optimises
- Lambda expressions add to the concise feature of Kotlin, thereby also resulting in a clear understandable code.
//JavaNo Lambda function in Java 6//Kotlinval sum = { x: Int, y: Int -> x + y } // type: (Int, Int) -> Int
val result = sum(2,7) // result == 9
#Conditions feel more natural than ever
- The usual conditional “if/else” or “switch” of Java is made not only more effective but also more readable in Kotlin by replacing it with “when”.
//Java
if(x==1)
println("x is 1");
else if(x==2)
println("x is 2");
else if(x==3||x==4)
println("x is 3 or 4");
else if(x>=5||x<=10)
println("x is 5, 6, 7, 8, 9, or 10");
else
println("x is out of range");//Kotlin
when (x) {
1 -> print("x is 1")
2 -> print("x is 2")
3, 4 -> print("x is 3 or 4")
in 5..10 -> print("x is 5, 6, 7, 8, 9, or 10")
else -> print("x is out of range")
}
#Kotlin gets rid of Click handling nightmares
- There might be no Android developer who has not hated one of the most unpleasant set of codes associated with event handling. Kotlin makes this almost to zero ceremonies.
//Java
view.setOnClickListener(new View.OnClickKistener(){
@Override
public void onClick(View v){
System.out.println("This is irritating");
}
});//Kotlin
view.onClick{
println("Woah!!")
}
Kotlin is concerned only about function that matters
#Kotlin nails it by ignoring view binding
- The iconic view binding of java adds too much to all of boilerplate codes and is often depressive and that is why Kotlin ends it forever.
//Java
TextView program = (TextView) findViewById(R.id.program);
program.setText("Kotlin");//Kotlin
view.program.text="Kotlin"
#Other cool features
- Kotlin focuses on what the developer might want and bundles all of it into the Kotlin Standard Library which is more powerful, independent & helpful than Java Standard Library.
//Java
if(name.toLowerCase().contains(firstName.toLowerCase())){
...
}//Kotlin
if(name.contains(firstName,true)){...}
Unlike Java Kotlin doesn’t need to worry about the type or case sensitivity before the conditional check
Now, with everything I said about Kotlin, you might want to move to Kotlin but still think that it might take a lot to move from Java to Kotlin and that’s fair, but that’s also the reason why you should be moving to Kotlin as its 100% interoperable with Java. Let us have a look how?
I wanna move from Java to Kotlin in Android
1.Install the Kotlin plugin
The Kotlin plugin is bundled with Android Studio starting from version 3.0. If you use an earlier version, you’ll need to install the Kotlin plugin.
Go to File | Settings | Plugins | Install JetBrains plugin and then install Kotlin.
If you are looking at the “Welcome to Android Studio” screen, choose Configure | Plugins | Install JetBrains plugin.
You’ll need to restart the IDE after this completes.
2.Convert Java code to Kotlin
Open Java file.
Then invoke action Convert Java File to Kotlin File. You can do it by several ways. The easiest one is to invoke Find Action and start typing an action name.
Alternatively you can call this option via the Code | Convert Java File to Kotlin File menu entry.
Start coding!
No, I wanna start from scratch in Android
1.Set up Kotlin Android plugin
buildscript {
ext.kotlin_version = '<version to use>' ... dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
2.Set up the source root directory
The following needs to be added under android:
android {
... sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
}
This lets Android Studio know that the Kotlin directory is a source root, so when the project model is loaded into the IDE it will be properly recognized. Alternatively, you can put Kotlin classes in the Java source directory, typically located insrc/main/java
.
3. Configure the dependencies
In addition to the kotlin-gradle-plugin
dependency shown above, you need to add a dependency on the Kotlin standard library:
repositories {
mavenCentral()
}dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
All done, you are up and running!
Thanks for reading through 🙌🏼. If you found this post useful, please applaud using the 👏 button and share it through your circles.
Peach Studio helps build functional web and mobile products, with laser-sharp focus on design and usability. Have an idea? Get in touch.