Java was launched in 1995 and developed by James Gosling at Sun Microsystems (which in 2009 was acquired by Oracle). It is an open-source, general-purpose, object-oriented programming language. As a multiplatform language, Java works on almost any device, operating system, and server. In addition, since it is compiled to bytecode, it can run on any Java Virtual Machine (JVM).
Moreover, Java is statically typed, performing type checking during compile time. Java's syntax shares some similarities with C and C++ but provides fewer lower-level facilities.
Kotlin is a much younger language than Java since it was first introduced in 2016. It's an open-source language that can also compile code to bytecode and run on Java Virtual Machine (JVM), enabling it to work on almost any platform. Plus, libraries and frameworks made in Java are also compatible to operate in a Kotlin project.
Inspired by Java, Kotlin aims to express an improved version that is cleaner, simpler, faster to compile, and entails a mix of object-oriented and functional programming.
One year after its launch, in 2017, Google recognized Kotlin as their second official language for Android development. In 2019, Kotlin was declared as the favored programming language for Android applications at Google. Consequently, this programming language underwent incredible growth.
Now that we have a bit of context, you might wonder how Kotlin's growth impacts Java. Will Kotlin replace it? The answer is not that simple. There are a lot of mixed opinions on this subject. To understand both sides of the debates, let's first take a close look at their differences.
The famous NullPointerExceptions in Java give developers quite a headache. The idea behind NullPointerExceptions is that it enables users to attribute a null value to any variable. Yet, suppose users attempt to use an object reference that happens to have a null value. In that case, Java's NullPointerExceptions comes into play and opens an exception that developers need to handle.
In contrast, in Kotlin, it is not possible to attribute null values to variables or objects by default. If we try to do so, the code will fail at compile time. Therefore, there are no NullPointerExceptions in Kotlin. However, if the developer wishes to assign a null value, it is possible to mark the variable in question as nullable explicitly. To do so, one must add a question mark:
val number: Int? = null
Unlike Java, Kotlin allows the developer to extend the functionality of classes without necessarily having to inherit from a class. To perform the extension function in Kotlin, the developer must prefix the name of the class (that will be extended) to the name of the function created by using the '.' notation.
In Java, to extend the functionality of an existing class, one must create a new class and inherit the functions from the parent class. In other words, the extension function is not available.
One of the key differences between Kotlin and Java is that Kotlin requires way less code. It is a very concise language, which reduces the chances of making code errors and simplifies the developers' work.
Overall, Kotlin's brevity makes it more manageable to write large projects considering that it typically requires fewer lines of code than Java to write the same functions. Plus, it knows how to keep it short and straight to the point without compromising syntax's readability.
In Android, by default, components that belong to the same application run in the same process and thread, typically referred to as the main thread and responsible for the UI. Network I/O and CPU-intensive operations are considered lengthy. When either one of these operations is initiated, the respective calling thread is blocked until the entire operation is completed.
To avoid complications on the main thread, Java enables the creation of multiple background threads when handling lengthy operations. The downside is that managing multiple threads is a complex task that may lead to more errors in the code.
Similarly, Kotlin also provides the capability to create multiple threads. Nonetheless, it introduces a better and more straightforward solution: coroutines.
How do coroutines work? Well, coroutines are stackless and allow the developer to write code, suspend the execution and later resume it again. This enables non-blocking asynchronous code that seems synchronous. Hence, instead of creating multiple threads that the developer must handle later, coroutines avoid having too many threads. Plus, they are clearer and more concise than Java's solution.
On the one hand, in Java, developers need to establish the fields (or variables) to store the data, the constructor, and the getter and setter functions for the fields/variables, as well as other functions, such as the hashCode(), equals(), and toString().
Truth be told, these classes are mainly intended to store data and have zero (or very little, at most) functionality.
On the other hand, Kotlin provides a more straightforward way to create classes to hold data by simply including the "data'' keyword in the class definition. Then the compiler will auto-generate the constructor and the getter and setter functions for several fields/variables.
To cast an object in Java, the developer must check the variables' type in consonance to the operation.
In Kotlin, the casting checks are handled by the smart casts feature. Kotlin's intelligent compiler automatically manages redundant casts (with stable values) via the "is-checks" keyword.
Checked exceptions are not available on Kotlin. Thus, Kotlin's developers do not require to catch or declare exceptions. Is this a good thing? Well, it depends.
Java developers have checked exceptions support. Hence, they must catch and declare exceptions. On the one hand, this can be frustrating and time-consuming. But, on the other hand, it ensures robust code and that errors are being handled. So, checked exceptions support has its pros and cons. Ultimately, it depends on what each developer prioritizes the most.
As mentioned at the beginning of the article, Kotlin is a mix of object-oriented and functional programming.
Functional programming is a declarative style of programming that handles computations based on mathematical functions. High-order functions and lambda expressions are (some) functional programming concepts.
The first one indicates that functions should be considered first-class. Thus, Kotlin, a statically typed language, can make the most out of various function types to represent functions. In other words, it is possible to operate functions in a variety of ways.
Furthermore, it is also possible to use lambda expressions or anonymous functions with Kotlin. These are considered a "functional literal". Hence, it represents a function that is not declared and immediately passes as an expression.
Contrarily, Java is more limited to the concept of object-oriented programming. However, it has been taking some steps toward functional programming too. Since Java 8, in 2014, Java has introduced lambda expressions, which is a function that can be created without necessarily belonging to a class. Lambda expressions in Java can be passed as objects and can be executed on demand.
Further, with the introduction of lambda expressions, Java also started supporting high-order functions. Java associates a function with a method, and Java 8 enabled lambda's return from methods.
In Java, variables of a primitive type are not objects; they are predefined Java's data types. Java has eight different primitive data types: int, byte, short, double, float, boolean, char, and long. Consequently, these variables cannot be an object represented from a struct or a class.
Even though primitive types are not classes, Java developers can use classes that can wrap a value of the primitive type. To do so using Java, the developer must indicate it explicitly.
In contrast, in Kotlin, as soon as you initiate a variable of a primitive type, it will be automatically considered an object.
Public fields (also known as non-private fields) are available in Java. They can be pretty convenient in case the callers of an object require to modify according to the representation of that same object since it enables the developer to change the representation of an object without needing to adjust the callers. This way, the fields can be public; thus, the public API remains unchanged, and the program can sustain a level of maintainability.
In contrast, Kotlin does not have public fields.
Typically, a question mark (?) in code is considered a wildcard, which suggests an unknown type (of variable, field, or parameter).
Unlike Java, Kotlin does not provide wildcards. Instead, it has a declaration-site variance and type projections, which serve as an alternative.
On the one hand, Kotlin does not provide support for implicit widening conversions. Therefore, smaller types cannot be converted to bigger types. To overcome this, Kotlin developers must execute an explicit conversion to achieve the desired type conversion.
On the other hand, Java supports implicit conversions, meaning the developers do not need to perform explicit conversions.
First and foremost, despite their differences, both Java and Kotlin compile to bytecode. Therefore, developers can easily call Kotlin code to Java or the other way around, which allows both languages to be used in the same development project.
As we have explained, Kotlin does offer numerous advantages regarding Android development, but is Kotlin better than Java? Well, it does have some benefits over its competitor:
Now that we have highlighted each language's benefits, it is even harder to choose between Kotlin and Java, right? Well, let's try to take a pragmatic look.
Kotlin has been emerging as the new Android language. Its success comes from the fact that this language introduces vital features that are making developers' life a lot easier, such as extension functions, lambda expressions, and high-order functions, coroutines, and no NullPointerExceptions.
These are just some of the features that make it safe to affirm that, yes, Kotlin is better than Java for Android development and is likely to dominate in the future.
Is Kotlin Replacing Java? Everything seems to be moving toward Kotlin, and the new development tools that are rising know it! However, Java still has a lot of value and should not be neglected.
For general-purpose programming, Java still got it. Even for Android development, it remains an excellent language, and it is entirely understandable why some developers choose it.
Truth be told, it also depends on what languages the development team is using and which programming language feels more comfortable. These are all valid concerns. Plus, Java has been one of the most popular languages for years, so the chances of being entirely replaced soon are low.
For Android development, Kotlin seems to be the best option at the moment. Many companies and developers are adopting it, and the language will most likely continue to grow.
However, Java remains an excellent general-purpose language. Plus, it has been Android's favorite for a long time, so it will not be that quickly replaced.
In conclusion, the debate over which language is better is not that straightforward and will probably result in exciting discussions. Moreover, there are more aspects to consider than only the languages' differences, such as the language the companies are using and how comfortable developers feel with Kotlin or Java.
Subscribe to get latest updates