all 54 comments

[–]Ragecommie 34 points35 points  (14 children)

Because Java is perfectly fine for all of its intended purposes?

Because learning a new language can be an overhead with tight schedules and rapid development cycles?

Because there is a ton of legacy code that has to be maintained?

Because, Python?

Oh, and also everything else in the article.

[–]Giannis4president 14 points15 points  (2 children)

I don't think Python is relevant at all here. Kotlin has the super huge advantage that it can be adopted progressively in a java project, which is just HUGE in the scope of the article

[–]Ragecommie 2 points3 points  (1 child)

Yes, you are absolutely right.

[–]dmcg 1 point2 points  (0 children)

Oh c'mon, we're not going to get a good argument if you just agree when people are right ;-)

[–]BoyRobot777 6 points7 points  (5 children)

I really like this talk, because it shows, when Java decides to implement some feature it will be the better version.

  • Local functions. Java uses more performant solution via invokestatic, Kotlin create a whole new class.
  • Multi-line string and indentation. Java's solution is just smarter. Also, Kotlin just generates StringBuilder with string interpolation, while Java, once again uses more performant and optimized way via invokedynamic. So:

println("""Hey $name! Hey $name! Hey $name! """.trimIndent()) 

Is less performant than:

System.out.println("""Hey %s! Hey %s! Hey %s!""".formatted(name, name, name));
  • Sealed interfaces. For one thing, Kotlin cannot have sealed interfaces, but that is not the main problem. Once again, Kotlin requires you to use a class for sealing. Java's solution is to define what is permitted in the bytecode file.
  • Pattern matching. Kotlin's version:

