This is the part 2 of series Java to Kotlin - Learning Simplified. This part is to show the difference in basics of Java & Kotlin. I hope you learn something new from every part. If you are not convinced why do you need Kotlin and want to know little history, check Part 1
π‘ Remember our 3 core principles? Concise, Smart and Powerful
Wherever possible, Kotlin tries to be concise and compiler is smart to help developers at compile time. Plus, Kotlin has some powerful offerings which we will see later.
Topics in Part 2: Semicolon, File & Package, Access Modifier, Equals ==, String Concatination, Variable, New Instance, Class Definition, Inheritance
1. SemiColon ;
Letβs start with the simplest syntax change. In Java, semicolon is mandatory after every statement but in Kotlin it is optional, compiler adds one for you. βThe concise principleβ Your muscle memory is not going to embrace it but why to press one extra keystroke?
Here is a snippet:
// Java
callSomeMethod();
x = 5;
// Kotlin
callSomeMethod()
x = 5
2. File & Package name
Java file ends with .java
extension and Kotlin file ends with .kt
extension.
In Java we can have many classes in a file but it has a weird restriction. There must be a public class with same name as the file name. Kotlin says why? There might be some logical reasoning back then but now IDE is powerful and we do not need that restriction any more. In kotlin, there is no such restriction
. Class name can differ from the file name.
Another difference is package name. In Java, the package name of the class must match the file path. It means if you have a Java file in src/util
, the package name has to be src.util
but in Kotlin there is no such restriction. You can write whatever you want as package name. However, it is considered a good practice to use file path as package name.
3. Access Modifiers
In Java, we have public, private, protected and default
access modifiers.
In kotlin, we have public private, protected and internal
. The difference is if we do not specify anything in Java, it becomes default
which is package-private. But in Kotlin, if we do not specify anything it is public
.
Another difference is in private
. In java, private means accessible only in the same Class but in Kotlin, private means accessible in the File. We will cover File later. Same goes to protected
, they are available to file + subclasses.
π₯ Internal is a new access modifier in Kotlin and it is really nice. If you work in multi module projects, then you are going to love it. Internal
fields and classes are available in the module. It is like public with a scope limited to module.
4. Equals == and ===
In Jave we use ==
to check objects are exact same or not and we use equals
method to check meaninful equivalence. That means equals as per business logic.
But Kotlin being concise and smart, encourages to use ==
for meaningful equivalence. When we use ==
in Kotlin, it uses equals
method under the hood. If you want to check objecs are exact same OR not, use ===
. Summary is ===
of Kotlin is same as ==
of Java and ==
of Kotlin is same as equals
method as compiler changes it.
// Java
Car car = new Car();
Car car2 = new Car();
car == car2 // false, checks the objects are same in memory
car.equals() // true/false depends on business logic
// Kotlin
val car = Car() // ignor how variable is defined, we will learn
val car2 = Car()
car.equals(car2) // true/false depends on business logic.
car == car2 // same as above, Converts to .equals
car === car3 // false, checks the objects are same in memory
5. String concatenation and Expression
This is one of the area Java is really ugly to look at. We need to use either +
operator to concatenate strings OR use string formatter. Former option is mostly used in common places like printing logs.
Kotlin offers a neat way, string templates. You can print value of the object inside a string liternal using $
. Check the snippet below, both are same:
// Java
String name = "Gaurav"
System.out.println("My Name is " + name);
// Kotlin
val name = "Gaurav"
println("My Name is $name")
Read more in the offical documentation here
Expressions inside string literal
This is where Kotlin shines. Suppose you have to use some expression while concatenating Strings. You might need to call a function OR you might need to perform some arithmatic operation. Kotlin offers another syntax ${expression_here}
. Check the snippet below, both output are same:
// Java
Car car = new Car();
System.out.println("My Car is " + car.getCompany() + "And model is " + car.getModel());
// Kotlin
val car = Car()
println("My Car is ${car.company} And model is ${car.model}")
Note: Ignore getter-setter in Kotlin code for now, We will explain later. To keep you surprised, kotlin code is also using getter-setter under the hood. Remember, I said expressions inside literal. Check the code below:
// Kotlin
val i = 10;
println("Number $i is ${ if(i % 2 == 0) "Even" else "Odd"}")
6. Defining Variable
This is one of the area where your habitual brain will complain. Remember it does not like change. In Java we define a variable by first telling its visibility, then the type and then the name of the variable.
Kotlin has little different philosophy here. Remember Kotlin is made to reduce errors. One of the error prone area is mutable states in Java. So Kotlin made it mandatory to choose. In Kotlin we define a variable by telling visibility, then it is mutable OR immutable, then name, then type. Check the snippet below:
// Java
private Car car; // visibility, type and name
// Kotlin
private val car:Car // visibility, mutablity, name and type
val and var
are two keywords used in Kotlin to define mutablity. val
means it is an immutable value
and var
means mutable variable
. val
is equivalent to final
in Java. Check Another Snippet:
// Java
Car car; // default visibility in Java
// Kotlin
val car:Car // default is public in Kotlin
// Kotlin
val x = 1 // Kotlin knows it is Int
x = 5 // error, x is final
var y = 1
y = 5 // all good, y is var (mutable)
7. Creating Objects, New Instances
This is very simple. Java uses the keyword new
followed by Constructor but Kotlin keeping its concise
promise does not use the new
keyword. It uses only constructor
// Java
Car car = new Car();
// Kotlin
val car : Car = Car();
The above kotlin snippet does not use new
keyword. Kotlin smart
principle can also be applied here. We can drop the type of the Object, Kotlin compiler can deduce the type from the Constructor. It is called Type Inference
which means based on the value, compiler can figure out the type.
val car = Car() // This is pure Kotlin flavor, concise and smart
val i = 5 // compiler knows it is Int
val x = "text" // compiler knows it is String
π‘ Important! Immutability
In object-oriented and functional programming, an immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created. wikipedia
Java has the notion of immutability
but you have to explicitly define what is immutable
. By default, classes and fields are mutable
. Whereas Kotlin took another approach, it claims immutability
leads to hard-to-find bugs. Thus everything by default is immutable
and you have to explicit mark mutable
8. Class Definition
In java, the classes are defined with keyword class
assigining them a name, a visibility modifier, and optional final
to mark them immutable
. Default visibility is default package
In Kotlin, The default visibility is public
and final
is not required as classes are final
by default (It means you can not extend them, they are immutable
). Here is a equivalent snippet in both langauges :
// Java
public final class Car{}
// Kotlin
class Car{}
/* public and final are not required in Kotlin */
π‘ My take: Initially I found it hard to accept, why everything is final. But the more I used, the more I realised It makes more sense. it allows us to think architecture better. Now we make classes Extendable
only if required and it has proven to be more effective.
So how to make classes extendable?
9. open Keyword
Kotlin does not have notion of final
keyword, class by default is not-extendable (final
) which means closed
. You can mark any class extendable with open
keyword. here is a snippet:
open class Car{}
// Now car is extendable
So how to extend a class
10. Inheritance - extend a class
In Java, we extend a class with extends
keyword. Simple and Nice.
In Kotlin, there is not extends
keyword but there is a syntax for that. We use colon :
. Here is a snippet:
// Java
public class Car{}
public class RaceCar extends Car{}
// Kotlin
open class Car{}
class RaceCar:Car(){}
π‘ RaceCar is closed, ()
after super class is to call the constructor, we will see later
Summary
We covered some differences between Kotlin and Java. If you are java developer, a few might seem absurd at first sight but trust me, it is your brain not liking the change. We see mainly 3 principles are at work Concise, Smart and Powerful
.
The very basic difference is no semicolon
in Kotlin, No restriction on file name and public class name inside, default visibility
modifer is public
in Kotlin, internal visibility means inside package, == calls equals
and ===
is used to compare objects in memory
, Strings allow concatenation with $variable
and we can evaluate expressions inside string with ${}
, variables are defined with val and var
, val
means final
and var
are immutable
, Kotlin offers type inference
and assigns the type to variable based on the value assigned, Classes are final
by default and we need open keyword
to make them extendable
, and finally there is no extends
keyword, but we use syntax colon :
to extend a class.