<?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 na SoftwareGarden.dev</title><link>https://softwaregarden.dev/pl/tags/java-28/</link><description>Ostatnie wpisy w Java 28 na SoftwareGarden.dev</description><generator>Hugo -- gohugo.io</generator><language>pl_PL</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/pl/tags/java-28/index.xml" rel="self" type="application/rss+xml"/><item><title>Java jeszcze nie umarła, ale Valhalli nie uniknie</title><link>https://softwaregarden.dev/pl/posts/new-java/valhalla/the-dawn/</link><pubDate>Wed, 28 Oct 2026 19:00:00 +0100</pubDate><guid>https://softwaregarden.dev/pl/posts/new-java/valhalla/the-dawn/</guid><description>&lt;p&gt;Niedawno zobaczyłem gdzieś w mediach społecznościowych fragment kodu. Jak mniemam, miał pokazać, że &amp;ldquo;Java jest zła i martwa&amp;rdquo;. Myślę, że to dobry moment, żeby przyjrzeć się niektórym twierdzeniom, nieprawdom i półprawdom, które pojawiły się w komentarzach i nie powiem, nawet mnie rozbawiły. Przy okazji odpowiem na część zarzutów, które padły podczas kilku wykładów konferencyjnych jesienią (sprawdza kalendarz) 2026 roku!&lt;/p&gt;
&lt;p&gt;TL;DR: kompaktowe pliki źródłowe już są z nami, obiekty &lt;em&gt;value&lt;/em&gt; z Valhalli nadchodzą, możesz nadal tkwić mentalnie w 2005 roku, ale miej świadomość, który rok mamy teraz.&lt;/p&gt;
&lt;h2 id="zagadka"&gt;Zagadka&lt;/h2&gt;
&lt;p&gt;Fragment kodu (odtwarzam go z pamięci) wyglądał mniej więcej tak:&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;Oczywiście, żeby udowodnić tezę, wykorzystywał &lt;code&gt;System.out.println()&lt;/code&gt;. Ponieważ nie żyję już na początku lat dwutysięcznych, pozwoliłem sobie unowocześnić go za pomocą &lt;code&gt;IO.println&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To może być jedna z tych zagadek, którymi &lt;del&gt;opchani własnym ego po grdykę&lt;/del&gt; Super Senior Software Engineerowie dręczą kandydatów ;-) Pozwólcie zatem, że zadam dwa pytania:&lt;/p&gt;
&lt;h2 id="pytania"&gt;Pytania&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Której wersji Javy potrzebujemy, żeby uruchomić ten kod?&lt;/li&gt;
&lt;li&gt;Co wypisze ten kod?&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="wersje"&gt;Wersje&lt;/h2&gt;
&lt;p&gt;Odpowiedź na pierwsze pytanie to (jeśli liczymy tylko funkcje GA) 25. Została wydana ponad rok temu! Dzięki &lt;a href="https://openjdk.org/jeps/512"&gt;JEP-512&lt;/a&gt; (oraz dwóm poprzedzającym go JEPom w wersji preview) naprawdę nie ma potrzeby tkwić w przeszłości i wciąż powtarzać: &amp;ldquo;och, uruchomienie czegokolwiek w Javie wymaga tyle ceremoniału&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Może nie dotarła do Ciebie notatka służbowa, a może ominęła Cię impreza sylwestrowa 2025/2026, ale teraz nie potrzebujesz już &lt;code&gt;public static void main (String[] args)&lt;/code&gt; opakowanej w &lt;code&gt;class&lt;/code&gt;. To znaczy, nadal możesz tak pisać, ale nie jest to obowiązkowe, zwłaszcza jeśli chcesz uczyć ludzi stawiających pierwsze kroki w Javie. A jako doświadczony Software Engineer możesz tego używać także do prototypowania!&lt;/p&gt;
&lt;p&gt;Co więcej, dostajemy zestaw wygodnych, przeciążonych metod &lt;code&gt;IO.println()&lt;/code&gt; i &lt;code&gt;IO.readln()&lt;/code&gt;, więc pisanie na standardowe wyjście i czytanie ze standardowego wejścia (czytaj: klawiatury) nie jest już tak upierdliwe. Jasne, jeśli &lt;code&gt;IO.&lt;/code&gt; przyprawia Cię o ból głowy, możesz wykorzystać &lt;code&gt;static import&lt;/code&gt;, ale dla nowicjuszy w inżynierii oprogramowania czyni to sprawy mniej oczywistymi, więc może jednak nie powinniśmy. Osobiście lubię ten prefiks, ponieważ jasno pokazuje intencję i to, że mamy do czynienia z WeWy (tak mówiliśmy na przełomie wieków na IO).&lt;/p&gt;
&lt;p&gt;Możesz więc skopiować powyższy kod, zapisać go w pliku, powiedzmy &lt;code&gt;riddle.java&lt;/code&gt;, a następnie uruchomić za pomocą Javy 25 lub nowszej:&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;I to naprawdę wszystko! Nie trzeba najpierw traktować go poleceniem &lt;code&gt;javac&lt;/code&gt;! Serio, mamy koniec 2026 roku; nie ma co marudzić o doświadczeniach naszych rodziców. Świat idzie naprzód, Java idzie naprzód, może my też powinniśmy?&lt;/p&gt;
&lt;h2 id="wynik"&gt;Wynik&lt;/h2&gt;
&lt;p&gt;Niektórym bardzo spodoba się odpowiedź na drugie pytanie, ponieważ&amp;hellip; &amp;ldquo;to zależy&amp;rdquo;! ;-)&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Zaraz, jak to zależy? Czy wynik nie powinien być zawsze taki sam?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Cóż, zwykle jest ;-) Zanim jednak na to odpowiemy, pozwólcie mi zboczyć z drogi i coś wyjaśnić.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Tak, w Javie nie można przeciążać operatorów (choć pozwalają na to nawet niektóre inne języki działające na JVMie).&lt;/li&gt;
&lt;li&gt;Tak, równość obiektów sprawdzamy za pomocą metody &lt;code&gt;equals&lt;/code&gt; (czy nam się to podoba, czy nie, jest, jak jest).&lt;/li&gt;
&lt;li&gt;Tak, operator &lt;code&gt;==&lt;/code&gt;,
&lt;ul&gt;
&lt;li&gt;w przypadku obiektów sprawdza, czy mamy do czynienia z tym samym obiektem, ponieważ sprawdza, gdzie obiekt znajduje się w pamięci,&lt;/li&gt;
&lt;li&gt;w przypadku typów prymitywnych porównuje ich wartość.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Przypomnienie: typy prymitywne w Javie to na przykład &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;i oraz &lt;code&gt;Integer&lt;/code&gt;y (podlegające [auto]boxingowi) są obiektami, a nie typami prymitywnymi. Dlatego jeśli mamy &lt;code&gt;Integer c = 128, d = 128;&lt;/code&gt;, a następnie wykonamy &lt;code&gt;c == d&lt;/code&gt;, porównujemy referencje, nie wartości przechowywane w obiektach utworzonych przez [auto]boxing.&lt;/p&gt;
&lt;h3 id="i-tutaj-robi-się-ciekawie"&gt;I tutaj robi się ciekawie&lt;/h3&gt;
&lt;p&gt;Dlatego &lt;code&gt;c == d&lt;/code&gt; daje &lt;code&gt;false&lt;/code&gt;: utworzyliśmy dwa różne obiekty, czy nam się to podoba, czy nie.
Ale &lt;code&gt;Integer a = 127, b = 127;&lt;/code&gt;, a następnie &lt;code&gt;a == b&lt;/code&gt;, daje nam&amp;hellip; &lt;code&gt;true&lt;/code&gt;. I tak, trzeba to w zasadzie wiedzieć, ponieważ &lt;code&gt;Integer&lt;/code&gt;y dla wartości od &lt;code&gt;-128&lt;/code&gt; do &lt;code&gt;127&lt;/code&gt; są przechowywane w puli. Kiedy więc poddamy je autoboxingowi, nie otrzymamy dwóch różnych instancji; zarówno &lt;code&gt;a&lt;/code&gt;, jak i &lt;code&gt;b&lt;/code&gt; wskazują na dokładnie ten sam obiekt. Wynik naszej zagadki to zatem:&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="to-zaraz-się-zmieni"&gt;To zaraz się zmieni&lt;/h2&gt;
&lt;p&gt;Kiedy? Najprawdopodobniej od marca 2027 roku, kiedy ma zostać wydana Java 28. A nawet wtedy nie dla wszystkich, tylko dla osób chętnych do wypróbowania funkcji preview ;-)&lt;/p&gt;
&lt;p&gt;Według dzisiejszych przewidywań Java 28 ma zawierać &lt;a href="https://openjdk.org/jeps/401"&gt;JEP 401&lt;/a&gt;, Value Objects (preview). Będzie to pierwsza wersja Javy, w której Value Objects staną się dostępne (poza wcześniejszymi specjalnymi buildami). Klasa &lt;code&gt;Integer&lt;/code&gt;, czyli główna bohaterka przykładu z tego wpisu, od Javy 16 &lt;a href="https://github.com/openjdk/jdk16/blob/4de3a6be9e60b9676f2199cd18eadb54a9d6e3fe/src/java.base/share/classes/java/lang/Integer.java#L71"&gt;jest oznaczona adnotacją &lt;code&gt;@ValueBased&lt;/code&gt;&lt;/a&gt;, a w Javie 28 &lt;a href="https://github.com/openjdk/jdk/blob/8c0d2c54ac1ea4073166b71f3687ffc56ef8674e/src/java.base/share/classes/java/lang/Integer.java#L86"&gt;jest także &lt;code&gt;value&lt;/code&gt;&lt;/a&gt;, jeśli zdecydujemy się na funkcje preview.&lt;/p&gt;
&lt;p&gt;Napiszę jeszcze więcej o obiektach &lt;code&gt;value&lt;/code&gt; w Javie, ponieważ teraz, dla nas, to już nie jest pieśń dalekiej przyszłości. Na razie krótkie wyjaśnienie: jeśli dodamy do klasy &lt;code&gt;value&lt;/code&gt;, JVM nie utworzy nowego obiektu tej klasy, o ile istnieje już jej obiekt przechowujący dokładnie taką samą wartość (lub wartości).&lt;/p&gt;
&lt;p&gt;Kiedy w naszym przykładzie wykorzystamy (wczesny build) Javy 28 z &lt;code&gt;--enable-preview&lt;/code&gt;, &lt;code&gt;Integer c = 128;&lt;/code&gt; utworzy nową instancję. Natomiast &lt;code&gt;Integer d = 128;&lt;/code&gt; nie utworzy kolejnej; dostaniemy ten sam obiekt, który został utworzony dla &lt;code&gt;c&lt;/code&gt;, a zatem &lt;code&gt;c == d&lt;/code&gt; da nam &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Rozumowanie, powiedziałbym, jest całkiem proste. &lt;code&gt;128&lt;/code&gt; to &lt;code&gt;128&lt;/code&gt;. Nie zmienia się. Gdyby się zmieniało, byłoby &lt;code&gt;127&lt;/code&gt; albo &lt;code&gt;129&lt;/code&gt;, a to zupełnie inna liczba. Nie musimy więc tworzyć opakowanego &lt;code&gt;128&lt;/code&gt; za każdym razem, gdy użytkownik go potrzebuje; możemy utworzyć je raz i (dopóki nie zostanie usunięte przez garbage collector) zwracać wciąż dokładnie ten sam obiekt reprezentujący &lt;code&gt;128&lt;/code&gt;. Nawet jeśli znajduje się poza &amp;ldquo;zakresem puli&amp;rdquo; &lt;code&gt;Integer&lt;/code&gt;ów.&lt;/p&gt;
&lt;p&gt;Na zagadkę można zatem odpowiedzieć także:&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;jeśli zaznaczymy, że uruchomiliśmy Javę 28 z włączonymi funkcjami preview, tak jak na zrzucie ekranu poniżej.&lt;/p&gt;
&lt;figure class="image image right"&gt;
&lt;img src="java28.png" alt="true false albo true true" width="772"&gt;
&lt;/figure&gt;
&lt;h2 id="podsumowanie"&gt;Podsumowanie&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Gdy chcesz ponarzekać na Javę, upewnij się, proszę, że narzekasz na którąś z ostatnich / najnowszą wersję. W przeciwnym razie to tak, jakby wyciągnąć starożytną mapę świata i upierać się, że Ziemia jest płaska, bo tak pokazuje mapa. Fun fact: jest okrągła. (Nawet jeśli tylko &amp;ldquo;okrągła niczym naleśnik&amp;rdquo;).&lt;/li&gt;
&lt;li&gt;Ocenianie różnych rzeczy, wyrabianie sobie zdania i dzielenie się nim w uprzejmy sposób to droga do postępu w ogólności, a w szczególności do postępu Javy; dlatego uruchamianie funkcji preview, korzystanie z modułów inkubacyjnych oraz dzielenie się tym, czego się nauczyliśmy, co zrobiliśmy, co nam się podobało lub nie, jest naszą drogą nowoczesnego samuraja.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;void main()&lt;/code&gt; istnieje i jest w porządku.&lt;/li&gt;
&lt;li&gt;Obiekty &lt;code&gt;value&lt;/code&gt; zaraz wstrząsną i zmienią nasze myślenie o przetwarzaniu i przechowywaniu danych w Javie.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Po więcej takich meta-narzekań naciśnij Subskrybuj i dzwoneczek :-P&lt;/p&gt;</description></item></channel></rss>