So, you've decided to watch From Justin to Kelly?
Oh, wait. That's next week's post. Sorry. Wibbly wobbly. -Reads correct script- Ahem.
So, you've decided to switch from Java to Kotlin?
Switching from one programming language to another can feel intimidating and daunting. There's so many new things to learn, so many things that look similar but have a change that trip you up, and just so many surprises. As an Android developer, we had to weigh our options: did we want to switch to Kotlin just because it was new and shiny, or was there some benefit? Could it wait? Is there a way to try out just a little bit?
Automatic Java to Kotlin conversion
Android Studio came prepared with a solution once Kotlin was adopted as an officially supported language for Android apps. By clicking Code -> Convert Java File to Kotlin File, Android Studio will perform some basic transformation of Java to Kotlin for you. I personally think that's the best place to start if you're trying out Kotlin for the first time. Take a small class you know and understand well and convert it, looking over the changes and similarities. Be warned, Android Studio doesn't always do it the best way, but it's more than enough to get started with.
public class MainActivity extends Activity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.id.activity_main);
}
}
class MainActivity: Activity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
From this quick example of a basic Activity, you can see that... not much is different. In Kotlin, everything is public
by default, so we can leave that word out. extends
(and implements
) is transformed into a simple :
. The @Override
annotation is shifted to just become override
and in line with the function name.
For me, the biggest change is that parameters and their types have shifted positions. Bundle savedInstanceState
is now savedInstanceState: Bundle?
(the question mark just means that it's Nullable). Also, lines don't end in semicolons, but you can add them if you want and it will still compile!
Data Classes
One of my favorite types of classes in Kotlin is Data classes. Here's a regular class in Java, with a constructor, getters, and setters.
public class YourObject {
private String title;
private int count;
private @Nullable String description;
private boolean isActive = true;
public YourObject(String title, int count, @Nullable String description, boolean isActive) {
this.title = title;
this.count = count;
this.description = description;
this.isActive = isActive;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
@Nullable
public String getDescription() {
return description;
}
public void setDescription(@Nullable String description) {
this.description = description;
}
public boolean isActive() {
return isActive;
}
public void setActive(boolean active) {
isActive = active;
}
}
This, my friend, is why I love Data classes:
data class YourObject(var title: String, var count: Int, var description: String?, var isActive: Boolean = true)
DO YOU SEE THIS?!
Kotlin doesn't really do getters and setters (but then they do but it's... nevermind); it prefers property access syntax (that's what Android Studio calls it; pretty much, it wants you to use the variables directly). Data classes are also why I've moved away from builders. I feel as if named parameters fulfill the same purpose. Here's an example:
val item = YourObject(
title = "A Year In Love",
count = 525600,
description = "How do you measure a year in the life?"
)
Using our Data class from before, we can create an instance of that class using named parameters. Everything feels neat and orderly. You can do them in any order (if you use the naming syntax, otherwise you have to do them in order). Your parameters that have default values aren't required (in constructors and methods).
Also, bonus love for data classes: they come with a .copy()
method.
val aCopy = item.copy(description = null,
title = "A Copy With No Description")
Interfaces and Abstract Classes
Interfaces
Interfaces and Abstract classes function relatively the same and even look very similar. There are some small benefits on the Kotlin side, though.
public interface TestInterface {
void someInterfaceMethod();
String howAboutAnother(String someParam);
}
interface TestInterface {
fun someInterfaceMethod()
fun howAboutAnother(someParam: String): String
fun forFunsies() {
// Some default implementation
}
}
The Kotlin example behaves the same, however, you can do something special with them, blurring the line between Interface and Abstract class so please use it wisely! In Kotlin interfaces, you can have non-required, default implementations of functions.
Abstract Class
There's less difference between a Java Abstract class and a Kotlin one, though there is one thing to note. Before I get into that, here's an example of an Abstract class in Java, with a class extending it:
abstract class AbstractJavaClass {
abstract void someMethod();
final void anotherMethod() {
//default implementation
//this method can NOT be overriden, 'cause it's final
}
void yetAnotherMethod() {
//default implementation
//this method CAN be overriden
}
}
class ImplementationJavaClass extends AbstractJavaClass {
@Override
void someMethod() {
//you're forced to implement this method
anotherMethod();
yetAnotherMethod();
}
// You can NOT override "anotherMethod"
@Override
void yetAnotherMethod() {
super.yetAnotherMethod();
// you have the option of overriding this one, though
}
}
Similarly, here is an Abstract class in Kotlin with an associated extending class:
abstract class AbstractClass {
abstract fun someMethod()
fun anotherMethod() {
//default implementation
//this method can NOT be overriden
}
open fun yetAnotherMethod() {
//default implementation
//this method CAN be overriden
}
}
class Testing(): AbstractClass() {
override fun someMethod() {
//you're forced to implement this method
anotherMethod()
yetAnotherMethod()
}
// You can NOT override "anotherMethod"
override fun yetAnotherMethod() {
super.yetAnotherMethod()
// you have the option of overriding this one, though
}
}
You'll notice in my Java example I explicitly labeled a method as final
. I did this to show the similarity in Kotlin: in Kotlin, all functions are final
by default. The same is true for Classes as well. To make them non-final
, you need to add open
before it. (An open
class would start off as open class ClassName
)
Interoperability: Use Java and Kotlin together!
If you want to get started with Kotlin, dive right in! You can use Kotlin inside your existing Java applications and files, and existing Java inside your Kotlin files.
At my current company, there's been a slow conversion of Java to Kotlin, and a good 80%-90% of our main Android application is now in Kotlin. And I dread having to dredge through the untamed Java territory. But I know that when I do get to the lawless West of Java-land, I can still use a lot of my Kotlin code. Even my extensions!
I name my extensions classes in Kotlin based on the class I'm extending. For instance, if I was adding an extension to the Throwable class, I would make a file called ThrowableExtensions.kt
. And, while I can't use the extension exactly like I would in Kotlin, if I need it in Java it's available to me in an automatically-generated class called ThrowableExtensionsKt
, and I can access my extension function statically, passing in the object I would be acting on.
... that sounds confusing. ๐ Here's an example:
# in a file called ThrowableExtensions
fun Throwable.log() {
/// my extension code
}
public void someErrorMethod(Throwable throwable) {
ThrowableExtensionsKt.log(throwable)
}
For the full code of my Throwable extension (and other useful ones!), visit my previous blog post on five super-useful Kotlin extensions I use every day.
#MakeItBetter: My Everyday Kotlin Extension Functions
Tavon ใป Feb 10 '20 ใป 4 min read
... And one* more thing
* = Actually, there's way more than one more thing.
Kotlin has a lot of different tricks up its sleeves, like val
vs var
(and even vs lateinit var
). There are lazy
variables, too! Oh, and classes can have Companion
s! But this post has gone on long enough. If there's something about Kotlin you'd like me to go over, let me know in the comments below or on Twitter @gatlingxyz
.
This post originally appeared on my blog, Gatling.XYZ. You can check
out the original post here and maybe you'll find something else you like, too.
Top comments (2)
Thanks for the informative post. I wanted to ask if it makes more sense for someone to start out learning Android using Java and switch to Kotlin at a later stage compared to learning Android using Kotlin from the get-go, assuming no knowledge about Java in either case.
Ooh, that's a tough one. Java is my foundation; it's the first programming language I learned in school. Switching to Kotlin was easy (or, easier) because I already had a foundation. Most of it is the same in both languages, with minor tweaks (such as no commas in Kotlin).
Personally, I would say just dive in with Kotlin for Android. It's officially supported, and a lot of stuff is happening with Kotlin in the forefront now. Start with Kotlin. If you find a tutorial in Java, you can always copy and paste it into Android Studio and it will automatically convert it to Kotlin for you as best as it can.