Kotlin VS Java: Basic Syntax Differences

Kotlin is much younger than Java, but it’s a really promising programming language and its community is constantly growing. Everyone’s talking about it and saying it’s cool. But why is it so special?

We’ve prepared a series of articles to share our experience developing Android apps in Kotlin with you. We’ll discuss how Kotlin differs from Java when it comes to syntax, usability, UI performance and asynchrony so you could decide which language suits you best.

Let’s start with some basic syntax differences. Here’s the first:

1. With Kotlin, you can do more with less code

One of the main advantages of Kotlin is its concision. You get more functionality with less code. And the less code you write, the fewer mistakes you make. It’s pretty straightforward. Let’s look at the basics of Kotlin, starting with classes.

public final class Person {
    private String name;
    private int age;
    private float height;

    public Person(String name, int age, float height) {
        this.name = name;
        this.age = age;
        this.height = height;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
        this.height = 1.8f;

    public String getName() {
        return name;

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

    public int getAge() {
        return age;

    public void setAge(int age) {
        this.age = age;

    public float getHeight() {
        return height;

    public void setHeight(float height) {
        this.height = height;

    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +

    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Person person = (Person) o;

        if (age != person.age) return false;
        if (Float.compare(person.height, height) != 0) return false;
        return name != null ? name.equals(person.name) : person.name == null

    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        result = 31 * result + (height != +0.0f ? Float.floatToIntBits(height) : 0);
        return result;

Above is a usual Java class. It doesn’t do much. It just contains some data. But it’s painful to see how large this snippet of code is when you realize how little it brings to the table. To cheer you up, we’ll show you an equivalent class written in Kotlin.

data class Person(var name: String,
                 var age: Int,
                 var height: Float = 1.8f)

Yes, you’ll automatically get needed getters, setters, equals(), hashcode(), toString() and copy() functions for your data class! Of course, you can easily override these functions, but in most cases it’s enough just to declare the class and its properties.

This is exactly what we meant when we said that Kotlin is concise.

2. You can avoid NullPointerException

Now we want to remind you about the biggest pain in numerous programming languages – the null pointer exception. We can hardly imagine how many developers have suffered from the null pointer ever since Tony Hoare invented it in 1965 while trying to make things a bit simpler.

Sadly, we can’t go back in time and prevent Tony from making this mistake. But with Kotlin, we can now easily escape the NullPointerException.

val person: Person? = null
person?.name = "John"

If the variable is nullable, the compiler will not permit you to access it without a proper check. Kotlin forces you to use a ?. operator. This prevents the app from crashing automatically.

How does it work under the hood? Let’s review the generated bytecode.

LDC "John"
INVOKEVIRTUAL igalata/com/kotlinexample/Person.setName (Ljava/lang/String;)V

As you can see, we’ve got the same null check here. JetBrains’ developers (who created Kotlin) knew that checking our variables every time is the only way to avoid a NullPointerException. But they also knew that Android developers don’t want to deal with the NullPointerException in their projects. They probably thought: “Why not to generate this check automatically if the variable is nullable?”

JetBrains’ developers did just that and made our lives that much easier for it!

3. You can get rid of util classes

Let’s talk about the ugly things that are util classes. Have you ever had a project without them? We can hardly remember that happening. Kotlin has a smart solution – extension functions – to help you get rid of all your util classes once and for all.

The extension function is almost a usual Kotlin function. But when you declare it, you need to specify the class whose instances will have the extension function.

fun Context.toast(text: String) = Toast.makeText(this, text, Toast.LENGTH_SHORT).show()

Notice ‘this’ that we pass as a parameter to the makeText() method? It’s not an instance of the class where we declare this function, rather it’s a Context instance. And now you can call this function directly from your Activity or any other Context instance. For example:


You should remember that the extension function doesn’t modify the class it extends in any way. So how does it work without changing the original class? Let’s see the bytecode one more time.

public final toast(Landroid/content/Context;Ljava/lang/String;)V
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0
    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1
    ALOAD 1
    LDC "$receiver"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    ALOAD 2
    LDC "text"
    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkParameterIsNotNull (Ljava/lang/Object;Ljava/lang/String;)V
    ALOAD 1
    ALOAD 2
    CHECKCAST java/lang/CharSequence
    INVOKESTATIC android/widget/Toast.makeText (Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;
    INVOKEVIRTUAL android/widget/Toast.show ()V
    LOCALVARIABLE this Ligalata/com/kotlinexample/MainActivity; L0 L3 0
    LOCALVARIABLE $receiver Landroid/content/Context; L0 L3 1
    LOCALVARIABLE text Ljava/lang/String; L0 L3 2
    MAXSTACK = 3

Ha! Your function implicitly receives the instance of the class it extends as the first parameter. So in the bytecode, any access to ‘this’ in the body of the function is replaced with the access to the first parameter. There’s no magic really. And you can use this function anywhere in your project.

Time to remove your util package!

4. You can forget about view binding

Do you remember the findViewById() method()? We’re sure you don’t like it. We don’t either. Also, we don’t like to declare variables and Butterknife annotations for every view we need to access.

You can forget about view binding with Kotlin Android Extensions. No longer do you need to create variables and bind views. You can access your views directly with their identifiers declared in the xml layout.

public class MainActivity extends AppCompatActivity {
    protected void onCreate(@Nullable Bundle savedInstanceState) {

        Button button = (Button) findViewById(R.id.button);
        final TextView text = (TextView) findViewById(R.id.text); 
        button.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                text.setText("You've clicked a button");

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) {
        super.onCreate(savedInstanceState, persistentState)

        button.setOnClickListener { text.text = "You've clicked a button" }

That’s so much simpler, isn’t it?

Basically, the findViewById() method is still in use. But there’s no need to write it yourself. Kotlin will do it for you.

When you use Android Extensions, the findCachedViewById() function and the HashMap instance will be generated automatically. Every access to your view by its identifier will be replaced with a new function call. If it’s the first time you access the view, this function will call the usual findViewById() function, and will add the received view into the HashMap to retrieve the view from it the next time you access it.

5. You can work with collections much more easily

Let’s talk about collections in Kotlin. Because quite often we need to perform difficult operations with collections of data models. For example, we might have a list of students from which we need to retrieve three students with A grades, and two students with B grades.

Look at the solution in Kotlin:

var students = listOf(Student("John", 0), Student("Julia", 2), Student("Matt", 1),
                Student("Katie", 0), Student("Dan", 0))

var firstList = students.filter { it.mark == 0 }.take(3)
var secondList = students.filter { it.mark == 1 }.take(2)

Here’s how we would solve the same problem in Java:

ArrayList<Student> students = new ArrayList<Student>() {{
            add(new Student("John", 0));
            add(new Student("Julia", 2));
            add(new Student("Matt", 1));
            add(new Student("Katie", 0));
            add(new Student("Dan", 0));

ArrayList<Student> firstList = new ArrayList<>();
ArrayList<Student> secondList = new ArrayList<>();

for (Student student: students) {
            boolean isFirstFilled = firstList.size() >= 3;
            boolean isSecondFilled = secondList.size() >= 2;

            if (isFirstFilled && isSecondFilled) break;
            int mark = student.getMark();
            if (mark == 0 && !isFirstFilled) {
            } else if (mark == 1 && !isSecondFilled) {

This is just a small example of how collections are used in Kotlin and in Java, but you can already see the difference! Can you imagine the difference Kotlin makes if we work on collections for a large project?

4.8/ 5.0
Article rating
Remember those Facebook reactions? Well, we aren't Facebook but we love reactions too. They can give us valuable insights on how to improve what we're doing. Whould you tell us how you feel about this article?