
What's new in Java 12, 13 and 14 - sindrebn
https://java.christmas/2019/17
======
pron
One thing I find a bit disappointing is the focus on language features. Most
of the effort in Java goes into the VM and libraries, while keeping the
language conservative. This is because VM/library features have a much bigger
impact on application quality, and more directly impact the application's
users; moreover, it's a strategy that's proven quite successful -- HN
notwithstanding, most developers don't like too much change in the language.
Still, many developers focus on language changes that affect _them_ , rather
than major changes than can affect their customers and their business. Recent
versions have seen major improvements to the GCs, startup time, and there's an
exciting new Java Flight Recorder (low-overhead, deep in-production profiling)
feature in 14 that allows streaming flight recorder events.

Also, the bit about LTS is problematic. While the multiple LTS update paths
have their place (although the widely in their offerings and intended
audiences), they are not less risky than the default path. The default path is
designed to be the cheapest and easiest, but requires a little bit more
agility. The effort required to update to a new feature release is not much
bigger than the effort required to update to a patch release, especially as
some of the LTS programs have major new features in their "patches." An LTS
program should be chosen only once it's been established that the default,
recommended update path is not right for your organization, and even then
you'll need to compare the different LTS programs, as they differ from one
another in about as much as LTS differs from the regular update path. LTS
should not be the default choice.

~~~
sreque
Language changes are super important when they enable you to program in a new
way, or in that way with significantly less boilerplate. For instance, Java 8
enabled new ways of programming via Lambdas and structural typing. You could
code in that way before, but anonymous class boilerplate was so high that few
bothered, and those that did were hard-pressed to convince their colleagues of
its value.

The problem with language changes is that to make use of them, your developer
community has to educate themselves on the new features and how to use them.
Certain VM changes like new GC algorithms often don't require this, as the
basic interface of the GC is the same (clean up garbage for me, thanks!).

I think the next big programming style Java may enable is what I call data-
oriented programming, which is enabled via sealed types and pattern matching.
This enables you to code the dual of OO, where you have a fixed number of sub-
types but an unbounded number of operations. I believe this style of
programming is useful far more often than it is used, simply because Java
doesn't make it easy to code in this style.

Other future changes I am excited for, but don't expect to get implemented any
time soon, if ever, frankly, are:

* Improved native code interop. I consider this to be both a language and VM change. * Improved memory layout control, including stack-allocated types and inlined objects inside of other objects. * project loom for golang-style I/O programming. * full tail recursion. Why was this feature rejected from the VM?

~~~
pron
> Other future changes I am excited for, but don't expect to get implemented
> any time soon, if ever, frankly, are:

Most if not all of them will land in the next few years. In fact, working on
those precise features is what most of the OpenJDK team does.

> Improved native code interop. I consider this to be both a language and VM
> change.

That would be Project Panama, making its initial, partial delivery in JDK 14
(GA next March, EA available now).

> Improved memory layout control, including stack-allocated types and inlined
> objects inside of other objects.

Project Valhalla. The most complicated of the bunch. Just had a recent major
breakthrough, and you can work with the EA release already.

> project loom for golang-style I/O programming.

Working on it :)

> full tail recursion. Why was this feature rejected from the VM?

Not at all rejected. It's still a goal for Loom. We'll just do lightweight
concurrency first. Cost/benefit prioritization etc.

~~~
tempguy9999
Utterly dumb question but why is tail recursion necessary in the JVM given
that the compiler is better placed simply to turn recursion into a loop. TR
removal should be done best at the highest level I'd think.

