#MakeTheChange: From Java to Kotlin
Tutorial

#MakeTheChange: From Java to Kotlin

Switching from one programming language to another can feel intimidating and daunting. I'm here to help ease some of the pain. Now that I've been introduced to Kotlin, I never wanna go back to Java.


So, you've decided to watch From Justin to Kelly?

Something tells me none of you even know this is a movie that exists. Totally worth it.

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?

I'm so glad you've decided to join us. Cookies are in the back, and we have trips twice a year.

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 extension 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.

... 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 lateinit var). There are lazy variables, too! Oh, and classes can have Companions! 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.



Share Tweet Send
0 Comments
Loading...