[HN Gopher] A categorized list of all Java and JVM features sinc...
       ___________________________________________________________________
        
       A categorized list of all Java and JVM features since JDK 8 to 16
        
       Author : pjmlp
       Score  : 255 points
       Date   : 2021-04-01 16:04 UTC (6 hours ago)
        
 (HTM) web link (advancedweb.hu)
 (TXT) w3m dump (advancedweb.hu)
        
       | zodiakzz wrote:
       | Is it in the realm of possibilities that Java will someday have
       | runtime generics support (instead of type erasure)? It's the most
       | frustrating aspect of the language because you can't use basic
       | Java features like method overloading with them. Also, I don't
       | understand how people use the `Optional <ErasedType>`..? Is there
       | a way to use method overloading with it? `ErasedType` could be
       | _anything_ at runtime, doesn't sound fun. Besides all references
       | types are already nullable/(optional)... so what's the point?
        
         | laurent92 wrote:
         | I wish we just had non-nullable types...
        
           | kaba0 wrote:
           | With checker framework, you can basically have it (and much
           | much more, I believe no other language comes close to that
           | level of static analysis). It is annotation-based and not a
           | fancy keyword, but it is there.
        
             | nesarkvechnep wrote:
             | Haskell, OCaml?
        
               | kaba0 wrote:
               | Higher kinded types do make some features obsolete, but
               | checker has MapKey checker, Lock and Index checker, and
               | while locks may not be needed that often with everything
               | is immutable by default mode, concurrency is hard and
               | that alone is not always enough. While index errors are
               | not as frequent in Haskell, due to (Head:Tail), but if
               | you do use Array, you can't express indexing safely
               | without dependent types.
               | 
               | I'm not saying that it is better in every aspect than
               | haskell (not too familiar with ocaml), but java is an
               | easy and extremely popular language. And thus it has
               | really really great tooling, and with annotations it is
               | really extensible.
               | 
               | And if static analysis is not enough, there is also JML.
               | 
               | Also, checker taps more into intersection types, which is
               | not really expressible in Haskell, but I'm yet again not
               | knowledgeable enough on this latter, correct me if I'm
               | wrong.
        
         | mc13 wrote:
         | I believe refied generics are being worked as part of project
         | Valhalla. Here's a related JEP which I could find.
         | 
         | http://openjdk.java.net/jeps/218
        
           | gizmo385 wrote:
           | From that JEP: "It is not a goal of this effort to produce
           | fully reified generics."
        
         | mopierotti wrote:
         | > Also, I don't understand how people use the `Optional
         | <ErasedType>`..?
         | 
         | I may be misunderstanding your question, but in general you
         | wouldn't be doing anything type-specific with an Optional's
         | value unless you were in a part of your code that knows the
         | type at compile time. For example, a data structure might
         | return an Optional<T> from a get() method, but all it's doing
         | is returning the T or an empty.
         | 
         | > Besides all references types are already
         | nullable/(optional)... so what's the point?
         | 
         | 1. It's nice to explicitly say if a value might not exist than
         | to be unsure if a null object is meaningful.
         | 
         | 2. It can force consumers of an Optional to deal with the empty
         | case (versus forgetting to null check)
         | 
         | 3. Null might mean something like "this value was accidentally
         | never initialized" versus "I am explicitly indicating an empty
         | value"
         | 
         | 4. It can give better developer ergonomics with convenience
         | methods or monadic style (such as with Scala's Option type,
         | where you could .map() on an Option, or merge multiple Options
         | together)
        
         | The_rationalist wrote:
         | Kotlin supports reified generics (through extension methods)
         | 
         | Java is getting reified generics and more importantly generic
         | specialization which is critical for performance
         | https://www.reddit.com/r/java/comments/m2dfb5/parametric_jvm...
        
           | pcl wrote:
           | Kotlin's reified generics are pretty limited -- they only
           | work in inlinable situations, as there is no JVM support.
           | 
           | I assume that Kotlin will quickly add proper reified generics
           | support as soon as the JVM allows.
           | 
           | (Your link above is about reified generics in the JVM, not
           | just the Java language. Which is great news.)
        
         | kaba0 wrote:
         | When exactly would you benefit from overloading based on a
         | generic type? How come it is never brought up with Haskell for
         | example, or the other majority of languages that employ type
         | erasure?
        
           | eweise wrote:
           | Haskell has higher kinded types.
        
       | suyash wrote:
       | nice to see everything in one place with short example code.
       | Specially helpful for those still using Java 8 and looking to
       | upgrade, Java 17 will be a LTS so that will be a good opportunity
       | to upgrade.
        
       | bluejekyll wrote:
       | One of the primary features I'm holding out hope for eventually
       | making it into the language is ValueTypes:
       | http://cr.openjdk.java.net/~jrose/values/values-0.html and the
       | current Valhalla Project:
       | https://wiki.openjdk.java.net/display/valhalla/Main
       | 
       | The simplest example of why this would be valuable (edit: this
       | was not an intentional pun), the Optional type could become stack
       | based, such that you could ensure that the variable referring to
       | the Optional type is never null. This would help reduce a common
       | class of bugs in Java code stemming from NPE's.
        
         | nlitened wrote:
         | I am not sure I understand, why would you want Optional type to
         | never be null? Isn't it being null sometimes -- the whole
         | point?
        
           | chrisseaton wrote:
           | > Isn't it being null sometimes -- the whole point?
           | 
           | No you have it backwards - the whole point is that Optional
           | is _never_ null. You use empty instead.
        
           | wffurr wrote:
           | There's a big difference between the Optional _containing_
           | null (useful) and the Optional itself _being_ null (but why).
        
           | wtetzner wrote:
           | Say you have:                   public void
           | doSomething(Optional<String> foo) { ... }
           | 
           | You want `foo` to be `Optional.empty()` or `Optional.of("some
           | string")`. The way things currently work, `foo` could _also_
           | be `null`.
        
             | nitrogen wrote:
             | Kotlin's approach of making null act kind of like Optional
             | is pretty nice, but I wish there was a strict option for
             | interacting with Java types -- by default, all Java-native
             | types (type names ending with _!_ ) can be null and are not
             | null checked at compile time.
        
             | savanu wrote:
             | How does making Optionals allocated on the stack (value
             | types) prevent this?
             | 
             | Or rather why do you need value types to accomplish this?
        
               | bluejekyll wrote:
               | Perhaps this example will make it more obvious:
               | boolean truthy = false;         truthy = null; //
               | compilation failure, type mismatch
               | 
               | vs. the Boolean type                   Boolean truthy =
               | new Boolean(false);         truthy = null; // compiles
               | just fine
               | 
               | The reason Boolean (and other boxed primitive types)
               | exist is because it is an Object (a reference type) and
               | that allows them to be used in things like collections
               | that expect Objects and not primitive types.
               | 
               | Looking at https://openjdk.java.net/jeps/401 it's not
               | totally clear to me at the moment how you can use
               | ValueTypes (primitive keyword) in Collections. Might be
               | that you'll need to take a reference to them with
               | Type.ref (but I need to read 401 in more detail to
               | understand that).
               | 
               | Hope that helps.
        
               | pgwhalen wrote:
               | > Looking at https://openjdk.java.net/jeps/401 it's not
               | totally clear to me at the moment how you can use
               | ValueTypes (primitive keyword) in Collections.
               | 
               | JEP 401 won't cover it quite yet, note this from the "Non
               | Goals" section:
               | 
               | > An important followup effort, not covered by these
               | JEPs, will enhance the JVM to specialize generic classes
               | and bytecode for different primitive value type layouts.
               | 
               | It wasn't until recently that I understood for myself
               | just how large the surface area of the "value types"
               | problem is - it will be delivered incrementally. JEP 401
               | and 402 are the first steps (if I were to guess they will
               | show up as previews soon? maybe JDK 17 or 18?), but there
               | is more to come.
        
               | savanu wrote:
               | So you are really looking for compiler checks for null?
               | Kind of like kotlin?
               | 
               | var truthy = null; // Compile fails
               | 
               | var nullable? = null; // Compile passes
               | 
               | You don't need value types for this?
        
               | bluejekyll wrote:
               | That's not exactly the same thing... It can also (again I
               | don't know if this is part of the jep or not) be used to
               | perform stack based destructors (finalize) and then Java
               | could implement RAII. Reading the jep it discusses
               | perhaps rejecting finalize as function on primitive
               | objects, so this might not be in scope.
               | 
               | Additionally, the type is also lighter weight than an
               | Object and should be stack allocated, so there are memory
               | advantages to not having to use boxed types as well.
        
         | meddlepal wrote:
         | You don't really need to hold out hope for this... it is coming
         | and soon. It's been in active progress for years now (its a
         | huge undertaking).
        
           | bluejekyll wrote:
           | Is there an update somewhere that I've missed? I keep looking
           | for updates and haven't seen them.
           | 
           | (And yes, I know it's a huge effort, I was definitely not
           | trying to say that it should be an easy change to get into
           | the language)
        
             | craigacp wrote:
             | There are JEPs out for parts of it now - Primitive Objects
             | (which is the new name for value types)
             | https://openjdk.java.net/jeps/401 and Unify the basic
             | primitives with objects https://openjdk.java.net/jeps/402
        
               | Yeroc wrote:
               | I haven't read up on the details of these but this is a
               | huge step in the right direction if pulled off properly.
               | The dichotomy between primitive and non-primitive types
               | in Java is a real rough spot. I'd have to see how they
               | deal with null values though because the introduction of
               | auto-boxing certainly introduced a new area for
               | NullPointerExceptions to catch the unwary off-guard.
        
               | craigacp wrote:
               | There is extensive discussion of that topic in the
               | valhalla-dev and valhalla-spec-experts mailing lists, but
               | I think the details are still being worked out.
        
         | halfmatthalfcat wrote:
         | Or use Scala :)
        
           | chrisseaton wrote:
           | Does Scala have value types?
        
             | halfmatthalfcat wrote:
             | https://docs.scala-lang.org/sips/value-classes.html
        
               | chrisseaton wrote:
               | Ah right - that's not really what we're talking about
               | here, even though they have the same name.
        
               | halfmatthalfcat wrote:
               | "Codes like a class, works like an int!" - Taken from the
               | top of the page.
               | 
               | This is exactly what Value Classes are in Scala. You
               | supply an underlying value which is then interpreted as
               | the value itself, not a reference.
        
               | bcrosby95 wrote:
               | > must have exactly one parameter,
               | 
               | Huge limitation. Not anywhere near the same thing.
        
               | chrisseaton wrote:
               | What you're talking about is just wrapping a single
               | value. It's a type-system thing.
               | 
               | What we're talking about are wrapping compound values.
               | It's a VM implementation thing.
               | 
               | They're not really comparable.
        
           | kaba0 wrote:
           | Which doesn't have value types because it should be
           | implemented in the JVM?
        
             | halfmatthalfcat wrote:
             | It has Value Classes which are essentially the same thing.
             | They transpile down into the value itself but wrap the
             | value in extra functionality if you so choose.
        
               | kaba0 wrote:
               | They can only wrap a single primitive type - it's a nice
               | feature but nothing extraordinary. When Java implements
               | primitive types, Scala will probably use this same
               | construct. But the change have to come from the runtime
               | level.
        
         | layer8 wrote:
         | Even more useful will be a Mandatory<T> type. Maybe with "T!"
         | and implicit conversion to T as syntactic sugar.
         | 
         | Edit: Unfortunately it would have the drawback of
         | nonoverloadability due to type erasure.
        
       | ballmerspeak wrote:
       | As someone who began programming in undergrad, Java was the
       | university's language of choice for the "introduction to
       | programming" course. My first internship was in Java SE 6 and
       | part of the big debate for that summer was when to move to 7.
       | 
       | I haven't used it since but I'm glad to see it's gotten the more
       | modern language features that make writing and reading code much
       | easier. Without this list, I probably would never have learned
       | this so thanks
        
       | foolinaround wrote:
       | very beautifully put together.
       | 
       | In fact, they should start with Java 5!
       | 
       | Even in 2021, I see code bases (and devs) who dont know/use
       | generics!
        
         | icedchai wrote:
         | You'd think they'd get tired of all those casts everywhere.
        
           | jerven wrote:
           | Well that is why they write GO right ;)
        
       | dehrmann wrote:
       | I'm torn over this because a lot of the features are quality of
       | life improvements, but is it too fast?
        
         | jmartrican wrote:
         | Not fast enough
        
         | jacques_chester wrote:
         | > _but is it too fast?_
         | 
         | It is not.
        
         | tasogare wrote:
         | A lot of things are coming straight from C#, so it's battle-
         | tested there before inclusion I guess.
        
           | cbm-vic-20 wrote:
           | I read an article that said that this is intentional- they
           | wait until other languages shake out features, and take it
           | slow so they get it right.
        
           | perrylaj wrote:
           | As someone unfamiliar with C# but interested in how languages
           | impact each-other, could you provide some examples? I know C#
           | was heavily inspired (perhaps not a strong enough word) by
           | Java, but not as familiar with the opposite.
           | 
           | Java does seem to absorb from tried and tested ideas. There
           | are a few major features I can think of that have largely
           | come from or been inspired by popular and mature 3rd party
           | libraries (time, reactive streams and various collection apis
           | come to mind).
        
             | jerven wrote:
             | C# and Java are kind of in the same space, they tend to
             | pick up the same kind of features. But not always in the
             | same way e.g. Records are different between the two
             | languages. As is the path to Async.
             | 
             | Java benefits from more experimentation in the JVM and
             | bigger variety in implementers.
             | 
             | I need to find the funny slide deck by Brian Goetz (java
             | language architect at Oracle) where in slide one (what
             | industry thinks he does) he shows his job is to copy from
             | C# and in slide two he shows what academia thinks he does,
             | copy from scala ;)
             | 
             | It is not this presentation,
             | https://www.infoq.com/presentations/java-futures-2019/ but
             | it is close in content.
        
             | tasogare wrote:
             | In the list provided in the article: record syntax, switch
             | expressions and var.
             | 
             | And by the way for the downvoters: there wasn't any snark,
             | C# itself being at first a copy-pasta from Java, and now
             | taking heavy inspiration from F#. That kind of features
             | transfer in-between languages is a good thing.
        
             | kaba0 wrote:
             | Java employs the "last mover advantage" strategy. They wait
             | a bit for other mainstream-ish languages to be a testbed
             | for a new feature, and if it proves worthwhile, they try to
             | incorporate it into the language. But a new feature is a
             | huge responsibility, since it will have to be maintained
             | "forever".
             | 
             | C# on the other hand is quite brave and quick to implement
             | everything under the Sun, sort of similarly to c++ - which
             | sooner or later will create a really bloated language (imo,
             | both are already quite complicated). And in backward
             | compatibility, Java definitely wins the cake.
        
         | rakoo wrote:
         | Java 8 was in 2014. Go was barely 2 years old. Many of the
         | features presented here were considered common in other
         | languages at the time, so if anything Java is late to the
         | party.
        
       | offbynull wrote:
       | They broke backwards compatibility when they moved from 8 to 9.
       | If this is all we got out of it after all this time, IMO it
       | wasn't worth the change.
        
         | Pet_Ant wrote:
         | What backward compatibility did they break except for internal
         | com.sun packages that weren't part of the JDK to begin with but
         | only Sun's implementation?
        
         | kaba0 wrote:
         | They broke some dependencies that depended on JVM internals,
         | that was never promised to not change (how could they implement
         | anything otherwise?). They implemented a strong encapsulation
         | by default so that in the future, such a step won't be
         | necessary ever.
        
       | crudbug wrote:
       | Waiting for project loom [1]
       | 
       | [1] https://openjdk.java.net/projects/loom/
        
         | cpleppert wrote:
         | Worth keeping in mind that the implementation they have chosen
         | of stack copying from the heap has a larger performance
         | overhead than something like Go which was designed around green
         | threads/fibers/virtual threads/ etc. from the start.
         | 
         | If you can keep your stack size very low in each task then this
         | probably won't be noticeable if you are doing lots of IO which
         | can trigger wakeups. More of a replacement for an async/await
         | state machine for handling a request than something like a
         | goroutine you could use for everything.
         | 
         | I have a feeling lots of existing Java libraries and frameworks
         | won't work well with it. Will be interesting to see how it
         | plays out.
        
           | kaba0 wrote:
           | The technical details are way out of my league, but I
           | remember reading that stack copying can be made really cheap
           | somehow? Perhaps due to the JVM having more abstraction below
           | a virtual thread than Go?
        
             | aardvark179 wrote:
             | Many virtual threads won't have large stacks, and many
             | others will not substantially grow or shrink their stacks
             | between yields. You only need to copy stack frames from the
             | heap as they are needed (so as the stack unwinds) and you
             | only need to copy new stack frames to the heap when a
             | thread yields. With a few other clever tricks this can
             | really reduce the data that has to be copied.
             | 
             | We can do these tricks because we know lots of properties
             | of the Java stack, and they give a different set of trade
             | offs to Go's approach.
        
         | iso1631 wrote:
         | To me, Loom will always be the latest masterpiece of fantasy
         | storytelling from Lucasfilm's(tm) Brian Moriarty(tm)
        
         | jacques_chester wrote:
         | I am unreasonably excited by Loom, for two reasons:
         | 
         | 1. I cannot wrap my head around library-based reactive systems.
         | I have tried and tried and continue to try. But they're like
         | some of the original Go4 design patterns: they exist to solve
         | the _language_ , not the _problem_. Loom 's promise to make
         | steam-powered linear code behave _mostly_ like a fully-dressed
         | reactive library system is extremely welcome.
         | 
         | 2. Structured concurrency. Among the entries on the thick
         | tablet of hatreds of Golang that I carry upon my heart, mystery
         | action at a distance due to go(to) routines appears
         | infrequently but painfully. Like so many Go features they
         | conspire against composability and testability. Structured
         | concurrency looks like an escape from the madness. Please let
         | it be true.
        
           | gher-shyu3i wrote:
           | What do you mean by structured concurrency? Do you mean
           | hierarchy management?
        
           | The_rationalist wrote:
           | What you're waiting for is already available with Kotlin
           | coroutines (which has a very clean API btw) And no reactive
           | streams still are useful for processing collection streams
           | asynchronously and here again kotlin solve it all
           | https://kotlinlang.org/docs/flow.html
        
             | jacques_chester wrote:
             | I like Kotlin coroutines and I've used them, but they (this
             | argument is controversial) have a function colouring
             | problem. As the JVM adds virtual threads I expect that a
             | rebasing of Kotlin's coroutines will remove that objection.
             | 
             | Plus, sometimes, I want to use Java.
        
               | ta988 wrote:
               | Also debugging with them can be quite painful. It is
               | getting better, but I still pull my hair frequently.
        
           | KptMarchewa wrote:
           | What's the difference in programming model (not
           | implementation) between Loom and goroutines?
        
             | jacques_chester wrote:
             | Briefly, that a thread cannot escape a scope. All threads
             | must be joined before leaving the scope.
             | 
             | Some resources:
             | 
             | https://wiki.openjdk.java.net/display/loom/Structured+Concu
             | r...
             | 
             | https://cr.openjdk.java.net/~rpressler/loom/loom/sol1_part2
             | ....
             | 
             | https://vorpus.org/blog/notes-on-structured-concurrency-
             | or-g...
        
           | crudbug wrote:
           | Agreed !
           | 
           | Current reactive code is littered with async/await for every
           | IO function, which feels like they are trying to bolt
           | reactive behavior. Library-based threading model provide the
           | sync thinking with optimized async compute model.
        
       | seniorsassycat wrote:
       | What is the point of String's transform?
        
       | wiradikusuma wrote:
       | After a long stint with Scala, I recently came back to Java
       | because I'm setting up a team for a greenfield project. Java has
       | a good balance for ease of use, type safety, massive+mature
       | ecosystem, and talent pool.
       | 
       | The new language features (post v5) and framework maturity help
       | reduce the "bloated" feeling that made me switch to Scala. Still
       | not happy with the semicolon.
        
         | pcl wrote:
         | You might consider Kotlin then. It's more JVM-aligned than
         | Scala, but waaaay terser than Java (as yet -- the Java team is
         | making great strides).
        
           | halfmatthalfcat wrote:
           | What do you mean by "JVM-aligned" and how is Kotlin more JVM-
           | aligned than Scala? Speaking as someone who uses Scala on a
           | daily basis and never touched Kotlin.
        
             | dbsmith83 wrote:
             | Kotlin types and Java types are much more compatible than
             | Scala types. No need to use converters. Also, Scala leans
             | very FP, while Kotlin and Java don't, so they are also more
             | similar in that regard, though I don't know if that's what
             | "JVM-aligned" means here. Overall, Kotlin and Java just
             | have better interoperability than Scala and Java
        
               | pcl wrote:
               | Yeah, that's exactly what I meant.
               | 
               | The JVM is designed to execute the constructs of the Java
               | language. Scala compiles to JVM bytecodes, but it does a
               | lot of (very cool!) things that are not natively
               | supported by the JVM, and thus tend to be pretty
               | expensive. Scala's pattern matching, for example, goes
               | beyond what can be efficiently expressed in the JVM.
               | 
               | As a rule, Kotlin does not take this approach. Instead,
               | almost all the constructs in Kotlin can be cleanly
               | expressed in JVM bytecodes.
               | 
               | Reified generics is a good example. Kotlin only allows
               | them when a function can be inlined, since in those
               | situations, you don't actually _need_ generic arguments,
               | since the code in the inlinable function can be dropped
               | in place. This allows for the convenience of reified
               | generics -- but only if you 're willing to live within
               | the limitations of the inline restriction. (And it's also
               | elegant, since it'll be easy to relax the constraint once
               | the JVM adds the needed support.)
               | 
               | I've run across one or two things in Kotlin that _don 't_
               | translate to JVM bytecode elegantly, although I'm
               | struggling to find a good example off the cuff. They're
               | definitely the exception, though, whereas the Scala team
               | took a more radical approach.
        
               | The_rationalist wrote:
               | It's not clear that bytecode changes are needed for
               | efficient pattern matching support. Java is getting
               | pattern matching support. The related JEPs mention that:
               | The implementation will likely make use of dynamic
               | constants https://openjdk.java.net/jeps/309 I strongly
               | suspect that Scala could be more efficient if it used it
               | too. However I have no idea if this could improve compile
               | time. (kotlin has until now procrastinated implementing
               | pattern matching support because they say it increase
               | compile time, but maybe that doesn't hold with constant
               | dynamics)
        
       | pimlottc wrote:
       | I've always admired Java for managing to slowly but surely move
       | the language forward while maintaining backwards compatibility
       | and keeping the community together. When you look at how many
       | other languages have faltered and lost momentum due to transition
       | issues (Perl 6, Python 2/3), it really shows have difficult of a
       | task it is.
       | 
       | Progress can seem glacially slow at times - it's always
       | disappointing to see your favorite upcoming feature get pushed to
       | a later release - but the current language is undeniably light
       | years better than what we started with.
       | 
       | Respect.
        
         | harshalizee wrote:
         | I would add C# to the list of languages with good backward
         | compatibility and progression with every new version. Very
         | similar to Java, and has a lot more feature set with somewhat
         | decent documentation.
        
           | Yhippa wrote:
           | One thing I've always admired about C# is that it's an ISO
           | standard. Which I'm not sure if that really means much these
           | days in terms of computer programming languages. It seems
           | like it would be an amazing hedge against a private
           | organization co-opting it in the future.
        
             | int_19h wrote:
             | The catch is that C# standardization lags behind language
             | evolution. At the moment, the most recent edition is
             | ECMA-334:2017 aka ISO/IEC 23270:2018. It corresponds to C#
             | version 5.0, originally released back in 2012 - it was the
             | one that introduced async/await, and it's still missing
             | stuff like null chaining.
             | 
             | (for the curious, here's the complete list of C# language
             | versions: https://docs.microsoft.com/en-
             | us/dotnet/csharp/whats-new/csh...)
        
         | carimura wrote:
         | A big benefit of the 6-month release cadence (since Java 10) is
         | that if your favorite feature gets pushed, the next release is
         | just around the corner.
        
       | tyingq wrote:
       | _" Helpful NullPointerExceptions describing precisely which
       | variable was null JDK 15"_
       | 
       | I wonder what number of collective hours would have been saved
       | with this one, had it come earlier.
        
         | pvorb wrote:
         | Oh yes. Did you ever have a statement where you chain more than
         | two method calls and don't know which returns null? I tend to
         | split calls like this on separate lines just to be able to tell
         | which call returns null from the line number in the stack
         | trace.                   obj.call1().call2().call3();
         | 
         | becomes                   obj.call1()             .call2()
         | .call3();
         | 
         | And if I now get an NPE at line three, I know that call2()
         | returned null.
        
       | dlbucci wrote:
       | All the backend projects I work on were originally written in
       | Java. I'll admit that Streams and Lombok make it a somewhat
       | pleasant experience to work with, at least compared to when I
       | used it in college (I think Java 8 was newest?).
       | 
       | But that said, I once tried writing a new feature in Kotlin, and
       | now all our code is Kotlin. I don't really see how Java can
       | compete with the non-nullable types, data classes, and type-
       | inferencing Kotlin gives you, with easy interoperability, to
       | boot! (Although you might start regretting your use of Lombok at
       | that point...)
        
         | still_grokking wrote:
         | Same goes for Scala, where those Kotlin features come form
         | originally.
        
           | pron wrote:
           | Those features (except for nullability types) predate Java,
           | let alone Scala and Kotlin, by a couple of decades. Those
           | three -- like all programming languages -- get inspiration
           | from similar sources. Java is just the most conservative of
           | the three with regards to language features.
        
             | ragnese wrote:
             | I think it's disingenuous to deflect by saying that Scala
             | didn't invent those concepts.
             | 
             | I think it's pretty clearly significant that Scala and
             | Kotlin are JVM languages, specifically.
             | 
             | If we just said "Well, StandardML had XYZ feature 30 years
             | ago," you could reasonably wonder whether implementing
             | those features on the JVM was a legitimate hurdle to not
             | including them.
             | 
             | But the fact that the guy who wrote generics for Java then
             | went and created Scala with these features is telling.
             | 
             | I also don't think that "Java is conservative" is the
             | correct description of what's going on here. Look at the OP
             | (I know you're a Java guy, so I don't mean that literally)-
             | Java used to get maybe one language change for each major
             | version until 16 where it got a bunch.
             | 
             | Why? I don't know. But I think it's totally fair to observe
             | two correlations in recent history:
             | 
             | 1. Oracle obtained control of Java
             | 
             | 2. Many other, very good, programming languages have been
             | coming on the scene: Swift, Go, Rust, Kotlin, TypeScript,
             | C#, F#. Even older programming languages have seen major
             | advances in the last 5-10 years: C++ and PHP among them. I
             | think it's pretty clear that Java just didn't feel the
             | pressure to make itself better until recently.
        
               | pron wrote:
               | You're right about your main points: for some years
               | before Sun's demise Java was neglected and lacked
               | resources, and Oracle has gradually but significantly
               | increased its investment in the platform. It is also true
               | that the abnormality of ~2000-2005, when there were few
               | popular languages, has ended. But the following two facts
               | are also true: Scala didn't invent those features, and
               | neither Kotlin nor Scala are big enough to be serious
               | competitors for Java. So Java might be feeling the heat
               | of competition, but not from those two, and, like all
               | other languages, it looks around and borrows features,
               | but not from those two more than others.
               | 
               | It is possible that Java platform languages might
               | indicate the palatability of certain features to Java
               | programmers more than non-Java platform languages, and
               | the Java language designers do have a closer relationship
               | with the designers of other Java platform languages. But
               | overall, these effects are not particularly big. Knowing
               | the current designers of the language, I can say with
               | certainty that Haskell has served as a bigger inspiration
               | than either Kotlin or Scala on recent features and their
               | design ( _inspiration_ , not direct source).
        
         | brabel wrote:
         | I write a lot of Kotlin code but still tend to use Java a lot.
         | All of the features you mention are not really an advantage for
         | Kotlin anymore.
         | 
         | Java has had tools to deal with nulls for a long time, we tend
         | to assume everything is non-null unless annotated with
         | `@Nullable` and let tools check correct usage at compile
         | time... data classes are very similar to Java 16's records.
         | Type-inference since Java introduced `var` is pretty much on-
         | par with Kotlin.
         | 
         | Some people have already started talking seriously about Kotlin
         | now just adding friction, as you need to keep updating its
         | version and the Gradle plugin (which is not compatible with
         | some versions of Gradle if you're stuck with some old Gradle
         | plugins). Java 17 should probably stabilize sealed classes,
         | which is one of the biggest advantages of Kotlin at the
         | moment... to be honest, even though I've always been a
         | proponent of Kotlin, I am not nearly as enthusiastic now as I
         | used to be about it.
        
           | ragnese wrote:
           | If I remember correctly, it's fairly easy to use @Nullable
           | and still end up with nulls there, even without an IDE
           | warning. I'll have to double check to see if I can still
           | reproduce that.
           | 
           | But, to be fair, it's actually fairly easy to break Kotlin's
           | null safety, too: https://blog.haroldadmin.com/circular-refs-
           | kotlin/
           | 
           | But I basically agree with what you've said. Kotlin is
           | certainly still a much more ergonomic language, but Java
           | caught up fast recently.
           | 
           | Kotlin 1.5 will be really cool, though, with the new value
           | classes and the mutable methods feature (stolen from Swift).
        
             | BoyRobot777 wrote:
             | Value classes cannot provide the performance/memory
             | flatness that Valhalla will bring though. So I'm not really
             | sure what benefit does "values classes" bring. Just to make
             | sure, you are talking about the inline class which is just
             | a wrapper around single property?                  inline
             | class Password(val value: String)
        
               | ragnese wrote:
               | Yes and no:
               | https://github.com/Kotlin/KEEP/blob/master/notes/value-
               | class...
               | 
               | "value class" is the next step for inline classes. They
               | are going to behave very much like Swift's struct and its
               | "mutating methods". And they are going to be "Valhalla
               | ready" so we'll get the performance improvements
               | automatically when it lands.
               | 
               | In a sense, they are an upgraded data class with a much
               | more precise and controlled form of mutation. Rather than
               | a `var` field meaning the object will mutate in-place, it
               | will basically automatically call a kind of (implicit)
               | "copy()" method. Further, you may _only_ mutate these
               | `var` fields inside of class methods that are marked with
               | a new keyword: `mutating`.
               | 
               | Read through the KEEP. It's pretty interesting stuff. At
               | first it kind of rubbed me the wrong way, but the more I
               | thought about it, the more excited I got about it-
               | especially after thinking about how Swift does it and it
               | works well there.
        
           | aphexairlines wrote:
           | You can only assume non-null for your own code though. The
           | java ecosystem of 3rd-party libraries will give you nulls,
           | and most of the time won't include nullability annotations.
           | 
           | var is a nice step, but encourages mutability since it's not
           | final by default.
        
           | EvilEy3 wrote:
           | > Java has had tools to deal with nulls for a long time, we
           | tend to assume everything is non-null unless annotated with
           | `@Nullable` and let tools check correct usage at compile
           | time...
           | 
           | Oh yeah, nothing like creating Frankenstein's monster instead
           | of using a tool that was designed for the purpose. And no,
           | it's not the same. You'll never beat Kotlin compiler , no
           | matter how many annotation you use - you will always miss
           | something.
           | 
           | > data classes are very similar to Java 16's records.
           | 
           | You mean Java 16's records are similar to data classes, since
           | those were first.
           | 
           | > Type-inference since Java introduced `var` is pretty much
           | on-par with Kotlin.
           | 
           | Not even close. Can't use it outside of functions, clunky
           | final var instead of val.
           | 
           | > Some people have already started talking seriously about
           | Kotlin now just adding friction, as you need to keep updating
           | its version and the Gradle plugin (which is not compatible
           | with some versions of Gradle if you're stuck with some old
           | Gradle plugins).
           | 
           | My favorite kind of people. 'Some'.
           | 
           | > Java 17 should probably stabilize sealed classes, which is
           | one of the biggest advantages of Kotlin at the moment...
           | 
           | Nice!
           | 
           | Let's wait until you'll upgrade to Java 17 while Kotlin has
           | everything already and much more with compilation to JS and
           | native in the future.
        
       | meddlepal wrote:
       | Java gets a bad rap from people that used it late 90's through
       | early 2000's and got burned out by XML and design pattern heavy
       | frameworks but its a lovely language that with a little
       | discipline can be used to create very lean looking code.
       | 
       | Go is one of the HN darling languages and I work in Go everyday
       | for work (and generally like it), but I really wish I could reach
       | for Java most days.
        
         | laurent92 wrote:
         | "Java is a big DSL to transform XML into stacktraces" -- so was
         | the joke at the time when domain-specific languages were the
         | hype.
         | 
         | This, and the FizzBuzz, Enterprise Edition:
         | https://github.com/EnterpriseQualityCoding/FizzBuzzEnterpris...
         | 
         | More seriously, what are you missing in Go that is well-done in
         | Java? I assume verbosity of the code is still the defining
         | characteristic of Java?
        
           | pgwhalen wrote:
           | Not OP, but...
           | 
           | > More seriously, what are you missing in Go that is well-
           | done in Java?
           | 
           | As cliche as it is to say, Go missing generics (for the time
           | being) does hold it back in many ways relative to Java. I
           | like and use both languages regularly, and as I thought about
           | my answer to this question I realized that essentially all of
           | my complaints stem from the lack of generics - things like
           | streams, a rich collection framework, and non-channel
           | concurrency features (java.util.concurrent among them) don't
           | exist in go because you can build them as generically as
           | needed for them to be useful.
           | 
           | You might have said "well-done" as a way of excluding
           | generics in Java since many people like to suggest they're
           | not well done; of course most developers would like more, but
           | they already enable an enormous amount of stuff not possible
           | in Go.
        
           | srparish wrote:
           | Verbosity of code is more of a go thing these days:
           | hasThing := false       for _, v := range stuff {         if
           | checkForThing(v) {           hasThing = true           break
           | }       }       if !hasThing {         return false       }
           | 
           | Java:                 if !stuff.stream().anyMatch(v ->
           | checkForThing(v)) {         return false;       }
           | 
           | In the 2020s, loops are the new "goto", too much boiler-plate
           | and ways to subtly be incorrect, much safer to use higher-
           | level collection methods.
        
           | matsemann wrote:
           | The java ecosystem is very nice. Not necessarily the language
           | itself, but everything else. The jvm, the tools, the
           | libraries are all very mature and good.
           | 
           | Skipping java and instead using Kotlin allows one to reuse
           | all that knowledge in a great language as well.
        
             | bcrosby95 wrote:
             | I guess it depends upon what you mean by ecosystem.
             | 
             | Java the language is ok. The culture (which is part of the
             | ecosystem) and how you're pushed to write code is the
             | biggest problem with Java. The wide array of tooling,
             | frameworks, and libraries within the ecosystem is nice.
             | 
             | But the way you have to use them tends to be shit due to
             | the culture surrounding the language. At least it seems to
             | be shifting to something more sane.
        
               | avmich wrote:
               | Good language ought to discourage (enough) the bad
               | practices. Culture forms slowly, and it's Java fault that
               | the culture managed to produce such excessities as
               | proverbial FactoryFactoryFactory.
               | 
               | Edit: I still think Java is a good language, especially
               | later versions, and both original goals and recent
               | advances are quite noble.
        
               | meddlepal wrote:
               | I somewhat agree, but Java grew up in a different era
               | when communication about these things wasn't as easy.
               | It's hard to change the direction of something as large
               | and widely deployed as Java. It's happening but it will
               | take time and its always going to dealing with its legacy
               | as there just so much of it out there.
        
               | geodel wrote:
               | Huh, one needs to see first party Java libraries from
               | earlier times. It is pretty clear engineers at Sun also
               | believed that AbstractFactoryFactory everything will be
               | the way world need to be rebuilt.
               | 
               | Of course one can show empathy and understand
               | justifications for things they like and simply laugh out
               | "LOL Go No Generics' when they don't.
        
           | tonyarkles wrote:
           | Now we've got Spring, which in my, admittedly limited,
           | experience does a great job of transforming what could have
           | been compile-time errors into run-time errors.
        
             | The_rationalist wrote:
             | Just use micronaut if compile time errors is what you want.
             | It can even validate generated queries.
        
             | jacques_chester wrote:
             | The wheel of karma is ever-turning, though [0],[1].
             | 
             | Disclosure: I work for VMware, which sponsors Spring
             | development.
             | 
             | [0] https://spring.io/blog/2021/03/11/announcing-spring-
             | native-b...
             | 
             | [1] https://github.com/spring-projects-experimental/spring-
             | fu
        
               | The_rationalist wrote:
               | Those are nice advances but I hope that spring will one
               | day support compile time validation of generated queries
               | and of beans like Micronaut do.
        
               | jacques_chester wrote:
               | I'm confident it'll reach that point.
        
               | noisem4ker wrote:
               | ...and probably well before Micronaut gets rid of its
               | bugs, comes close to feature parity and generally matures
               | as a framework.
        
               | victor106 wrote:
               | Spring native is a game changer for so many organizations
               | using containers for startup times. There are other
               | spring related issues you still have to deal with
        
             | avmich wrote:
             | Well said :) . Spring looks so much as to show how useful
             | ideas can be misapplied with catastrophic results. For
             | example, liberate encouraging of dependency injections
             | leads to multitude of interfaces which are only ever
             | implemented once by a production code class, and maybe one
             | more time by a test class, even though Java has all methods
             | virtual and testing could be done without requiring the
             | interface.
        
               | mamon wrote:
               | >> Java has all methods virtual and testing could be done
               | without requiring the interface.
               | 
               | Not sure what you mean by that. I thought that
               | interface/implementation divide is the way to implement
               | virtual calls. Unless you want testing frameworks to do
               | bytecode instrumentation.
        
               | nitrogen wrote:
               | Modern testing frameworks can indeed mock concrete
               | classes, which beats the bytecode generation that Spring
               | would be doing anyway.
        
               | avmich wrote:
               | If your interface is going to be implemented by just one
               | class, I'd offer to skip interface - it reduces amount of
               | code. If you still need to pass, as a parameter, a class
               | A in order to test a class B, you can instead pass class
               | C inherited from A, with all necessary methods
               | overloaded.
               | 
               | If you just create a class A in java, no interfaces
               | involved, class A will have its methods virtual. I'm not
               | sure what do you mean by interface/implementation divide.
        
               | oftenwrong wrote:
               | It's reasonable to provide a single implementation of an
               | interface, if the goal is to facilitate dependency
               | injection for that component. The problem I find with
               | Spring is that it is designed for dependency injection at
               | all levels of its architecture, leading it to be one of
               | the ultimate examples of Ravioli Code.
               | 
               | https://wiki.c2.com/?RavioliCode
               | 
               | DI is a powerful concept, but Spring projects rely on DI
               | in such a generic way that it often doesn't even make
               | sense for your application. You have to gain intimate
               | knowledge of the abstractions, and inject a bunch of code
               | in a bunch of places just to make it do the very-
               | straightforward thing you were trying to do.
        
             | blntechie wrote:
             | Running 'mvn install' on even a simple Spring project with
             | default dependencies is scary to watch on the console. So
             | many things happen and it's not even the verbose mode.
             | 
             | Running 'dotnet build' is much more saner and one can
             | reasonably understand what happens.
        
               | frant-hartm wrote:
               | Try `npm install` then..
        
             | geodel wrote:
             | Yep. Give it a one line error description and it turn into
             | stack trace longer than "War and Peace".
        
           | meddlepal wrote:
           | > More seriously, what are you missing in Go that is well-
           | done in Java?
           | 
           | 1. Generics. And yea, I know Go is getting generics "Real
           | Soon Now" (tm), but it is incredibly annoying to write the
           | same collection code over and over and there's some third-
           | party libs that would really benefit from generics (looking
           | at you Azure Go SDK).
           | 
           | 2. Error handling... with the big caveat that I actually like
           | Go's error handling mechanism at small scale but wish there
           | was a good way to chain several operations together and
           | return an error to the top if any failed... I find myself
           | writing a lot of `err != nil` checks in sequence and I've
           | found baking my own abstractions around this to be leaky or
           | difficult to grow as the program requirements change.
           | 
           | 3. Diverse collections API.
           | 
           | 4. Iterators.
           | 
           | 5. Not Java-the-language but the JVM has amazing monitoring
           | tools.
           | 
           | > I assume verbosity of the code is still the defining
           | characteristic of Java?
           | 
           | Pound for pound... I think Go and Java have about the same
           | verbosity. I'm honestly never quite sure what people mean by
           | "verbosity" in Java. Generally I interpret this as
           | "frameworks" but I predicated my OP on the idea that legacy
           | framework bloat is where most of people's frustration with
           | Java lies... not the language itself.
        
             | ragnese wrote:
             | I agree with your points here, but just want to add that,
             | while Java's generics are better than the non-existent
             | generics in Go, I still find Java's type system to be
             | really subpar for today's era.
             | 
             | The type system is not strong or expressive enough to do
             | full type erasure, but then we're stuck with type-erased
             | generics, so it's just incredibly frustrating.
        
             | avmich wrote:
             | > I'm honestly never quite sure what people mean by
             | "verbosity" in Java.
             | 
             | Java improved with "var" keyword (use with caution!) and
             | introduction of records. These are not the only code-
             | shortening features (there are e.g. interface methods,
             | diamond operator, lambdas, convenience "of(...)" methods,
             | even "fluid style"), but they, used well, can really reduce
             | verbosity.
        
               | Scarbutt wrote:
               | I'm surprised you didn't mention the Streams API.
        
               | bobthepanda wrote:
               | Also, a lot of verbosity in Java came from people going
               | off the rails with design patterns to hide crap multiple
               | levels deep in a file with 5+ words in the class name.
               | 
               | If you have a hammer everything's a nail.
        
               | nitrogen wrote:
               | Frameworks like Spring/Spring Boot kind of force that as
               | well with their runtime creation of proxy classes.
        
             | twh270 wrote:
             | Much of the verbosity came from the false presumption that
             | every field in every class needs a public getter and
             | setter. (I cannot express in words how terrible this is.)
             | Some can come from the framework, mostly poorly-designed
             | ones.
             | 
             | I think Java 11 and higher are reasonably terse/expressive
             | without being overly dense.
        
               | DaiPlusPlus wrote:
               | Remind me, _why_ doesn't Java have object-properties yet?
               | 
               | So far the only reason I've concluded is Java's language
               | designers' egos were so damaged by C#, Swift, Kotlin,
               | TypeScript, etc that after dogmatically denying the
               | developer-productivity benefits of properties for the
               | past 20 years that to concede now would mark the end of
               | Java as a language entirely.
               | 
               | ...I kid, but seriously I haven't heard any compelling
               | argument from the Java camp yet for refusing to add this
               | feature. Object-properties are easily the lowest-hanging-
               | fruit with the biggest productivity-gains.
               | 
               | Heck, even some of the most popular C++ compilers support
               | object-properties as proprietary extensions.
        
               | zmmmmm wrote:
               | It's so crazy - with all the huge and radical features
               | they've added this would surely have been so simple by
               | comparison and yet added more value than about 80% of the
               | things they've done. It's about half the reason I still
               | use Groovy now since Java has solved most of the rest
               | over time. But I just cannot go back to writing getters
               | and setters!
        
               | doctor_eval wrote:
               | Couldn't agree more, the madness of idiomatically adding
               | setters and getters to every field was something I ended
               | up putting an end to in my last gig, and my life improved
               | immeasurably as a result.
        
               | The_rationalist wrote:
               | Kotlin property access solves this. You access to the
               | property but behind the hood it will call the
               | getter/setter if it exists.
        
             | kerblang wrote:
             | Sorry that I find it necessary for yet _another_ answer to
             | your verbosity question, but: The real verbosity is in the
             | standard libraries. What would be a one-liner in any other
             | language is usually at least 2, often 3, and sometimes
             | enough that you end up writing your own wrapper function or
             | library. Especially noticeable is the agony of Lists  &
             | Maps, which are first-class citizens in most languages
             | (classic job interview question: what is the difference
             | between ArrayList and LinkedList? Real answer: Nobody
             | actually uses LinkedList).
             | 
             | The stdlib often seems to be written by people who had no
             | intention of using it. I guess maybe this applies to C++ as
             | well, so for some folks it seems normal.
        
             | hibbelig wrote:
             | About verbosity: you needed to define classes for so many
             | things. Eg you want others to hook into processing in
             | certain places. So you create a listener interface with
             | some methods. And the provider needed to work with those,
             | and the consumer also needs to work with them.
             | 
             | In modern Java maybe you can make do with functional
             | interfaces and lambda, but it doesn't always work I think.
             | 
             | And in emacs: the provider does run-hooks, and the consumer
             | defines a function and says add-hook. Done. Very little
             | ceremony.
        
           | pron wrote:
           | I'd say the defining characteristic of Java is an
           | unparalleled combination of performance, observability, and
           | maintainability.
        
         | Thaxll wrote:
         | "Go is one of the HN darling languages"
         | 
         | It's def not the case, I spend too much time here and on Reddit
         | and people are always complaining about Go ( generics, errors,
         | type system etc ... ), if you want the godly language it would
         | be Rust, anything about Rust will be upvoted.
         | 
         | As for Java, it's a good language / runtime that is overly
         | complicated behind layers of abstraction. Take Spring for
         | examnple, magic everywhere, add an anotation there and it does
         | x.y.z, you can't see it in the code but it does something.
        
           | geodel wrote:
           | > if you want the godly language it would be Rust, anything
           | about Rust will be upvoted.
           | 
           | That is just better half part, sad part is anything negative
           | about Rust will be heavily downvoted. Most of the time I
           | disagree with Java/Go in their thread it would be just fine
           | but not with Rust.
        
             | The_rationalist wrote:
             | The same can be said about pro chromium or contra mozilla
             | comments, it's a kind of cargo cultism/echo chamber
        
           | kaba0 wrote:
           | Java itself is most definitely not overly complicated. Many
           | frameworks, and created programs are due to enterpriseTM
           | software development, but it's orthogonal. And spring is a
           | really feature-packed framework which has a solution for
           | almost every business problem that one can face. Of course it
           | comes with a great deal of complexity, but it is a tradeoff.
           | I rather tinker with how to use a given feature than
           | implement it myself, often in an inferior way.
        
           | ragnese wrote:
           | The hype around Rust is largely justified. There. I said it.
           | 
           | Rust is nowhere near perfect. It's also supposed to be a
           | systems language- it was probably not originally intended to
           | replace languages like Java for general "app" development.
           | 
           | But it's so much better of a language than most of the higher
           | level languages you see in popular use: Java, PHP,
           | JavaScript, Python, etc, that people are actually willing to
           | deal with the lack of garbage collection just to get to use
           | its excellent type system and well-designed standard library
           | API. I think that says a lot about Rust _and_ the programming
           | language environment today.
        
             | DaiPlusPlus wrote:
             | It surprises me that we don't yet have an applications
             | language with an ultra-modern type-system. It's so strange
             | that the current leaders are a scripting-transpiler
             | (TypeScript) and a systems language (Rust) - but not an
             | apps language in-between.
             | 
             | ...then again it's understandable when you see how the
             | traditional apps languages (C#, Java, etc) are severely
             | hobbled by their VM/runtime, because that's usually the
             | source of constraints on their type-system. Kotlin and F#
             | do some neat tricks to work-around the limitations they
             | inherited from the JVM and the .NET CLR respectively, but I
             | think we've reached the limits of what platforms originally
             | designed ~25 years ago can reach. I just don't see the JVM
             | nor the CLR getting anything like first-class support for
             | higher-kinded types or true algebraic types: there's too
             | much pressure from establishment banks and insurance
             | companies not to break their decades-old codebases
             | maintained by outsourcing companies. Languages like Swift
             | and Go are free to break their own molds because they're
             | happy not leaving a legacy, but what will that mean for
             | Rust? Systems code is the last place you need major
             | breaking changes, but I don't see Rust's progress slowing
             | down the way ISO C++ languished for almost 20 years. Hmmm.
        
               | int_19h wrote:
               | The situation is changing in the CLR land, now that they
               | can just say that legacy codebases can stay on .NET 4.x,
               | and .NET Core is where all the fancy development is
               | happening. There are already some C# language features
               | that are Core-only because they require the corresponding
               | runtime changes.
               | 
               | The other thing is - people always forget that, unlike
               | JVM, CLR has more than just the object layer. By design,
               | it has enough low-level constructs to compile a language
               | like C++, complete with multiple inheritance, unions,
               | varargs etc. Obviously, you can do pretty much anything
               | on top of that - the only problem is that you won't be
               | able to interop with other .NET code, except through
               | C-style FFI. But, hypothetically, it would be possible to
               | establish a higher-level ABI without baking it into the
               | VM as an object model, thus allowing a reboot without
               | throwing everything away.
        
               | ragnese wrote:
               | It surprises me as well. And to belabor my own point some
               | more: there's a reason the #1 question about Rust from
               | newbies seems to be "Is there a language like Rust, but
               | with a garbage collector?" - sometimes reworded as "Is
               | there a way to turn off the borrow checker?"
               | 
               | To be fair, I think that a decent amount is possible on
               | JVM and CLR. Scala, for as much hate as it gets, has a
               | much stronger type system than Kotlin/Java.
               | 
               | And Swift has its own backwards baggage! It has to work
               | with Objective-C. There's actually a few weird things in
               | Swift that I've bumped into that I'm _pretty_ sure are
               | only there because of Objective-C.
               | 
               | The Rust devs certainly take backwards compatibility very
               | seriously and they guarantee backwards compatibility
               | forever. There will be no breaking changes in Rust except
               | in extreme cases of finding unsoundness or whatever.
               | 
               | There are currently ZERO good high level app-building
               | languages, IMO.
               | 
               | Rust isn't it because of the lack of garbage collection
               | (which is not a point against Rust- just for the "domain"
               | of optimizing for user-space app development).
               | 
               | Swift would probably be it, but it's pretty much Apple-
               | only and I don't expect that to change.
               | 
               | TypeScript is close, but it's held back by needing to
               | work with JavaScript and the JavaScript standard library
               | and ecosystem suck. It also can't do threads.
               | 
               | Kotlin/Java are decent, but not good at concurrency, and
               | having things like different sized integer types is
               | really silly for a high-level language where everything
               | goes on the heap anyway...
               | 
               | Python is slow and can't do threads.
               | 
               | Some languages like Lisps and MLs might be good for
               | building apps if they just had the ecosystem around it.
               | Haskell would be a giant pain the ass because real apps
               | are full of "IO".
               | 
               | So, yeah. It's kind of a miracle that we can get anything
               | done. I guess that's why we get paid so well...
        
               | The_rationalist wrote:
               | Kotlin is the application language you're looking for
               | (and Scala 3 to a lesser extent). Contrary to what you
               | say it is the best language I've ever used for
               | concurrency. It has it all, structured concurrency,
               | cancelation, Flow, transparency (no await), etc.
               | Regarding your second point the JVM is increasingly using
               | the stack and with the soon complete generics you'll be
               | able to avoid the boxed versions of the primitive types
               | (though they remain useful when you want identity)
        
         | kukx wrote:
         | It also gets a bad rep because of Oracle.
        
         | superyesh wrote:
         | >got burned out by XML and design pattern heavy frameworks
         | 
         | Most succinct summary I have heard lately :) I think a good
         | bunch of blame is also on the developers who blindly adhere to
         | said patterns. https://www.quora.com/What-are-the-most-
         | ridiculous-Java-clas... to rest the case.
        
         | ragnese wrote:
         | I disagree that it's a lovely language. I think, as developers,
         | we very quickly develop Stockholm syndrome. Once you "learn" a
         | language, it's really easy to churn out code and apply idioms
         | without even realizing that you're constantly writing
         | workarounds and kludges for your language's deficiencies.
         | 
         | As a polyglot dev, the following are my gripes with Java:
         | 
         | * null - we all know, so I'm not going to bother expanding
         | except to say that @NotNull is NOT a solution and it doesn't
         | guarantee shit.
         | 
         | * interfaces are extremely lacking compared to type classes and
         | lead to verbose and cumbersome patterns such as "Adapter".
         | 
         | * Type-erased generics. Why shouldn't I be able to implement a
         | generic interface for multiple types? E.g., class MyNumber
         | implements Comparable<Integer>, Comparable<Short>,
         | Comparable<Long> {}
         | 
         | * It only just got Records and sealed interfaces, so thank
         | goodness for that. But prior versions of Java are extremely
         | lacking in expressiveness without these.
         | 
         | * I don't hate checked exceptions as a concept, but the fact
         | that you can't be "generic" over the exceptions in a function
         | signature is frustrating. This is why everyone says they're
         | "incompatible" with Java's closure APIs.
         | 
         | * No unsigned ints.
         | 
         | * Silent integer overflow/wrap-around. It's not C- did it
         | _really_ have to copy this insanity?
         | 
         | * Dates and timezones are still insane, even in Java 8+.
         | 
         | * The fact that arrays got type variance wrong.
         | 
         | * JDBC sucks. JPA also kind of sucks.
         | 
         | * No concept of `const` or immutability.
         | 
         | I'm not saying that Java is the worst language in the world or
         | anything, but it's far from great, IMO. Most programming
         | languages are pretty awful, IMO.
        
           | MaxBarraclough wrote:
           | > No unsigned ints.
           | 
           | I think that's a mixed blessing. I believe Java did this
           | deliberately to avoid the trouble that C and C++ have with
           | signed and unsigned integer types having to coexist.
           | Personally I've never been inconvenienced by Java's lack of
           | unsigned integer types, but I'm sure it can be annoying in
           | some situations.
           | 
           | I'm quite fond of Ada's approach to integer types, but I
           | suspect I'm in a minority.
           | 
           | > Silent integer overflow/wrap-around. It's not C- did it
           | really have to copy this insanity?
           | 
           | Curiously this cropped up 10 days ago. [0] You're not alone.
           | The great John Regehr put it thus: [1]
           | 
           | > _Java-style wrapping integers should never be the default,
           | this is arguably even worse than C and C++'s UB-on-overflow
           | which at least permits an implementation to trap._
           | 
           | > The fact that arrays got type variance wrong.
           | 
           | At least Java has the defence that they didn't know how it
           | would pan out. C# has no such excuse in copying Java.
           | 
           | > No concept of `const` or immutability.
           | 
           | I recall a Java wizard commenting that although a const
           | system is the sort of feature that aligns with Java's
           | philosophy, it's just too difficult to retrofit it.
           | 
           | [0] https://news.ycombinator.com/item?id=26538842
           | 
           | [1] https://blog.regehr.org/archives/1401
        
             | int_19h wrote:
             | > I believe Java did this deliberately to avoid the trouble
             | that C and C++ have with signed and unsigned integer types
             | having to coexist.
             | 
             | The problems really only come from mixing those types, and
             | the simple solution is to disallow such mixing without
             | explicit casts in cases where the result type is not wide
             | enough to represent all possible values - this is exactly
             | what C# does.
             | 
             | I think Java designers just assumed that high-level code
             | doesn't need those, and low-level code can use wrappers
             | that work on signed types as if they were unsigned (esp.
             | since with wraparound, many common operations are the
             | same).
             | 
             | > Java-style wrapping integers should never be the default
             | 
             | The ironic thing about this one is that C# introduced
             | "checked" and "unchecked" specifically to control this...
             | and then defaulted to "unchecked", so most C# code out
             | there assumes the same. Opportunity lost.
             | 
             | While we're on the subject of numeric types - the other
             | mistake, IMO, is pushing binary floating point numbers as
             | the default representation for reals. It makes sense perf-
             | wise, sure - but humans think in decimal, and it makes for
             | a very big difference with floats, that sometimes
             | translates to very expensive bugs. At the very least, a
             | modern high-level language should offer decimal floating-
             | point types that are _at least_ as easy to use as binary
             | floating-point (e.g. first-class literals, overloaded
             | operators etc).
             | 
             | C# almost got it right with "decimal"... except that
             | fractional literals still default to "double", so you need
             | to slap the "M" suffix everywhere. It really ought to be
             | the other way around - slower but safer choice by default,
             | and opt into fast binary floating-point where you actually
             | need perf.
             | 
             | > At least Java has the defence that they didn't know how
             | it would pan out. C# has no such excuse in copying Java.
             | 
             | I think both Java and C# did it as an attempt to offer some
             | generic data structure that could cover as many use cases
             | as possible, since neither had user-defined generic types.
             | In retrospect, it was an error - but before true generics
             | became a thing, it was also a godsend in some cases.
        
           | The_rationalist wrote:
           | Your analysis is interesting and far from exhaustive, It
           | would be nice to have a collaborative feature matrix for
           | languages, on github.
           | 
           | Kotlin solve the following points:
           | 
           |  _null - we all know, so I 'm not going to bother expanding
           | except to say that @NotNull is NOT a solution and it doesn't
           | guarantee shit.
           | 
           | I don't hate checked exceptions as a concept, but the fact
           | that you can't be "generic" over the exceptions in a function
           | signature is frustrating. This is why everyone says they're
           | "incompatible" with Java's closure APIs.
           | 
           | No unsigned ints.
           | 
           | No concept of `const` or immutability._
           | 
           | Kotlin allow to specify either variance or contravariance so
           | I guess it fixe this point too? * The fact that arrays got
           | type variance wrong*
           | 
           | * interfaces are extremely lacking compared to type classes
           | and lead to verbose and cumbersome patterns such as
           | "Adapter".* Interesting, can you link to an example? Kotlin
           | has first class support for delegation as an alternative.
           | 
           | * Type-erased generics. Why shouldn't I be able to implement
           | a generic interface for multiple types? E.g., class MyNumber
           | implements Comparable<Integer>, Comparable<Short>,
           | Comparable<Long> {}* Kotlin has support for reified generics
           | to some extent. The JVM is currently getting state of the art
           | support for it too and for specialization.
           | 
           | * Dates and timezones are still insane, even in Java 8+.* I
           | always hear that Java has got the best Time library, what is
           | the complaint about?
           | 
           | * JDBC sucks. JPA also kind of sucks.* Do yourself a favor
           | and use the JDBI or so many other sexy alternatives.
           | 
           | Of all your points the only unaddressed are: * interfaces are
           | extremely lacking compared to type classes and lead to
           | verbose and cumbersome patterns such as "Adapter".
           | 
           | And Silent integer overflow/wrap-around*
           | 
           | Strong agree about stockolmization and cargo cultism of
           | language constructs.
           | 
           |  _Most programming languages are pretty awful_ Correct, hence
           | why Kotlin stands out.
        
         | happyweasel wrote:
         | Java isn't the worst C++ program I know.
        
         | ericbarrett wrote:
         | I got burned out by endless JVM preening and devs configuring
         | their runtime options to use 128MB in a 2GB container, or
         | capitalizing their -Xm option wrong, or what have you. So now
         | with cloud computing you have the JVM in a container on a
         | virtual host, all of which have their own constraints to set--
         | matryoshka dolls all the way down.
         | 
         | Like, people always say, "Well that just means they didn't know
         | what they were doing with the JVM"--yes, and it's been a
         | problem for two decades and is about as likely to go away as
         | buffer overflows in C.
         | 
         | Honestly the thing I like about Go, Rust, C++ the most is the
         | resultant binary just runs in userspace, and you can set the
         | constraints there. Even Python scripts don't have to muck with
         | the JVM.
         | 
         | FactoryFactoryFactoryFactory code is the least of Java's
         | issues.
        
           | edp wrote:
           | Starting with OpenJDK 11 (and I think available in OpenJDK8
           | with an optional flag), the JVM will use the memory
           | constraints of the container, so no more -Xmx flags and so on
           | if you are running the JVM in a container environment.
        
             | oftenwrong wrote:
             | No flag necessary for latest versions of OpenJDK 8, either.
        
       | forty wrote:
       | What's the best way to run java apps in a container nowadays?
       | 
       | The official openjdk images are based on "oracle Linux" and that
       | doesn't sound right :) is there good small and well supported
       | java image based on a popular distribution?
        
         | germanier wrote:
         | Isn't Oracle Linux basically rebranded RHEL?
        
         | inyorgroove wrote:
         | If that is a problem for you there is AdoptOpenJDK:
         | https://hub.docker.com/_/adoptopenjdk
         | 
         | EDIT: Also openjdk has buster based images:
         | https://hub.docker.com/layers/openjdk/library/openjdk/jdk-bu...
        
         | aphexairlines wrote:
         | Use jib (java image builder) with maven or gradle and it will
         | build an image with distroless-java plus your app:
         | 
         | https://github.com/GoogleContainerTools/jib
         | https://github.com/GoogleContainerTools/distroless/blob/mast...
        
       | jillesvangurp wrote:
       | I've been using Java and the JVM since about 1995 when Sun
       | released the early betas (pre 1.0). It's more or less a
       | convenience marriage. Right place and right time I guess. I
       | happened to specialize in it for a while. A long story short: I
       | pivoted to Kotlin a while ago and stopped caring about what
       | Oracle is doing to keep up. Too little, too late; and it seems to
       | perpetually not matter at all unless you are still doing Java,
       | which I'm not.
       | 
       | Kotlin works great on the JVM and about the same across Jdk 8-16
       | (probably from v6 even). A lot of stuff happened in between but
       | the Kotlin compiler and library ecosystem seems to cover up and
       | smooth out the differences. Most of the Java compiler or standard
       | library changes stopped mattering to me. There's not a single
       | thing from v15 to v16 that I can name that matters to me, at all.
       | All my code works fine with v11 (the first and only post v8 LTS
       | release) and the delta with getting it to work with v8 is
       | trivial. There's just nothing since about 2014 that actually
       | matters to me. Not even a little bit. All of my Kotlin code bases
       | trivially work with any release since then.
       | 
       | I use Spring and Spring Boot in their latest versions and there's
       | no question about Kotlin being the preferred language for that at
       | this point. You get basically everything they did to make it work
       | with Java 8 plus everything that Kotlin adds on top, which is a
       | lot. Some of that even works with recent Java versions.
       | 
       | At this point that includes stuff like co-routines and Flows that
       | makes the whole abomination that is Spring Flux usable (as
       | opposed to a minefield of complexity you have to deal with via
       | 2014 era Java), data classes instead of last century style Java
       | Beans (just, no!), etc. Java 9 and on-wards is kind of half
       | getting there with things like Loom and records landing only very
       | recently and not havig had any impace yet whatsoever. You want
       | something modern, fresh, and nice with Spring that is not
       | experimental and well supported: Kotlin is it. Everything else is
       | stuck at being experimental until way after Oracle labels latest
       | & greatest Java version as LTS, which might happen in the next
       | two years or so. Java 11 technically happened but never really
       | registered in the same way that Java 8 did. For a lot of
       | conservative places, 8 was the last stable release. That was in
       | 2014! Everything after that is optional, nice to have, and yet to
       | impact major frameworks. Except of course if you use Kotlin,
       | which fast forwards you about seven years plus whatever Java has
       | left to catch up.
       | 
       | There really is no functional difference between JDKs other than
       | slight changes in Java APIs you probably should not be using with
       | Kotlin anyway. All the important stuff is tested with and works
       | fine with v8. I'm talking libraries, tools, and frameworks. Most
       | of my code works exactly the same with Java 8 as it does with
       | Java 16. I get very little value out of using something more
       | recent than jdk 8. But I still upgrade. Kotlin uses some of that
       | transparently but mostly it does not matter, at all.
       | 
       | We are basically talking purely non functional things that are
       | mostly about things like performance being slightly better, new
       | garbage collectors, or the whole modules thing that is largely
       | irrelevant to any kind of server side usage having happened or
       | not. I've never been on project where that actually mattered even
       | the slightest. Complete waste of time that pre-dates the
       | acquisition by Oracle even. But nice that they cleared some
       | technical debt there and got rid of some circular dependencies in
       | a standard library that I largely don't depend on with Kotlin.
       | 
       | Which is a different way of saying that I get very little out of
       | Java updates in the last seven years. My mode is mostly that,
       | well if you are going to pick a JVM, you might as well pick a
       | recent one because it probably has a few fixes that may or may
       | not matter to you. But it's going to work fine either way.
       | 
       | The next big thing with Kotlin is multi-platform and cutting
       | loose from Oracle. I'm already utilizing kotlin-js for some front
       | end stuff and am keeping an eye on their WASM efforts and native
       | stuff as well. A lot of what I care about already works fine
       | across all of those.
        
       | The_rationalist wrote:
       | The JVM will be getting state of the art, fine grained generics
       | specialization, riefied generics and even Constant generics (you
       | know that big feature that make a lot of noise in the Rust world)
       | https://www.reddit.com/r/java/comments/m2dfb5/parametric_jvm...
       | 
       | (note that Kotlin already has riefied generics to some extent and
       | that Scala support explicit Specialization (and Kt too through
       | overloading))
        
       | the_only_law wrote:
       | Thank god someone did this?
       | 
       | Not sure what it was about those versions particularly, but I
       | kinda lost track of the language and runtime after Java 8 and
       | I've spoken to a lot of other people who did as well.
       | 
       | Admittedly it's around the time I stopped working in Java a lot,
       | but I guess a lot of others did as well?
        
       ___________________________________________________________________
       (page generated 2021-04-01 23:02 UTC)