From Kotlin to Java: moving back seeing all the flaws

In previous week I had to resign from using Kotlin in one of my game projects. By porting the code manually I can point out what I didn’t like about Kotlin. Let’s see few differences between Kotlin and Java.

Why port?

Libgdx enables us to build our games to HTML5 webapp through the Google Web Toolkit. Kotlin compiles directly to bytecode, while GWT works on top of Java to generate JavaScript. So, bytecode and Kotlin? No, won’t work.

It seems there appears something new on the horizon, it’s called Dragome but it’s too early to use it.

Manually?

There is beautiful functionality that translates Java directly to Kotlin. Most of the transpilation looks pretty good. Some comments are broken and constants are put into companion object without const  keyword. Few issues about interfaces or docs, too. However, transpilation is pretty awesome.

Any other way? No. There is no option. Unless, you’ll use an output of decompilation of generated bytecode. However, this stuff needs too much of manual cleaning, fixing and redefining:

  • lots of annotations (like @Metadata  or @NotNull )
  • getters and setters instead of pure fields
  • are comments are lost
  • formatting is generated basing on formatter configuration

So, yeah. It’s a lot easier to copy-paste code and “fix” the syntax. Doing this, I rediscovered what I learned when porting the first way some time ago (those were Java classes that I further developed in Kotlin).

My dislikes on Kotlin

Bit shifting

Shifting some bits to the left is done using shl operator, not the << anymore. Why do we need this innovation?

instead of:

Looks like nothing disturbing. Well, look at this part of code from my serializer:

While it could look like this:

Still, nothing too fancy. However, I can’t stand seeing too much shr and shl mixed together. Operators based on symbols like >> and << work simply better for me.

No static finals to imitate constants

It’s pretty usual in Java to type this boring text to define some constant:

In Kotlin I have to create a companion object to simply define some static  things! The approach here is simple – classes have only the methods that are attached to instance. You want something static? Define such object, thus companion object.

I was little unlucky with this one because the official Java-Kotlin converter didn’t made it well and it wouldn’t compile. The converter forgot to put the const  keyword as in below:

Otherwise, I’m cool with it when I don’t try to call this from Java code. In Java it would be:

SomeSuperClass.companion.TYPE_OMG  – language interopability pains me here!

using types for reflection cache

Please compare these two on your own:

AssetSystem::class.java ↔ AssetSystem.class

Then, type such things multiple times in a row as I do with artemis-odb. Oh, you know about AssetSystem::class? Well, this gives you not an instance of Class<*>  but KClass<*> . When a coding custom serializer – it does matter which type you choose because those are separate objects.

Overall syntax is shorter but this makes it less readable

Some syntax may look neat but here’s the interface implementation vs class extension:

See the colon ( :)? I don’t know whether the TemporalExecutor is a class or interface! I have to visit the file. In Java it would be either  implements  or extends .

Another one. Generics are little different – they’re not invariant anymore

Look at the Executor. Now I’m back to Java equivalent:

Just evaluate it on your own.

My, ooooh, my likes on Kotlin!

There are lots of course. But let’s point out a few.

Null safety

There’s not much to say. You don’t have this in Java. You can’t simply pass null  if function argument doesn’t accept it by definition. Sometimes it is incovenient but most of all it catches errors just by converting Java code to Kotlin code and seeing what it has found about null safety.

Read about Null safety

Functional approach

What I did like – support for mapping arrays and such – it’s just easy to type. May not be something unusual comparing to other languages (especially functional ones) but it’s nice compared to Java 7!

KDoc: Markdown-like comments for classes and methods

I was pretty much amazed by this one. No more writing HTML <ul><li></li><li></li></ul>  just for bullet points, instead just use asterisk (the * ) symbols preceeded with whitespace each in new line.

More to it, linking to classes and fields changed from Java’s:

  • {@link ClassName} to just [ClassName]
  • fields of external classes {@link ClassName#fieldName} to [ClassName.fieldName]
  • fields of the same classes from {@link #fieldName} to [fieldName]

More on KDoc here.

No redundancy for data-like classes

(psst, yeah, I know data class  keyword but it’s not important here)

So, why not have this:

instead of the Java boring equivalent:

It’s beautiful difference for small classes. One downside here – it’s worse when class has more constructors than one (of course, when argument default value doesn’t do job).

Summary

There is no perfect language. Kotlin seems to be really interesting just by looking at these these features:

  • null safety
  • functional approach to data manipulation
  • introduces immutability (like in functional langs)
  • no semicolons (I mean it)
  • val  and var  keywords
  • neat lambdas (outer scope variables don’t have to be final  like in Java)
  • destructuring (functional languages again)
  • compiles to JavaScript (sort of)
  • (and it’s being developed to be able to compile into native code (Kotlin Native))

References

  • Teerapong Suksuwan

    Sorry, I honestly just took a glance on your article. But I have idea about static constant. You said, you have to create companion object to just declare constant. For me, If you normal have MyObject.someConstant declared. In Kotlin, instead of having MyObject.Companion.someConstant. You can have MyObjectConsts.someConstant. I believe you know how.

    • Are you referring to @JvmStatic or @JvmField? As far as I know, you can’t declare a static constant without an object.

      • Teerapong Suksuwan

        I’m not referring to neither @JvmStatic nor @JvmField (I don’t even know what they are). I agree with you that it’s impossible to have namespace bound constant in Kotlin without an object. But from my point of view I am OK with declaring object without declaring a class. For example, object MyObjectConsts { val someConstant = 112 }. By this code, I have a constant that I can access by calling MyObjectConsts.someConstant. I guess Kotlin might do declaration of class behind the scene which I cannot instantiate it manually but I don’t care. I’m OK with the syntactical benefit I got. Another way of having constant without class or object (syntactically) is just declaring global level constant like val MY_SOME_CONSTANT = "some value" in Kotlin source file in top level, outside of any class or object declaration. Then we can use MY_SOME_CONSTANT anywhere in the code base. The problem of this approach is that since it’s global scope so it has no namespace to help managing identifier names. I share my thought from my practical experience. I know that I spent not much time doing in-depth research. So please forgive me if I am wrong and thank you if you may correct me.

        • Thanks for your input! The perspective I was looking from was a Java language. If I have a constant declared in Kotlin then how do I access it from Java code? That was the (small) issue or rather a question about practicality. Also, please note that this is not a negative critique towards Kotlin.

          • Teerapong Suksuwan

            Understood, Namek. I found some irritation trying to call Kotlin from Java. It’s simple in some scenario but quite complicated in some other scenarios. I wish I don’t have to do it much. Cheers! :D.

  • Teerapong Suksuwan

    For class MoveByExecutor : TemporalOperation.TemporalExecutor
    It is obvious that TemporalExecutor is interface. If it is class, we have to call its constructor like class MoveByExecutor : TemporalOperation.TemporalExecutor()

    • Good point. If we use a default constructor!