Java pierwszy program: main, javac i nowa składnia Javy 25
Czas czytania: 13 minut

Java pierwszy program to klasa z metodą main, którą kompilujecie poleceniem javac, a uruchamiacie poleceniem java. Od Javy 25 ten sam program może mieć jedną linijkę w metodzie void main() i obywać się bez deklaracji klasy, bo funkcja z JEP 512 przestała być podglądem i jest częścią języka. W tej lekcji poznacie oba zapisy i dowiecie się, kiedy który ma sens.

To czwarta lekcja kursu Javy dla testerów. Pod filmem jest pełna wersja tekstowa: budowa klasy z main, kompilacja i uruchomienie z terminala, nowa składnia Javy 25, sześć typowych błędów z prawdziwymi komunikatami kompilatora, pierwszy program, który otwiera przeglądarkę, oraz ćwiczenie z rozwiązaniem. Każdy przykład uruchomiliśmy 10 października 2026 roku na JDK Temurin 25.0.2, a przykłady dla starszej wersji na Temurin 21.0.12.1.

Jak wygląda pierwszy program w Javie?

Klasyczny pierwszy program w Javie ma pięć linii i każda coś znaczy. Zapiszcie go w pliku HelloWorld.java. Nazwa pliku musi być dokładnie taka jak nazwa publicznej klasy, z wielkimi literami włącznie.

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Witaj, testerze!");
    }
}
Fragment Co oznacza
public class HelloWorld deklaracja klasy; każdy kod w klasycznej Javie mieszka w jakiejś klasie
public static void main(String[] args) punkt wejścia programu, od którego maszyna wirtualna zaczyna wykonanie
static metodę można wywołać bez tworzenia obiektu klasy
void metoda niczego nie zwraca
String[] args argumenty podane w wierszu poleceń, przydadzą się w ćwiczeniu
System.out.println(...) wypisanie tekstu i przejście do nowej linii na standardowym wyjściu
; i { } średnik kończy instrukcję, nawiasy klamrowe wyznaczają bloki

Według specyfikacji języka Java SE 25 (rozdział 12.1, 2025) maszyna wirtualna zaczyna wykonanie od metody main wskazanej klasy. Do Javy 24, poza trybem podglądu, taka metoda musiała być publiczna, statyczna i przyjmować tablicę napisów, stąd ta słynna linijka, którą pokolenia programistów przepisywały, zanim zrozumiały z niej choć połowę.

Jak skompilować i uruchomić program z terminala?

Program w Javie przechodzi dwa etapy. Kompilator javac zamienia kod źródłowy na kod bajtowy w pliku .class, a polecenie java uruchamia ten kod bajtowy w maszynie wirtualnej. Dlatego ten sam plik .class działa na Windows, macOS i Linuxie.

Droga od kodu do wyniku

1. Kod źródłowy

HelloWorld.java, tekst, który piszecie w edytorze

2. javac

kompilator sprawdza składnię i typy, przy błędzie zatrzymuje się z komunikatem

3. Kod bajtowy

HelloWorld.class, niezależny od systemu operacyjnego

4. java

maszyna wirtualna ładuje klasę i wywołuje main

Cały scenariusz lekcji Java pierwszy program zamyka się w dwóch poleceniach. W terminalu, w katalogu z plikiem:

javac HelloWorld.java
java HelloWorld
Witaj, testerze!

Zwróćcie uwagę, że przy java podajecie nazwę klasy, bez rozszerzenia. Kompilujecie plik, uruchamiacie klasę. Po kompilacji w katalogu pojawi się plik HelloWorld.class. Istnieje też skrót: według JEP 330 od Javy 11 polecenie java HelloWorld.java kompiluje plik w pamięci i od razu go uruchamia, bez zostawiania pliku .class. Według JEP 458 od Javy 22 ten sam tryb obsługuje program złożony z kilku plików źródłowych. Do nauki i krótkich skryptów to wygoda, ale w projekcie Maven z poprzedniej lekcji kompilacją i tak zajmuje się Maven.

Co zmienia Java 25: compact source files i instancyjna metoda main

Java 25 pozwala napisać ten sam program bez deklaracji klasy, bez public, bez static i bez parametru args. Według strony JEP 512 w OpenJDK funkcja ma status Closed / Delivered w wydaniu 25, czyli jest stałą częścią języka, a nie podglądem włączanym flagą. Wcześniej przeszła cztery rundy podglądu: w Javie 21 (JEP 445), 22 (JEP 463), 23 (JEP 477) i 24 (JEP 495). Zapiszcie plik Witaj.java:

