[HN Gopher] Rating 26 years of Java changes
       ___________________________________________________________________
        
       Rating 26 years of Java changes
        
       Author : PaulHoule
       Score  : 113 points
       Date   : 2025-10-11 18:29 UTC (4 hours ago)
        
 (HTM) web link (neilmadden.blog)
 (TXT) w3m dump (neilmadden.blog)
        
       | JanisErdmanis wrote:
       | > if you wanted to store an integer in a collection, you had to
       | manually convert to and from the primitive int type and the
       | Integer "boxed" class
       | 
       | I have never worked with Java. What is this? Why would one want
       | to have a class for an Integer?
        
         | morcus wrote:
         | It's because the collection types (and generics) don't support
         | primitives, only objects. So you been to stuff the primitives
         | into objects to use them with a lot of the standard library.
        
           | JanisErdmanis wrote:
           | That doesn't sound very pleasant.
        
             | dcminter wrote:
             | Well, it was annoying until autoboxing came in.
             | // Before autoboxing       list.add(new Integer(42));
             | // After autoboxing       list.add(42);
             | 
             | Mostly it's a non-issue now. If you're desperately
             | cycle/memory constrained you're likely not using Java
             | anyway.
        
               | marginalia_nu wrote:
               | You can get pretty good performance out of Java these
               | days, so long as you know to avoid stuff like boxed
               | primitives and the streams api, as they generally have
               | god-awful memory locality, and generally don't vectorize
               | well.
        
               | dcminter wrote:
               | Yeah, I know there are even oddballs using it for HFT and
               | the like - I like Java a lot, but even I find that a bit
               | peculiar.
               | 
               | Edit: actually, if someone here _is_ using it for
               | something like that I 'd love to hear the rationale...?
        
             | Arwill wrote:
             | There are libraries, like fastutil, that provide
             | collections for primitive types.
        
             | coldtea wrote:
             | Either the same of this feature or always hiding the boxing
             | (e.g. a Python int is actually a wrapper object as well,
             | with some optimizations for some cases like interning) is
             | the case in almost all languages.
        
               | JanisErdmanis wrote:
               | I personally use Julia, which does not have such boxing
               | issues. Rust, C, C++, and Fortran also avoid boxing like
               | this. Perhaps Go is also free from such boxing? Python
               | does it, that's true.
        
           | dcminter wrote:
           | One of the more amusing bugs I had to figure out resulted
           | from the fact that some of the autoboxed values get cached,
           | resulting in peculiar behaviour when someone managed to
           | reflectively change the boxed primitive value...
           | 
           | i.e. something like:                 Integer x = 42
           | highlyQuestionableCode(x);       println(x); // "24" WAT?
           | 
           | I'm a fan of JEP-500...
           | 
           | https://openjdk.org/jeps/500
        
         | raspasov wrote:
         | I think your intuition is correct: you probably don't.
         | 
         | That's also very likely changing. Lookup "project Valhalla".
         | It's still a work in progress but the high level goal is to
         | have immutable values that "code like a class, work like an
         | int".
         | 
         | PS When I say "changing": it's being added. Java tries hard to
         | maintain backward compatibility for most things (which is
         | great).
        
         | iceboundrock wrote:
         | Primitive variables in Java, such as `int`, `boolean`, and
         | `double`, store their actual values directly in memory. When
         | they are local variables inside a method, this memory is
         | typically allocated on the thread's stack. These primitives do
         | not have the structure or overhead of an object, including the
         | object header used by the Garbage Collector (GC) to manage
         | heap-allocated objects.
         | 
         | If a primitive value must be treated as an object (e.g., when
         | stored in a Java Collection like ArrayList or when passed to a
         | method that requires an object), Java uses a process called
         | `boxing` to wrap the primitive value into an instance of its
         | corresponding Wrapper class (e.g., Integer, Boolean, Double).
         | These Wrapper objects are allocated on the heap and do possess
         | the necessary object header, making them subject to the GC's
         | management.
        
           | wpollock wrote:
           | Aside from this, having such a class provides a convenient
           | place to hold all the int utility functions, and the same for
           | the other primitive types.
        
       | iceboundrock wrote:
       | It appears that most of the good changes are imported from C#.
        
         | sjrd wrote:
         | Or Scala. Or Kotlin. Or any of the other languages that had
         | most of these features years if not decades before Java. ;)
        
           | marginalia_nu wrote:
           | Yeah that's very much an explicit design philosophy of Java,
           | dating way back. Let other languages experiment, and adapt
           | what proves useful.
           | 
           | It hasn't worked out in terms of delivering perfect language
           | design, but it has worked out in the sense that Java has an
           | almost absurd degree of backward compatibility. There are
           | libraries that have had more breaking changes this year than
           | the Java programming language has had in the last 17
           | releases.
        
             | agos wrote:
             | What other language made them think checked exceptions were
             | a good idea?
        
         | coldtea wrote:
         | Most of original C# was imported from Java, so there's that...
        
       | dkarl wrote:
       | Definitely underrates the impact of annotations. I'm personally
       | not a fan of the way annotations are used to implicitly wire
       | together applications, but I have to admit the impact. Maybe 5/10
       | is fair in light of the wide range of positive and extremely
       | negative ways annotations can be used.
       | 
       | So many of these features were adopted after they were proven in
       | other languages. You would expect that since Java took such a
       | slow and conservative approach, it would end up with extremely
       | polished and elegant designs, but things like streams ended up
       | inferior to previous developments instead of being the
       | culmination. Really disappointing. Java is now a Frankenstein's
       | monster with exactly as much beauty and charm.
        
         | dhosek wrote:
         | I used to joke that the direction spring was heading was that
         | you'd have an application be a boilerplate main method with a
         | dozen lines of annotations. Then I actually encountered this in
         | the wild: we had an app that sent updates from db2 to rabbitmq,
         | and the application literally was just configuration via
         | annotations and no actual Java code other than the usual spring
         | main method.
        
           | bdangubic wrote:
           | this is _exactly_ why spring succeeded. I need to run a
           | scheduled job, @EnableScheduling then @Scheduled(cron =
           | "xxxxxx") - done. I need XYZ, @EnableXYZ the @XYZ... sh*t
           | just works...
        
             | vbezhenar wrote:
             | Yeah, it works until it isn't. And they good luck debugging
             | it. I'd prefer simple obvious linear code calling some
             | functions over this declarative magic any day.
             | cronService.schedule("xxx", this::refresh);
             | 
             | This isn't any harder than annotation. But you can
             | ctrl+click on schedule implementation and below easily. You
             | can put breakpoint and whatnot.
        
               | bdangubic wrote:
               | never had any issues debugging as I am never debugging
               | the scheduler (that works :) ) but my own code.
               | 
               | and what exactly is "cronService"? you write in each
               | service or copy/paste each time you need it?
        
               | alex_smart wrote:
               | You can write your own libraries?
               | 
               | My goodness. What a question!
        
             | skeletal88 wrote:
             | Then you need to deploy it on multiple nodes and neex to
             | make sure it only runs once for each run of the cron, etc.
        
               | bdangubic wrote:
               | while not working on out of the box clustered this is
               | trivial issue to address
        
             | taftster wrote:
             | And then I realize I need to change that schedule. And
             | would like to do it without recompiling my code. Oh, and I
             | need to allow for environment specific scheduling, weekdays
             | on one system, weekends on others. And I need other
             | dependencies that are environment specific.
             | 
             | I much prefer Spring's XML configuration from the old days.
             | Yeah, XML sucks and all that. But still, with XML, the
             | configuration is completely external from the application
             | and I can manage it from /etc style layouts. Hard coding
             | and compiling in dependency injection via annotations or
             | other such behaviors into the class directly has caused me
             | grief over the long term pretty much every time.
        
               | nunobrito wrote:
               | The only real-world usage I see for annotations are in
               | GSON (the @Expose) and JUnit with @Test.
               | 
               | Never really came across with any other real cases where
               | it solves a pressing issue as you mention. Most times is
               | far more convenient to do things outside the compiled
               | code.
        
           | 9dev wrote:
           | Is that strictly bad, though? Being able to run an enterprise
           | service by setting configuration values declaratively, and
           | get all the guarantees of a well-tested framework, seems like
           | a pretty good thing.
           | 
           | Yes, it's weird how that's still Java, but using standard
           | components and only using code as glue where it's absolutely
           | necessary seems very similar to other engineering disciplines
           | to me.
        
             | SkiFire13 wrote:
             | I think the general adversity against this specialized
             | configurations is that they often tend to be fairly
             | limited/rigid in what they can do, and if you want to
             | customize anything you have to rewrite the whole thing.
             | They effectively lock you into one black box of doing
             | things, and getting out of it can be very painful.
        
         | tormeh wrote:
         | It's seriously puzzling. I just don't get how it's possible to
         | look at what so many others have done better, and somehow
         | design something worse. For what reason? Consistency with the
         | rest of the language, possibly? But is that really so
         | important. Do they just not want to tackle certain parts of the
         | compiler?
        
           | dcminter wrote:
           | Some of the weirder choices have been the result of a desire
           | to avoid making breaking changes to JVM bytecode.
           | 
           | Also there was a long period when changes were _very_ lumpy -
           | it could be multiple years for a feature to make it into the
           | release, and anything that might screw up other features got
           | a lot of pushback. Then other conventions /tools emerged that
           | reduced the urgency (e.g. the Lombok stuff)
           | 
           | Edit: I should add that it's now on a fixed 6-monthly release
           | cycle which IMO works _much_ better.
        
           | rzwitserloot wrote:
           | OpenJDK redesigns massive swaths of the compiler every other
           | month.
           | 
           | The true explanation, at least the way OpenJDK says it, is
           | that designing language features is more complex than a
           | casual glancer can fathom, and there's 30 years of "Java is
           | in the top 5 most used languages on the planet, probably #1
           | especially if focussing on stuff that was meant to be
           | supported for a long time" to think about.
           | 
           | From personal experience, essentially every single last "Just
           | do X to add (some lang feature) to java; languages A and B do
           | it and it works great!" would have been bad for java. Usually
           | because it would cause a 'cultural split' - where you can
           | tell some highly used library in the ecosystem was clearly
           | designed before the feature's introduction.
           | 
           | Even if you introduce a new feature in a way that doesn't
           | break existing code, it's still going to cause
           | maintainability headaches if you've cornered the pillars of
           | the ecosystem into total rewrites if they want to remain up
           | to date with the language. Because they will (or somebody
           | will write an alternative that will) and you've _still_
           | 'python 2 v python 3'd the language and split the baby in the
           | half.
           | 
           | For what its worth, I think the OpenJDK team doesn't take
           | this seriously enough, and a number of recently introduced
           | features have been deployed too hastily without thinking this
           | through. For example, `LocalDate`, which has 'this should be
           | a record' written all over it, _is not a record_. Or how the
           | securitymanager is being ditched without replacements for
           | what it is most commonly used for here in the 2020s. (To be
           | clear: Ditching it is a good idea, but having no in-process
           | replacement for  "let me stop attempts to access files and
           | shut down the JVM, not for security purposes but simply for
           | 'plan B' style fallback purposes" - that's a bit
           | regrettable).
           | 
           | I'm nitpicking on those points because on the whole OpenJDK
           | is doing a far better job than most languages on trying to
           | keep its ecosystem and sizable existing codebase on board
           | _without_ resorting to the crutch of: "Well, users of this
           | language, get to work refactoring everything or embrace
           | obsoletion".
        
         | vbezhenar wrote:
         | I don't really feel that Java uses proven features.
         | 
         | For example they used checked exceptions. Those definitely do
         | not seem like proven feature. C++ has unchecked exceptions.
         | Almost every other popular language has unchecked exceptions.
         | Java went with checked exceptions and nowadays they are almost
         | universally ignored by developers. I'd say that's a total
         | failure.
         | 
         | Streams another good example. Making functional API for
         | collections is pretty trivial. But they decided to design
         | streams for some kind of very easy parallelisation. This led to
         | extremely complicated implementation, absurdly complicated. And
         | I've yet to encounter a single use-case for this feature. So
         | for very rare feature they complicated the design immensely.
         | 
         | Modules... LoL.
         | 
         | We will see how green threads will work. Most languages adopt
         | much simpler async/await approach. Very few languages implement
         | green threads.
        
           | rzwitserloot wrote:
           | > For example they used checked exceptions.
           | 
           | Those are from java 1.0 and thus don't appear to be relevant
           | to the part of the discussion I think this part of the thread
           | is about (namely: "Why doesn't java crib well designed
           | features from other languages?").
           | 
           | > Java went with checked exceptions and nowadays they are
           | almost universally ignored by developers.
           | 
           | They aren't.
           | 
           | Note that other languages invented for example 'Either' which
           | is a different take on the same principle, namely: Explicit
           | mention of all somewhat expectable alternative exit
           | conditions + enforcing callers to deal with them, though also
           | offering a relatively easy way to just throw that
           | responsibility up the call chain.
           | 
           | The general tenet (lets lift plausible alternate exit
           | conditions into the type system) is being done left and
           | right.
        
           | JavierFlores09 wrote:
           | Stuart Marks and Nicolai Parlog recently had a discussion
           | about checked exceptions in the Java channel [0]. In short,
           | while they mentioned that there are certainly some things to
           | improve about checked exceptions, like the confusing
           | hierarchy as well as the boilerplate-y way of handling them,
           | they're not necessarily a failed concept. I do hope they get
           | to work on them in the near future.
           | 
           | 0: https://www.youtube.com/watch?v=lnfnF7otEnk
        
             | vbezhenar wrote:
             | They are absolutely failed concept in Java. Every first
             | popular library uses unchecked exceptions, including famous
             | Spring. Java streams API does not support checked
             | exceptions. Even Java standard library nowadays includes
             | "UncheckedIOException". Kotlin, Scala: both languages grown
             | from JVM, threw away do not support checked exceptions.
        
         | torginus wrote:
         | which is kinda horrifying - it means the framework designers
         | didn't find the language powerful enough to express app logic,
         | and hotglued their own custom arbitrary behavior on top of it.
         | 
         | Clear language code should be endeavor to be
         | readable/understandable when printed on a sheet of paper by
         | anyone, acceptable code should be understandable by anyone who
         | knows a bit about the technologies and has some IDE support.
         | 
         | Garbage code is what you have when the code in question is only
         | understandable when you actually run it, as it uses arbitrary
         | framework logic to wire things together based on metadata on
         | the fly.
        
           | Groxx wrote:
           | people have been gluing other languages on top of languages
           | practically forever - it's a DSL.
           | 
           | no single language is ideally suited for every situation,
           | it's not inherently a sign of failure that someone makes a
           | DSL.
           | 
           | and since annotations are part of the language, this is still
           | all "the language is flexible enough to build the framework
           | [despite being wildly different than normal code]" so I don't
           | think it even supports that part.
        
         | rzwitserloot wrote:
         | That's not how the OpenJDK sees things. They tend to think that
         | the features they deliver are at best mildly informed by other
         | languages. Not out of some sense of hubris, but out of a sense
         | of pragmatics: Simply copy and pasting features from other
         | languages into java - _that_ would produce a frankenstein.
         | 
         | For example, java is somewhat unique in having lambda syntax
         | where the lambda *must* be compile-time interpretable as some
         | sort of 'functional type' (a functional type being any
         | interface that defines precisely 1 unimplemented method). The
         | vast, vast majority of languages out there, including scala
         | which runs on the JVM, instead create a type hierarchy that
         | describe lambdas as functions, and _may_ (in the case of scala
         | for example) compile-time automatically  'box'/'cast' any
         | expression of some functional type to a functional interface
         | type that matches.
         | 
         | Java's approach is, in other words, unique (as far as I know).
         | 
         | There was an alternate proposal available at the time that
         | would have done things more like other languages does them,
         | completely worked out with proof of concept builds readily
         | available (the 'BGGA proposal'). The JVM would autogenerate
         | types such as `java.lang.function.Function2<A, B, R>`
         | (representing a function that takes 2 arguments, first of type
         | A second of type B, and returns a value of type R), would then
         | treat e.g. the expression:
         | 
         | `(String a, List<Integer> b) -> 2.0;`
         | 
         | As a `Function2<String, List<Integer>, Double>`, and would also
         | 'auto-box' this if needed, e.g. if passing that as the sole
         | argument to a function:
         | 
         | ``` void foo(MyOperation o) {}
         | 
         | interface MyOperation { Double whatever(String arg1,
         | List<Integer> arg2); } ```
         | 
         | This proposal was seriously considered but rejected.
         | 
         | The core problem with your comment is this:
         | 
         | Define the terms "polished" and "elegant". It sounds so simple,
         | but language features are trying to dance to quite a few
         | extremely different tunes, and one person's 'elegance' is
         | another person's 'frankensteinian monster'.
         | 
         | The same mostly goes for your terms "beauty" and "charm", but,
         | if I may take a wild stab in the dark and assume that most
         | folks have a very rough meeting of the minds as to whatever
         | might be a "charming" language: I know of no mainstream long-
         | term popular languages that qualify for those terms. And I
         | think that's _inherent_. You can 't be a mainstream language
         | unless your language is extremely stable. When you're not just
         | writing some cool new toy stuff in language X - you're writing
         | production code that lots of euros and eyeballs are involved
         | in, and there's real dependence on that software continuing to
         | run, then you __must__ have stability or it becomes extremely
         | pricey to actually maintain it.
         | 
         | With stability comes the handcuffs: You need to use the
         | 'deprecation' hammer extremely sparingly, essentially never.
         | And that has downstream effects: You can't really test new
         | features either. So far I have not seen a language that truly
         | flourishes on the crutches of some `from future import ...`
         | system. That makes some sense: Either the entire ecosystem
         | adopts the future feature and then breaking _that_ brings the
         | same headaches, or folks don't use these features / only for
         | toy stuff, and you don't get nearly the same amount of
         | experience from its deployment.
         | 
         | Said differently: If java is a frankenstein, so is Javascript,
         | C#, Python, Ruby, Scala, and so on. They have to be.
         | 
         | I'd love to see a language whose core design principles are
         | 100% focussed on preventing specifically that. Some sort of
         | extreme take on versioning of a language itself that we haven't
         | seen before. I don't really know what it looks like, but I
         | can't recall any language that put in the kind of effort I'd
         | want to see here. This is just a tiny sliver of what it'd take:
         | 
         | * The language itself is versioned, and all previous versions
         | continue to be part of the lang spec and continue to be
         | maintained by future compilers. At least for a long time, if
         | not forever.
         | 
         | * ALL sources files MUST start with an indication about which
         | version of the language itself they use.
         | 
         | * The core libraries are also versioned, and separately. Newer
         | versions are written against old language versions, or can be
         | used by source on old language versions.
         | 
         | * The system's compilers and tools are fundamentally operating
         | on a 'project' level granularity. You can't compile individual
         | source files. Or if you can, it's because the spec explains how
         | a temporary nameless project is implied by such an act.
         | 
         | * All versions ship with a migrator tool, which automatically
         | 'updates' sources written for lang ver X to lang ver X+1,
         | automatically applying anything that has a near-zero chance of
         | causing issues, and guiding the programmer to explicitly fixing
         | all deprecated usages of things where an automated update is
         | not available.
         | 
         | * The language inherently supports 'facades'; a way for a
         | library at version Y to expose the API it had at version X (X
         | is older than Y), but using the data structures of Y, thus
         | allowing interop between 2 codebases that both use this
         | library, one at version X and one at version Y.
         | 
         | That language might manage the otherwise impossible job of
         | being 'elegant', 'simple', 'mainstream', 'suitable for serious
         | projects', and 'actually good'.
        
         | nine_k wrote:
         | Absolutely. It seems that the author never touched Spring, for
         | instance, or a dependency-injection framework of any kind.
         | Annotations allow to do things in a _completely_ different way,
         | removing tons of boilerplate.
         | 
         | I'd give annotations 9/10 at least.
         | 
         | (And I lost the interest in the rest of the article, given such
         | a level of familiarity with the subject matter.)
        
           | Groxx wrote:
           | and that's before even touching on the compilation steps they
           | can add, which are a _pluggable_ codegen and macro system
           | that is also integrated into IDEs, which is completely
           | missing from almost every other language.
        
         | jayd16 wrote:
         | The ratings are really all over the place. Jshell is a 6/10?
        
       | Supermancho wrote:
       | Can someone explain why developers like var?
        
         | pgwhalen wrote:
         | It reduces (often repetitive) visual noise in code, which can
         | make it more readable. I wouldn't recommend using it in all
         | cases, but it's a good tool to have.
        
         | Traubenfuchs wrote:
         | It's a harmful code smell: It often obfuscates the type,
         | forcing you to actively check for the type and should not be
         | used.
        
           | Supermancho wrote:
           | This is what it looks like to me. If you wanted to do this,
           | why not use a scripting language where you can use this kind
           | of practice everywhere? In Java, I don't expect to have to
           | look up the return type of something to discover a variable
           | type. Graciously, I can see how you can save rewriting the
           | Type declaration when it's a function return you want to
           | mutate.
           | 
           | Generally, you save some keystrokes to let other people (or
           | future you) figure it out when reading. It seems like bad
           | practice altogether for non trivial projects.
        
             | guax wrote:
             | Modern IDEs will show you the type of anything at all
             | times. I do not understand your point unless you're doing
             | raw text editing of Java source.
             | 
             | Those keystrokes are not just saved on writing, they make
             | the whole code more legible and easier to mentally parse.
             | When reading I don't care if the variable is a specific
             | type, you're mostly looking whats being done to it, knowing
             | the type becomes important later and, again, the IDE solves
             | that for you.
        
           | newAccount2025 wrote:
           | Your IDE can do that?
        
           | a57721 wrote:
           | It is used for things like "Foo x = new Foo()" where the type
           | is obvious.
        
         | tofflos wrote:
         | It's terse and it lines up the variable names.
        
         | flykespice wrote:
         | It's another thing they adopted from Kotlin, since Kotlin is
         | supposed to be a "better java". Now Java is retroactively
         | adopting Kotlin freatures.
        
           | speed_spread wrote:
           | Kotlin didn't invent type inference, it's a feature from ML.
        
         | speed_spread wrote:
         | It's called type inference and it's the way things should be.
         | You get the same types but you don't have to spell them out
         | everywhere. Java doesn't even go all the way, check OCaml to
         | see full program inference.
        
           | miningape wrote:
           | OCaml's type inference is truly amazing, makes it such a
           | delight to write statically typed code - reading it on the
           | other hand...
           | 
           | But I think that's easily solved by adding type annotations
           | for the return type of methods - annotating almost anything
           | else is mostly just clutter imo.
        
             | Supermancho wrote:
             | Annotations would be a substitute for writing the return
             | type. Extra code for a shortcut seems like the worst
             | solution.
        
         | N70Phone wrote:
         | Previously (or if you simply don't use var), a lot of java code
         | takes the form of                 BeanFactoryBuilder builder =
         | new BeanFactoryBuilder(...);
         | 
         | This is just straight up a duplicate. With generics, generic
         | parameters can be left out on one side but the class itself is
         | still duplicated.
        
         | guax wrote:
         | To me var is what makes modern java somewhat readable and more
         | bearable. It was always a joke that it takes too long to write
         | anything in java because of the excessive syntax repetitions
         | and formalities. To me that joke is heavily based on a reality
         | that modern Java is tackling with this quality of life
         | features.
        
           | whartung wrote:
           | I get the attraction to var, but I, personally, don't use it,
           | as I feel it makes the code harder to read.
           | 
           | Simply, I like (mind, I'm 25 year Java guy so this is all
           | routine to me) to know the types of the variables, the types
           | of what things are returning.                 var x = func();
           | 
           | doesn't tell me anything.
           | 
           | And, yes, I appreciate all comments about verbosity and code
           | clutter and FactoryProxyBuilderImpl, etc. But, for me, not
           | having it there makes the code harder for me to follow. Makes
           | an IDE more of a necessity.
           | 
           | Java code is already hard enough to follow when everything is
           | a maze of empty interfaces, but "no code", that can only be
           | tracked through in a debugger when everything is wired up.
           | 
           | Maybe if I used it more, I'd like it better, but so far, when
           | coming back to code I've written, I like things being more
           | explicit than not.
        
             | nunobrito wrote:
             | Yes, well expressed. For that case using var is not a wise
             | approach.
             | 
             | It does help when writing:                   var x = new
             | MyClass();
             | 
             | Because then you avoid repetition. Anyways, I don't ever
             | use "var" to keep the code compatible with Java-8 style
             | programming and easier on the eyes for the same reasons you
             | mention.
        
             | CrimsonRain wrote:
             | 1. Just because you can use var in a place, doesn't mean
             | you should. Use it where the type would be obvious when
             | reading code like                 var myPotato = new
             | PotatoBuilder.build();
             | 
             | not like                 var myFood = buyFood();
             | 
             | where buyFood has Potato as return type.
             | 
             | 2. Even if you don't follow 1, IDEs can show you the type
             | like                 var Potato (in different font/color)
             | myFood = buyFood();
        
           | mi_lk wrote:
           | I have the opposite feeling. var makes it easier to write but
           | harder to read/review. Without var you know the exact type of
           | a variable without going through some functions for example
        
       | haunter wrote:
       | I'm sorry, please don't hate me (I'm tired and don't have
       | anything better to do) https://files.catbox.moe/ge4el3.png
        
         | rvitorper wrote:
         | Dude, this is awesome
        
         | alex_smart wrote:
         | Why so much hate for modules? They seem to be almost
         | universally disliked by everyone on this thread and I don't
         | understand why.
        
       | harladsinsteden wrote:
       | I don't know what to make of this list...
       | 
       | Very strange reasoning and even stranger results: Streams 1/10?!
       | Lambdas (maybe the biggest enhancement ever) a mere 4/10?!
       | 
       | Sorry, but this is just bogus.
        
         | tofflos wrote:
         | I will make any excuse to use Streams but understand the
         | negativity. They are difficult to debug and I feel the support
         | for parallelism complicated, and in some cases even crippled,
         | the API for many common use cases.
        
         | nunobrito wrote:
         | I'm that author. It has been more than a decade and still won't
         | use streams nor lambdas. Makes the code too difficult to write
         | and debug for me.
         | 
         | Really prefer to have more lines of code and understanding very
         | clearly what each one is doing, than convoluting too many
         | instructions on a single line.
        
       | Arwill wrote:
       | -10 for modules is fair, only 4 for lambdas is not. My
       | programming style changed after using lambdas in Java, even when
       | using a different programming language later that doesn't have
       | lambdas as such.
        
       | marginalia_nu wrote:
       | I think the author is sleeping on Java assertions.
       | 
       | I really like the feature, and it's really one of the features I
       | feel Java got right.
       | 
       | The syntax is very expressive, and they can easily be made to
       | generate meaningful exceptions when they fail.
       | 
       | It's also neat that it gives the language a canonical way of
       | adding invariant checks that can be removed in production but run
       | in tests or during testing or debugging (with -da vs -ea).
       | 
       | You could achieve similar things with if statements, and likely
       | get similar performance characteristics eventually out of C2, but
       | this way it would be harder to distinguish business logic from
       | invariant checking. You'd also likely end up with different
       | authors implementing their own toggles for these pseudo-
       | assertions.
        
         | rwmj wrote:
         | I'm quite surprised that he said asserts are not found in
         | production code. Is that really so? I rarely write Java, but in
         | C code we use asserts (in production code) all the time. It's
         | not uncommon for functions to contain 2 or 3 asserts.
        
           | dcminter wrote:
           | I very rarely see assertions in "real" Java code; I think the
           | author is right - in fact the place I see them the most often
           | is in unit tests where they've been used _by mistake_ in
           | place of an assertion library 's methods!
           | 
           | I don't know why they're not more popular.
        
             | nunobrito wrote:
             | Good conversation, I had no idea what assertions are beyond
             | JUnit.
        
           | marginalia_nu wrote:
           | If you're only doing like CRUD endpoints, they may be less
           | useful, but that's hardly the extent of Java production code.
           | I certainly use asserts in production code quite a lot in
           | Java, though the use biases toward more low level functions,
           | rarely in high level application logic.
        
         | brap wrote:
         | What are the pros of making this a keyword vs just a standard
         | function?
        
       | zylepe wrote:
       | I haven't used markdown in javadoc yet but this seems like at
       | least 3/10? I often want to put paragraphs or bulleted lists in
       | javadoc and find myself wanting to use markdown syntax for
       | readability in the code but need to switch to less readable html
       | tags for tooling to render it properly.
        
         | ronyeh wrote:
         | I hate using html in comments.
         | 
         | Markdown in javadoc is at least 7/10 for me. Improves comment
         | readability for humans while allowing formatted javadocs.
        
       | rsynnott wrote:
       | I feel this is overly harsh on Collections. You have to take into
       | account just how awful that which it replaced was.
       | 
       | > Java Time: Much better than what came before, but I have barely
       | had to use much of this API at all, so I'm not in a position to
       | really judge how good this is.
       | 
       | Again, it is hard to overstate just _how_ bad the previous
       | version is.
       | 
       | Though honestly I still just use joda time.
        
         | wpollock wrote:
         | >Again, it is hard to overstate just _how_ bad the previous
         | version [of Java time] is.
         | 
         | The original Java Time classes were likely a last-minute
         | addition to Java. They were obviously a direct copy of C
         | language time.h. It feels as if the Java team had a
         | conversation like this: "Darn, we ship Java 1.0 in a month but
         | we forgot to include any time functions!" "Oh no! We must do
         | something!" "I know, let's just port C time.h!"
        
       | zkmon wrote:
       | Applets (Java 1.1 - that's where I started),
       | 
       | Servlets (Together with MS ASP, JSP/Servlets have fuelled the
       | e-commerce websites)
       | 
       | I think Java dominated the scene mostly because of its enterprise
       | features (Java EE) and the supporting frameworks (Spring etc) and
       | applications (Tomcat, Websphere, Weblogic etc) and support from
       | Open source (Apache, IBM)
        
       | foolfoolz wrote:
       | the biggest things to change java have been type inference,
       | lambdas, records, streams (functional ops on collections), and
       | pattern matching. these are all must-have features for any modern
       | programming language. at this point any language without these
       | features will feel old and legacy. it's impressive java was able
       | to add them all on decades after release, but you do feel it
       | sometimes
        
       | newAccount2025 wrote:
       | For my part, returning to Java a couple years back after 15+
       | years away, streams + var/val were my favorite discoveries.
        
       | sedro wrote:
       | Autoboxing's evil twin, auto-unboxing should knock the score down
       | a few points.                 Integer a = null;       int b = 42;
       | if (a == b) {} // throws NullPointerException
        
         | dcminter wrote:
         | Or my favourite...                 Short w = 42;       Short x
         | = 42;       out.println(w == x); // true       Short y = 1042;
         | Short z = 1042;       out.println(y == z); // false
        
           | prein wrote:
           | Once, after we had an application go live, we started getting
           | reports after a few hours that new users were unable to log
           | in.
           | 
           | It turns out, somewhere in the auth path, a dev had used `==`
           | to verify a user's ID, which worked for Longs under (I
           | believe) 128, so any users with an ID bigger than that were
           | unable to log in due to the comparison failing.
        
       | tombert wrote:
       | Interesting; I actually have grown pretty fond of NIO.
       | 
       | I will acknowledge that the interface is a bit weird, but I feel
       | like despite that it has consistently been a "Just Works" tool
       | for me. I get decent performance, the API is well documented, and
       | since so many of my coworkers have historically been bad at it
       | and used regular Java IO, it has felt like a superpower for me
       | since it makes it comparatively easy to write performant code.
       | 
       | Granted, I think a part of me is always comparing it to writing
       | raw epoll stuff in C, so maybe it's just better in comparison :)
        
       | simonklee wrote:
       | java.util.Date and java.util.Calendar are the two packages I
       | remember struggling with as a new programmer. Which I guess is
       | solved with java.time after Java 8.
        
       | b_e_n_t_o_n wrote:
       | I haven't written much Java but I am learning Kotlin and I really
       | appreciate the language and the whole JVM ecosystem. Yeah yeah,
       | Gradle is complicated but it's waaaaay easier to figure out than
       | my adventures with Cmake, and when I read Java code there is a
       | certain _comfort_ I feel that I don 't get with other languages,
       | even ones I'm experienced with like Go. Java feels a bit like a
       | stranger I've known my whole life, same with Kotlin. Perhaps
       | despite all its flaws, there is a certain intrinsic quality to
       | Java that has helped make it so popular.
        
       | MarkMarine wrote:
       | I'm sure there are better ways to do streams on the JVM, scala
       | being a great example, but however imperfect the implementation
       | is streams are such a net positive I can't imagine the language
       | without them. I pine for the streams API when I write go.
        
       | AbuAssar wrote:
       | so java 22, 23, 24 are all released in 2024?
        
         | dcminter wrote:
         | No, it's a 6 month release cadence. You might be confusing the
         | initial release with a point release which are less regular.
         | Edit: oh, my bad, I see the article author had the wrong year
         | for 24.                 22 was March 2024       23 was
         | September 2024       24 was March 2025       25 was September
         | 2025
         | 
         | This is much better than the old "release train" system where
         | e.g Java 5 and Java 6 were released in Sept 2004 and Nov 2006
         | respectively!
        
       | linuxhansl wrote:
       | Didn't Java 1.3 (Sun's JDK) introduce the JIT? I remember talking
       | to colleagues about what a joke Java performance was (we were
       | working in C++ then). And then with Java 1.3 that started to
       | change.
       | 
       | (Today, even though I still C++, C, along with Java, I'll
       | challenge anyone who claims that Java is slower then C++.)
        
       | brap wrote:
       | Wow I can't believe try with resources is so old! I've been
       | working with Java for years and only learned this exists
       | recently, I thought it must be relatively new. 14 years!
        
       | travisgriggs wrote:
       | Ah Java. The language I never got to love. I came of coding age
       | during the "camps" era of object oriented stuff: Eiffel,
       | Smalltalk, CLOS, C++, etc. Java, from 95ish to oh 98ish, was like
       | a giant backdraft. Completely sucked the air out of the room for
       | everything else.
       | 
       | Does anyone remember the full page ads in WSJ for programming
       | language, that no on quite yet knew what it really was? So my
       | formative impressions of Java on were emotional/irrational,
       | enforced by comments like:
       | 
       | "Of Course Java will Work, there's not a damn new thing in it" --
       | James gosling, but I've always suspected this might be urban
       | legend
       | 
       | "Java, all the elegance of C++ syntax with all the speed of
       | Smalltalk" - Kent Beck or Jan Steinman
       | 
       | "20 years from now, we will still be talking about Java. Not
       | because of its contributions to computer programming, but rather
       | as a demonstration of how to market a language" -- ??
       | 
       | I can code some in Java today (because, hey, GPT and friends!! :)
       | ), but have elected to use Kotlin and have been moderately happy
       | with that.
       | 
       | One thing that would be interesting about this list, is to break
       | down the changes that changed/evolved the actual computation
       | model that a programmer uses with it, vs syntactic sugar and
       | library refinements. "Languages" with heavy footprints like this,
       | are often just as much about their run time libraries and
       | frameworks, as they are the actual methodology of how you compute
       | results.
        
       | rr808 wrote:
       | Java is great, Spring ruined the platform.
        
       | taspeotis wrote:
       | Which release did they add the URL class that checks for equality
       | by connecting to the internet? 10/10
        
       | pixelmonkey wrote:
       | A cool thing about Doug Lea's java.util.concurrent (received a
       | 10/10 rating here) is that its design also inspired Python's
       | concurrent.futures package. This is explicitly acknowledged in
       | PEP 3148[1] (under "Rationale"), a PEP that dates back to 2009.
       | 
       | [1]: https://peps.python.org/pep-3148/
        
       | nunobrito wrote:
       | Fully agree with most votings but 3/10 text blocks?!
       | 
       | That has got to be one of the most useful recent features. :-)
       | 
       | The pleasure of just copying and paste text in plain ASCII that
       | looks as intended rather than a huge encoded mess of "\r\n"+
       | concatenations.
       | 
       | But ok, I'm just an ASCII art fan. ^_^
        
       | w10-1 wrote:
       | It's nice to review the features, but the history of Java isn't
       | really about features or even programmer popularity.
       | 
       | (1) It was the first disruptive enterprise business model. They
       | aimed to make everyone a Java programmer with free access (to
       | reduce the cost of labor), but then charge for enterprise (and
       | embedded and browser) VM's and containers. They did this to
       | undercut the well-entrenched Microsoft and IBM. (IBM followed
       | suit immediately by dumping their high-end IDE and supporting the
       | free Eclipse. This destroyed competition from Borland and other
       | IDE makers tying their own libraries and programming models.)
       | 
       | (2) As an interpreted language, Java became viable only with good
       | JIT's. Borland's was the first (in JDK 1.1.7), but soon Urs
       | Holzle, a UCSB professor, created the HotSpot compiler that has
       | seeded generations of performance gains. The VM and JIT made it
       | possible to navigate the many generations of hardware delivering
       | and orders-of-magnitude improvements and putting software in
       | every product. Decoupling hardware and software reduced the
       | vertical integration that was killing customers (which also
       | adversely affected Sun Microsystems).
       | 
       | btw, Urs Holzle went on to become Google employee #8 and was
       | responsible for Google using massively parallel off-the-shelf
       | hardware in its data centers. He made Google dreams possible.
        
       ___________________________________________________________________
       (page generated 2025-10-11 23:00 UTC)