Live data from Hacker News

From Java to Kotlin and Back Again

allegro.tech

21–30 of 199 posts

Re: From Java to Kotlin and Back Again

#21

I found the transition from Java to Kotlin painless because Android Studio (Intellij) holds your hand all the way. If at first you're unsure of the syntax, you can just write code in Java and convert to Kotlin. I agree that the null-safety Java interoperability does not work properly if the Java code is not annotated correctly (or you're parsing JSON) but I'd still prefer to have it than not. I like Kotlin because: *…

I'm unfamiliar with Kotlin in detail. Can you explain "Functions are first-class (you can pass functions to functions)"? Are they more powerful than Java's lambdas?

Yes, Java lambdas are just syntactic sugar over anonymous classes with a single method IIRC. You must define a full Interface to use when defining the function signature. Kotlin functions are essentially objects that can be passed around, stored in variables, etc. You can also have functions that don’t belong to any class, no need to use static methods for that.

Re: From Java to Kotlin and Back Again

#22
interesting function parameter name shadowing issue they highlight. had not run into that, but, wow, that adds some serious confusion.

i also heartily agree with the article's points about nullable types and Java library interop: it's pretty annoying to deal with Kotlin non-nullable types that have to interoperate with existing Java libraries that have nullable types in return values or function callback parameters. i have way more question marks in my Kotlin code than i originally thought i would.

i also appreciated the article's scrutiny of the name and type order reversal in Kotlin and the "::" syntax for getting the class literal (::class vs ::class.java). still trying to get used to that.

and as for the learning curve, i have to admit that it's been steeper than i expected when i first saw introductory presentations. Kotlin feels very abbreviated. the smart type inference and things like 'lateinit' have sometimes surprised me in their behavior. these aspects of Kotlin are indeed very smart, sometimes too smart for me. i feel like i have to think harder to understand a piece of Kotlin code, which is ok, but somehow, i wasn't expecting that based upon the initial presentations.

overall, Kotlin is ok i guess, but, to go off-topic for a sec, as an Android programmer i wondered why Google chose to emphasize adding a new language when many other aspects (e.g. documentation, the jumble of GPS, Firebase, GCM and 3rd party libs, mysterious adb failures, emulator problems, instant run, etc), of the ecosystem needed improvement/simplification/clarification more desperately.

Re: From Java to Kotlin and Back Again

#23

My 5 cents: It seems to me that the author did not spent enough time to learn Kotlin. The way he mixes Java types (Integer.parseInt) inside pure Kotlin code and then complains about lack of Null-Safety? It is enough to use an extension function String.toInt() to stick to Null-Safety and compiler will do the rest. His main() function? Another weird argument because Kotlin's documentation has some examples on how to wr…

Yup, I wrote a longer form of basically this. I wouldn't want the person posting to make the language decisions at my company.

Or have to work with that person, which is especially bad since one of the goals of this kind of posts is to advertise your company.

Re: From Java to Kotlin and Back Again

#24

Earlier quoted context omitted.

I'm unfamiliar with Kotlin in detail. Can you explain "Functions are first-class (you can pass functions to functions)"? Are they more powerful than Java's lambdas?

I think the big use-case is on Android where you're stuck with Java 7 and therefore can't use lambdas.

That used to be the case, but the build tools have supported lambdas for a while now, and it works even on very old devices.

On the other hand, Java 8 classes like java.util.Stream only exist on API 24+ devices. So if you want to support older classes, you can't use the standard stream library.

Re: From Java to Kotlin and Back Again

#25

My 5 cents: It seems to me that the author did not spent enough time to learn Kotlin. The way he mixes Java types (Integer.parseInt) inside pure Kotlin code and then complains about lack of Null-Safety? It is enough to use an extension function String.toInt() to stick to Null-Safety and compiler will do the rest. His main() function? Another weird argument because Kotlin's documentation has some examples on how to wr…

Disclaimer: not super familiar with Kotlin or Java.

Safely calling option.map and having the function assume it's not called with null is very useful. Is that a real drawback to Kotlin or is there something missing from this post?

Re: From Java to Kotlin and Back Again

