Niedawno zobaczyłem gdzieś w mediach społecznościowych fragment kodu. Jak mniemam, miał pokazać, iż “Java jest zła i martwa”. Myślę, iż to dobry moment, żeby przyjrzeć się niektórym twierdzeniom, nieprawdom i półprawdom, które pojawiły się w komentarzach i nie powiem, choćby 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!
TL;DR: kompaktowe pliki źródłowe już są z nami, obiekty value z Valhalli nadchodzą, możesz przez cały czas tkwić mentalnie w 2005 roku, ale miej świadomość, który rok mamy teraz.
Zagadka
Fragment kodu (odtwarzam go z pamięci) wyglądał mniej więcej tak:
Oczywiście, żeby udowodnić tezę, wykorzystywał System.out.println(). Ponieważ nie żyję już na początku lat dwutysięcznych, pozwoliłem sobie unowocześnić go dzięki IO.println.
To może być jedna z tych zagadek, którymi opchani własnym ego po grdykę Super Senior Software Engineerowie dręczą kandydatów ;-) Pozwólcie zatem, iż zadam dwa pytania:
Pytania
- Której wersji Javy potrzebujemy, żeby uruchomić ten kod?
- Co wypisze ten kod?
Wersje
Odpowiedź na pierwsze pytanie to (jeśli liczymy tylko funkcje GA) 25. Została wydana ponad rok temu! Dzięki JEP-512 (oraz dwóm poprzedzającym go JEPom w wersji preview) naprawdę nie ma potrzeby tkwić w przeszłości i wciąż powtarzać: “och, uruchomienie czegokolwiek w Javie wymaga tyle ceremoniału”.
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ż public static void main (String[] args) opakowanej w class. To znaczy, przez cały czas możesz tak pisać, ale nie jest to obowiązkowe, zwłaszcza jeżeli chcesz uczyć ludzi stawiających pierwsze kroki w Javie. A jako doświadczony Software Engineer możesz tego używać także do prototypowania!
Co więcej, dostajemy zestaw wygodnych, przeciążonych metod IO.println() i IO.readln(), więc pisanie na standardowe wyjście i czytanie ze standardowego wejścia (czytaj: klawiatury) nie jest już tak upierdliwe. Jasne, jeżeli IO. przyprawia Cię o ból głowy, możesz wykorzystać static import, ale dla nowicjuszy w inżynierii systemu czyni to sprawy mniej oczywistymi, więc może jednak nie powinniśmy. Osobiście lubię ten prefiks, ponieważ jasno pokazuje intencję i to, iż mamy do czynienia z WeWy (tak mówiliśmy na przełomie wieków na IO).
Możesz więc skopiować powyższy kod, zapisać go w pliku, powiedzmy riddle.java, a następnie uruchomić dzięki Javy 25 lub nowszej:
I to naprawdę wszystko! Nie trzeba najpierw traktować go poleceniem javac! 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?
Wynik
Niektórym bardzo spodoba się odpowiedź na drugie pytanie, ponieważ… “to zależy”! ;-)
Zaraz, jak to zależy? Czy wynik nie powinien być zawsze taki sam?
Cóż, zwykle jest ;-) Zanim jednak na to odpowiemy, pozwólcie mi zboczyć z drogi i coś wyjaśnić.
- Tak, w Javie nie można przeciążać operatorów (choć pozwalają na to choćby niektóre inne języki działające na JVMie).
- Tak, równość obiektów sprawdzamy dzięki metody equals (czy nam się to podoba, czy nie, jest, jak jest).
- Tak, operator ==,
- w przypadku obiektów sprawdza, czy mamy do czynienia z tym samym obiektem, ponieważ sprawdza, gdzie obiekt znajduje się w pamięci,
- w przypadku typów prymitywnych porównuje ich wartość.
Przypomnienie: typy prymitywne w Javie to na przykład int, long, double, boolean. Stringi oraz Integery (podlegające [auto]boxingowi) są obiektami, a nie typami prymitywnymi. Dlatego jeżeli mamy Integer c = 128, d = 128;, a następnie wykonamy c == d, porównujemy referencje, nie wartości przechowywane w obiektach utworzonych przez [auto]boxing.
I tutaj robi się ciekawie
Dlatego c == d daje false: utworzyliśmy dwa różne obiekty, czy nam się to podoba, czy nie. Ale Integer a = 127, b = 127;, a następnie a == b, daje nam… true. I tak, trzeba to w zasadzie wiedzieć, ponieważ Integery dla wartości od -128 do 127 są przechowywane w puli. Kiedy więc poddamy je autoboxingowi, nie otrzymamy dwóch różnych instancji; zarówno a, jak i b wskazują na dokładnie ten sam obiekt. Wynik naszej zagadki to zatem:
To zaraz się zmieni
Kiedy? Najprawdopodobniej od marca 2027 roku, kiedy ma zostać wydana Java 28. A choćby wtedy nie dla wszystkich, tylko dla osób chętnych do wypróbowania funkcji preview ;-)
Według dzisiejszych przewidywań Java 28 ma zawierać JEP 401, Value Objects (preview). Będzie to pierwsza wersja Javy, w której Value Objects staną się dostępne (poza wcześniejszymi specjalnymi buildami). Klasa Integer, czyli główna bohaterka przykładu z tego wpisu, od Javy 16 jest oznaczona adnotacją @ValueBased, a w Javie 28 jest także value, jeżeli zdecydujemy się na funkcje preview.
Napiszę jeszcze więcej o obiektach value w Javie, ponieważ teraz, dla nas, to już nie jest pieśń dalekiej przyszłości. Na razie krótkie wyjaśnienie: jeżeli dodamy do klasy value, JVM nie utworzy nowego obiektu tej klasy, o ile istnieje już jej obiekt przechowujący dokładnie taką samą wartość (lub wartości).
Kiedy w naszym przykładzie wykorzystamy (wczesny build) Javy 28 z --enable-preview, Integer c = 128; utworzy nową instancję. Natomiast Integer d = 128; nie utworzy kolejnej; dostaniemy ten sam obiekt, który został utworzony dla c, a zatem c == d da nam true.
Rozumowanie, powiedziałbym, jest całkiem proste. 128 to 128. Nie zmienia się. Gdyby się zmieniało, byłoby 127 albo 129, a to zupełnie inna liczba. Nie musimy więc tworzyć opakowanego 128 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 128. choćby jeżeli znajduje się poza “zakresem puli” Integerów.
Na zagadkę można zatem odpowiedzieć także:
jeśli zaznaczymy, iż uruchomiliśmy Javę 28 z włączonymi funkcjami preview, tak jak na zrzucie ekranu poniżej.
Podsumowanie
- Gdy chcesz ponarzekać na Javę, upewnij się, proszę, iż narzekasz na którąś z ostatnich / najnowszą wersję. W przeciwnym razie to tak, jakby wyciągnąć starożytną mapę świata i upierać się, iż Ziemia jest płaska, bo tak pokazuje mapa. Fun fact: jest okrągła. (Nawet jeżeli tylko “okrągła niczym naleśnik”).
- 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.
- void main() istnieje i jest w porządku.
- Obiekty value zaraz wstrząsną i zmienią nasze myślenie o przetwarzaniu i przechowywaniu danych w Javie.
Po więcej takich meta-narzekań naciśnij Subskrybuj i dzwoneczek :-P









