Kotlin VS Java - Hvilket programmeringssprog skal du lære i 2020?

Det har været flere år siden Kotlin kom ud, og det har gjort det godt. Siden Kotlin blev oprettet specifikt for at erstatte Java, er det naturligvis blevet sammenlignet med Java i mange henseender.

For at hjælpe dig med at beslutte, hvilket af de to sprog du skal hente, vil jeg sammenligne nogle af hovedfunktionerne på hvert sprog, så du kan vælge det, du vil lære.

Dette er de 8 punkter, jeg vil diskutere i denne artikel:

  • Syntaks
  • Lambda-udtryk
  • Null Håndtering
  • Modelklasser
  • Globale variabler
  • Samtidighed
  • Udvidelsesfunktioner
  • Fællesskab

Syntaks sammenligning

For at starte det hele, lad os lave en grundlæggende syntaks sammenligning. Mange af jer, der læser dette, har måske allerede en vis viden om Java og / eller Kotlin, men jeg vil give et grundlæggende eksempel nedenfor, så vi kan sammenligne dem direkte:

Java

public class HelloClass { public void FullName(String firstName, String lastName) { String fullName = firstName + " " + lastName; System.out.println("My name is : " + fullName); } public void Age() { int age = 21; System.out.println("My age is : " + age); } public static void main(String args[]) { HelloClass hello = new HelloClass(); hello.FullName("John","Doe"); hello.Age(); } } 

Kotlin

class NameClass { fun FullName(firstName: String, lastName:String) { var fullName = "$firstName $lastName" println("My Name is : $fullName") } } fun Age() { var age : Int age = 21 println("My age is: $age") } fun main(args: Array) { NameClass().FullName("John","Doe") Age() }

Følelsen af ​​koden er ikke så forskellig bortset fra nogle små syntaksændringer i metoder og klasser.

Men den virkelige forskel her er, at Kotlin understøtter typeinferens, hvor den variable type ikke behøver at blive deklareret. Vi har heller ikke brug for semikolon ( ;) længere.

Vi kan også bemærke, at Kotlin ikke strengt håndhæver OOP som Java, hvor alt skal være indeholdt i en klasse. Se på fun Ageog fun maini eksemplet, hvor det ikke er indeholdt i nogen klasse.

Kotlin har også typisk færre linjer med koder, mens Java holder sig mere til en traditionel tilgang til at gøre alt ordentligt.

En fordel ved Kotlin frem for Java er Kotlins fleksibilitet - det kan vælge at gøre alt i den traditionelle OOP-tilgang, eller det kan gå en anden vej.

Lambda-udtryk

Hvis vi taler om Java og Kotlin, skal vi selvfølgelig tale om det berømte lambda-udtryk. Kotlin har indfødt Lambda-support (og har altid gjort), mens lambda først blev introduceret i Java 8.

Lad os se, hvordan de begge ser ud.

Java

//syntaxes parameter -> expression (parameter1, parameter2) -> { code } //sample usage ArrayList numbers = new ArrayList(); numbers.add(5); numbers.add(9); numbers.forEach( (n) -> { System.out.println(n); } );

Kotlin

//syntax { parameter1, parameter2 -> code } //sample usage max(strings, { a, b -> a.length < b.length })

I Java er parenteserne mere lette: hvis der kun findes en parameter, er der ikke behov for parenteser. Men i Kotlin er der altid brug for parenteser. Samlet set er der dog ikke mange forskelle bortset fra syntaksen.

Efter min mening vil lambda-funktioner ikke blive brugt meget bortset fra at bruge dem som tilbagekaldsmetoder. Selvom lambda-funktioner har så mange flere anvendelser, gør læsbarhedsproblemer det mindre ønskeligt. De vil gøre din kode kortere, men det vil være meget vanskeligere at finde ud af koden senere.

Det er bare et spørgsmål om præference, men jeg synes det er nyttigt, at Kotlin håndhæver de obligatoriske parenteser for at hjælpe med læsbarhed.

Null Håndtering

I et objektorienteret sprog har null-type værdier altid været et problem. Dette spørgsmål kommer i form af en Null Pointer Exception (NPE), når du prøver at bruge indholdet af en nulværdi.

