Posted on: March 29, 2022 Posted by: rahulgite Comments: 3,320
Kotlin and Java

GitHub – https://github.com/rahulgite/Kotlin

Why a New JVM Language?

  • Wordy and full of boilerplate
  • Requires tedious getters and setters
  • Difficult to avoid null pointer exceptions
  • Lacks many modern programming features

Why Kotlin?

  • 100% compatible with Java.
  • Eliminates most null pointer exceptions.
  • The syntax is clean and easy to read.
  • Modern features like smart casting.

The easiest way to get a taste of Kotlin on

https://play.kotlinlang.org/

Create Kotlin Project in Intellij

  • New Project
  • Select Gradle with below framework options
    • Select Java
    • Select Kotlin JVM
  • Next
  • Enter Project Name and Finish.

The project will get built and you will have below project structure

Create Kotlin main file :

Right-click on kotlin folder > New > Select Kotlin Class/File.

Enter package and file name > Select type File and Enter

HelloWorld Program in Kotlin

fun main(args:Array<String>){
    println("Hello, World")
}

Build Kotlin code in Intellij

Windows/ Linux : Ctrl+ Shift + F10

MAC : Ctrl + Option + R

 

Val and Var in Kotlin

Val: short for value; used when the variable doesn’t change (Immutable)

Var: short for variable; can change over a program’s lifetime (Mutable)

NOTE: Val is preferred and considered a best practice.

The Beauty of immutability

  • Immutable objects are thread-safe.
  • Immutable data makes code parallelization easier.
  • References to immutable objects can be cached.
  • Less moving parts, easier to understand

Type Inference in Kotlin

fun main(args:Array<String>){

    //Type Inference
    val asentence = "I'm a string"
    val myPi = 3.14
    val myAnswer=42

    var mvDouble = 1.999
    var mvFloat= 1.9F
    var myLong= 123123122L
    var mvInt= 199
    var mvShort: Short = 12
    var myBvte: Byte = 127
    val alongNumber = 123-456789
    val thesameNumber= 123456789
    
    // Specify type to avoid ambugity
    
    var aString: String
    val aDouble: Double
    val aInt: Int

}

Comments in Kotlin

//I am end of line comment

/*
I am a block comment
*/

/*
fun meaninglessFunc(){
    /*
    I am a nested comment, Java gives error for nested Comments
     */
     }
 */

Control Flow: If

  • If is the most basic way to control flow in Kotlin.
  • If is an expression, not a statement.

What is the statement?

Program instructions that return no value; can’t be on the right side of an equals sign

What is the expression?

Program instructions that return values; can be on the right side of an equals sign

val lowest= if (10 < 20) 10 else 20
print("Lowest is $lowest");
  • The Value return is the value of the last expression.
  • So the ternary expression doesn’t exist in kotlin, because it would be redundant.
  • if, IF is used as an expression it must contain the else clause. The expression must have value in all cases.
var tempInDegreeCelsius=40;
var enableAC= if(tempInDegreeCelsius>=40){
    true;
}else{
    false;
}
print("AC Enabled : $enableAC");

When in Kotlin (Switch cases in Java)

val order=20;

    //with arguments
    println("***** When with arguments *****");

    when(order){
        0 -> println("Zero Order");
        in 1..10 -> println("Small Order");
        else -> println("Huge Order");
    }
    //without arguments
    println("***** When without arguments *****");

    when{
        order<10 -> println("Small Orders");
        order>=10 -> println("Huge Order")
    }

While and Do-While loop in Kotlin

println("***** While Loop *****");

var x=0
while(x <30){
    println("$x");
    x+=3;
}
println("***** Do While Loop *****");

do{
    println("$x");
    x-=3;
}while (x>0);

For loop in Kotlin

//For loop - Classic for loop dosent exits in kotlin e.g for(i=0;i<10;i++){}
    // range
    println("***** For loop with Integer range *****");

    for(no in 1..10){ //no is immutable -cant change it value in block
        println(no);
    }
    // string
    println("***** For loop with String *****");

    for(ch in "RAHUL"){
        println(ch);
    }
    //for with external index
    println("***** for with external index *****");

    var idx=0;

    for(no in 10.rangeTo(20).step(2)){
        print("${++idx}) $no,")
    }

    //for with internal index
    println("\n***** for with internal index *****");
    for((index,no) in 10.rangeTo(20).step(2).withIndex()){
        print("${index + 1}) $no,");
    }

println("\n***** for Array using indices property *****");
var myArray= arrayOf(10,20,30,40,50)
for(item in myArray.indices){
println("Item at ${item} is ${myArray[item]}");
}

