This is the part 3 of series Java to Kotlin - Learning Simplified. This part is to show more differences in basics of Java & Kotlin. I hope you learn something new from every part. If you have not read part 2, please do. It shows core differences. check Part 2
💡 Remember our 3 core principles? Concise, Smart and Powerful
As usual, we will start our differences with easy ones. I care for you.
Index of Part 3: Explicit Cast , Instance Of, Smart Cast, Ternary, Functions, Top Level members, Multi Line String
1. Explicit Cast
In Java if we need to cast an object to other class at runtime, we use (TargetClass)
syntax. I always found it little difficult to read and honestly never liked it.
In Kotlin, there is a dedicated keyword as
to cast object. Here is a snippet:
// java
void doSomething(Car car){
RaceCar raceCar = (RaceCar)car;
}
// Kotlin
fun doSomething(car:Car){
val raceCar = car as RaceCar
}
💡 One place I found Java compiler smarter: If you use incompatible types like Car and String, compiler will not allow to cast Car into String and vice versa. Comiler only allows classes in hierarchy.
But in Kotlin, if you use as
keyword for incompatible types, compiler will show a warning not error. Here is a snippet:
// Java
String abc = (String)car; // won't compile
// Kotlin
val abc:String = car as String // only warning
2. Type Check - instanceof
and is
Java has a keyword instaceof
and Kotlin has a keyword is
to check the type of an object at runtime.
// Java
if(car instanceof RaceCar){
}
// Kotlin
if(car is RaceCar) {
}
3. Smart Cast
In Java, as we saw above we need instanceof and explicit cast when required. Kotlin also offers as
keyword to cast explicitly.
Kotlin has a special feature here smart cast
. If compiler is sure the object is instace of some other class, it will cast automatically for you. Here is a snippet:
// Java
if(car instanceof RaceCar){
car.someRaceCarMethod() // wont compile
((RaceCar)car).someRaceCarMethod() // will compile
}
// Kotlin
if(car is RaceCar) {
car.someRaceCarMethod() // will compile, no need to explicit cast after as check
}
🔥 As we saw above, we did not need to cast explicity. Kotlin compiler is smart
to cast for us. Smart cast only works with as
type-check
4. Conditional/Ternary Operator ? : and if else
This is one more area you are not going to like at first glance but you will make peace with it very soon. Java has conditional operator condition ? expression : epxression
and it also has if else
Kotlin says why do you need these two and combined if else
with the use case of conditional operator
In jave, we use conditional operator
when we assign conditionally OR return conditionally. Kotlin says use the normal if-else
. There is no conditional/ternary operator
in Kotlin. Here is a snippet:
// Java
int x = 10;
boolean even = x % 2 == 0 ? true : false;
boolean isEven(int x){
return x % 2 == 0 ? true : false;
}
// Kotlin
val x = 10
val even = if(x % 2 ==0) true else false
5. Method/Function definition
One more area where you will take sometime to make peace. In jave we define a method with visibility modifier, followed by special keyword like static/final, then return type and then name.
Kotlin has a keyword fun
reserved to define a function. We assign the name and then return type. Keeping its Concise
promise, return type is optional in Kotlin. If you do not state anything, it marks it Unit
which is a Kotlin Class. The default visibility is public` in Kotlin and package in Java. Here is the snippet:
// Java
public void doSomething(){}
// Kotlin
fun doSomething(){} // no return specified
💡 As we saw return type is optional. Default value is Unit
which we will learn later.
Function with return value
// Kotlin, function returns String
fun doSomething() : String{
}
The return type is after the colon : after method name
Similarly the argument are also accepted in the Kotlin syntax, with name and colon :
and Type, Function with arguments
// Kotlin, function accepts an Int and returns String
fun doSomething(x: Int) : String{
}
Smart Kotlin
🔥 In Kotlin, Functions can be assigned with expression.
This is not possible in Java and you will find it little difficult at first glance. Check the snippet
// Kotlin, function accepts an int and returns Int multipled by 100
fun multiply100(x:Int) = x * 100
Yes, that is not allowed in Java, closest resemblence in Java is Lambda which we will see later.
🔥 In Kotlin, functions parameters can have default value and that is really powerful.
// Kotlin, function has parameter with default value
fun doSomething(x:Int = 10){}
// can be called without passing value, default will be assigned
doSomething()
// can be called with value
doSomething(50)
🔥 In Kotlin, caller can name the parameters and use any order she likes
// Kotlin
fun doSomething(x:Int, y:Boolean){}
// caller can call in normal order
doSomething(1, true)
// caller can call with names
doSomething(x=1, y=true)
// caller can change the orders
doSomething(y=true, x=1)
💡 Nothing like that exists in Java
🔥 In Kotlin, You can mix named parameters and default value of the methods
// Kotlin
fun doSomething(x:Int = 10, y:Boolean){}
// caller can call with name parameters and leave the default one
doSomething(y=true) // now x will get 10
🔥 Smart Kotlin
: If your default value parameter is last in the function definition, you can call the function and pass the value for other parameters without using names
// Kotlin
fun doSomething(y:Boolean, x:Int = 10){}
// caller can call without name and x will get 10
doSomething(true)
6. Top Level members and functions
In Java, everything revolves around classes. You can not have a function Or a variable+constant without a class. Either it could be class member OR statics.
But in Kotlin, you can define a function OR variable+constant without declaring any class. They are called top level functions and values. ** You do not need any object OR class to call them ** Here is a snippet:
// Java
class Sample {
public static void doSomething(){}
public static final int VALUE = 100;
}
// Any other Java class can call it with
Sample.doSomething()
Sample.VALUE
// Kotlin
fun doSomething(){}
const val VALUE = 100
// Any other Kotlin class can call the function without class name
// in other Kotlin Class
doSomething()
"The value is $VALUE"
💡 Coming from Java background, this might seem absurd. Your mind can not accept a function OR a value without any supporting class. But Kotlin allows you to have Global functions and values
. When they are used within Kotlin classes, you can use without object OR class. But when you use them from Java, they behave like statics. You need the file name and dot. We will see it later. I will put it under Powerful
principle.
6. Multi Line String
This is another feature of Kotlin you are going to love. Many a times, we need to write strings in multiple lines. Java has an ugly +
concatenation operator when we spread string in multi lines.
Kotlin offers a powerful syntax three quote """
which can be used to spread a string in multiple lines. Here is a snippet:
// Java
String sample = "This is a sample "+
" which is a long string and it " +
"spreads in multiple lines. The syntax is okay but "+
"Not Great. It is difficult to read."
// Kotlin
val sample = """
This is a sample which is a long string and it
spreads in multiple lines. The syntax is better and
it is easier to read as the line continues..
"""
🔥 Clearly the Kotlin syntax is better than the java alternative. Wait, does it get even better? Yes, it does. You can spread the string in multiline and use any indentation you want. Here is a snippet:
// Kotlin
val sample = """
This is a sample which is a long string and it
spreads in multiple lines. The syntax is better and
it is easier to read as the line continues..
"""
// In above string, the spaces will be maintained. If you do not want the spaces, you can use trimMargin
val sample = """
|This is a sample which is a long string and it
|spreads in multiple lines. The syntax is better and
|it is easier to read as the line continues..
"""
sample.trimMargin() // you can pass your own delimiter instead of pipe
🔥 In the second example, we used the default delimiter pipe |
. trimMargin
function will trim all the spaces before pipe and remove the pipe. There is no such offering in Java.