Da NPE altid har været et problem, har både Java og Kotlin deres egen måde at håndtere null-objekter på, som jeg vil vise nedenfor.

Java

Object object = objServ.getObject(); //traditional approach of null checking if(object!=null){ System.out.println(object.getValue()); } //Optional was introduced in Java 8 to further help with null values //Optional nullable will allow null object Optional objectOptional = Optional.ofNullable(objServ.getObject()); //Optional.of - throws NullPointerException if passed parameter is null Optional objectNotNull = Optional.of(anotherObj); if(objectOptional.isPresent()){ Object object = objectOptional.get(); System.out.println(object.getValue()); } System.out.println(objectNotNull.getValue());

Kotlin

//Kotlin uses null safety mechanism var a: String = "abc" // Regular initialization means non-null by default a = null // compilation error //allowing null only if it is set Nullable var b: String? = "abc" // can be set null b = null // ok print(b)

Så længe jeg kan huske, har Java brugt traditionel nulkontrol, der er tilbøjelig til menneskelig fejl. Derefter kom Java 8 med valgfrie klasser, der giver mulighed for mere robust nulkontrol, især fra API / serversiden.

Kotlin giver derimod nul sikkerhedsvariabler, hvor variablen skal være nul, hvis værdien kan være nul.

Jeg har ikke rigtig brugt valgfri klasse endnu, men mekanismen og formålet ligner temmelig Kotlins nul sikkerhed. Begge hjælper dig med at identificere, hvilken variabel der kan være nul, og hjælper dig med at sikre, at den korrekte kontrol er implementeret.

Nogle gange i kode kan der være lige for mange variabler, der ligger rundt og for mange til at kontrollere. Men at tilføje kontrol overalt gør vores kodebase grim, og ingen kan lide det, ikke?  

Efter min mening føles det dog lidt rodet at bruge Java's valgfri på grund af den mængde kode, der skal tilføjes til kontrollen. I mellemtiden i Kotlin kan du bare tilføje en lille mængde kode for at foretage nulkontrol for dig.

Modelklasse

Nogle mennesker henviser muligvis også til dette som Entity-klassen. Nedenfor kan du se, hvordan begge klasser bruges som modelklasser på hvert sprog.

Java

public class Student { private String name; private Integer age; // Default constructor public Student() { } public void setName(String name) { this.name = name; } public String getName() { return name; } public void setAge(Integer age) { this.age = age; } public Integer getAge() { return age; } }

Kotlin

//Kotlin data class data class Student(var name: String = "", var age: Int = 0) //Usage var student: Student = Student("John Doe", 21)

In Java, properties are declared as private, following the practice of encapsulation. When accessing these properties, Java uses Getters and Setters, along with the isEqual or toString methods when needed.

On the Kotlin side, data classes are introduced for the special purpose of model classes. Data classes allow properties to be directly accessed. They also provide several in-built utility methods such as equals(), toString() and copy().

For me, data classes are one of the best things Kotlin offers. They aim to reduce the amount of the boilerplate code you need for regular model classes, and they do a really good job of that.

(contact me for the full resoluton image)

Global Variables

Sometimes your code might need a variable needs to be accessed everywhere in your code base. This is what global variables are used for. Kotlin and Java each have their own ways of handling this.

Java

public class SomeClass { public static int globalNumber = 10; } //can be called without initializing the class SomeClass.globalNumber;

Kotlin

class SomeClass { companion object { val globalNumber = 10 } } //called exactly the same like usual SomeClass.globalNumber

Some of you might already be familiar with the static keyword here since it's also used in some other language like C++. It's initialized at the start of a program's execution, and is used by Java to provide global variables since it is not contained as an Object. This means it can be accessed anywhere without initializing the class as an object.

Kotlin is using quite a different approach here: it removes the static keyword and replaces it with a companion object which is pretty similar to a singleton. It let's you implement fancy features such as extensions and interfacing.

The lack of the static keyword in Kotlin was actually quite surprising for me. You could argue that using the static keyword might not be a good practice because of its nature and because it's difficult to test. And sure, the Kotlin companion object can easily replace it.

Even then, using static for global variable should be simple enough. If we are careful with it and don't make it a habit of making every single thing global, we should be good.

The companion object might also give us some flexibility with interfacing and such, but how often will we ever be interfacing singleton classes?

I think static keywords help us keep things short and clean for global variables.

Concurrency

Nowadays, concurrency is a hot topic. Sometimes the ability of a programming language to run several jobs concurrently might help you decide if that will be your language of choice.

Let's take a look at how both languages approach this.

Java