Functions in Kotlin

fun main(args: Array<String>) {   
 println("***** Functions *****");
    println("Addition normal function ${add1(10,20)}");
    println("Addition single line function function ${add2(10,20)}");
    println("Addition single line function compact function ${add3(10,20)}");
    println("Addition with default parameter value function ${add4()}");
    println("Addition with default parameter value function with named parameter ${add4(param2 = 30)}");
}
fun add1(param1: Int, param2: Int): Int {
    return param1+param2;
}

fun add2(param1: Int, param2: Int): Int = param1 + param2;

fun add3(param1: Int, param2: Int) = param1 + param2;

fun add4(param1: Int=10, param2: Int=20) = param1 + param2;

 

Kotlin Default imports

kotlin.*
kotlin.ranges.
kotlin.annotation.*
kotlin.sequences.*
kotlin.collections.*
kotlin.text.*
kotlin.comparisons.*
java.lang.*
kotlin.io.*
kotlin.jvm.*

Class in Kotlin

  • By default classes are public, the opposite of java.
  • A new keyword is not needed.
  • A class can have 1 primary constructor and multiple secondary constructors.
class PersonClass internal constructor(firstName:String,lastName:String) {
    init {
        println("Name is $firstName $lastName")
    }

    constructor(firstName:String,lastName:String, age:Int) : this(firstName, lastName) {
        println("Name is $firstName $lastName and Age is $age")
    }
}

fun main(args:Array<String>){
    // Primary Constructor
    val person1=PersonClass("Rahul","Gite")
    // Secondary Constructor
    val person2=PersonClass("Rahul","Gite",5)

}

Objects in Kotlin

object MyObject{
    var a=20;
    var b=30;
    fun add(){
        println("Addition is ${a+b}")
    }
}

fun main(array: Array<String>){
    // Named Object
    MyObject.add();
    // Direct Object
    val add=object{
        var a=20;
        var b=30;
        fun add(){
            println("Addition is ${a+b}")
        }
    }
    add.a=5
    add.b=5
    add.add();
}

Interfaces in Kotlin

interface InterfaceInKotlin {
    var name:String;
    fun start(){
        println("Started")
    }
    fun stop(){
        println("Stop")
    }
    fun getInt():Int;
}

class Car:InterfaceInKotlin{
    override var name: String="Tesla";
    override fun getInt(): Int {
        return 100;
    }
}

fun main(array: Array<String>){
    var car=Car();
    car.start();
    car.stop();
    println(car.getInt());
}

Generics in Kotlin

fun main(args:Array<String>){
    var maxInt:Int=max(10,20);
    var maxLong:Long=max(10000L,200000L);
    var maxByte:Byte=max((-128).toByte(),(127).toByte());
    var maxString:String=max("Rahul","Gite");

    println(maxInt);
    println(maxLong);
    println(maxByte);
    println(maxString);

}

//Generic function
fun <T:Comparable<T>> max(p1: T, p2: T): T {
    val result=p1.compareTo(p2);
    return if(result>0) p1 else p2;
}

Interoperability

 

Use Java in Kotlin

