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.
If you have a hammer everything’s a nail.
I think Java 11 and higher are reasonably terse/expressive without being overly dense.
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.
I think the current future view is Withers ( https://github.com/openjdk/amber-docs/blob/master/eg-drafts/... ).
So I did some small standalone projects and demonstrated how much easier life was with this and other (more significant) changes. For example, we had loads of operational problems with dependency injection - the usual cognitive and debugging issues - so I threw all of that out too, along with the frameworks that implemented them. Things started booting in a few seconds instead of minutes and I’d say the lack of setters/getters was mostly done because I built trust in my team that I was making their lives better so they just followed me.
Probably not the answer you were looking for but there was friction from the devs and in the end I just showed them how much nicer life could be...
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.
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.
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.
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.