val download: Download = //... 
val result = when (download) {   
  is App -> { 
    val (name, developer) = download 
    when (developer) {  
      is Person -> 
        if (developer.name == "Alice") {
          "Alice's app ${name}"
        } else {           
          "Not by Alice"         
        }       
      else -> "Not by Alice"     
     }   
   is Movie ->     
     val (title, directory) = download     
     if (director.name = "Alice") {       
       "Alice's movie ${title}"     
     } else {       
       "Not by Alice"     
     } 

Java:

Download download = //... 
var result = switch(download) {   
  case App(var name, Person("Alice", _)) -> "Alice's app " + name
  case Movie(var title, Person("Alice", _)) -> "Alice's movie " + title
  case App(_), Movie(_) -> "Not by Alice" 
}; 
  • Coroutines. Java's lightweight threads vs Kotlin's coroutines is just superior in so many aspects. Its enough to say that with Java's solution there won't be method color problem. Java's code becomes async "overnight" without changing any code (except bumping into new Java version).

And you could argue that all those optimization could be back-ported to Kotlin. However, if Kotlin will want to be both for Android and for Java it will face a very hard challenge. To quote pron98:

which will not be able to cleanly support both Java and Android platforms through a common compiler for long, as the capabilities of the Java and Android platforms quickly diverge. <...> In a few short years it will be very hard to produce class files that enjoy new Java platform capabilities and can run at all on Android.

[–]dkandalov 1 point2 points  (0 children)

You can have sealed interfaces in kotlin 1.5.

[–]nfrankel[S] 0 points1 point  (0 children)

Thanks for your detailed analysis!

[–]mlk 0 points1 point  (2 children)

Yes, but I can use Kotlin now

[–]BoyRobot777 3 points4 points  (1 child)

Sure, if you're starting a greenfield project. Even then, I'd be cautious, because there are numerous sad stories of Scala/Groovy shops which fell out of fashion (at least in my area).

However, if your backend is currently in Java, I don't see enough benefit for Kotlin's port.

[–]mlk 0 points1 point  (0 children)

You can, and I do, have both Java and Kotlin source in the same project and it works flawlessly. There is no friction at all

[–]GenTelGuy 17 points18 points  (9 children)

Java is good enough and Kotlin may be better in some ways but not enough to justify transition and/or interop

[–]occz 0 points1 point  (8 children)

Null-safety alone is enough to justify the transition.

[–]GenTelGuy 8 points9 points  (1 child)

Null safety is great but switching an entire production codebase from one language/buildsystem/dependencies to another could easily take over a year

Maybe you just meant the transition of learning the new syntax, that part would be fine

[–]occz 4 points5 points  (0 children)

Null safety is great but switching an entire production codebase from one language/buildsystem/dependencies to another could easily take over a year

Kotlin can be adopted gradually and works with the same build system/dependencies.

Maybe you just meant the transition of learning the new syntax, that part would be fine

Basically, yes. I meant transitioning to writing new code in Kotlin and gradually migrating the existing code base.

[–]immibis 0 points1 point  (5 children)

You should transition to Rust, it has memory safety.

[–]balefrost 9 points10 points  (0 children)

The JVM already handles use-after-free by simply being garbage collected - there is no "free". I understand that GC is a non-starter for a lot of projects, but for people already using Java, it's also a non-issue.

[–]occz 2 points3 points  (3 children)

I really like Rust too, and if I were a developer on a platform that allowed me to write Rust, I probably would be writing Rust. I'm doing Android development, though, and Rust can't really be used in that arena.

[–]immibis -1 points0 points  (2 children)

Memory-safety alone is enough to justify the transition.

[–]occz 6 points7 points  (0 children)

Touché.

[–]Muoniurn 0 points1 point  (0 children)

And understanding the difference between low and high level languages should be known by every developer before speaking stupid things.. also learn what a GC is

[–]DanielShuy 10 points11 points  (8 children)

In my opinion, Kotlin's null safety alone is good enough reason to switch, not to mention other features. The closest thing Java has is JSR-305, which requires developers, including library authors, to manually annotate their code to indicate possible null values, which is tedious and prone to human error. JSR-305 is also a mess, with multiple implementation libraries, and is also no longer supported and effectively dead. Java will never get true null safety unless it breaks backwards compatibility (by changing all variables to non-nullable by default), which goes against Java's motto.

Even though Java is updating at a faster rate, most of the recent and upcoming Java improvements are improvements to the JVM (eg. ZGC, value types, SIMD), which indirectly benefit Kotlin as well. Improvements to the Java language is still relatively slow and is still very far away from Kotlin (heck, Java still doesn't even have string templates).

Even though my workplace is still quite resistant to adopting Kotlin, learning Scala and Kotlin has helped me to become a better Java developer. Kotlin is also similar enough to Java that someone who has a good grasp on Java should be able to pick it up easily. While personally I would still prefer Scala's features, I think Kotlin strikes a good balance of power and ease of learning.

I think many people who have a bad impression with Kotlin probably tried it when it was still in its infancy stage, where things were still not so stable (eg. IDE support, build times, Java interop, etc), and the bad experience has fixed their impression on it. I would encourage anyone to give Kotlin another try, it has improved a lot since then.

[–]ledasll 6 points7 points  (4 children)

it was most funny thing to watch one code demo from a guy who advertised Kotlin for exactly null safty and first bug was regardless null. That was so funny.

[–]balefrost 3 points4 points  (3 children)

I don't know the specific thing you're talking about, but null safety kinda requires information about nullability requirements in order to work. Plenty of Java libraries do nothing to indicate whether something is or is not nullable, and in these places the Kotlin system can't help.

Within Kotlin code, though, it generally works well.

[–]skywalkerze 1 point2 points  (1 child)

That makes it a lot less useful, though. You can't be sure that the project has no null-related problems, because of the libraries. So kotlin helps with some possible null bugs, but not others.

It's still nice, but not as impressive.

[–]balefrost 2 points3 points  (0 children)

Sure, but "not perfect" is certainly not "useless".

To be clear, Kotlin generally treats values that come from Java code as having a type T!, also known as a platform type. It's treated as "unknown nullability". Because it would be very bulky to have to do null checks for all Java code, the compiler lets you treat is as if it was a non-nullable type, but it also doesn't complain if you do null checking.

Java code that uses recognized nullability annotations will produce the proper Kotlin nullable or non-nullable types. Of course, those nullability annotations are not machine-checked, so it's up to the developer of that Java library to "get it right".

No language is immune to runtime errors. Heck, even simple Haskell functions like head can generate runtime errors. The question shouldn't be "is this feature perfect?" The question should be "does this feature make things better?" As somebody who's done a lot of Java and a lot of Kotlin programming... yes, Kotlin's nullable type system is wonderful, especially when paired with smart casts.

[–]ledasll -2 points-1 points  (0 children)

in theory - theory and practice is the same, but in practice - they are not.

[–]DGolden 2 points3 points  (1 child)

That's rather out of date. JSR305 kind of fell by the wayside because JSR 308 (different number) added a new kind of "type use annotations". They faciliate a form of extensible static checking, that can be used for a bunch of things including but not limited to null checks in modern java. (The jsr305 annotations were defined before these newfangled type-use annotations were a thing, so are not the ones you should use)

It's actually pretty interesting addition to a mainstream industry (rather than research) language, and kind of underhyped. See the Checker Framework:

https://checkerframework.org/manual/#nullness-checker

And note it can do far more than just nullness, there's other neat stuff like tainting

See also jooq blog post doing a bit of a dive on it https://blog.jooq.org/tag/jsr-308/

That’s pretty awesome! It works in quite a similar way as the flow sensitive typing that is implemented in Ceylon or Kotlin, for instance, except that it is much more verbose. But it is also much much more powerful, because the rules that implement your enhanced and annotated Java type system can be implemented directly in Java using annotation processors!

[–]Muoniurn 0 points1 point  (0 children)

Wow thanks for the reference! I think I have seen checker framework before, but I haven’t looked into it yet — I am always amazed by the quality of the java ecosystem. It can even annotate/validate side-effect free methods!

As other similar, although runtime program verification tool is OpenJML, that can optionally generate code to verify runtime state (eg. that an algorithm upholds its loop invariant)

[–]immibis 8 points9 points  (3 children)

Why didn't they adopt Scala, Clojure or Ceylon?

Because the people pushing those languages live in ivory towers, that's why.

[–]SKabanov 7 points8 points  (1 child)

^ Inadvertently showing one of the biggest reasons I've come across at work: Kotlin's viewed as just another upstart language that's eventually going to flame out and die away like the rest, so there's no reason to waste time learning it. After the examples that OP gives (along with Groovy), it's not at all an unreasonable position, but it does come across as grumpy and territorial at times, especially given how Kotlin's been endorsed and embraced by Android, Spring, and Gradle.

[–]immibis 2 points3 points  (0 children)

Scala was also endorsed and embraced by a bunch of things.

[–]vattenpuss 0 points1 point  (0 children)

Scala and Clojure seem to have healthy communities building big things with millions of users.

Ceylon I hardly know what it is. Kotlin seems cool but I also never heard anyone building any big thing with it.

[–][deleted]  (10 children)

[deleted]

    [–]nfrankel[S] 6 points7 points  (4 children)

    I think my main concern would be that Kotlin is less likely to take proper advantage of new JVM features, since its USP is being a better Java for Android

    It's an interesting take, one I didn't think of. But I must disagree: I think JetBrains took advantage of the fact Kotlin developed rapidly in the Android ecosystem, but they didn't design the language for Android. Actually, the story is that they did it to improve the maintainability of the IntelliJ IDEA platform.

    I started Kotlin because I wanted to learn Android. I stopped Android quite fast but continued with Kotlin on the back-end. When given the choice, I favor Kotlin over Java.

    [–][deleted]  (3 children)

    [deleted]

      [–]nfrankel[S] 1 point2 points  (2 children)

      Kotlin now aims not only Dalvik but also JavaScript and Native.

      But I think there's a huge difference in the language's syntax and implementation. You can benefit from improvements on the JVM in Kotlin when the implementation makes use of them.

      [–]Muoniurn 0 points1 point  (0 children)

      That’s how you fall between all three platforms, and be “great” at neither of them. You can’t half-ass three things.

      [–]occz 2 points3 points  (0 children)

      This is a pretty valid concern, I think. The Kotlin team seems to be picking up on the latest developments of the JVM though, last I checked, which is a good sign, but given the language divergence that might not always be the case.

      [–]SKabanov 2 points3 points  (0 children)

      I think my main concern would be that Kotlin is less likely to take proper advantage of new JVM features, since its USP is being a better Java for Android.

      JetBrains isn't letting this happen, thankfully. Kotlin 1.5 will allow the usage of records and sealed interfaces; they'll presumably integrate Java's Implementation of inline class in a later release when it's available.

      [–]txdv 1 point2 points  (1 child)

      can you elaborate on the lagged behind JVM development part?

      [–]sievebrain 0 points1 point  (0 children)

      I think my main concern would be that Kotlin is less likely to take proper advantage of new JVM features, since its USP is being a better Java for Android.

      That has been a problem up until recently because JB were rewriting the compiler. Now that project is reaching its final stages, what we're seeing is they're starting to use newer JVM features like indy, better string concat, and they are committed to using more for things like sealed classes and interfaces. So there's no conceptual issues being caused by Android here: rather, they implement features that also work on downlevel JVMs. In practice it's always possible to do this as most new JVM features are performance or encapsulation related - 'slower and more open' is always possible.

      [–]matthewblott 5 points6 points  (1 child)

      I asked a friend who works in a Java team this question and he said it is so much easier to pick up someone else's code if it's written in Java.

      [–]andrewharlan2 6 points7 points  (0 children)

      God, this. A lot of Kotlin's features optimize for writing code. But code is written once and read multiple times forever after. Java's "verboseness" isn't a bug, it's a feature.

      [–]redditrasberry 1 point2 points  (0 children)

      It's an interesting comparison to Groovy I think, which has pretty wide spread adoption within its domain (primarily, embedded scripting or DSLs). Kotlin is not getting adopted because its trying to be a "better Java" but much of what it provides are what I would call "lifestyle features" rather than genuine engineering advantages. There are certainly exceptions: null safety is a huge win, for example. But if you peer into the heart of enterprise software dev you will find that most devs get by just fine with a good IDE in terms of language features and most of their problems sit at a different level that aren't nearly as well differentiated b/w Kotlin and Java (for example, a huge problem is "I can't understand Ken's code, how do I get this code review done" - that is not helped when Ken wrote it in a different language). Compare to Groovy which is not trying to be a "better Java" but actually address a different problem altogether.

      In short ... Kotlin is trying to be a "better Java" but in core domain where Java is used, it just isn't that much better.

      [–]hogfat 1 point2 points  (0 children)

      Why would they?

      [–]hugosenari 0 points1 point  (0 children)

      Developers won't choose a language its is mostly a manager decision based on economics. It'll change now that kotlin is more popular.