void main() {
    IO.println("Witaj, testerze! To compact source file z Javy 25.");
}
java Witaj.java
Witaj, testerze! To compact source file z Javy 25.

Ten zapis to tak zwany compact source file, czyli zwarty plik źródłowy. Klasa nadal istnieje, tylko kompilator deklaruje ją za Was. Według JEP 512 nowa klasa IO leży w pakiecie java.lang, więc nie wymaga importu, ale jej metody wywołujecie z nazwą klasy, czyli IO.println, a nie samym println. Zwarty plik źródłowy automatycznie importuje też klasy z modułu java.base, dlatego poniżej List działa bez żadnej linii import:

void main(String[] args) {
    String srodowisko = args.length > 0 ? args[0] : "test";
    int liczbaTestow = 3;
    IO.println("Środowisko: " + srodowisko);
    IO.println("Do uruchomienia: " + liczbaTestow + " testy logowania");
    List<String> przegladarki = List.of("chromium", "firefox", "webkit");
    IO.println("Przeglądarki: " + przegladarki);
}
java Logowanie.java
Środowisko: test
Do uruchomienia: 3 testy logowania
Przeglądarki: [chromium, firefox, webkit]
Cecha Klasyczna klasa Compact source file (Java 25+)
Deklaracja klasy wymagana brak, kompilator tworzy klasę sam
Metoda startowa public static void main(String[] args) void main() albo void main(String[] args)
Wypisanie tekstu System.out.println IO.println albo System.out.println
Importy java.lang automatycznie, reszta ręcznie cały moduł java.base automatycznie
Pakiet dowolny brak, plik żyje poza pakietami
Najlepsze zastosowanie projekty, testy, frameworki nauka, skrypty, szybkie próby

Uruchomienie zwartego pliku na starszej Javie kończy się błędem kompilacji. Tak zareagował javac z JDK 21 na plik Witaj.java:

