<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Java 28 on SoftwareGarden.dev</title><link>https://softwaregarden.dev/en/tags/java-28/</link><description>Recent content in Java 28 on SoftwareGarden.dev</description><generator>Hugo -- gohugo.io</generator><language>en_GB</language><copyright>© Piotr Przybył SoftwareGarden.dev CC BY-NC-SA 4.0</copyright><lastBuildDate>Wed, 28 Oct 2026 19:00:00 +0100</lastBuildDate><atom:link href="https://softwaregarden.dev/en/tags/java-28/index.xml" rel="self" type="application/rss+xml"/><item><title>Java isn't dead yet, but it can't avoid Valhalla</title><link>https://softwaregarden.dev/en/posts/new-java/valhalla/the-dawn/</link><pubDate>Wed, 28 Oct 2026 19:00:00 +0100</pubDate><guid>https://softwaregarden.dev/en/posts/new-java/valhalla/the-dawn/</guid><description>&lt;p&gt;Recently, somewhere on social media, I saw a code snippet. I guess the intention was to show how &amp;ldquo;Java is bad and dead&amp;rdquo;. I think it&amp;rsquo;s a good time to focus on some claims, falsehoods and half-truths that appeared in the comments, which I found pretty amusing. It also answers some of the criticisms raised in conference talks in autumn (checks the calendar) of 2026!&lt;/p&gt;
&lt;p&gt;TL;DR: compact source files are already here, value objects from Valhalla are coming, you can keep your head in 2005, but be aware what year it is now.&lt;/p&gt;
&lt;h2 id="the-riddle"&gt;The riddle&lt;/h2&gt;
&lt;p&gt;The snippet (I&amp;rsquo;m recreating it from memory) was something like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;void&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; Integer a &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 127,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; b &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 127,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; c &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 128,
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; d &lt;span style="color:#f92672"&gt;=&lt;/span&gt; 128;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IO.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(a &lt;span style="color:#f92672"&gt;==&lt;/span&gt; b);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; IO.&lt;span style="color:#a6e22e"&gt;println&lt;/span&gt;(c &lt;span style="color:#f92672"&gt;==&lt;/span&gt; d);
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Of course, to prove the point, it was using &lt;code&gt;System.out.println()&lt;/code&gt;. Since I no longer live in early 2000s, I allowed myself to go more modern, hence &lt;code&gt;IO.println&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This might be one of the riddles that &lt;del&gt;pretending to be clever&lt;/del&gt; Super Senior Software Engineers use to torment candidates ;-) So let me ask you two questions:&lt;/p&gt;
&lt;h2 id="the-questions"&gt;The questions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;What Java version do I need to run this code?&lt;/li&gt;
&lt;li&gt;What is the output of this code?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="the-versions"&gt;The versions&lt;/h2&gt;
&lt;p&gt;The answer to the first one is (if we count only GA features) 25. It was released over a year ago! With &lt;a href="https://openjdk.org/jeps/512"&gt;JEP-512&lt;/a&gt; (and two preview JEPs before it), there&amp;rsquo;s really no need to keep your head in the past and keep saying, &amp;ldquo;oh, Java needs so much ceremony to start&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Maybe you didn&amp;rsquo;t get the memo, or maybe you missed the Happy New Year 2026 party, but now you don&amp;rsquo;t need &lt;code&gt;public static void main (String[] args)&lt;/code&gt; wrapped in a &lt;code&gt;class&lt;/code&gt;. I mean, you still can, but that&amp;rsquo;s not mandatory, especially if you wish to teach people so they can take their first steps in Java. Or, as an experienced Software Engineer, you can use it for prototyping too!&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s more, it comes with a bunch of handy overloaded &lt;code&gt;IO.println()&lt;/code&gt; and &lt;code&gt;IO.readln()&lt;/code&gt; methods, so writing to standard output and reading from standard input (think: keyboard) is not a tedious task. And sure, if &lt;code&gt;IO.&lt;/code&gt; is too much of a headache for you, you can use a &lt;code&gt;static import&lt;/code&gt;, but that makes things more obscure for newcomers to software engineering, so maybe we shouldn&amp;rsquo;t. Personally, I like this prefix because it clearly shows the intent and that IO is involved.&lt;/p&gt;
&lt;p&gt;So, you can copy the code above, save it to a file, say &lt;code&gt;riddle.java&lt;/code&gt;, and then run it with Java 25 or later:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;java riddle.java
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;That&amp;rsquo;s really all that&amp;rsquo;s needed! You don&amp;rsquo;t need to &lt;code&gt;javac&lt;/code&gt; it first! Seriously, it&amp;rsquo;s late 2026; no need to whine about your parents&amp;rsquo; experience. The world moves on, Java moves on, maybe you should too?&lt;/p&gt;
&lt;h2 id="the-output"&gt;The output&lt;/h2&gt;
&lt;p&gt;Some people will love the answer to the second question, because&amp;hellip; &amp;ldquo;it depends&amp;rdquo;! ;-)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Wait, what do you mean it depends? Shouldn&amp;rsquo;t it always be the same?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;And most of the time it is ;-) But before we answer this, allow me to detour via some explanations.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Yes, in Java you can&amp;rsquo;t override operators (which is allowed even in some other JVM languages).&lt;/li&gt;
&lt;li&gt;Yes, the equality of objects is checked with the &lt;code&gt;equals&lt;/code&gt; method (like it or not, it is what it is).&lt;/li&gt;
&lt;li&gt;Yes, the &lt;code&gt;==&lt;/code&gt; operator,
&lt;ul&gt;
&lt;li&gt;in the case of objects, actually checks if we&amp;rsquo;re dealing with the same object, because it checks where the object is located in memory,&lt;/li&gt;
&lt;li&gt;in the case of primitive values, compares, well, their value.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Reminder: in Java primitive types are like &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;long&lt;/code&gt;, &lt;code&gt;double&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;. &lt;code&gt;String&lt;/code&gt;s and &lt;code&gt;Integer&lt;/code&gt;s (which are [auto]boxed) are objects, not primitive types. Therefore, if you have &lt;code&gt;Integer c = 128, d = 128;&lt;/code&gt; and later on you &lt;code&gt;c == d&lt;/code&gt;, then you&amp;rsquo;re comparing the references, not the values stored in the [auto]boxed objects.&lt;/p&gt;
&lt;h3 id="heres-where-things-get-a-bit-tricky"&gt;Here&amp;rsquo;s where things get a bit tricky&lt;/h3&gt;
&lt;p&gt;This is why &lt;code&gt;c == d&lt;/code&gt; yields &lt;code&gt;false&lt;/code&gt;: we created two different objects, like it or not.
But &lt;code&gt;Integer a = 127, b = 127;&lt;/code&gt; followed by &lt;code&gt;a == b&lt;/code&gt; gives us&amp;hellip; &lt;code&gt;true&lt;/code&gt;. And yes, you kinda have to know this, because the &lt;code&gt;Integer&lt;/code&gt;s for values between &lt;code&gt;-128&lt;/code&gt; and &lt;code&gt;127&lt;/code&gt; are pooled. So when you autobox them, you won&amp;rsquo;t get two different instances; both &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; point to the very same object. So the output of our riddle is:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;false&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="its-about-to-change"&gt;It&amp;rsquo;s about to change&lt;/h2&gt;
&lt;p&gt;When? Most probably since March 2027, when Java 28 is going to be released. And even then, not for everyone, but only for folks eager to try preview features ;-)&lt;/p&gt;
&lt;p&gt;As of today, Java 28 is expected to come with &lt;a href="https://openjdk.org/jeps/401"&gt;JEP 401&lt;/a&gt;, Value Objects (preview). It&amp;rsquo;s going to be the first Java version with Value Objects available (apart from previous custom builds). The very example we&amp;rsquo;re focusing on in this post, the &lt;code&gt;Integer&lt;/code&gt; class, since Java 16, &lt;a href="https://github.com/openjdk/jdk16/blob/4de3a6be9e60b9676f2199cd18eadb54a9d6e3fe/src/java.base/share/classes/java/lang/Integer.java#L71"&gt;has been annotated with &lt;code&gt;@ValueBased&lt;/code&gt;&lt;/a&gt;, and in Java 28 &lt;a href="https://github.com/openjdk/jdk/blob/8c0d2c54ac1ea4073166b71f3687ffc56ef8674e/src/java.base/share/classes/java/lang/Integer.java#L86"&gt;it is also a &lt;code&gt;value&lt;/code&gt;&lt;/a&gt;, if you decide to go with preview features.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ll write more about value objects in Java, since right now, for us, the masses, they&amp;rsquo;re no longer beyond the horizon. For now, the short explanation is: if you add &lt;code&gt;value&lt;/code&gt; to a class, the JVM won&amp;rsquo;t create a new object for this class as long as there is already an object of this class which holds exactly the same value(s).&lt;/p&gt;
&lt;p&gt;In our example, when we run it using (an early build of) Java 28 with &lt;code&gt;--enable-preview&lt;/code&gt;, &lt;code&gt;Integer c = 128;&lt;/code&gt; creates a new instance. And &lt;code&gt;Integer d = 128;&lt;/code&gt; doesn&amp;rsquo;t create a new one; instead, we get the same object which was created for &lt;code&gt;c&lt;/code&gt;, hence &lt;code&gt;c == d&lt;/code&gt; gives us &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The reasoning behind this is quite straightforward, I&amp;rsquo;d say. &lt;code&gt;128&lt;/code&gt; is &lt;code&gt;128&lt;/code&gt;. It doesn&amp;rsquo;t change. If it did, it&amp;rsquo;d be &lt;code&gt;127&lt;/code&gt; or &lt;code&gt;129&lt;/code&gt;, and that&amp;rsquo;s a completely different number, so we don&amp;rsquo;t have to create a boxed &lt;code&gt;128&lt;/code&gt; every time the user wants one; we can create it just once and (as long as it&amp;rsquo;s not garbage collected) keep returning the very same object representing &lt;code&gt;128&lt;/code&gt;. Even if it&amp;rsquo;s outside &amp;ldquo;the pooled range&amp;rdquo; of &lt;code&gt;Integer&lt;/code&gt;s.&lt;/p&gt;
&lt;p&gt;So you can also answer the riddle with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-java" data-lang="java"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;if you specify you ran Java 28 with preview features enabled, as shown in the screenshot below.&lt;/p&gt;
&lt;figure class="image image right"&gt;
&lt;img src="java28.png" alt="true false or true true" width="772"&gt;
&lt;/figure&gt;
&lt;h2 id="summary"&gt;Summary&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Whenever you want to rant about Java, please make sure you rant about a recent / the latest version. Otherwise, it&amp;rsquo;s as if you pulled out an ancient map of the world and kept arguing the Earth is flat because the map says so. Guess what: it is round. (Even if just &amp;ldquo;round as a pancake&amp;rdquo;.)&lt;/li&gt;
&lt;li&gt;Evaluating things, having an opinion, and sharing it in a polite way are key to progress in general, and Java&amp;rsquo;s progress in particular; so running preview features, using incubation modules, and sharing what you&amp;rsquo;ve learnt, did or didn&amp;rsquo;t like, is simply awesome.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;void main()&lt;/code&gt; is a thing and it&amp;rsquo;s fine.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;value&lt;/code&gt; objects are about to shake and (re-)shape how we think about processing and storing data in Java.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For more meta-rants like this, please hit Subscribe and the bell button :-P&lt;/p&gt;</description></item></channel></rss>