 // Java code for thread creation by extending // the Thread class class MultithreadingDemo extends Thread { public void run() { try { // Displaying the thread that is running System.out.println ("Thread " + Thread.currentThread().getId() + " is running"); } catch (Exception e) { // Throwing an exception System.out.println ("Exception is caught"); } } } // Main Class public class Multithread { public static void main(String[] args) { int n = 8; // Number of threads for (int i=0; i
    

Kotlin

for (i in 1..1000) GlobalScope.launch { println(i) } 

Java mostly uses threads to support concurrency. In Java, making a thread requires you to make a class that extends to the in-built Java thread class. The rest of its usage should be pretty straightforward.

While threads are also available in Kotlin, you should instead use its coroutines. Coroutines are basically light-weight threads that excel in short non-blocking tasks.

Concurrency has always been a hard concept to grasp (and also, to test). Threading has been used for a long time and some people might already been comfortable with that.

Coroutines have become more popular lately with languages like Kotlin and Go (Go similarly has goroutines). The concept differs slightly from traditional threads – coroutines are sequential while threads can work in parallel.

Trying out coroutines, though, should be pretty easy since Kotlin does a very good job explaining them in their docs.  And one bonus for Kotlin over Java is the amount of boilerplate code that can be removed in Kotlin.

Extension Functions

You might be wondering why I'm bringing these up since Java itself doesn't even have this feature.

But I can't help but mention it, because extension functions are a very useful feature that was introduced in Kotlin.

fun Int.plusOne(): Int { return this + 1 } fun main(args: Array) { var number = 1 var result = number.plusOne() println("Result is: $result") }

They allow a class to have new functionality without extending it into the class or using any of the fancy Design Patterns.  It even lets you to add functionality to Kotlin variable classes.

You can practically say goodbye to those lib method that need you to pass everything inside your parameters.

Community

Last but not least, let's talk about something non-technical. First, let's take a look at this survey showing top commonly used programming languages in 2020.

We can see that Java is one of the most commonly used languages. And while Kotlin is still rising a lot in popularity, the Java community still remains several times larger than Kotlin and it will probably not change anytime soon.

So what does that matter then? Actually it does matter, a lot. With the amount of people in the Java community, it's much easier to find references and get help when you need it, both on the Internet and in the real world.

Many companies are also still using Java as their base and it might not change anytime soon even with Kotlin's interoperability with Java. And usually, doing a migration just doesn't serve any business purpose unless the company has really really important reasons for it.

Wrapping up

For those just scrolling for the summary, here's what we discussed:

  • Syntax: the patterns don't differ that much aside from slight syntax differences, but Kotlin is more flexible in several aspects.
  • Lambda Expressions: the syntax is almost the same, but Kotlin uses curly brackets to help readability.
  • Null Handling: Java uses a class to help with null handling while Kotlin uses in-built null safety variables.
  • Model Classes: Java uses classes with private variables and setter / getter while Kotlin supports it with data classes.
  • Global Variables: Java uses the static keyword while Kotlin uses something akin to sub-classes.
  • Concurrency: Java uses multi-threading whereas Kotlin uses coroutines (which are generally lighter).
  • Extension Functions: a new feature introduced by Kotlin to easily give functionality into classes without extending it.
  • Community: Java still reigns supreme in the community aspect which makes it easier to learn and get help.

There are many more features we could compare between Java and Kotlin. But what I've discussed here are, in my opinion, some of the most important.

I think Kotlin is well worth picking up at the moment. From the development side it helps you remove long boilerplate code and keep everything clean and short. If you are already a Java programmer, learning Kotlin shouldn't be too hard and it's okay to take your time at it.

Thanks for reading! I hope that this article will help you decide which programming language you should pick, Java or Kotlin. And for anything that I'm missing, feel free to leave feedback for me as it will be very much appreciated.