Celem laboratorium jest zapoznanie się z podstawowymi pojęciami oraz instrukcjami sterującymi w Javie.
Najważniejsze zadania:
- Konfiguracja środowiska.
- Stworzenie klasy
World
sterującej programem. - Stworzenie typu wyliczeniowego
MoveDirection
i narzędziaOptionsParser
.
Uwaga 1: Przed zainicjowaniem projektu zalecamy upewnić się, czy połączenie z Internetem jest stabilne i wystarczająco szybkie. Stworzenie projektu wymaga pobrania kilku dodatkowych narzędzi w tle. W szczególności NIE polecamy pracy na otwartej sieci AGH-Guest
(lepiej skorzystać z AGH-5
lub AGH-WPA
).
Uwaga 2: Projekt tworzony na zajęciach powinien znaleźć się w utworzonym wcześniej repozytorium Git. Kolejne laboratoria będą wymagały rozszerzania tego projektu o nowe elementy. Pamiętaj, by każdą laborkę rozpoczynać od utworzenia brancha z aktualnego stanu repo (np. "lab1"), a także o regularnym commitowaniu zmian i udostępnieniu gotowego rozwiązania w formie Pull Requesta do oceny zgodnie z wytycznymi prowadzącego. Zwracaj też uwagę na pliki, które commitujesz - nie umieszczaj w repo śmieci (w razie potrzebny zmodyfikuj .gitignore), jedynie sam kod i pliki konfiguracyjne gradle. Polecamy na początek zajrzeć do dodatkowej instrukcji o pracy z Gitem podczas laboratoriów.
-
Uruchom program IntelliJ.
-
Utwórz nowy projekt o nazwie
oolab
typu Gradle. Pamiętaj, by w kreatorze projektu ustawić poleLanguage
naJava
,Build system
naGradle
(a nie naIntelliJ
), aGradle DSL
najlepiej naGroovy
. Możesz wybrać (lub w razie potrzeby pobrać) najnowszą wersję JDK, ale zalecamy 21, ponieważ jest to wersja LTS i instrukcje do laboratoriów są o nią oparte. -
Po utworzeniu projektu poczekaj aż IntelliJ zainicjuje projekt - może to chwilę potrwać. Jeśli wszystko poszło ok, po lewej stronie zobaczysz drzewo katalogów. Katalog
java
(wsrc/main
) powinien mieć niebieską ikonę (oznacza to, że został wykryty jako katalog ze źródłami po zainicjowaniu przez Gradle). -
W katalogu
src/main/java/
utwórz pakietagh.ics.oop
(ppm nasrc/main/java
->New package
). Możesz też od razu usunąć ewentualne "śmieci" wygenerowane przez IntelliJ (pakietorg.example
). -
W pakiecie
agh.ics.oop
utwórz klasęWorld
ze statyczną metodąmain
. -
Zaimplementuj metodę
main
tak aby wyświetlały się dwa komunikaty:system wystartował
system zakończył działanie
-
Uruchom program, np. klikając zieloną ikonę pojawiającą się na początku linii, w której występuje metoda
main
. -
Dodaj metodę statyczną
run
, która jest wywoływana pomiędzy tymi komunikatami. -
Metoda
run
powinna informować o tym, że zwierzak idzie do przodu. -
Uruchom program.
-
Rozszerz metodę
run
tak, by akceptowała tablicę argumentów typuString
. Przekaż do niej tablicęargs
, która zawiera parametry wywołania programu. -
Po komunikacie o poruszaniu się do przodu wypisz w konsoli wartości wszystkich argumentów tej metody oddzielone przecinkami. Zwróć uwagę na to, żeby nie było nadmiarowych przecinków.
-
Uruchom program z dowolnymi parametrami (muszą występować co najmniej 2). W IntelliJ parametry programu możesz ustawiać po wejściu w konfigurację uruchomieniową (rozwijane menu z nazwą klasy -->
Edit configurations...
--> poleProgram arguments
). -
Zmodyfikuj program tak, aby interpretował wprowadzone argumenty:
f
- oznacza, że zwierzak idzie do przodu,b
- oznacza, że zwierzak idzie do tyłu,r
- oznacza, że zwierzak skręca w prawo,l
- oznacza, że zwierzak skręca w lewo,- pozostałe argumenty powinny być ignorowane.
-
Poruszanie się oraz zmiana kierunku ma być oznajmiana odpowiednim komunikatem. Program powinien akceptować dowolną liczbę argumentów. Przykładowo wprowadzenie sekwencji
f f r l
powinno dać w wyniku następujące komunikaty:- Start
- Zwierzak idzie do przodu
- Zwierzak idzie do przodu
- Zwierzak skręca w prawo
- Zwierzak skręca w lewo
- Stop
-
Zdefiniuj typ wyliczeniowy (enum)
MoveDirection
, który będzie zawierał wszystkie opcje ruchu (np.FORWARD
,BACKWARD
itp.). Enum powinien znajdować się w nowym pliku w pakiecieagh.ics.oop.model
(utwórz w tym celu pod-pakietmodel
). -
Zmodyfikuj program w ten sposób, aby metoda
run
nie akceptowała tablicy łańcuchów znaków, lecz tablicę wartości typu wyliczeniowego (enum
). W tym celu dodaj nową klasęOptionsParser
, zawierającą jedną statyczną metodę. Powinna ona przyjmować tablicę łańcuchów znaków i zwracać tablicęMoveDirection[]
. Niepoprawne opcje powinny być pomijane (tablica wynikowa powinna zawierać wyłącznie prawidłowe kierunki). Uwaga: Każdy plik.java
może zawierać tylko jedną klasę publiczną i nazwa klasy musi być identyczna z nazwą pliku (także pod względem wielkości liter). WięcOptionsParser
również powinien znaleźć się w osobnym pliku. Umieść go w głównym pakiecieagh.ics.oop
. -
Zweryfikuj poprawność działania programu poprzez jego uruchomienie.
-
Zamknij IntelliJ.
-
W pliku
build.gradle
w sekcjiplugins
dodaj linięid 'application'
:plugins { id 'application' id 'java' }
-
W tym samym pliku dodaj sekcję:
application { getMainClass().set('agh.ics.oop.World') }
-
W tym samym pliku dodaj sekcję:
java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } }
(możesz wybrać inną wersję Javy).
-
Otwórz konsolę (np. terminal/PowerShell).
-
Wywołaj komendę
export JAVA_HOME=/usr/lib/jvm/java-21
(pod Windows trzeba będzie ustawić zmienną środowiskową wskazującą na katalog, w którym zainstalowana jest Java). Komendę trzeba zaadaptować do lokalnej instalacji Javy! -
Uruchom program poleceniem
./gradlew run --args="f l"
(lubgradlew.bat ...
w systemie Windows) -
Zmodyfikuj argumenty wywołania i sprawdź zachowanie programu.
-
W programie Javy funkcja (a właściwie metoda)
main
musi być częścią jakiejś klasy. Jest ona punktem startowym programu. -
Metoda
main
akceptuje tablicę argumentów typuString
, ponadto jest publiczną metodą statyczną:public class World { public static void main(String[] args) { // treść metody } }
-
Do wypisywania komunikatów użyj metod
System.out.print()
orazSystem.out.println()
. -
Warunki logiczne w Javie są przechowywane w zmiennej typu
boolean
- nie ma automatycznej konwersji z innych typów. -
W Javie dostępna jest standardowa pętla
for
znana z C/C++. Można również użyć alternatywnej pętlifor
(tzw.for each
) do iterowania po elementach kolekcji:for (String argument : arguments) { }
-
Uwaga: W Javie łańcuchy znaków (oraz inne typy referencyjne) porównuje się za pomocą wywołania
equals
, np.string1.equals(string2)
. Zapisstring1 == string2
jest składniowo poprawny, ale sprawdza identyczność referencji. -
Typ wyliczeniowy deklaruje się za pomocą słowa kluczowego
enum
, np.:enum MoveDirection { FORWARD, BACKWARD, RIGHT, LEFT }
-
Typu wyliczeniowego można użyć odwołując się do jego składowych, np.:
MoveDirection direction = MoveDirection.FORWARD;
-
Instrukcję
switch
można używać m. in. na typach wyliczeniowych oraz napisach zarówno w formie instrukcji, jak i wyrażenia, którego wynik można przypisać do zmiennej (od Javy 14):switch (argument) { case "f" -> System.out.println("Do przodu"); case "b" -> System.out.println("Do tyłu"); } String message = switch (argument) { case "f" -> "Do przodu"; case "b" -> "Do tyłu"; default -> "Nieznana komenda"; }; System.out.println(message);
-
W Javie można dość łatwo przekazać fragment tablicy, np. jako rezultat wywołania funkcji lub jako argument pętli
for
. Służy do tego wywołanie:Arrays.copyOfRange(array, startInclusive, endExclusive);