~~~
pron
The compiler can only make this transformation in special cases, in
particular, when it doesn't break any of the JVM's semantics (also, not all
recursion is self-recursion, i.e. a tail call to the subroutine you're in).
You can't just discard a frame of a call in a tail position, because some
security mechanisms require knowing the full call-stack (plus, developers
might hate you when their stack traces start missing crucial frames). So we're
talking about explicit tail calls, in places that can be checked for the
safety of the optimization.

------
cies
Pattern matching in switch statements (calling them match statements would
then be more fitting), a nice way to deal with nulls, and proper sum types
(aka tagged unions, like enums in Rust) and Java would be pretty up-to-date.

~~~
MaxBarraclough
I'm still not sure why imperative/OOP language have been so resistant to
adding pattern-matching of the sort seen in Haskell and OCaml.

There are plenty of almost entirely pointless features that get implemented in
major languages, like 'events' in C#. They add almost no value to the
programmer. Pattern-matching would be really useful for avoiding rats' nests
of control-flow, but until recently no major imperative language even seemed
to consider adding them.

The extremely obscure Felix programming language has had pattern matching for
years. [0] As nestorD says, Rust has them now, as does Kotlin. About time.

[0] [http://felix-lang.github.io/felix/](http://felix-lang.github.io/felix/)

~~~
goto11
The reluctance might be because polymorphism and pattern matching are kind-of
solving the same problem from different angles.

~~~
dkarl
That's an interesting point. I've been wondering for a long time why a lot of
people who are exposed to pattern matching in Scala never start using it
themselves, even if they understand it well enough to read pattern matching
code without difficulty. It often offers a simple, transparent way to express
logic that looks very tricky using if/else, but despite seeing examples they
keep reaching for if/else even in awkward cases. And I've observed that they
end up adding methods to classes solely to be used in a single piece of
if/else business logic, which often (in my opinion) are the concern of the
business logic that uses them, not the concern of the class.

And I find that we disagree. When I frame a question as, "How does this
algorithm handle this value?" they frame it as, "How does this class behave in
this algorithm?" Is the difference in how the types are treated in the
algorithm best expressed as the concern of the class (via polymorphism) or as
the concern of the algorithm (via pattern-matching)?

I write a lot of OO code with polymorphic methods and am not opposed to
modeling things that way, but I think it's often not the best way. I feel like
business logic that could be expressed coherently in a single place gets
scattered across many classes, and to understand the algorithm you have to
gather the logic from a bunch of different places and reconstruct it. Not only
that, classes accumulate little fragments of logic that belong to disparate
concerns that are supposed to be handled elsewhere. If you have polymorphism
and not pattern matching, this is inevitable. If you have both, it can be
avoided.

------
bendiksolheim
Java is actually getting quite a few nice features these days. I am especially
excited about these improvements to the `switch` statement – I have always
felt that the `switch` statement is more or less useless in its current form.
Now, if it only had exhaustiveness..

------
skocznymroczny
I'm more looking forward to things like Project Panama.

A big gap between Java and C# is value types and better interop with native
code ("pointers"). ByteBuffers in Java are painful for many usages and very
poor compared to things like [StructLayout(LayoutKind.Sequential)] in C#.

------
EnderMB
As someone that used to write a lot of C#, I find that the language is
changing so often that it's hard to know what's new and what's been around for
years.

In contrast, Java hasn't changed all that much over the years, and I wonder if
an approach of taking the more useful features from C# and ignoring some of
the others would be a good approach.

I often wonder how Java developers feel when they look over at C#, and see a
language that has exploded in functionality over the last decade, all while
Java has mainly optimised the JVM and slowly added features.

~~~
pron
It's not taking some features and _ignoring_ others. It's taking features than
have shown good cost/benefit, and _not_ taking those that haven't. The choice
here is about which features _not_ to adopt, just as much as it is about which
features to adopt. Java's philosophy is still innovation in the VM while
keeping the language conservative. It's just that conservative is a relative
term, here. If some language feature seems to have a good cost/benefit ratio
_and_ it's become mainstream enough, Java will adopt it.

BTW, Java has also "exploded in functionality over the last decade", it just
hasn't translated to _language_ changes. Even the project I work on, adding
lightweight concurrency, will not change the language at all, while in C# it
took the form of a _huge_ language change (async/await). Nevertheless, in Java
the added functionality will be at least the same as it's been in .NET.

~~~
mumblemumble
> It's taking features than have shown good cost/benefit, and not taking those
> that haven't.

I actually wonder if it's more taking features that have proven sexy, and
ignoring the rest. I still think that the single biggest source of verbosity -
and design damage in some of the newer APIs such as streams - is that Java
hasn't implemented extension methods. That costs me time and money on a
regular basis. By comparison, the cost of fall through by default in switch
statements is that I have to use a linter. Which I already have to do for a
fistful of other reasons, anyway, so, while this -> operator certainly
scratches an itch I've had, it doesn't move the needle much in terms of
productivity or code quality.

 _edit_ : Should add, in C#'s defense - .NET's lightweight concurrency was
initially implemented as a library. C#'s async/await came later, and is just
syntactic sugar as far as I've ever been able to tell.

~~~
pron
First, no language feature has been shown to move the needle much in terms of
productivity or code quality. We are unable to detect differences between
(reasonable) language choices, let alone individual features, so it's mostly
about ergonomics. I'd be extremely surprised if you could show that any
feature or lack thereof actually costs you money, but if you could, that would
be quite a discovery. As to extension methods, they're not ignored. The
language team is just unconvinced it's a good feature, which doesn't mean
there aren't people who like it. As to switch statements, the language team
had actually analyzed many hundreds of millions of lines of code before
committing to the feature.

~~~
mumblemumble
> First, no language feature has been shown to move the needle much in terms
> of productivity or code quality.

Absolutely true. When I've looked at that research, I was really quite
impressed by how little has gone into looking into it, considering how
interesting the subject is to so many people. My guess would be that it's
because it's prohibitively expensive to study. That said, there was one result
that I believe was shown to be fairly robust, and independent of language:
that bug rate and cost are both generally proportional to lines of code
written.

To that extent that that may be true, while I certainly don't have a $500,000
study by a team of professors at Stanford to back me, there's at least a
plausible basis for my own perception of doing better work in object-oriented
languages that do or do not have some sort of mixin mechanism: I find that
using them often lets me get the same job done in less code. (Without that, I
admit I have to retreat to pointing out that absence of evidence is not
evidence of absence.)

There's also the design damage thing. Some developers on my team are quite
resistant to using streams instead of loops in Java, and it's precisely
because of the poor ergonomics. If you need to do an operation that isn't
built into the Java API, you have some sub-par options: You can implement a
collector, which is justifiably criticized as being a hassle (6 methods to
implement) that yields code that scans poorly (every other verb is "collect").
Or you can implement a function, but using that function requires breaking the
flow of the stream code by creating a bunch of intermediate variables, or,
worse, constructing a pyramid of doom. By contrast, when we're working in
Kotlin, you can just write a function and deploy it the same way you'd deploy
any other method in its equivalent APIs. It's less effort, it's less code
(read: stuff to get wrong), and, perhaps critically, it's a lot less annoying.

~~~
pron
What operation that isn't in the stream API would you say you need most often?

------
lemagedurage
The new style of switch statements is very nice. I've found myself using if
else blocks to replace switch statements because they're simply more legible,
and they take up less vertical space. Now the new style switch statements will
be an improvement over that.

~~~
aliakhtar
Its copied from Scala pattern matching, and still isn't as good as it.

~~~
pron
Almost all features in the Java language are guaranteed to be copied from
other languages because it is in Java's "charter" not to introduce features
that haven't been tried in other languages first, and then copy only those
that have shown a good cost/benefit. The question you should ask is not which
features are copied, but which ones _aren 't_.

------
maximente
what's up with all these .christmas domains appearing high on HN listings?

there appear to be accounts dedicated to posting from javascript.christmas,
java.christmas, and functional.christmas , all of the same style/format/etc.

the only posts they submit are from those domains. is this a coordinated
boosting effort?

functional.christmas =>
[https://news.ycombinator.com/submitted?id=bendiksolheim](https://news.ycombinator.com/submitted?id=bendiksolheim)

javascript.christmas =>
[https://news.ycombinator.com/submitted?id=ewendel](https://news.ycombinator.com/submitted?id=ewendel)

~~~
oauea
Looks like spam. I've flagged the most recent posts, hopefully the mods see
this.

~~~
volkk
how is it spam if it's just shared various blog posts from a single website?

------
nikeee
If I'm not mistaking, there is no JEP for making throw statements expressions.
Is there an obvious thing that I'm missing here? It would make sense for
concise method bodies [1] and throwing in switch expression branches more
consistent (over making exceptions for throw statements). Also, C# did the
same thing.

[1]:
[https://openjdk.java.net/jeps/8209434](https://openjdk.java.net/jeps/8209434)

------
toopok4k3
Why are they spewing Java versions so quickly? I have barely moved to 8 yet.

~~~
cstuder
Java moved to a six-months release cycle in 2017:
[https://en.wikipedia.org/wiki/Java_version_history](https://en.wikipedia.org/wiki/Java_version_history)

Java 8 had its end-of-life for commercial usage in january 2019. The new long
term release is Java 11.

Time to move on for you.

~~~
tristanperry
Some companies spend longer than six months to discuss/agree to a 'major
version upgrade' of software.

Naturally the gap between (say) Java 10 and 11 is fairly small, meaning it
shouldn't take many months to merely discuss an upgrade - but not all
companies have got round to the regular-release way of thinking.

~~~
qw
Java 8 was released March 18, 2014, so they had 5 years to upgrade.

But I see your point about the new release schedule, where the LTS version is
not supported after 6 months.

I think the companies need to change their mindsets. New Java version are
backwards compatible, as they introduce changes gradually.

It is actually more dangerous to wait, because they risk that some features
(like GC) are deprecated after 4-5 versions. By updating regularly and keeping
an eye on deprecated features, they should have time to adjust

~~~
vbezhenar
I still need to pass weird flags for Tomcat to make it work under Java 9+,
almost 6 years later. Modules were a mistake. If not for modules, a lot of
people would have migrated to 9+.

~~~
ivolimmen
Modules where not a mistake but we will likely benefit from it in say at least
5 years. Every artifact/library you use has to be a (real) module to be able
to use it's full potential.

~~~
jillesvangurp
I've yet to see a real world use that is meaningful. Mostly it just adds
deployment bureaucracy for opting in to stuff that used to be there by
default. I'm not seeing a huge adoption of modules outside of Java's core
libraries.

A good thing that came out of it was that it forced them to untangle the 2
decades old standard library. This was disruptive but it seems to have also
unblocked a bit of progress and also allows the to have experimental modules
in non lts releases (9,10,12,13).

------
MockObject
I really wish they would use a numbering scheme that used points for the non-
LTS releases: 8.0, 8.1, 8.2, 9.0...

~~~
colejohnson66
I’m wondering when Java 2 comes. Java 12 is actually 1.12...

~~~
kjeetgill
They dropped the pretend Java 7 => Java 1.7 thing already. They don't even do
7u80 style versions anymore.

~~~
colejohnson66
Really? When?

EDIT: It went Java 1.4 -> 5.0[0]

[0]:
[https://en.wikipedia.org/wiki/Java_version_history](https://en.wikipedia.org/wiki/Java_version_history)

------
iainmerrick
That “instanceof” change looks strictly worse than Kotlin’s “smart casts”
(after checking x is an instance of Y, x implicitly casts to Y as long as its
value doesn’t change).

The new Java shorthand, by introducing a new variable name, also introduces
some sneaky variable shadowing risks (as this blog post itself explains!)

 _Edit to add:_ maybe the difficulty is in formally specifying “smart casts”,
or at least clearly documenting them? I don’t think Jetbrains has documented
all the rules used by Kotlin. It doesn’t seem undoable, though.

------
dry_soup
Cached:
[https://web.archive.org/web/20191217093210/https://java.chri...](https://web.archive.org/web/20191217093210/https://java.christmas/2019/17/)

(Google hasn't cached it yet as of this writing)

~~~
matsemann
Curios, why post this?

~~~
dry_soup
Because I tried to access the page a few times over a two-hour period, and it
always timed out.

------
splittingTimes
Will we ever get to see golang-style multiple return values/results?

~~~
rohan1024
Method chaining becomes complicated if you have multiple return values. In Go,
you can't return error values if you want to do method chaining. Error
handling then becomes even more complicated.

~~~
Polyisoprene
I would like to have the result type for this, like in Rust:

enum Result<T, E> { Ok(T), Err(E), }

~~~
lllr_finger
I've implemented this in Kotlin with sealed classes, and it's slowly taking
over within our org. You don't get a few things (like the ? sugar) but it's
still really nice.

I have no idea why the Kotlin std lib has a Result type but limits it to
exceptions - such a missed opportunity.

------
cutler
When is Java going to fix its ugliest wart - regex backslashitis? Seriously,
which other language in 2019 requires you to escape every sodding backslash in
a regex?

~~~
doyoung
Second that. It's the most annoying thing in Java.

------
zelly
Every language is becoming Rust. I love it.

------
gigatexal
off-topic: What a cool TLD!

~~~
ksec
You have got to be joking, now Christmas is a domain?

~~~
trewtey
Why not? There was a lot of pressure on .com, now with all these GTLDs it's
easy and cheap to find a cute name.

------
kimi
"Welcome to Kotlin"?

------
hildaman
Soon Java will become the new PERL with 20 ways to do the same thing &
developers will have to spend hours on Google trying to figure out what that
wierd bit of syntax actually does.

------
ken
It seems that most languages these days are on a path to adding as much syntax
as possible. Is there no limit? The mainstream languages are already too
complex for me to understand fully, let alone use effectively.

We used to joke about APL (the "beautiful diamond") and Lisp (the "ball of
mud"). Lisp was big, at the time, but most of it is what we'd call the
standard library today. The actual core was quite small, and everything was
remarkably coherent for a system of its size. Today, many core languages are
as big as all of Common Lisp.

When I see a language add new syntax for a trivial transformation, in the
compiler because the language isn't extensible, using ASCII art because
they've run out of symbols on the keyboard, it just looks like the worst of
APL combined with the worst of Lisp.

~~~
bartread
I'm not sure what you're objecting to here. The switch enhancements, in
particular, seem to me to reduce boilerplate and improve readability. If I
ever go back to spending time in Java I'll certainly be using them.

------
vturner
Sigh, I know new language features are cool, but I highly doubt the growing
dominance of Python and JS is a question primarily of language features.
Python has a REPL and the outstanding tooling built on that along with an
ecosystem of libraries where a default use case is the design choice. That all
leads to "fast" development which what a lot of people care about. JS has the
default use app deployment area: browser.

Meanwhile Java's REPL is a pretty sad imitation, and I see no movement toward
trying to get back in the user app space.

I love the JVM and the language itself is good enough, but the management of
Java features through the years leaves me disappointed.

* I know Android is Java and Kotlin focused but Android development is entirely different than writing a JavaSE app. Also know Kotlin compiles to JS, and I think that supports my grumpy young man persona. A hugely successful language IDE company saw it useful to build a cross compiling language on your platform.

~~~
smitty1e
Right, but will We Assembly be a JS killer?

If I can stay in Python and target the browser without the fuss and bother of
JavaScript, why would I?

~~~
zelly
WASM won't kill JavaScript because there is a whole generation of programmers
that actually prefers it to Python etc. and goes out of their way to use it
(nodejs).

There are also more technical reasons like WASM not being able to access DOM.

------
nennes
Is it me or does the below sound condescending?

 _Trying new features is a good way to broaden your skill set, and if there is
something you strongly dislike about the usability of a feature you can even
provide feedback to the JDK developers._

To me it reads like: Try our experimental features because that will make you
a better (rounded | paid) developer, and if you really really want you may
even provide feedback.

~~~
jlillesand
No offense, but that's probably you. Even if I try to read that as
condescending, I have a hard time doing it.

I read that as: trying new stuff in code generally makes you a better
programmer. And when you test stuff that's still in an experimental phase, the
language designers are probably still open to feedback from the broader
public.

~~~
nennes
None taken! I'm getting allergic to corpo talk lately and it looks like I'm
overreacting!