Create Java Class
public class JavaClassForKotlin {
    private String name; //with setter and getter
    private Integer age; // only with getter

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public JavaClassForKotlin(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    @Override
    public String toString() {
        return "JavaClassForKotlin{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
Use java class in kotlin file
fun main(args:Array<String>){
    val obj= JavaClassForKotlin("Rahul",5);
    println(obj.toString());

    // We can set values if java class have setter
    // Property is considered as var
    obj.name="Gite"

    // We can't set values if java class does not have setter,
    // The Property is considered as val

    //obj.age=6
    println(obj.toString());
}

Use Kotlin in Java

create kotlin class
Note: 
  • var name in the constructor: It will provide setter and getter to properties
  • val name in the constructor: It will only provide getter to properties
class KotlinClassForJava constructor(var name:String,var age:Int) {
  init {
      println("name $name, Age $age")
  }
}
use kotlin class in java class
public class CallKotlinFromJava {
    public static void main(String[] args) {
        KotlinClassForJava obj=new KotlinClassForJava("Rahul",5);
        // Kotlin automatically create setter and getters for its properties
        obj.setAge(10);
        obj.setName("Gite");
        System.out.println("New Name :"+obj.getName()+",New Age :"+obj.getAge());

        Integer maxInt=GenericsInKotlinKt.max(25,50);
        System.out.println("Max is :"+maxInt);
    }
}

 

Advance Kotlin Features

Operator Overloading

Overloadable Binary Operators in Kotlin

Overloadable Binary Operator in Kotlin

Overloadable Unary Operators in Kotlin
Unary Overloadable Operators in Kotlin
Other Overloadable Operators in Kotlin

There are more than 30 operators you can overload see Kotlin documentation.

Operator overoverloading example in kotlin
data class OperatorOverloading(var x: Int, var y: Int) {
    operator fun plus( other: OperatorOverloading): OperatorOverloading {
        return OperatorOverloading(x + other.x, y + other.y);
    }
}

fun overload(){
    val o1=OperatorOverloading(10,20);
    val o2=OperatorOverloading(30,40);
    val ans=o1+o2;
    println(ans);
}

fun main(args:Array<String>) {
overload();
}

//Output : OperatorOverloading(x=40, y=60)

 

Annotation in Kotlin

Just add @ and annotation name before class, same as java

 Example

@Deprecated("Use New Instead",ReplaceWith("New"))
class Old(name:String){

}
class New(name:String){

}

fun main() {
    val obj=Old("Rahul") //IDE will tell to replace the depricated class
}

 

Reflection in Kotlin

  • Reflection allows us to access programmatic information dynamically at run time.
  • To minimize the size of kotlin run time, reflections are kept in a separate jar
  • We need to add kotlin-reflect.jar file in our classpath
Reflection in Kotlin
fig. Reflection in Kotlin

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Functional Programming in Kotlin

Pros of functional programming
  • No Messy State issues: Functional Programming doesn’t store states and only uses immutable data, Code generally has fewer bugs.
  • Easier Code Reuse: Peer functions only depend on their parameters, so reusing and testing them is easy.
  • Safe Multithreading: Synchronizing Data between threads is a huge headache in multithreaded programming. But the use of immutable data mostly eliminates it.
Cons of functional programming
  • Less efficient code: Functional Programming doesn’t have loops and depends heavily on recursion. This tends to make them less efficient.
  • Harder to Conceptualize: Especially for beginners, It can be hard to break down problems functionally.

Lambdas in Kotlin

data class Student(var name: String, var age: Int);
fun getStudents(): List<Student> {
    return listOf(
        Student("Rahul", 5),
        Student("Gite", 10)
    )
}

fun main() {
    val student =getStudents();
    val combos=student.map { a-> a.name+" : "+ a.age }
    println("Combos : "+combos)
    println("The Oldest Student: ${student.maxByOrNull { it.age }}")

    val studentWithLongestName= student.filter { it.name.length>4 }
    println("Student with longest name : "+ studentWithLongestName)
}

Closures in Kotlin

Closures are when the local variables of the functions are kept alive after the functions are ended.

fun closureMaker():()->Unit{
    var num=0;
    return {println(num++)}
}

fun main() {
    val counter1=closureMaker();
    val counter2=closureMaker();

    counter1();
    counter1();
    counter1();
    counter2();
    counter2();
    counter1();
}

/*
Output
0
1
2
0
1
3
 */

Method Chaining/ Sequences in Kotlin

  • A sequence is a lazily evaluated collection. They are pretty much identical to streams in Java. The only thing is sequences cant run on multiple CPUs. The thing to note sequences are not collections. Sequences aren’t generated until terminal operations such as sum() or toList() are called.
fun sequences() {
    val student = getStudents();
    val sqStudent = student.drop(1).take(1).toList();
    println("Student Sequence :" + sqStudent)

    val numbers = generateSequence(100) { it + 1 }
    println("Numbers:"+numbers.drop(5).take(20).toList())

    val squares = generateSequence(1) {it+1  }.map { it*it }
    println("Square:"+squares.take(5).toList())

    val evenSquares=squares.filter { it%2==0 }
    println("Even Square:"+evenSquares.take(5).toList())

    val fibo= generateSequence(1 to 1){it.second to it.first +it.second}.map { it.first }
    println("Fibonacci: "+fibo.take(5).toList())
}
fun main() {
    sequences()
}

/*
Output :
Student Sequence :[Student(name=Gite, age=10)]
Numbers:[105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124]
Square:[1, 4, 9, 16, 25]
Even Square:[4, 16, 36, 64, 100]
Fibonacci: [1, 1, 2, 3, 5]
 */

 

Conclusion

Kotlin Docs: https://kotlinlang.org/docs/home.html

Kotlin Online Editor/Compiler: https://play.kotlinlang.org/

Kotlin News: https://blog.jetbrains.com/kotlin/

Loading

Comments are closed.