Witaj.java:1: error: unnamed classes are a preview feature and are disabled by default.
void main() {
^
  (use --enable-preview to enable unnamed classes)
1 error

Na stronie wprowadzenia do kursu ten sam plik daje inny komunikat: implicitly declared classes are not supported in -source 21. To nie sprzeczność, tylko inny kompilator. Powyżej odpowiada javac z JDK 21, który zna tę funkcję jako podgląd pod starą nazwą „unnamed classes”. Komunikat z wprowadzenia daje javac z JDK 25 uruchomiony z opcją --release 21: kompilator zna już funkcję pod nową nazwą, ale odmawia jej użycia, bo każecie mu celować w Javę 21. Oba komunikaty sprawdziliśmy 11.10.2026.

Jedna funkcja, trzy nazwy

W komunikacie z JDK 21 widać nazwę „unnamed classes”. To nie pomyłka: według historii opisanej w JEP 512 funkcja zaczynała jako klasy nienazwane, potem nazywała się „implicitly declared classes”, a w Javie 25 przyjęła nazwę compact source files. Jeśli więc w starszym kursie albo na Stack Overflow traficie na którąkolwiek z tych nazw, chodzi o to samo. A flaga --enable-preview z komunikatu na Javie 21 nie jest dobrym pomysłem w projekcie testów: podgląd zmieniał się między wersjami, więc kod z Javy 21 nie musi skompilować się na Javie 25.

IntelliJ IDEA od wersji wspierającej Javę 25 ma osobny szablon pliku. Według dokumentacji JetBrains tworzycie go przez New | Java Compact File, a gdy program urośnie, akcja Convert into a regular class (Alt+Enter na void main()) zamieni go w zwykłą klasę, którą przeniesiecie do pakietu.

Który zapis wybrać w kursie i w testach?

Wasz Java pierwszy program może mieć dowolną z dwóch form. W kursie zobaczycie oba zapisy, a w projektach testów prawie zawsze klasyczny. Test JUnit to metoda w klasie w pakiecie, uruchamiana przez framework, a nie przez main, więc zwarty plik źródłowy nie ma w nim zastosowania. Zwarty plik świetnie sprawdza się za to w trzech sytuacjach, które tester zna z codziennej pracy:

  • szybkie sprawdzenie, jak działa metoda z biblioteki standardowej, zanim użyjecie jej w teście;
  • mały skrypt, który generuje dane testowe albo czyta plik z wynikami;
  • nauka składni, gdy nie chcecie jeszcze myśleć o pakietach i modyfikatorach dostępu.

Jeśli Wasz projekt w pracy jest na Javie 21, a w wielu firmach tak jest, piszcie klasycznie. Według harmonogramu wsparcia Oracle z 2026 roku Java 21 ma wsparcie Premier do września 2028, więc ten kod jeszcze długo będzie żył obok nowego.

Jakie błędy popełniają początkujący?

Java pierwszy program rzadko kompiluje się za pierwszym razem i to dobra wiadomość, bo komunikaty kompilatora uczą najszybciej. Wszystkie komunikaty poniżej wywołaliśmy celowo na JDK 25. Kompilator Javy mówi po angielsku i bywa lakoniczny, ale zawsze podaje plik, numer linii i znaczek ^ pod miejscem, w którym się zgubił.

Błąd Komunikat Poprawka
nazwa pliku inna niż klasy class HelloWorld is public, should be declared in a file named HelloWorld.java zmieńcie nazwę pliku albo klasy, wielkość liter też się liczy
brak średnika ';' expected dopiszcie średnik na końcu wskazanej linii
mała litera w System package system does not exist Java rozróżnia wielkość liter: System
polskie cudzysłowy „ ” illegal character: '\u201e' w kodzie tylko proste cudzysłowy "
uruchamianie pliku .class Could not find or load main class HelloWorld.class java HelloWorld, bez rozszerzenia
brak metody main Main method not found in class BezMain dodajcie metodę main

Dwa z tych błędów w pełnej postaci, bo ich wygląd warto zapamiętać. Brak średnika:

Srednik.java:3: error: ';' expected
        System.out.println("Brakuje średnika")
                                              ^
1 error

I polskie cudzysłowy, które wpadają do kodu przy kopiowaniu z dokumentu tekstowego albo z czatu. Edytor tekstu chciał dobrze, typograficznie ładnie, a kompilator odpowiada dwoma błędami, po jednym na każdy elegancki znak.

Cudzyslow.java:3: error: illegal character: '\u201e'
        System.out.println(„Polski cudzysłów”);
                           ^
Cudzyslow.java:3: error: illegal character: '\u201d'
        System.out.println(„Polski cudzysłów”);
                                            ^

Zasada przy czytaniu komunikatów: zaczynajcie od pierwszego błędu na liście. Jeden brakujący średnik albo nawias potrafi wywołać kilka kolejnych komunikatów, które znikną same po poprawce pierwszego.

Java pierwszy program w pracy testera: Playwright w metodzie main

Metoda main to najkrótsza droga do sprawdzenia, czy narzędzie w ogóle działa na Waszym komputerze, zanim zbudujecie wokół niego testy. Dokumentacja Playwright for Java zaczyna dokładnie od takiego programu. Poniższy kod uruchamia przeglądarkę Chromium bez okna, otwiera stronę i wypisuje jej tytuł. Wymaga projektu Maven z lekcji o IntelliJ i zależności com.microsoft.playwright:playwright, według Maven Central w wersji 1.63.0 z września 2026 roku. Według dokumentacji Playwright wymaga Javy 8 lub nowszej, więc JDK 25 z poprzednich lekcji wystarczy z zapasem.

package pl.qualityisland;

import com.microsoft.playwright.Browser;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;

public class PierwszyPlaywright {

    public static void main(String[] args) {
        try (Playwright playwright = Playwright.create()) {
            Browser browser = playwright.chromium().launch();
            Page page = browser.newPage();
            page.navigate("https://qualityisland.pl/");
            System.out.println("Tytuł strony: " + page.title());
        }
    }
}

Uruchomiliśmy ten program w projekcie Maven na JDK 25. Wynik:

Tytuł strony: Quality Island firma QA, testy oprogramowania, szkolenia IT

Widzicie w nim wszystko z tej lekcji: pakiet, klasę, metodę main i System.out.println. Następnym krokiem jest zamiana wypisywania tytułu na asercję w teście JUnit, co pokazujemy na szkoleniu automatyzacja testów z Playwright w Javie. Jeśli w Waszym zespole standardem jest Selenium, ta sama ścieżka prowadzi przez szkolenie automatyzacja testów Selenium WebDriver. W naszej praktyce zachęcamy, żeby pierwszy program uruchomić w terminalu, a nie tylko zieloną strzałką w IDE, bo dokładnie tak, poleceniem w konsoli, uruchamia kod pipeline CI. W Quality Island przeszkoliliśmy ponad 2 500 specjalistów i tę radę warto przyjąć od pierwszego dnia nauki.

Ćwiczenie z rozwiązaniem

Zadanie: napiszcie program DaneTestowe, który przyjmuje z wiersza poleceń imię i nazwę środowiska, a wypisuje login testowy w formacie imie.srodowisko@example.com małymi literami. Gdy argumentów brak, ma użyć wartości Anna i test. Napiszcie dwie wersje: zwarty plik źródłowy dla Javy 25 i klasyczną klasę dla Javy 21.

To zadanie łączy wszystko z lekcji Java pierwszy program: metodę main, argumenty i wypisywanie tekstu. Rozwiązanie dla Javy 25:

void main(String[] args) {
    String imie = args.length > 0 ? args[0] : "Anna";
    String srodowisko = args.length > 1 ? args[1] : "test";
    String email = imie.toLowerCase() + "." + srodowisko + "@example.com";
    IO.println("Użytkownik testowy: " + imie);
    IO.println("Login: " + email);
}

Rozwiązanie dla Javy 21 i starszych projektów:

public class DaneTestowe {
    public static void main(String[] args) {
        String imie = args.length > 0 ? args[0] : "Anna";
        String srodowisko = args.length > 1 ? args[1] : "test";
        String email = imie.toLowerCase() + "." + srodowisko + "@example.com";
        System.out.println("Użytkownik testowy: " + imie);
        System.out.println("Login: " + email);
    }
}
java DaneTestowe.java
java DaneTestowe.java Marek staging
Użytkownik testowy: Anna
Login: anna.test@example.com
Użytkownik testowy: Marek
Login: marek.staging@example.com

Zapis warunek ? a : b to operator warunkowy: gdy argument istnieje, bierze go, w przeciwnym razie wartość domyślną. Więcej o warunkach znajdziecie w lekcji o instrukcji warunkowej if. Klasyczną wersję uruchomiliśmy na JDK 21 i dała identyczny wynik. Typ String i metodę toLowerCase() omawiamy dokładniej w lekcji o łańcuchach znakowych, a skąd w ogóle typy danych, wyjaśnia lekcja o typach danych w Javie.

Poprzednia lekcja3. IntelliJ IDEA: pierwszy projektSpis kursuWszystkie lekcje kursu JavyNastępna lekcja5. Komentarze w kodzie

O tym, jak programowanie zmienia codzienną pracę testerów i zespołów QA, piszemy także na portalu Strefa QA, skierowanym do zespołów jakości i ich liderów.

Co zabrać z tego artykułu

01Java pierwszy program w klasycznej postaci to klasa z public static void main(String[] args), a nazwa pliku musi zgadzać się z nazwą publicznej klasy.

02Kompilujecie plik (javac HelloWorld.java), uruchamiacie klasę (java HelloWorld); od Javy 11 działa też java HelloWorld.java.

03W Javie 25 compact source files i void main() są finalne (JEP 512); na Javie 21 ten zapis się nie skompiluje.

04W projektach testów piszecie klasy w pakietach, zwarte pliki zostawcie na naukę i skrypty.

05Czytajcie pierwszy komunikat kompilatora: plik, numer linii i znaczek ^ wskazują miejsce błędu.

Źródło: OpenJDK (JEP 330, 458, 512), specyfikacja Java SE 25, Playwright for Java; kod uruchomiony 10.10.2026 na Temurin 25.0.2 i 21.0.12.1.

Na szkoleniu Java dla testerów przechodzicie od pierwszego programu do testów automatycznych z trenerem i na własnym projekcie, bez kopiowania gotowców.

Zobacz szkolenie z Javy


Powiązane na blogu Quality Island

Pełna lista źródeł

Co o tym sądzisz?

Dodaj komentarz

Bądź na bieżąco
Strefa QA, portal z eksperckimi artykułami o jakości oprogramowania
Bądź na bieżąco
AI Act w wyrobach medycznych
AI Act w wyrobach medycznych: testy i dokumentacja AI pod MDR

1690,00 PLN

30.11.26, 18.01.27, 08.03.27
1 dzień
AI Act w bankowości i ubezpieczeniach
AI Act w bankowości i ubezpieczeniach: scoring kredytowy, wycena ubezpieczeń i FRIA

1690,00 PLN

27.11.26, 15.01.27, 05.03.27
1 dzień
Testowanie systemów AI wysokiego ryzyka pod AI Act
Testowanie systemów AI wysokiego ryzyka pod AI Act: dokumentacja testowa i QMS dla dostawców

2390,00 PLN

26.11.26, 14.01.27, 04.03.27
2 dni
Popularne artykuły
Język Gherkin: co to jest i jak go używać w testowaniu oprogramowania
Smoke test: co to jest, kiedy go uruchamiać i czym różni się od sanity testu
Jak zostać testerem oprogramowania: ścieżka krok po kroku bez dyplomu informatyka
Najnowsze artykuły
Ile kosztują testy oprogramowania: cennik i czynniki ceny
Strategia testowania w organizacji: czego uczy nas case PKO BP
Koszt zespołu QA: własny zespół czy outsourcing? Rachunek dla CTO na 2026 rok
Popularne kategorie