#26

My 5 cents: It seems to me that the author did not spent enough time to learn Kotlin. The way he mixes Java types (Integer.parseInt) inside pure Kotlin code and then complains about lack of Null-Safety? It is enough to use an extension function String.toInt() to stick to Null-Safety and compiler will do the rest. His main() function? Another weird argument because Kotlin's documentation has some examples on how to wr…

Disclaimer: not super familiar with Kotlin or Java. Safely calling option.map and having the function assume it's not called with null is very useful. Is that a real drawback to Kotlin or is there something missing from this post?

Calling Optional.map(foo -> foo.bar) is effectively equivalent to foo?.bar in Kotlin. What GP was saying is that the author is using things like parseInt and other non-idiomatic things because the author is not familiar enough with the language. Even if it weren't about parseInt vs toInt, the author could have used "number?.let(Integer::parseInt)" instead of "number?.let { Integer.parseInt(it) }" (but of course "number?.toInt()" is the idiomatic way to convert a nullable string to a nullable int).

Re: From Java to Kotlin and Back Again

#27
TypeScript also has the weird reversed type declaration. I've never understood it; it's so much less natural to read. Having the type first allows you to easily mentally parse it as "A Foo named bob".

Re: From Java to Kotlin and Back Again

#28
Java version in the article:

    public int parseAndInc(String number) {
        return Optional.ofNullable(number)
                   .map(Integer::parseInt)
                   .map(it -> it + 1)
                   .orElse(0);
    }
And the Kotlin equivalent...

"No problem one might say, in Kotlin, for mapping you can use the let function:

    fun parseAndInc(number: String?): Int {
        return number.let { Integer.parseInt(it) }
                 .let { it -> it + 1 } ?: 0
    }
Can you? Yes, but it’s not that simple. The above code is wrong and throws NPE from parseInt()."

Yes - that's why Kotlin standard library provides, among many others, a convenient extension function String.toInt(), which is a wrapper around Integer.parseInt().

You're supposed to use that, and then you're safe from NPE, because the receiver has to be explicitly non-nullable (it's String.toInt(), not String?.toInt()).

Also there is no need to redundantly repeat "it" inside the lambda - plus you could further simplify the implementation by using type inference and converting it to expression body:

    fun parseAndInc(number: String?) = number
        ?.toInt()
        ?.let { it + 1 } 
        ?: 0
"Now, compare readability of the Java and Kotlin versions. Which one do you prefer?"

Well, I'll say orElse(0) is more readable than "?: 0" dangling at the end of the expression. However Java is more verbose. I'd say it's a matter of taste.

The difference is that thanks to Kotlin's features - which allow for creating custom DSL easily - implementing orElse is trivial, if you can't live without it:

    fun Int?.orElse(fallback: Int) = this ?: fallback
This allows for:

    fun parseAndInc(number: String?): Int = number
        ?.toInt()
        ?.let { it + 1 }
        .orElse(0)
And this, to me, is already nicer than your Java version.

Re: From Java to Kotlin and Back Again

#29
post #27

TypeScript also has the weird reversed type declaration. I've never understood it; it's so much less natural to read. Having the type first allows you to easily mentally parse it as "A Foo named bob".

See, that's interesting to me, because I have always read declarations aloud as "bob the Foo", even when they're written "Foo bob". Reasonable people can differ, of course. Where it's harder to differ is that is much easier to parse type-after declarations and to make a consistent syntax with them--that's why Rust et al have gone that route. To do type inference in Java (or C#) they've had to add a new keyword, `var` (and the comedic `final var` in Java), because their declaration structure just wasn't up to doing it any other way.

Re: From Java to Kotlin and Back Again

#30

Earlier quoted context omitted.

I think the big use-case is on Android where you're stuck with Java 7 and therefore can't use lambdas.

That used to be the case, but the build tools have supported lambdas for a while now, and it works even on very old devices. On the other hand, Java 8 classes like java.util.Stream only exist on API 24+ devices. So if you want to support older classes, you can't use the standard stream library.

Ah interesting. Thanks for the info.
Post reply on HN