PROGRAMOWANIE W JĘZYKU JavaSpis treści ROZDZIAŁ I WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW. 4 1. PODSTAWOWE INFORMACJE O JĘZ...
ROZDZIAŁ I WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW. 4 1. PODSTAWOWE INFORMACJE O JĘZYKU JAVA ................................................................................................... 4 1.1. O języku Java.......................................................................................................................................... 4 1.2. Wirtualna maszyna Javy......................................................................................................................... 6 1.3. Charakterystyka języka Java – podstawowe pojęcia .............................................................................. 7 2. TWORZENIE PROGRAMU W JAVIE .................................................................................................................... 7 2.1. Tekst źródłowy w Javie ........................................................................................................................... 8 2.2. Kompilacja programu............................................................................................................................. 8 2.3. Interpretacja programu przez wirtualną maszynę JVM ......................................................................... 8 3. ŚRODOWISKO PROGRAMISTYCZNE NETBEANS ................................................................................................ 9 3.1. Co to jest NetBeans?............................................................................................................................... 9 3.2 Pobieranie NetBeans ............................................................................................................................... 9 3.3. Instalacja programu NetBeans ............................................................................................................. 10 3.4. Uruchomienie programu NetBeans i tworzenie projektów................................................................... 14 ROZDZIAŁ II PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ 17 1. TYPY DANYCH ............................................................................................................................................... 17 1.1. Liczby całkowite ................................................................................................................................... 17 1.2. Liczby zmiennoprzecinkowe.................................................................................................................. 17 1.3. Typ znakowy ......................................................................................................................................... 18 1.4. Typ logiczny.......................................................................................................................................... 18 2. UśYWANIE ZMIENNYCH I STAŁYCH ............................................................................................................... 18 2.1. Nazywanie zmiennych........................................................................................................................... 18 2.2. Przypisanie i inicjalizacja zmiennych................................................................................................... 19 2.3. Stałe i ich uŜywanie .............................................................................................................................. 19 3. OPERATORY .................................................................................................................................................. 20 3.1. Operatory inkrementacji i dekrementacji ............................................................................................. 20 3.2. Operatory arytmetyczne i relacji .......................................................................................................... 20 3.3. Operatory logiczne ............................................................................................................................... 21 3.4. Operatory bitowe.................................................................................................................................. 21 3.5. Rzutowane............................................................................................................................................. 22 3.6. Kolejność wykonywania działań........................................................................................................... 22 3.7. Łańcuchy i operacje na łańcuchach ..................................................................................................... 23 ROZDZIAŁ III PĘTLE I INSTRUKCJE WARUNKOWE ....................................................................................................... 25 1. INSTRUKCJA WARUNKOWA............................................................................................................................ 25 2. PĘTLE OKREŚLONE I NIEOKREŚLONE ............................................................................................................. 26 2.1. Pętle while i do ..................................................................................................................................... 26 2.2 Pętla for................................................................................................................................................. 29 3. INSTRUKCJA WIELOKROTNEGO WYBORU ....................................................................................................... 31 ROZDZIAŁ IV ZMIENNE TABLICOWE.................................................................................................................................. 35 1. INICJALIZACJA TABLIC I TABLICE ANONIOMOWE ........................................................................................... 35 2. KOPIOWANIE TABLIC ..................................................................................................................................... 36 3. SORTOWANIE TABLIC .................................................................................................................................... 37 4. TABLICE WIELOWYMIAROWE ........................................................................................................................ 38
ROZDZIAŁ V OBIEKTY, KLASY, METODY I POLA.......................................................................................................... 41 1. OBIEKTY ....................................................................................................................................................... 41 2. KORZYSTANIE Z ISTNIEJĄCYCH KLAS ............................................................................................................ 41 3. TWORZENIE WŁASNYCH KLAS ....................................................................................................................... 44 4. POLA I METODY ............................................................................................................................................. 45 5. KONSTRUKTORY ........................................................................................................................................... 47 6. POLA I METODY STATYCZNE .......................................................................................................................... 50 6.1. Pola statyczne....................................................................................................................................... 50 6.2. Stałe ...................................................................................................................................................... 52 6.3. Metody Statyczne .................................................................................................................................. 54 ROZDZIAŁ VI APLIKACJE OKIENKOWE ............................................................................................................................ 58 1. TWORZENIE APLIKACJI OKIENKOWYCH PRZY UśYCIU BIBLIOTEKI SWING ..................................................... 58 2. UMIESZCZANIE INFORMACJI W OKNIE – PRACA Z PANELAMI ......................................................................... 60 3. RYSOWANIE W JAVIE ..................................................................................................................................... 62 4. OBSŁUGA ZDARZEŃ ....................................................................................................................................... 64 ROZDZIAŁ VII TWORZENIE APLETÓW ................................................................................................................................ 67 1. TWORZENIE PROSTEGO APLETU ..................................................................................................................... 68 2. OBSŁUGA ZDARZEŃ W APLETACH.................................................................................................................. 70 3. PRZEKAZYWANIE PARAMETRÓW DO APLETÓW.............................................................................................. 71 ROZDZIAŁ VIII ZADANIA DO SAMODZIELNEGO WYKONANIA ..................................................................................... 76 ROZDZIAŁ IX PRZYKŁADOWE ROZWIĄZANIA I ODPOWIEDZI DO WYBRANYCH ZADAŃ................................ 77 ZADANIE 1. ....................................................................................................................................................... 77 ZADANIE 2. ....................................................................................................................................................... 77 ZADANIE 3. ....................................................................................................................................................... 78 ZADANIE 9. ....................................................................................................................................................... 78 ZADANIE 10. ..................................................................................................................................................... 81
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Rozdział I Wirtualna maszyna Javy i programy wspomagające tworzenie programów 1. Podstawowe informacje o języku Java
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Niezawodność i bezpieczeństwo W zamierzeniu Java miała zastąpić C++ - obiektowego następcę języka C. Jej projektanci zaczęli od rozpoznania cech języka C++, które są przyczyną największej liczby błędów programistycznych, by stworzyć język prosty w uŜyciu, bezpieczny i niezawodny. O ile po pięciu odsłonach Javy jej prostota jest dyskusyjna, o tyle język faktycznie robi duŜo, by utrudnić programiście popełnienie błędu. Przede wszystkim Java ma system wyjątków czyli sytuacji, gdy kod programu natrafia na nieprzewidywane trudności, takie jak np.: • • •
operacje na elemencie poza zadeklarowaną granicą tablicy lub elemencie pustym czytanie z niedostępnego pliku lub nieprawidłowego adresu URL podanie nieprawidłowych danych przez uŜytkownika
W innych językach programowania programista oczywiście moŜe wprowadzić wewnętrzne testy sprawdzające poprawność danych, pozycję indeksu tablicy, inicjalizację zmiennych itd., ale jest to jego dobra wola i nie jest to jakoś szczególnie wspierane przez dany język. W Javie jest inaczej - obsługa wyjątków jest obowiązkowa, bez tego program się nie skompiluje. Przy tym obiekty wchodzące w skład pakietu standardowego Javy (i gros obiektów z pakietów pochodzących od powaŜnych programistów niezaleŜnych) implementują wyjątki w kaŜdym miejscu kodu, którego wykonanie jest niepewne ze względu na okoliczności zewnętrzne. Sama obsługa wyjątków polega na napisaniu kodu, który wykona się w odpowiedzi na taką sytuację nadzwyczajną. MoŜe to być np. podstawienie wartości domyślnej przy natrafieniu na nieprawidłową wartość parametru, zaniechanie danej akcji i powrót do stanu stabilnego czy choćby zapisanie pracy przed wyjściem. W sytuacji wyjątkowej program przerywa normalne wykonanie i tworzy specjalny obiekt wyjątku odpowiedniej klasy, który "wyrzuca" z normalnego biegu programu. Następnie zdefiniowany przez uŜytkownika kod "łapie" ten obiekt wyjątku i podejmuje odpowiednie działanie. Działanie moŜe być dwojakiego typu: wspomniane wyŜej środki zaradcze lub odrzucenie takiego "śmierdzącego jaja" dalej, do bloku programu, który nakazał wykonanie wadliwej operacji. Takie podawanie sobie wyjątku moŜe być wieloetapowe i jeśli skończy się w bloku głównym programu powoduje jego przerwanie i ogłoszenie błędu krytycznego. Oprócz systemu wyjątków Java od wersji 1.4 ma dwa inne systemy wspomagające pisanie niezawodnych programów: logowanie i asercje. Pierwsze pozwalają na zapisanie w plikach dziennika przebiegu działania programu, z dodatkową moŜliwością filtrowania zawartości, określenia poziomu logowanych błędów itp. Drugie rozwiązanie pozwala na upewnienie się, Ŝe pewne załoŜenia co do określonych wyraŜeń (np. Ŝe liczba, z której wyciągamy pierwiastek jest nieujemna) są prawdziwe. Asercje są o tyle ciekawe, Ŝe działają tylko z odpowiednią opcją wykonania programu, dzięki czemu programista moŜe sprawdzić działanie programu, a później bez wysiłku spowodować pominięcie testowej części kodu po prostu przez ominięcie tej opcji. Krytyka i kontrowersje Język Java pomimo swoich wielu zalet, ma wiele wad w tym takie, które wzbudzają liczne kontrowersje: •
Najczęściej wymienianą wadą języka Java jest to, Ŝe programy pisane w Javie wykonują się wolniej niŜ programy pisane w językach natywnie kompilowanych (np. C++). Zarzut ten odnosi się szczególnie do starych wersji Javy, kiedy zaawansowane mechanizmy takie jak JIT albo współbieŜny odśmiecacz nie były dostępne. Obecnie zdania są mocno podzielone. MoŜna podać przykłady programów zarówno takich,
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
•
•
•
które w Javie będą wykonywały się wolniej niŜ w C++, jak i takich, które będą wykonywały się szybciej. Javie zarzuca się, Ŝe niezbyt dobrze nadaje się do zastosowań czasu rzeczywistego. Głównym problemem jest brak przewidywalności wydajności oraz nieoczekiwane przestoje powodowane działaniem odśmiecacza. W nowych wersjach Javy ten drugi problem został radykalnie ograniczony, jednak nadal do zastosowań czasu rzeczywistego lepiej stosować języki natywnie kompilowane. Często Javie zarzucane jest to, Ŝe ma mniejszą funkcjonalność niŜ np. C++, co ogranicza programistę. Jako przykład przywołuje się czasami fakt, Ŝe aby uruchomić niewielki program trzeba napisać dłuŜszy kod programu. Niektórzy jednak zwracają uwagę, Ŝe równieŜ język C++ nie ma wielu elementów, które moŜna znaleźć w Javie jak np. klasy anonimowe, garbage collector, system pakietów, dynamiczne ładowanie klas czy reflection API. Java wymusza konwersję typów prostych (np. int) na odpowiadający typ referencyjny (np. java.lang.Integer) przy pracy z kolekcjami, co moŜe mieć negatywny wpływ na wydajność w specyficznych sytuacjach i zmniejsza czytelność programu. Typy generyczne, wprowadzone w wersji 5 oraz tzw. autoboxing, czyli automatyczna konwersja pomiędzy typami prostymi i ich obiektowymi odpowiednikami usunęły problem czytelności. Programista moŜe juŜ takŜe wybrać, jakim algorytmem zostanie zaimplementowana dana kolekcja (np. lista moŜe być zaimplementowana jako tablica o zmiennym rozmiarze, drzewo, albo lista jednokierunkowa), co pozwala na poprawienie wydajności.
JRE a JDK Pakiety z hierarchii java i javax (dodatki wprowadzone w późniejszych wersjach) naleŜą do podstawowego zestawu klas rozprowadzanych jako Java. Zestaw ten jest dostępny w dwóch wersjach: JRE (Java Runtime Environment) - udostępnia bytecode wszystkich klas standardowych i wirtualną maszynę do ich uruchamiania, zaś JDK (Java Development Kit) dodatkowo udostępnia źródła tych klas oraz dodatkowe narzędzia takie jak kompilator, paker czy debuger. Podział ten wprowadzono dlatego, Ŝe uŜytkownik Javy do uruchamiania programów potrzebuje tylko JRE, natomiast do programowania działających aplikacji potrzeba juŜ JDK.
1.2. Wirtualna maszyna Javy Wirtualna maszyna Javy (ang. Java Virtual Machine, w skrócie JVM) to niezaleŜny od platformy system uruchomieniowy dla programów. Standardowo słuŜy programom napisanym w języku Java, ale moŜna go uŜywać takŜe jako środowisko uruchomieniowe takŜe dla innych języków, np. Jython to implementacja Pythona właśnie na JVM. Programy napisane dla maszyny wirtualnej Javy są niezaleŜne od platformy dzięki temu, Ŝe uruchamiane są bezpośrednio w JVM (po konwersji na kod pośredni, poprzez kompilator jak javac dla programów Javy lub w locie jak dla wspomnianego wyŜej Jythona), a nie w rodzimym środowisku. MoŜna je uruchomić na dowolnym komputerze i systemie operacyjnym na którym istnieje JVM. Poza tym moŜna je uruchamiać przez klasyczną kompilację kodu źródłowego do maszynowego, umoŜliwia to na przykład kompilator GCJ z pakietu GCC.
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW Wirtualna maszyna Javy jest dostępna dla wielu platform. Istnieją róŜne jej implementacje, zwykle będące częścią całego pakietu narzędzi Javy, oraz samodzielne projekty jak na przykład JikesRVM, Kaffe, SableVM czy CACAO, które zazwyczaj dla swojego działania korzystają z zestawu standardowych bibliotek Javy GNU Classpath. Sun Microsystems, firma która stworzyła język Java, wraz z pakietem Java Runtime Environment dostarcza maszynę wirtualną. Od wersji 1.3 domyślną maszyną wirtualną jest HotSpot. Starsze wersje maszyn wirtualnych miały problemy z wydajnością. Działo się tak, poniewaŜ maszyny były interpreterami kodu pośredniego języka Java. Obecne implementacje maszyn wirtualnych stosują kompilację kodu pośredniego do kodu maszynowego w trakcie uruchomienia (just-in-time compilation). Dzięki zastosowaniu tej technologii nowoczesne maszyny wirtualne niewiele ustępują wydajnością powszechnie uŜywanym kompilatorom innych języków.
1.3. Charakterystyka języka Java – podstawowe pojęcia 1) Obiektowy język Java – składnia języka podobna do języka C++. Pliki źródłowe: nazwa_klasy_publicznej.java, gdzie nazwa musi być nazwą klasy publicznej, zdefiniowanej w tym pliku. 2) Kompilator przetwarza program nazwa_klasy_publicznej.java na kod binarny zwany B-kod (bytecode, J-code) Pliki po kompilacji: nazwa_klasy_publicznej.class B-kod moŜe być zinterpretowana i wykonywana przez maszynę wirtualną Java (JVM Java Virtual Machine), czyli urządzenie logiczne 3) Maszyna wirtualna Java (JVM Java Virtual Machine). JVM jest abstrakcyjnym komputerem, który wykonuje programy nazwa.class: a. interpretator wbudowany w przeglądarkę WWW, b. oddzielny program, c. Just-In-Time (na maszynie, na której program zostaje uruchomiony, maszyna wirtualna przeprowadza kompilację kodu pośredniego do kodu maszynowego.) 4) Biblioteka Javy – pakiety z oprogramowaniem wspomagającym tworzenie programów działających w sieci np. Internet, umoŜliwiającym tworzenie interfejsu uŜytkownika, ogólnego przeznaczenia.
2. Tworzenie programu w Javie W języku Java jest moŜliwe utworzenie: •
Aplikacji (application) - programem interpretującym aplikacje jest uruchamiany w systemie operacyjnym plik znajdujący się w pakiecie JRE - java.exe
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW Program musi zawierać między innymi jeden moduł źródłowy, którego klasa publiczna zawiera publiczną metodę klasową o nagłówku public static void main(String args[]) •
Aplet (applet) – program interpretujący aplety jest wbudowany np. w przeglądarkę WWW Program zawierający między innymi jeden moduł źródłowy, którego klasa publiczna zawiera miedzy innymi podstawowe metody: init(), start(), stop(), paint(), reprint(), destroy() Uwaga: moŜliwe jest napisanie programu w Javie, który będzie pracował jako aplet i jako aplikacja.
2.1. Tekst źródłowy w Javie public class Witaj { public static void main(String args[]) { System.out.print("Dzien dobry, nazywam się Jan Kowalski\n"); } }
2.2. Kompilacja programu javac Witaj.java gdzie połoŜenie (katalog) programu javac (kompilator Javy) powinno być znane systemowi operacyjnemu, a katalog bieŜący powinien zawierać plik źródłowy Witaj.java. Zostanie wygenerowany plik Witaj.class z instrukcjami dla JVM
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Interpretator java (połoŜenie znane systemowi operacyjnemu) • wyszuka plik o nazwie Witaj.class w katalogu bieŜącym • sprawdzi, czy klasa Witaj posiada publiczną metodę statyczną main • wykona instrukcje zawarte w bloku funkcji main, czyli wyświetli na ekranie napis Dzień dobry, nazywam się Jan Kowalski i przejdzie do następnego wiersza
3. Środowisko programistyczne NetBeans
3.1. Co to jest NetBeans? NetBeans IDE to zintegrowane środowisko programistyczne (IDE) dla języka Java, którego głównym celem jest przyśpieszenie budowy aplikacji Java, w tym równieŜ usług sieciowych oraz aplikacji mobilnych. Wymagania systemowe Przed zainstalowaniem NetBeans IDE musi w systemie być zainstalowane oprogramowanie JDK (Java SE Development Kit (JDK) 5.0 Update 19 (wersja 1.5.0_19) lub JDK 6 Update 14). Jeśli nie ma oprogramowania JDK, nie moŜna kontynuować instalacji. Najnowszą wersję JDK moŜna pobrać na stronie: http://java.sun.com/javase/downloads.
3.2 Pobieranie NetBeans Najnowszą wersję programu NetBeans moŜna pobrać ze strony http://www.netbeans.org
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
MoŜna równieŜ skorzystać z gotowego pakunku instalacyjnego zawierającego środowisko JDK oraz NetBeans IDE dostępnego na stronie: http://java.sun.com/javase/downloads/index.asp
3.3. Instalacja programu NetBeans Po pobraniu pliku z pakietem instalacyjnym naleŜy uruchomić instalatora. Do uruchomienia instalatora niezbędne będą uprawnienia administratora.
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Po wstępnej konfiguracji instalatora ukaŜe się okno z informacją o wersji instalowanych programów. Aby przejść do następnego etapu naleŜy kliknąć w przycisk Next.
Następnie naleŜy zaakceptować warunki licencji poprzez zaznaczenie pola I akcept the terms in the license agreement oraz kliknąć przycisk Next.
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW Następnie naleŜy wybierać katalog, w którym zostanie zainstalowane środowisko JDK.
W kolejnym kroku naleŜy wskazać lokalizację katalogów, w których zainstalowane zostaną programy NetBeans i JDK.
Po kliknięciu w przycisk Install rozpoczyna się właściwy proces instalacji.
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Instalacja kończy się po naciśnięciu przycisku Finish. MoŜna równieŜ przekazać anonimowe informacje dotyczące oprogramowania oraz dokonać rejestracji produktów (są to kroki nieobowiązkowe).
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW
Następnie w sekcji Cetegories wybieramy Java, a w sekcji Projects – Java Application.
Następnym krokiem jest wybór nazwy projektu i jego lokalizacji na dysku. Wpisując nazwę klasy głównej (Create Main Class) naleŜy pamiętać, Ŝe nazwa pliku źródłowego (w tym przypadku WitajSwiecie.java) musi być zgodna z nazwą klasy publicznej zdefiniowanej w tymŜe pliku.
ROZDZIAŁ I. WIRTUALNA MASZYNA JAVY I PROGRAMY WSPOMAGAJĄCE TWORZENIE PROGRAMÓW Po utworzeniu projektu moŜemy przystąpić do pisania programu. Gotowy program moŜemy uruchomić wybierając z menu Run.
Efekt działania programu widoczny będzie w okienku Output.
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ
Rozdział II Podstawowe typy zmiennych, operatory, kolejność wykonywania działań 1. Typy danych
1.1. Liczby całkowite Do pamiętania liczb całkowitych uŜywamy typów danych: int, short, long i byte. Wszystkie z tych typów umoŜliwiają zapamiętanie liczb zarówno dodatnich jak i ujemnych. W większości sytuacji uŜywać będziemy typu int, który daje moŜliwość zapamiętania liczb z zakresu ok. -2 miliardy do nieco ponad 2 miliardy. W przypadku liczb mniejszych, z zakresu od -128 do 127 wystarczy uŜyć typu byte. PoniŜsza tabela przedstawia zestawienie typów liczbowych uŜywanych w Javie. Typ danych byte short int long
Zakres pamiętanych liczb od -128 do 127 od -32768 do 32767 od -2 147 483 648 do 2 147 483 647 od -231 do 231 -1
Zajmowany obszar pamięci 1 bajt 2 bajty 4 bajty 8 bajtów
Liczby całkowite typu long, zwane czasem liczbami długimi, mają sufiks L (na przykład 90000000000L). Liczby szesnastkowe (heksadecymalne) mają prefiks 0x (na przykład 0xA0B3). Liczby ósemkowe (oktalne) mają prefiks 0. Na przykład 010 oznacza liczbę 8. Zaletą języka Java jest fakt, Ŝe niezaleŜnie od typu maszyny, na której uruchamia się program w Javie typy danych mają zawsze taki sam zakres i zajmują taki sam obszar pamięci. W Javie więc rozmiar typów numerycznych jest niezaleŜny od platformy sprzętowej i systemowej.
1.2. Liczby zmiennoprzecinkowe Typy zmiennoprzecinkowe słuŜą do zapamiętywania liczb rzeczywistych, posiadających część ułamkową. W Javie występują dwa typy zmiennoprzecinkowe: float i double. Liczby typu float zajmują 4 bajty, a double – 8 bajtów (nazywa się je czasem liczbami podwójnej precyzji). Liczby typu float posiadają sufiks F, np. 3.1415F. Liczby bez sufiksu traktowane są jako typu double (moŜna je równieŜ oznaczać sufiksem D, np. 3.1415D). PoniŜsza tabela przedstawia zestawienie typów zmiennoprzecinkowych uŜywanych w Javie.
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ Typ danych float byte
Zakres pamiętanych liczb w przybliŜeniu ±3.4E+38F (6-7 znaczących cyfr dziesiętnych) w przybliŜeniu ±1.8E+308 (15 znaczących cyfr dziesiętnych)
Zajmowany obszar pamięci 4 bajty 8 bajtów
1.3. Typ znakowy Do pamiętania znaków uŜywamy typu char. Stałe znakowe zapisujemy za pomocą apostrofów. Np. zapis 'x' symbolizuje literę x. Typ danych char został zaprojektowany do pamiętania róŜnorodnych zestawów znaków, gdyŜ określa znaki w standardzie Unicode. Za pomocą tego typu danych moŜna zapamiętać 65536 roŜnych znaków, w szczególności znaków pochodzenia niełacińskiego. Przykładowo '\u2122' to symbol fabryczny (™). Znak specjalny \u informuje, Ŝe znak został zakodowany w standardzie Unicode, a liczba bezpośrednio po nim oznacza kod w standardzie Unicode zapisany w systemie heksadecymalnym. W Javie występują równieŜ inne znaki specjalne, najwaŜniejsze z nich przedstawiono w tabeli poniŜej. Znak \t \n \' \\
Wartośc Unicode \u0009 \u000A \u0027 \u005C
Nazwa tabulacja koniec linii apostrof backslash
1.4. Typ logiczny Typ logiczny boolean moŜe przyjmować dwie wartości - false (fałsz) oraz true (prawda). W Języku Java nie moŜna dokonać konwersji pomiędzy typem liczbowym a typem logicznym (podobnie jak w języku C++).
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ
int wiek; long WielkaLiczba; char Symbol_towaru; boolean Karany; double Cena1, Cena2, Cena3; MoŜna zadeklarować kilka zmiennych w jednej linii, jednak ten sposób deklaracji nie jest zbyt czytelny i nie jest polecany. Jak widać w powyŜszych przykładów w nazwach zmiennych moŜna uŜywać zarówno wielkich jak i małych liter – wielkość liter jest istotna. Znaczy to, Ŝe zmienne o nazwach zMiEnNa oraz ZmIeNnA – odnoszą się do róŜnych zmiennych.
2.2. Przypisanie i inicjalizacja zmiennych Zmienne, którą zadeklarowaliśmy w programie nie ma ściśle określonej wartości. Aby jej uŜywać naleŜy dokonać jej inicjalizacji. MoŜna tego dokonać za pomocą instrukcji przypisania, np.: int wiek; wiek = 18;
// deklaracja //inicjalizacja
Inną, wygodną metodą inicjalizacji zmiennych jest moŜliwość równoczesnej deklaracji i inicjalizacji. Na przykład: double Cena1 = 100.98;
//jednoczesna deklaracja i inicjalizacja
Podobnie jak w języku C++ zmienne moŜna deklarować w kaŜdym miejscu programu. Przykładowo fragment kodu języka Java moŜe wyglądać następująco: int wiek = 18; System.out.println(wiek); long WielkaLiczba
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ double MocSilnikaWKM = 60; System.out.println("Moc silnika w kW: " + MocSilnikaWKM * KM_NA_KW); } } Zgodnie z umownymi zasadami nazwy stałych piszemy wielkimi literami.
3. Operatory
3.1. Operatory inkrementacji i dekrementacji Bardzo często w programach musimy zwiększać lub zmniejszać wartości zmiennych np. zmiennych sterujących pętlami. Do tego celu słuŜą operatory inkrementacji i dekrementacji czyli zwiększania i zmniejszania wartości zmiennych. Na przykład, kod: int x=10; x++; spowoduje zwiększenie wartości zmiennej o 1, do wartości 11. Natomiast x-- spowoduje zmniejszenie wartości zmiennej x do 9. Istnieje równie inna, prefiksowa wersja tych operatorów ++x; --x. RóŜnice pomiędzy tymi wersjami są zauwaŜalne, gdy uŜyjesz ich wewnątrz innych wyraŜeń. Forma prefiksowa najpierw dokonuje operacji zwiększenia wartości zmiennej, natomiast forma postfiksowa zwraca wcześniejszą wartość zmiennej, a dopiero później zwiększa jej wartość. Przeanalizujmy poniŜszy fragment kodu: int int int int
a=5; b=5; x = 10 * ++a; y = 10 * b++;
// x ma wartość 60, ++a ma wartość 6, a ma wartość 6 // y ma wartość 50, b++ ma wartość 5, b ma wartość 6
3.2. Operatory arytmetyczne i relacji W języku Java moŜna uŜywać podobnych operatorów arytmetycznych jak w innych językach programowania. Do wykonywania podstawowych czterech działań uŜywamy operatorów: +, -, *, / (dodawanie, odejmowanie, mnoŜenie, dzielenie). Istniej równieŜ operator %, który symbolizuje operację modulo czyli reszty z dzielenia całkowitego. Operatorami relacji są: > (większy), < (mniejszy), >= (większy bądź równy), <= (mniejszy bądź równy). Do sprawdzania czy wyraŜenia są równe naleŜy uŜyć operatora = =. NaleŜy zwrócić uwagę na podobieństwo operatora przypisania (=) i równości (= =). W języku C++ zapis (x = 5) stosowany przy tworzeniu wyraŜeń logicznych nie spowoduje błędu kompilacji, natomiast kompilator Javy zaprotestuje w tym miejscu. W Javie nie istnieje bezpośrednia
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ metoda zapisu operatora róŜny. W tym przypadku stosujemy zapis !=. Np. zapis 10 != 11 zwróci wartość true.
3.3. Operatory logiczne W przypadku tworzenia warunków logicznych uŜywamy w Javie operatorów logicznych. Operatorem iloczynu logicznego "i" jest &&, natomiast operatorem sumy logicznej "lub" jest ||. Operatorem logicznej negacji jest znak wykrzyknika !. Przy obliczaniu wartości wyraŜeń logicznych z zastosowaniem operatorów logicznych obowiązuje tzw. skrócony sposób obliczania wartości wyraŜeń. Polega on na tym, Ŝe wartość wyraŜenia obliczana jest od strony "lewej" do "prawej". Jeśli w wyniku obliczeń wynik wyraŜenia jest z góry ustalony, dalsza część wyraŜenia nie jest juŜ obliczana. Sytuację tę przedstawia przykład poniŜej. (y !=0) && (1/y > 100) // nie moŜna dzielić przez 0 Jeśli y jest równe zero, to druga część wyraŜenia nie będzie obliczana i nie wystąpi błąd dzielenia przez zero. Podobnie jeśli mamy wyraŜenie X || Y, a wyraŜenie X ma wartość true, to nie ma potrzeby obliczania wartości Y. W Javie występuje równieŜ operator ?. SłuŜy on do tworzenia tzw. wyraŜeń warunkowych. warunek_logiczny ? wartość_1 : wartość_2 WyraŜenie to w zaleŜności od tego czy warunek logiczny jest prawdą czy fałszem zwraca wartość nr 1 lub wartość nr 2. Na przykład: a < b ? a : b zwróci zawsze mniejszą z liczb a i b.
3.4. Operatory bitowe Operatory bitowe słuŜą do wykonywania działań bezpośrednio na poszczególnych bitach liczb. Operatory bitowe to: & (iloczyn bitowy), | (suma bitowa), ^ (róŜnica symetryczna bitowa), ~ (negacja bitowa). Istnieją równieŜ operatory bitowe przesunięcia bitowego w prawo >> i w lewo <<. Działanie operatorów bitowych dla przykładowych danych zostało przedstawione w poniŜej tabeli. byte a = 17; byte b = 149;
3.5. Rzutowane Z rzutowaniem mamy do czynienia w przypadku gdy chcemy zmienić typ docelowy zmiennej. Na przykład: double a = 3.14; int b = (int)x; W takim przypadku zmienna b będzie miała wartość 3 gdyŜ operacja rzutowania liczby zmiennoprzecinkowej na całkowitą "obetnie" część ułamkową.
3.6. Kolejność wykonywania działań Jeśli nie jesteśmy pewni w jakiej kolejności będą wykonywane działania, najbezpieczniejszą metodą jest zastosowanie nawiasów. JeŜeli działania nie będą ujęte w nawiasy kolejność wykonywania działań zaleŜy od ich hierarchii. W przypadku działań jednakowego typu wykonywane są one (najczęściej, z małymi wyjątkami) od strony lewej do prawej. PoniŜej przedstawiono hierarchię wykonywania działań: operator ! ~ ++ -*/% +<< >> < <= > >= = = != & ^ | && ||
kolejność działań od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej od lewej do prawej
22
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ 3.7. Łańcuchy i operacje na łańcuchach Łańcuchem nazywać będziemy ciąg znaków, np. "Java". Do obsługi łańcuchów Java posiada w standardowej bibliotece predefiniowaną klasę String. KaŜdy łańcuch (napis opatrzony znakami cudzysłów) staje się obiektem klasy String. String napis = "Powitanie"; Łańcuchy w Javie moŜna łączyć za pomocą operatora konkatenacji, który zapisujemy za pomocą znaku +. Np.: String imie = "Jan"; String nazwisko = "Kowalski"; String dane_osobowe = imie + " " + nazwisko; W tym przypadku w zmiennej dane_osobowe zostanie zapamiętany łańcuch "Jan Kowalski". Jeśli chcemy połączyć łańcuch z wartością, która nie jest łańcuchem (na przykład z wartością liczbową) przed połączeniem zostanie ona niejawnie skonwertowana do łańcucha. Na przykład: int a=5; String wynik = "a="+a; spowoduje zapisanie z zmiennej wynik łańcucha "a=5". Taki schemat będziemy często wykorzystywać przy wyświetlaniu wartości zmiennych na ekran. Klasa String posiada wiele przydatnych metod. Jedną z nich jest metoda substring, dzięki której moŜna w łatwy sposób "wyciąć" z łańcucha dowolny fragment, na przykład: String nazwa = "Informatyka"; String n = nazwa.substring(0, 5); zapisuje w zmiennej n łańcuch "Infor". Pierwszy parametr metody substring określa indeks pierszego znaku, który chcemy wyciąć, natomiast drugi parametr określa indeks pierwszego znaku, jakiego nie chcemy skopiować do nowego łańcucha. NaleŜy pamiętać, Ŝe indeksowanie łańcuchów rozpoczynamy od liczby 0. Inną przydatną funkcja klasy String jest bezparametrowa funkcja length(). Na przykład: String napis = "Informatyka"; int n = napis.length(); zapisze w zmiennej n wartość 11. Aby przeczytać konkretny znak zmiennej klasy String moŜna zastosować funkcji CharAt(x), gdzie x jest indeksem czytanego znaku. Na przykład: String imie = "Marek"; char Inicjal_Imienia = imie.CharAt(0);
ROZDZIAŁ II. PODSTAWOWE TYPY ZMIENNYCH, OPERATORY, KOLEJNOŚĆ WYKONYWANIA DZIAŁAŃ Częstym zabiegiem w programowaniu jest porównywanie łańcuchów tekstowych. Bardzo złą metodą porównywania łańcuchów jest srosowanie operatora = =. Zamiast niego naleŜy porównywać łańcuchy za pomocą metody equals(x), gdzie x jest łańcuchem, z którym chcemy porównać nasz łańcuch. Prześledźmy to na przykładzie: String Imie= "Jan"; Imie.equals("Marek"); // wynik porówania false Jeśli chcemy porównać łańcuchy bez rozróŜniania wielkości liter naleŜy zamiast metody equals uŜyć metody equalsIgnoreCase.
Rozdział III Pętle i instrukcje warunkowe 1. Instrukcja warunkowa Instrukcja warunkowa w Javie ma postać: if (warunek_logiczny) polenie_jeśli_prawda; else polecenie_jeśli_fałsz; Jeśli po warunku logicznym (lub po słowie else) chcemy uŜyć więcej niŜ jedno polecenie, musimy zawrzeć je w nawiasy klamrowe. Taką konstrukcję będziemy nazywać blokiem instrukcji. Na przykład: if (x % 2 = = 1) { System.out.println("nieparzysta"); x++; } else { System.out.println('parzysta"); x++; } MoŜna równieŜ "zagnieŜdŜać" instrukcje warunkowe, jeśli chcemy uzyskać moŜliwość przetestowania więcej niŜ dwóch przypadków. Dla przykładu: if (sredniaOcena > 5) { opis = "celująco"; premia = 1000; } else if (sredniaOcena > 4) { opis = "bardzo bobrze"; premia = 500; } else if (sredniaOcena > 3) { opis = "dobrze"; premia = 100; } else if (sredniaOcena > 2) { opis = "dostatecznie";
ROZDZIAŁ III. PĘTLE I INSTRUKCJE STERUJĄCE premia = 50 } else opis = "musisz się jeszcze postarać!!!";
2. Pętle określone i nieokreślone 2.1. Pętle while i do W języku Java występują dwie pętle o nieokreślonej z góry ilości przejść. Pierwszą z nich jest pętla while. Ogólna postać tej pętli jest następująca: while (warunek_logiczny) instrukcja; Jeśli warunek logiczny ma wartość prawda, to wykona się instrukcja (lub instrukcje) zawarte w pętli. W przypadku gdy warunek_logiczny ma wartość fałsz, pętla kończy swoje działanie. Pętla while jest czasem zwana pętlą z warunkiem na początku. PoniŜej przedstawiono przykład prostego programu z wykorzystaniem pętli while.
import javax.swing.*; public class Zgadywanka { public static void main(String args[]) { int IloscProb=1; int liczba; String wejscie = JOptionPane.showInputDialog(null, "Podaj liczbę całkowitą z zakresu 0 - 100"); liczba = Integer.parseInt(wejscie); while (liczba != NIEWIADOMA) { if (liczba > NIEWIADOMA)JOptionPane.showMessageDialog(null,"Za duŜo\nSpróbuj jeszcze raz."); else JOptionPane.showMessageDialog(null,"Za mało\nSpróbuj jeszcze raz."); IloscProb++; wejscie = JOptionPane.showInputDialog(null, "Podaj liczbę całkowitą z zakresu 0 - 100"); liczba = Integer.parseInt(wejscie); } JOptionPane.showMessageDialog(null,"Brawo zgadłeś. Ilość prób = " + IloscProb); } private static final int NIEWIADOMA = 77; }
W typ programie zakodowano w postaci stałej NIEWIADOMA pewną liczbę (linia 20). Następnie uŜytkownik musi wprowadzać liczby (linia 6), które są następne porównywane ze stałą NIEWIADOMA (linia 10). Jeśli wczytana liczba jest róŜna od zakodowanej stałej (warunek logiczny w linii 10 zwróci wartość prawda), to wykonywać się będą instrukcje zawarte w pętli while (linie od 12 do 16). Tworząc programy z pętlą while naleŜy wziąć pod uwagę fakt, Ŝe warunek wejścia do pętli jest sprawdzany na początku i moŜe się zdarzyć, Ŝe pętla nie wykona się ani raz. Dlatego teŜ w powyŜszym programie instrukcje z linii 8 i 9 zostały powtórzone w liniach 15 i 16.
Drugą pętlą, tym razem z warunkiem sprawdzanym na końcu jest pętla do – while. Jej składnia jest następująca: do instrukcja while (warunek_logiczny); W tej pętli instrukcja (instrukcje) wykonają się przynajmniej jeden raz. Pętla ta jest często nazywana pętlą z warunkiem na końcu. Prześledźmy działanie tej pętli na podstawie poniŜszego programu. Oprocentowanie.java 1. 2. 3. 4. 5.
import javax.swing.*; import java.text.NumberFormat; import java.util.*; public class Oprocentowanie {
public static void main(String args[]) { int i=1; double KwotaBiezaca; NumberFormat formator = NumberFormat.getNumberInstance(); formator.setMinimumFractionDigits(2); formator.setMaximumFractionDigits(2); String wejscie; String wyjscie="Kwota lokaty wraz z oprocentowaniem w poszczególnych latach:\n\n"; wejscie = JOptionPane.showInputDialog(null, "Podaj kwotę lokaty"); double KwotaLokaty = Double.parseDouble(wejscie); wejscie = JOptionPane.showInputDialog(null, "Podaj kwotę docelową"); double KwotaDocelowa = Double.parseDouble(wejscie); KwotaBiezaca = KwotaLokaty; wejscie = JOptionPane.showInputDialog(null, "Podaj roczne oprocentowanie w %"); double Oprocentowanie = Double.parseDouble(wejscie); do { KwotaBiezaca = KwotaBiezaca+KwotaBiezaca*Oprocentowanie/100; wyjscie = wyjscie+i+". "+formator.format(KwotaBiezaca)+" zł\n"; i++; } while (KwotaBiezaca < KwotaDocelowa); JOptionPane.showMessageDialog(null, wyjscie); } }
Program słuŜy do symulacji po ilu latach osiągniemy zakładaną kwotę docelową na lokacie przy załoŜonej kwiecie lokaty, kwocie docelowej oraz oprocentowaniu rocznemu środków na lokacie. W liniach 11 i 12 ustalamy wyświetlanie kwot z dwoma miejscami po przecinku. W tym celu wykorzystamy metody klasy NumberFormat setMinimumFractionDigits oraz setMaximumFractionDigits. Następnie za pomocą trzech okien dialogowych (linie od 13 do 21) wczytamy z klawiatury i zamienimy na liczby kwotę początkową na lokacie, kwotę docelową oraz oprocentowanie roczne. NaleŜy zwrócić uwagę, Ŝe wczytane z klawiatury za pomocą okna dialogowego Input dane traktowane są jako łańcuchy znaków i naleŜy je zamienić na liczby za pomocą odpowiedniej metody parseDouble. Podstawową częścią programu jest pętla, w której dokonywane jest obliczenie bieŜącej kwoty na lokacie po doliczeniu rocznego oprocentowania (linia 24). W linii 25 budowany jest łańcuch wyjściowy, który zostanie uŜyty przez metodę showMessageDialog do wyświetlenia wyniku działania programu. NaleŜy zwrócić uwagę na zastosowanie w budowaniu tego łańcucha metody format klasyNumerFormat, dzięki której kwoty zostaną wyświetlone z jako liczby z dwoma miejscami po przecinku.
Wynik symulacja narastania zgromadzonego kapitału na lokacie w polu Message
2.2 Pętla for Trzecim rodzajem pętli w Javie jest pętla for. Nazywamy ją czasem pętlą określoną, gdyŜ w jej definicji moŜna przewidzieć ilość powtórzeń. Ogólna budowa pętli for jest następująca: for (wartość_początkowa_licznika_pętli; instrukcja_zmieniająca_licznik) instrukcja;
warunek_logiczny;
Instrukcja będzie wykonywana w pętli for, aŜ do momentu, gdy warunek logiczny zwróci wartość false. PoniŜszy przykład wyświetli na ekranie cyfry od 0 do 9.
for (int i = 0; i <= 9 ; i++) System.out.println(i); MoŜna równieŜ budować pętle, w których licznik poddawany będzie dekrementacji: for (int i = 9; i >= 0 ; i--) System.out.println(i); W pętli for moŜna równieŜ zastosować bardziej złoŜoną instrukcję opisująca w jaki sposób moŜe zmieniać się licznik pętli. PoniŜej podano program z zastosowaniem pętli for wyświetlający na ekranie n kolejnych potęg liczby 2. public class Potegi2 { public static void main(String args[]) { for (int i=1;i <= n; i *= 2) System.out.println(i); } public static final int n = 128; } W programie powyŜszym naleŜy zwrócić uwagę na wyraŜenie zmieniające wartość licznika i* = 2, które jest skróconym zapisem wyraŜenia i = i * 2. PoniŜej przedstawiono program słuŜący do obliczania wyraŜenia n! Silnia.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
import javax.swing.*; public class Silnia { public static void main(String[] args) { int n; String wejscie = JOptionPane.showInputDialog(null, "Podaj liczbę całkowitą z zakresu 0 - 20"); n = Integer.parseInt(wejscie); String wyjscie = Silnia(n); JOptionPane.showMessageDialog(null, wyjscie); } private static String Silnia(int ile) { String temp=""; long silnia = 1; for (int i=1;i<=ile;i++) silnia *= i; return ile+"!"+" = "+Long.toString(silnia); } }
W programie tym zastosowano instrukcję pętli for w metodzie statycznej Silnia. W metodzie tej w pętli for obliczana jest wartość zmiennej pomocniczej s. Następnie zmienna s zostaje zamieniona na łańcuch za pomocą metody toString (nie jest to konieczne poniewaŜ w linii 18 i tak nastąpi niejawna konwersja zmiennej typu liczbowego na łańcuchowy). PoniŜsze zrzuty ekranowe prozentują działanie tego programu:
Wyświetlenie wyniku – silni z liczby 10 w pola Message
3. Instrukcja wielokrotnego wyboru Często w programach musimy dokonać wyboru składającego się z wielu wariantów. MoŜna oczywiście do tego celu zastosować instrukcję warunkową if wielokrotnie zagnieŜdŜoną, lecz jest nie niezbyt wygodne. W Javie mamy instrukcję wyboru switch, działającą podobnie jak w języku C++. Działanie instrukcji switch jest następujące: switch (wybor) { case 1: //instrukcje break; case 2: //instrukcje break; case 3: //instrukcje break; default: //instrukcje Ŝadnej opcji break; }
dla wartości zmiennej wybor równej 1
dla wartości zmiennej wybor równej 2
dla wartości zmiennej wybor równej 3
dla wartości zmiennej wybor nie pasującej do
W zaleŜności od wartości zmiennej sterującej instrukcja switch (zmienna wybor) wykonywać się będą instrukcje zawarte po słowach case. Np. jeśli zmienna wybor ma wartość 1, to wykonają się instrukcje bezpośrednio po słowie kluczowym case 1:. Jeśli zmienna wybór będzie mieć wartość nie pasującą do Ŝadnej liczby po słowach case, to wykonają się instrukcje po słowie default. PoniŜej przedstawiono program realizujący prostą "tabliczkę mnoŜenia" zrealizowaną przy uŜyciu instrukcji case.
import javax.swing.*; public class TabliczkaMnozenia { public static void main(String[] args) { String wejscie; String TekstMenu="Tabliczka mnoŜenia\n\n"; TekstMenu+="1 - dodawanie\n2 - odejmowanie\n3 - mnoŜenie\n4 - dzielenie\n\n"; TekstMenu+="Wybierz liczbę od 1 do 4\n"; wejscie = JOptionPane.showInputDialog(null,TekstMenu ); int wybor = Integer.parseInt(wejscie); wejscie = JOptionPane.showInputDialog(null,"Podaj pierwszą liczbę" ); int liczba1 = Integer.parseInt(wejscie); wejscie = JOptionPane.showInputDialog(null,"Podaj drugą liczbę" ); int liczba2 = Integer.parseInt(wejscie); switch (wybor) { case 1: JOptionPane.showMessageDialog(null, liczba1+" + "+liczba2+" = "+(liczba1+liczba2)); break; case 2: JOptionPane.showMessageDialog(null, liczba1+" - "+liczba2+" = "+(liczba1-liczba2)); break; case 3: JOptionPane.showMessageDialog(null, liczba1+" * "+liczba2+" = "+(liczba1*liczba2)); break; case 4: String wynik = liczba2!=0 ? Double.toString(liczba1/(double)liczba2) : "Nie moŜna dzielić przez zero!"; JOptionPane.showMessageDialog(null, liczba1+" + "+liczba2+" = "+wynik); break; default: JOptionPane.showMessageDialog(null, "Nieznanie działanie"); break; } } }
Wyboru działania dokonujemy za pomocą instrukcji switch. W przypadku wybrania np. dodawania wykona się instrukcja w linii 19. Na uwagę zasługuje wyraŜenie będące parametrem metody showMessageDialog: liczba1+" + "+liczba2+" = "+(liczba1+liczba2). Występuje w nim kilka operatorów "+". Są to operatory konkatenacji łączące łańcuchy tekstowe. Ostatnia część tego wyraŜenia (liczba1+liczba2) została wzięta w nawias aby poinformować, Ŝe chcemy dodać dwie liczby całkowite, a nie połączyć je jako łańcuchy. Nasz program jest równieŜ zabezpieczony przed sytuacją błędu dzielenia przez zero. W linii 28 zastosowano wyraŜenie warunkowe, które daje dwa róŜne wyniki w zaleŜności od wartości zmiennej liczba2. RównieŜ w tej linii zastosowano rzutowanie zmiennych typu int na typ double, aby uzyskać poprawny wynik z dzielenia. PoniŜej zaprezentowano wynik uruchomienia powyŜszego programu z przykładowymi danymi.
Wynik działania programu przy podaniu drugiej liczby równiej zero i wyborze dzielenia jako działania
W powyŜszym programie zastosowano równieŜ instrukcję break, która przerywa działanie instrukcji switch po wykonaniu ciągu instrukcji związanych z obliczaniem wybranej opcji. Polecenia break moŜna równieŜ uŜyć do przerwania działania pętli przed jej "normalnym" zakończeniem. Na przykład: while (LataOszczedzania <=100) { StanKonta += Wplata; if (StanKonta > CelOszczedzania) break; LataOszczedzania++; } W powyŜszym przykładzie pętla zakończy swoje działanie najprawdopodobniej wcześnie niŜ po 100 przejściach, jeśli StanKonta będzie przekraczał CelOszczędzania. Wtedy to wykona się instrukcja break, która zakończy działanie pętli. W Javie występuje równieŜ instrukcja sterująca continue, której wywołanie powoduje natychmiastowe przerwanie bieŜącego przebiegu pętli i przejście na początek następnego przebiegu pętli. Wielu programistów uwaŜa instrukcje break i continue za mylące i radzą aby ich nie uŜywać. Te dwie instrukcje uwaŜamy więc za opcjonalne i będziemy stać się ich nie uŜywać w naszych programach.
Rozdział IV Zmienne tablicowe Tablicami nazywamy struktury danych zawierające wartości tego samego typu, np. liczby całkowite, znaki, czy wartości logiczne. Podstawową częścią tablicy jest komórka. Dostęp do komórek tablicy realizowany jest poprzez tzw. indeks. Deklaracja tablicy składa się z podania typu danych przechowywanych w tablicy, nawiasów kwadratowych [ ] oraz nazwy tablicy. Na przykład deklaracja tablicy liczb całkowitych o nazwie tab ma postać: int[] tab; MoŜna równie zastosować nieco inny zapis słuŜący do deklaracji tablic: int tab[]; Jednak większość programistów w Javie zaleca deklarowanie tablic za pomocą pierwszego sposobu. Polecenie powyŜsze dokona tylko deklaracji tablicy. Aby ją zainicjalizować naleŜy uŜyć operatora new. int[] tab = new int[100]; PowyŜsze polecenie tworzy tablice 100-elementową liczb całkowitych. Komórki tej tablicy są indeksowane od 0 do 99, a więc jest ich w sumie 100. Po inicjalizacji tablicy nie jesteśmy w stanie odpowiedzieć jakie wartości są przechowywane w tablicy. Aby mieć pewność, Ŝe w komórkach umieszczono konkretne dane naleŜy w pętli wpisać do komórek tablicy wartości początkowe. int[] tab = new int[100]; for (int i = 0; i < 100; i++) tab[i]=0; //wypełnienie tablicy liczbami 0
1. Inicjalizacja tablic i tablice anoniomowe W Javie moŜliwe jest zadeklarowanie tablicy oraz jej inicjalizacja w tym samym momencie. PoniŜej podano przykład takiego polecenia: int[] LiczbyParzyste = {2, 4, 6, 8, 10}; Instrukcja powyŜsza inicjalizuje tablicę 5-elementową i umieszcza w kolejnych jej komórkach liczby parzyste. W tej konstrukcji nie uŜywamy operatora new. W języku Java moŜna zainicjalizować tzw. tablicę anonimową, która nie będzie posiadać swojej nazwy. Na przykład zapis: new int[] = {1, 3, 5, 7, 9}; deklaruje nową 5-elementową tablicę anonimową. MoŜna ją później przypisać na przykład do wcześniej zadeklarowanej innej tablicy takiego samego typu. Podana poniŜej konstrukcja przypisuje anonimową tablicę do tablicy InneLiczby:
int[] InneLiczby; InneLiczby = new int[] {1,2,3,4,5};
2. Kopiowanie tablic Wygodną metodą klasy System słuŜącą do kopiowania tablic jest metoda arraycopy. Jej składnia jest następująca: System.arraycopy(tab_zrodlowa, indeks_zrodla, tab_docelowa, indeks_celu, ilość_kopiowanych_danych)
Tablica docelowa musi mieć wystarczający rozmiar aby zapamiętać kopiowane elementy. PoniŜszy program prezentuje działanie metody słuŜącej do kopiowania tablic. KopiowanieTablic.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13.
import javax.swing.*; public class KopiowanieTablic { public static void main(String[] args) { String wyjscie="Tablica docelowa\n\n"; int[] TablicaZrodlowa = {1,2,3,4,5,6,7,8,9}; int[] TablicaDocelowa = {101,102,103,104,105,106,107,108,109,110}; System.arraycopy(TablicaZrodlowa, 1, TablicaDocelowa, 2, 5); for (int i=0; i < TablicaDocelowa.length;i++) wyjscie+=(i+": "+TablicaDocelowa[i]+"\n"); JOptionPane.showMessageDialog(null,wyjscie); } }
W liniach 6 i 7 inicjalizujemy przykładowymi danymi dwie tablice liczb całkowitych. W linii 8 wywołujemy metodę arraycopy, która przepisuje do tablicy o nazwie TablicaDocelowa 5 liczb z tablicy TablicaZrodlowa, począwszy od komórki o indeksie 1. Liczby te są "wklejone" i przepisują dane z drugiej tablicy począwszy od komórki o indeksie nr 2. Sytuacja ta została przedstawiona na poniŜszym zrzucie prezentującym wynik działania programu.
Zawartość tablicy TablicaDocelowa po wykonaniu metody arraycopy
3. Sortowanie tablic Bardzo wygodną funkcjonalnością języka Java jest moŜliwość szybkiego sortowania tablic. Jedną z metod klasy Array jest metoda sort, która do sortowania tablic uŜywa algorytmu QuickSort. Prześledźmy działanie następującego programu: Sortowanie.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25.
import javax.swing.*; import java.util.Arrays; public class Sortowanie { public static void main(String[] args) { String wyjscie = "Tablica nieposortowana\n\n"; int[] tab = new int[N]; for (int i=0;i
W programie została zadeklarowana i zainicjowana wartościami losowymi tablica tab. Wypełnienie tej tabeli odbywa się w linii 11. UŜyta tu została metoda random klasy Math, zwracająca liczbę pseudolosową z przedziału od 0 do 1. Nastęnie liczba ta została przemnoŜona przez stałą ZAKRES. PoniewaŜ metoda random zwraca wartość zmiennoprzecinkową powyŜsze wyraŜenie naleŜy po przemnoŜeniu rzutować do typu int. Sotorowanie tablicy odbywa się w linii 15. Następnie wyświetlania jest na ekranie tablica posortowana (linia 21). PoniŜej przedstawiono zrzuty prezentujące tablice przed i po sortowaniu.
4. Tablice wielowymiarowe Tablice wielowymiarowe są to tablice operujące na więcej niŜ jednym indeksie. Często w programach uŜywamy tablic dwuwymiarowych. Deklaracja takie tablicy wygląda następująco: int [] [] liczby; Inicjalizacja takiej tablicy moŜe być następująca: int [] [] liczby =
Dostęp do konkretnych komórek tablicy odbywa się za pomocą dwóch indeksów. Np. w komórce liczby[2][3] zapamiętana została liczba 12 (Pamiętajmy, Ŝe komórki w tej tabeli są indeksowane od liczby 0 – zarówno w wierszach jak i w kolumnach). PoniŜszy program prezentuje wydruk popularnej "tabliczki mnoŜenia", w którym mamy moŜliwość podania w jakim zakresie będzie ona wyświetlana.
import javax.swing.*; public class Tablica2Wymiarowa { public static void main(String[] args) { String wejscie; String wyjscie="Tabliczka mnoŜenia\n\n"; String Komunikat="Podaj stopień \"tabliczki mnoŜenia\" (liczba z zakresu 1 - 10)\n\n"; wejscie=JOptionPane.showInputDialog(Komunikat); int n = Integer.parseInt(wejscie); int[][] liczby = new int[n][n]; for (int i=0; i
W linii 10 następuje inicjalizacja tablicy dwuwymiarowej, która następnie wypełniania jest liczbami w dwóch pętlach. PoniewaŜ pamiętamy, Ŝe tablice są indeksowane od 0 obliczając wartość odpowiedniej komórki musimy do liczników pętli dodać liczbę 1. Tak więc w komórce tabeli o indeksach i, j musimy umieścić liczbę (i+1)*(j+1). W następnej zagnieŜdŜonej pętli realizowane jest wyświetlanie zawartości tabeli. PoniewaŜ chcemy, aby liczby wyświetlane były "równo" w kolumnach moŜna uzupełnić wyświetlane wyniki o dodatkowe "spacje". Zostało to zrealizowane w liniach 19 – 21. PoniŜej przedstawiono wynik działania programu wyświetlający tabliczkę mnoŜenia w zakresie do 100.
RóŜnice w wyświetleniu wyników w obu okienkach spowodowane są tym, Ŝe Java do wyświetlania danych w oknie Message uŜywa czcionki o zmiennej szerokości i – co za tym idzie – bardzo trudno jest uzyskać właściwe "wypozycjonowanie" wyświetlanych elementów. Natomiast w okienku Output wyniki są wyświetlone czcionką o stałej szerokości.
Rozdział V Obiekty, klasy, metody i pola Programowanie zorientowane obiektowo obecnie jest najpopularniejszą metodą programowania. Wyparło ono programowanie strukturalne. W dziedzinie języków programowania zorientowanych obiektowo Java jest przykładem języka, w którym "obiektowość" zauwaŜalna jest na kaŜdym kroku. Jak widać po poprzednich przykładach pisząc program zawsze tworzyliśmy nowe klasy i w nich umieszczaliśmy metodę main, w której to wykonywaliśmy róŜne operacje na nowotworzonych i istniejących obiektach. Na rzecz obiektowy wywoływaliśmy róŜnorodne metody oraz modyfikowaliśmy pola tych obiektów. PoniŜej omówimy najwaŜniejsze pojęcia związane z programowaniem zorientowanym obiektowo (OOP).
1. Obiekty Programowanie zorientowane obiektowo – jak wskazuje nazwa – będzie polegać na wykonywaniu określonych działań na obiektach. KaŜdy obiekt posiada trzy kluczowe właściwości: • Zachowanie obiektu • Stan obiektu • ToŜsamość obiektu Zachowanie obiektów jednej klasy jest podobne. Za zachowanie obiektów odpowiedzialne są metody, które moŜna wykonać na rzecz obiektu. Stan obiektu będzie zaleŜeć od aktualnie przechowywanych w obiekcie danych składowych. Zmiany stanu obiektu moŜna dokonać tylko poprzez działanie metod na tym obiekcie. Jeśli stan obiektu uległby zmianie w sytuacji gdy Ŝadna z metod nie została wykonana na rzecz obiektu to znak, Ŝe została złamana zasada enkapsulacji czyli hermetyzacji danych. Indywidualne obiekty danej klasy zawsze róŜnią się swoją toŜsamością i zazwyczaj róznią się teŜ swoim stanem. W konwencjonalnym programie strukturalnym programowanie zaczynamy zazwyczaj od funkcji main czyli "od góry". W programach zorientowanych obiektowo zazwyczaj zaczynamy od tworzenia klas, a następnie od projektowania metod działających na rzecz obiektów tej klasy. W przypadku niewielkich programów stosowanie podejścia strukturalnego daje dobre rezultaty. W przypadku duŜych projektów programistycznych podział na klasy i metody jest bardzo wygodne. Na przykład prosta przeglądarka internetowa moŜe wymagać utworzenia 2000 funkcji. MoŜna to samo wykonać definiując np. 100 klas, z których kaŜda ma średnio 20 metod. Programiście będzie o wiele łatwiej pracować z taką strukturą programu, zwłaszcza gdy pracujemy nad projektem w grupach. RównieŜ mechanizm enkapsulacji pozwoli uniknąć nieprzewidzianych błędów gdyŜ klasy będą ukrywały swoje dane przed wszystkimi metodami spoza własnej klasy.
2. Korzystanie z istniejących klas Właściwie trudno sobie wyobrazić program w języku Java bez korzystania z istniejących klas. We wcześniejszych programach korzystaliśmy wielokrotnie z innych wbudowanych klas. Dobrym przykładem na korzystanie z istniejących klas jest klasa Date.
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA Jeśli chcemy wyświetlić dzisiejszą datę moŜna do metody System.out.println przekazać obiekt klasy Date. System.out.println(new Date()); NaleŜy zauwaŜyć, Ŝe do metody przkazujemy obiekt klasy Date, dlatego teŜ naleŜy zastosować słowo new, które słuŜy do tworzenia nowych obiektów danej klasy. Dopiero po utwodzeniu obiektu moŜna na jego rzecz wywoływać metody danej klasy. Jedną z metod klasy Date jest metoda toString(). Metoda ta zwraca tekstową reprezentację bieŜącej daty. Jeśłi będziemy chcieli skorzystać z obiektu klasy wiecej niŜ jeden raz to wygodniej będzie zachować nowoutworzony obiekt w zmiennej. Date DataUrodzenia = new Date(); Po takiej instrukcji zmienna obiektu DataUrodzenia wskazywać będzie na nowo utworzony obiekt klasy Date. Istnieje wielka róŜnica pomiędzy zmienną obiektu, a obiektem. Aby moŜna było odnosić się do obiektu poprzez zmienną obiektu, naleŜy ją wcześniej zainicjować. PoniŜej przedstawiono przykładową inicjalizację zmiennej obiektu klasy Date. Date wazny_termin; // na razie ta zmienna nie wskazuje na Ŝadny obiekt; termin = new Date(); Teraz zmienna obiektu wazny_termin wskazuje na obiekt klasy Date. Na rzecz tego obiektu moŜna będzie wykonywać metody lub przypisywać do niej inne obiekty tej klasy, na przykład: wazny_termin = DataUrodzenia; Po tej instrukcji obydwie zmienne obiektu (wazny_termin i DataUrodzenia) wskazywać będą na ten sam obiekt. Inna podobną klasą jesta klasa GregorianCalendar. Posiada ona wiele uŜytecznych metod i konstruktorów. Np. new GregorianCalendar() tworzy obiekt, który przechowuje datę i czas, w jakim został utworzony. Natomiast zapis: new GregorianCelendar(2010, Calendar.FEBRUARY, 20) tworzy obiekt, który jest "ustawiony": na datę 20 lutego 2010 roku. PoniŜszy program prezentuje proste działania na obiektach klasy GregorianCalendar. KlasaGregorianCalendar.java 1. 2. 3. 4. 5. 6.
import java.util.*; import javax.swing.*; import java.text.NumberFormat; public class KlasaGregorianCalendar { public static void main(String[] args) {
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
NumberFormat formator = NumberFormat.getNumberInstance(); formator.setMinimumIntegerDigits(2); GregorianCalendar dzisiaj = new GregorianCalendar(); GregorianCalendar sylwester2009 = new GregorianCalendar(2009, Calendar.DECEMBER, 31); int rok = dzisiaj.get(Calendar.YEAR); String miesiac = formator.format(dzisiaj.get(Calendar.MONTH)+1); String dzien = formator.format(dzisiaj.get(Calendar.DAY_OF_MONTH)); String wyjscie; wyjscie = "BieŜąca data: "+rok+"-"+miesiac+"-"+dzien; wyjscie +=" "+DzienTygodnia(Calendar.DAY_OF_WEEK)+"\n\n"; rok = sylwester2009.get(Calendar.YEAR); miesiac = formator.format(sylwester2009.get(Calendar.MONTH)+1); dzien = formator.format(sylwester2009.get(Calendar.DAY_OF_MONTH)); wyjscie +="Sylwester 2009: "+rok+"-"+miesiac+"-"+dzien; wyjscie +=" "+DzienTygodnia(Calendar.DAY_OF_WEEK)+"\n\n"; JOptionPane.showMessageDialog(null, wyjscie); }
W liniach 9 i 10 tworzone są obiekty klasy GregorianCalendar. Pierwszy z nich przechowuje informację o bieŜącej dacie – drugi o konkretnej dacie (w tym przypadku o dacie 31 grudnia 2009 r.). W liniach 7 i 8 ustawiamy format wyświetlania numeru dnia i numeru miesiąca. Metoda setMinimumIntegerDigits wymusza wyświetlenie numeru dnia i miesiąca na dwóch miejscach, przy czy jeśli liczba będzie mniejsza od 10 to zostanie ona uzupełniona z lewej strony zerem. W liniach 12 i 13 za pomocą metody get wywołanej z odpowiednim parametrem wydobywane są z daty numer dnia i miesiąca. W lini 16 widzimy wywołanie statycznej metody DzienTygodnia, która na podstawie przekazanej jej parametru liczbowego zwraca słowny opis dnia tygodnia. PoniŜej przedstawiono działanie programu.
Efekt działania programu na obiektach klasy GregorianCalendar
O tym, Ŝe Java jest językiem czysto obiektowym moŜemy się przekonać na przykładzie instrukcji w linii 13. Prześledźmy zaleŜności pomiędzy poszczególnymi zapisami tworzącymi to wyraŜenie. Do obiektu dzien klasy String przypisana jest wartość uzyskana dzięki wywołaniu metody format na rzecz obiektu formator klasy NumberFormat. Parametrem tej metody jest predefiniowana w klasie GregorianCalendar stała DAY_OF_MONTH. ZaleŜności pomiędzy wymienionymi obiektami zostały przedstawione poniŜej.
3. Tworzenie własnych klas W poprzednich przykładach tworzyliśmy klasy, które nie posiadały własnych metod. Zamiast tego posiadały jedną statyczną metodę main, w której zawierał się cały kod programu. Schemat budowy klasy w języku Java został przedstawiony poniŜej: class Nazwa { konstruktor1; konstruktor2; // dalsze konstruktory metoda1; metoda2; //dalsze metody pole1; pole2; //dalsze pola } Kolejność składników klasy jest dowolna, jednak przyjęło się, aby na pierwszym miejscu umieszczać definicje konstruktorów, później metod, a na samym końcu pól. Zdefiniujmy klasę o nazwie osoba, słuŜącą do zapamiętywania podstawowych danych osobowych, takich jak imię, nazwisko i wiek. KlasaOsoba.java 1. 2. 3. 4. 5. 6. 7. 8.
public class KlasaOsoba { // konstruktor public KlasaOsoba(String i,String n, int w) { nazwisko = n; imie = i; wiek = w;
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34.
} // metoda1 public String PobierzDane() { return imie+" "+nazwisko+"lat "+wiek+"\n"; } // metoda 2 public void WczytajDane(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } // pola składowe private String imie; private String nazwisko; private int wiek;
public static void main(String[] args) { // kod funkcji } }
Definicja klasy KlasaOsoba posiada jeden konstruktor, dwie metody o nazwach PobierzDane i WczytajDane oraz trzy pola o nazwach imie, nazwisko i wiek.
4. Pola i metody Działania jakie moŜemy przeprowadzić na polach klasy za pomocą wywoływania odpowiednich metod moŜna prześledzić na przykładzie programu operującego na obiektach klasy DaneOsobowe. DaneOsobowe.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23.
import javax.swing.*; public class DaneOsobowe { // konstruktor1 public DaneOsobowe(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } // konstruktor2 public DaneOsobowe() { } // metoda1 public String PobierzDane() { String ramka=""; String kreskaL="| "; String kreskaP=" |\n"; String dane = imie+" "+nazwisko+", lat "+wiek; int dlugosc = 4 + dane.length(); for (int i=1;i<=dlugosc;i++) ramka +="-";
ramka+="\n"; String wynik=ramka+kreskaL+dane+kreskaP+ramka+"\n"; return wynik; } // metoda 2 public void WczytajDane(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } // pola składowe private String imie; private String nazwisko; private int wiek; public static void main(String[] args) { String wejscie = JOptionPane.showInputDialog("Ile osób chcesz zapamiętać? (1 - 5 osób)"); int ile = Integer.parseInt(wejscie); DaneOsobowe[] uczen = new DaneOsobowe[ile]; // Umieszczanie danych w tablicy obiektów for (int i=1;i<=ile;i++) { String Imie = JOptionPane.showInputDialog("Podaj Imię osoby nr "+i); String Nazwisko = JOptionPane.showInputDialog("Podaj Nazwisko osoby nr "+i); wejscie = JOptionPane.showInputDialog("Podaj wiek osoby nr "+i); int Wiek = Integer.parseInt(wejscie); uczen[i-1] = new DaneOsobowe(); uczen[i-1].WczytajDane(Imie, Nazwisko, Wiek); } // Wyświetlanie danych z tablicy obiektów String wyjscie=""; for (int i=1;i<=ile;i++) { wyjscie+=uczen[i-1].PobierzDane(); } JOptionPane.showMessageDialog(null, wyjscie); System.out.println(wyjscie); } }
Program zawiera klasę DaneOsobowe, której definicja jest bardzo podobna do definicji klasy KlasaOsoba. RóŜnica polega na zmodyfikowaniu konstruktora tej klasy (konstruktor1) oraz dołoŜeniu drugiego konstruktora (o konstruktorach dowiemy się więcej w następnym punkcie rozdziału). W liniach 42 i 43 następuje podanie ilości osób, które chcemy zapamiętać. W następnej linii wykorzystujemy wczytane wcześniej dane do inicjalizacji n-elementowej tablicy obiektów klasy DaneOsobowe. Następnie w liniach od 48 do 51 wczytywane są kolejno: imię, nazwisko i wiek poszczególnych osób. W linii 52 następuje inicjalizacja konkretnego obiektu, w którym pamiętane będą wczytane dane osoby, a w linii 53 wywołanie funkcji WczytajDane, która zapisuje wczytane wcześniej dane do odpowiednich pól obiektu. W drugiej pętli – linia 59 – na rzecz kolejnych obiektów wywoływana zostaje funkcja PobierzDane. Wyświetlanie wyników odbywa się w liniach 61 i 62. Efekt działania programu przedstawiono poniŜej.
5. Konstruktory Konstruktorem w programowaniu obiektowym nazywamy metodę danej klasy, wywoływaną podczas tworzenia jej instancji. Zadaniem konstruktora jest zainicjowanie obiektu. Istnieje zasadnicza róŜnica pomiędzy metodami klasy, a konstruktorem. Konstruktor moŜe być wywołany tylko w połączeniu z operatorem new. Nie moŜna wywołać konstruktora istniejącego obiektu aby zmienić jego pola. uczen.DaneOsobowe("Jan", "Kowalski",18); //Błąd !!!
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA Podstawowymi cechami konstruktora są: • konstruktor nosi tę samą nazwę co klasa • klasa moŜe posiadać więcej niŜ jeden konstruktor • konstruktor moŜe nie posiadać parametrów • konstruktor jest funkcja nie wracającą wartości • konstruktor jest zawsze wywoływany przez operator new W poprzednim rozdziale omawiana była klasa DaneOsobowe. Posiadała ona dwa konstruktory: // konstruktor1 public DaneOsobowe(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } // konstruktor2 public DaneOsobowe() { } Jak widać występuje tu dwukrotnie definicja metod o tej samej nazwie. Takie rozwiązanie nazywamy przeładowaniem. Przeładowanie występuje gdy kilka metod posiada tę samą nazwę, ale róŜne parametry. Kompilator wyszukuje właściwą metodę analizując typy danych i ilość przekazanych do metody parametrów. Jeśli klasa nie zawiera definicji Ŝadnego konstruktora, to zostanie dla niej zbudowany konstruktor domyślny, który nadaje wszystkim zmiennym wartości domyślne. Tak więc danym numerycznym zostanie nadana wartość 0, zmiennym logicznym zostanie nadana wartość false, a wszystkim zmiennym obiektów zostanie zadana wartość null. JeŜeli w klasie zdefiniujemy chociaŜ jeden konstruktor, to nie będzie moŜna wykorzystać konstruktora domyślnego. Any uniknąć tej niedogodności trzeba podać jawnie definicję bezparametrowego konstruktora – tak jak to wykonano w powyŜszej klasie DaneOsobowe. PoniŜej przedstawiono przykład klasy z czterema konstruktorami: Planety.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.
import java.util.Random; import javax.swing.*; class Planety { String nazwa; int rozmiar; Random random = new Random(); Planety() { nazwa = "BezNazwy"; rozmiar = Math.abs( random.nextInt() ) % 10000 + 1; } Planety( String nazwa ) { this.nazwa = nazwa; rozmiar = Math.abs( random.nextInt() ) % 10000 + 1; } Planety( String aNazwa, int aRozmiar ) {
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45. 46. 47. 48. 49. 50. 51. 52.
nazwa = aNazwa; if ( aRozmiar <= 10000 && aRozmiar >=1 ) { rozmiar = aRozmiar; } else if( aRozmiar > 10000 ) { rozmiar = 10000; } else { rozmiar = 1; } } Planety( int rozmiar ) { nazwa = "Jeszcze nienazwana"; this.rozmiar = rozmiar; } public String Wypisz() { return "Planeta: \""+nazwa+"\" "+"Rozmiar: "+rozmiar+"\n\n"; } public static void main(String angs[]) { Planety planeta1 = new Planety(); Planety planeta2 = new Planety("Ziemia"); Planety planeta3 = new Planety("Wenus", 20000); Planety planeta4 = new Planety(5000); String wyjscie=""; wyjscie+=planeta1.Wypisz(); wyjscie+=planeta2.Wypisz(); wyjscie+=planeta3.Wypisz(); wyjscie+=planeta4.Wypisz(); JOptionPane.showMessageDialog(null,wyjscie); } }
W powyŜszym przykładzie zdefiniowano cztery przeładowane wersje konstruktora Planeta. Pierwszy z nich (linie 9 – 12) – bezparametrowy – konstruuje obiekt, który przechwuje nazwę "BezNazwy" i losowy rozmiar. Do wygenerowania liczby losowej zastosowano obiekt klasy Random, na rzecz którego wykonano metodę nextInt. Drugi konstruktor (linie 14 – 17) tworzy obiekt, który przechwuje nazwę podaną w parametrze, natomiast rozmiar wybierany jest losowo z zakresu od 1 do 10000. Trzeci konstruktor (linie 19 – 28) jest najbardziej rozbudowanym z konstruktorów. Tworzy on obiekt, który przechwuje podaną w parametrze nazwę, natomiast rozmiar jest poddany porównaniom. Jeśli rozmiar zawiera się w przedziale od 1 do 1000, to zostaje bez zmian, w przeciwnych przypadkach rozmiar zostaje zmieniony na jedną ze skrajnych wartości (1 lub 10000). Czwarty – ostatni konstruktor – tworzy obiekt, który przechwuje nazwę "Jeszcze nienazwana" i rozmiar podany jako parametr. PoniŜej zaprezentowano efekt działania programu.
Efekt działania czterech konstruktorów klasy Planety
6. Pola i metody statyczne 6.1. Pola statyczne Jeśli zdefiniujemy zmienną klasy jako statyczną (odbywa się to za pomocą słowa static przed podaniem typu zmiennej), taka zmienna będzie istniała dla całej klasy. W innym przypadku kaŜdy obiekt będzie posiadał własną kopię takiej zmiennej. Tak więc zmienna statyczna (pole statyczne) odnosić się będzie do całej klasy, a nie do poszczególnych obiektów tej klasy. Aby zaprezentować zastosowanie pól statycznych posłuŜymy się nieco zmodyfikowaną klasą DaneOsobowe o nazwie DaneOsobowe2. DaneOsobowe2.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40. 41. 42. 43. 44. 45.
import javax.swing.*; public class DaneOsobowe2 { // konstruktor1 public DaneOsobowe2(String i,String n, int w) { IloscOsob++; numer=IloscOsob; nazwisko = n; imie = i; wiek = w; } // metoda1 public String PobierzDane() { String ramka=""; String kreskaL="| "; String kreskaP=" |\n"; String dane = numer+". "+imie+" "+nazwisko+", lat "+wiek; int dlugosc = 4 + dane.length(); for (int i=1;i<=dlugosc;i++) ramka +="-"; ramka+="\n"; String wynik=ramka+kreskaL+dane+kreskaP+ramka+"\n"; return wynik; } // metoda 2 public void WczytajDane(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } // pola składowe private int numer; private String imie; private String nazwisko; private int wiek; // składnik statyczny public static int IloscOsob=0; public static void main(String[] args) { String wejscie = JOptionPane.showInputDialog("Ile osób chcesz zapamiętać? (1 - 5 osób)"); int ile = Integer.parseInt(wejscie); DaneOsobowe2[] uczen = new DaneOsobowe2[ile]; // Umieszczanie danych w tablicy obiektów
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA 46. 47. 48. 49. 50. 51. 52. 53. 54. 55. 56. 57. 58. 59. 60. 61. 62. 63. 64.
for (int i=1;i<=ile;i++) { String Imie = JOptionPane.showInputDialog("Podaj Imię osoby nr "+i); String Nazwisko = JOptionPane.showInputDialog("Podaj Nazwisko osoby nr "+i); wejscie = JOptionPane.showInputDialog("Podaj wiek osoby nr "+i); int Wiek = Integer.parseInt(wejscie); uczen[i-1] = new DaneOsobowe2(Imie, Nazwisko, Wiek); } // Wyświetlanie danych z tablicy obiektów String wyjscie=""; for (int i=1;i<=ile;i++) { wyjscie+=uczen[i-1].PobierzDane(); } wyjscie+="Liczba zapamiętanych osób = "+IloscOsob; JOptionPane.showMessageDialog(null, wyjscie); System.out.println(wyjscie); } }
W klasie tej zadeklarowano składnik statyczny IloscOsob (linia 39), który za kaŜdym razem gdy tworzymy obiekt klasy DaneOsobowe2 jest przypisywany do prywatnego pola numer, a następnie zwiększany o 1 (linie 7 i 8). W tym składniku przechowywana jest więc ilość utworzonych obiektów tej klasy. Składnik statyczny IloscOsob wykorzystywany jest równieŜ w linii 60 do wyświetlenia łącznej ilości osób zapamiętanych w tablicy obiektów. PoniŜej przedstawiono przykład działania programu z zastosowaniem składnika statycznego.
Wyświetlenie danych zapamiętanych osób oraz ich ilości za pomocą składnika statycznego
6.2. Stałe Stałych statycznych uŜywamy w klasach jeśli chcemy zdefiniować pewną wartość, która będzie niezmienna przez cały czas trwania programu. Przykładowo w klasie Math jest zdefiniowana stała statyczna PI w sposób następujący: public class Math { // …… public static final double PI = 3.14159365358979323846; // …… } Słowo final przed nazwą typu danych oznacza, Ŝe mamy do czynienia ze stałą, i Ŝe nie będziemy mieli moŜliwości zmienić wartości stałej oznaczonej tym słowem. Zastosowanie stałych zostało zaprezentowane w klasie JednostkiMocy. JednostkiMocy.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
import javax.swing.*; import java.text.NumberFormat; public class JednostkiMocy { public static void main(String[] args) { String wejscie; NumberFormat formator = NumberFormat.getNumberInstance(); formator.setMaximumFractionDigits(2); wejscie = JOptionPane.showInputDialog("Podaj moc silnika w kW"); int moc = Integer.parseInt(wejscie); String wyjscie=moc+" kW = "+formator.format(moc*KW_NA_KM)+" KM"; JOptionPane.showMessageDialog(null, wyjscie); wejscie = JOptionPane.showInputDialog("Podaj moc silnika w KM"); moc = Integer.parseInt(wejscie); wyjscie=moc+" KM = "+formator.format(moc*KM_NA_KW)+" kW"; JOptionPane.showMessageDialog(null, wyjscie); } private static final double KW_NA_KM = 1.359623; private static final double KM_NA_KW = 0.735498; }
W tej klasie zdefiniowano dwie stałe: KW_NA_KM i KM_NA_KW. SłuŜą one do przeliczania mocy silnika z koni mechanicznych na kilowaty i odwrotnie (linie 18 i 19). Przykładowy wynik działania programu przedstawiono poniŜej.
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA 6.3. Metody Statyczne Metody statyczne – podobnie jak pola statyczne – nie operują na obiektach danej klasy. PoniewaŜ metody statyczne nie operują na obiektach nie moŜesz za ich pomocą sięgać do zmiennych składowych klasy. Mają one natomiast dostęp do pól statycznych klasy. Na przykład nigdy nie tworzy się obiektów klasy Math aby wywołać funkcję Math.pow. PoniŜej zamieszczono przykład zastosowania metod statycznych.
import javax.swing.*; public class KonwersjaSystemow { public static void main(String[] args) { String wejscie=JOptionPane.showInputDialog("Podaj liczbę w systemie dziesiątkowym"); int x = Integer.parseInt(wejscie); String wyjscie=x+"(10) = "+ KonwersjaSystemow.Wspak(Dec2Bin(x))+"(2)\n\n"; JOptionPane.showMessageDialog(null,wyjscie); } private static String Dec2Bin(int x) { String temp=""; int reszta; while (x != 0) { reszta = x % 2; temp+=reszta; x /= 2; } return temp; } private static String Wspak(String wejscie) { String temp=""; for (int i=wejscie.length()-1;i>=0;i--) temp=temp+wejscie.charAt(i); return temp; } }
W klasie KonwersjaSystemow występują dwie metody statyczne: Dec2Bin i Wspak. Widzimy, Ŝe ich wywołanie odbywa się bez podawania jakichkolwiek nazw obiektów (linia nr 9). Nazwa funkcji statycznej przy wywołaniu moŜe zostać poprzedzona nazwą klasy (ma to miejsce przy wywołaniu funkcji statycznej Wspak). PoniŜej przedstawiono efekt działania programu z zastosowanie metod statycznych.
Zamiana liczby na system binarny Specjalną metodą statyczną jaka moŜe być zdefiniowana w klasie jest metoda main. Metoda main danej klasy nie operuje na obiektach tej klasy. Metoda ta zaczyna działanie programu więc właściwie jeszcze Ŝadne obiekty nie zostały utworzone. To właśnie w metodzie main tworzone są potrzebne do działania programu obiekty. Właściwie kaŜda klasa moŜe posiadać metodę main. Stosuje się ją często aby przetestować działanie naszej klasy. Aby przetestować działanie testowanej klasy za pomocą zdefiniowanej w niej metody main naleŜy wpisać: java TestowanaKlasa Jeśli testowana klasa jest częścią jakiejś większej aplikacji, wtedy piszemy: java TestowanaAplikacja W tym przypadku nie zostanie wykonana metoda main testowanej klasy – wykona się natomiast metoda main testowanej aplikacji. Do prezentacji programu z dwiema klasami i dwiema metodami main uŜyjemy zmodyfikowanej DaneOsobowe o nazwie DaneOsobowe3; DaneOsobowe3.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17.
import javax.swing.*; public class DaneOsobowe3 { public static void main(String[] args) { String wejscie = JOptionPane.showInputDialog("Ile osób chcesz zapamiętać? (1 - 5 osób)"); int ile = Integer.parseInt(wejscie); Osoba[] uczen = new Osoba[ile]; // Umieszczanie danych w tablicy obiektów for (int i=1;i<=ile;i++) { String Imie = JOptionPane.showInputDialog("Podaj Imię osoby nr "+i); String Nazwisko = JOptionPane.showInputDialog("Podaj Nazwisko osoby nr "+i); wejscie = JOptionPane.showInputDialog("Podaj wiek osoby nr "+i); int Wiek = Integer.parseInt(wejscie); uczen[i-1] = new Osoba(Imie, Nazwisko, Wiek); }
// Wyświetlanie danych z tablicy obiektów String wyjscie=""; for (int i=1;i<=ile;i++) { wyjscie+=uczen[i-1].PobierzDane(); } wyjscie+="Liczba zapamiętanych osób = "+Osoba.IloscOsob; JOptionPane.showMessageDialog(null, wyjscie); System.out.println(wyjscie); } } class Osoba { // konstruktor1 public Osoba(String i,String n, int w) { IloscOsob++; numer=IloscOsob; nazwisko = n; imie = i; wiek = w; } // metoda1 public String PobierzDane() { String ramka=""; String kreskaL="| "; String kreskaP=" |\n"; String dane = numer+". "+imie+" "+nazwisko+", lat "+wiek; int dlugosc = 4 + dane.length(); for (int i=1;i<=dlugosc;i++) ramka +="-"; ramka+="\n"; String wynik=ramka+kreskaL+dane+kreskaP+ramka+"\n"; return wynik; } // metoda 2 public void WczytajDane(String i,String n, int w) { nazwisko = n; imie = i; wiek = w; } //statyczna metoda main klasy Osoba public static void main(String args[]) { Osoba profesor = new Osoba("Profesor","Mądry",45); System.out.println(profesor.PobierzDane()); } // pola składowe private int numer; private String imie; private String nazwisko; private int wiek; // składnik statyczny public static int IloscOsob=0; }
ROZDZIAŁ V. OBIEKTY, KLASY, METODY I POLA obiekt o nazwie profesor (linia 64) i wyświetliliśmy jego stan za pomocą metody PobierzDane (linia 65). MoŜemy wybrać, która metoda main ma zostać wykonana. W tym celu naleŜy w okienku Projects ustawić się na pliku źródłowym i wybrać opcję Run File lub nacisnąć kombinację klawiszy SHIFT + F6.
Wybór klasy, której funkcja main ma być uruchomiona
Rozdział VI Aplikacje okienkowe 1. Tworzenie aplikacji okienkowych przy uŜyciu biblioteki Swing Dotychczasowe programy, które tworzyliśmy w Javie najczęściej wyświetlały wyniki bądź w okienku Output lub Message. Współczesne programy działają przewaŜnie jako samodzielne aplikacje okienkowe. Jak sama nazwa wskazuje uruchamiają się one w oknie, w którym zbudowany jest interfejs uŜytkownika. Interfejs ten stanowią przyciski, pola rozwijane, pola dialogowe, przyciski opcji, napisy, menu itd. Po zbudowaniu interfejsu uŜytkownika naleŜy napisać procedury obsługi zdarzeń takich jak kliknięcie myszką czy wybranie odpowiedniej opcji. Java w wersji 1.0 zawierała juŜ bibliotekę AWT, która słuŜyła do prostego programowania graficznego interfejsu uŜytkowanika (GUI). Obecnie do programowania GUI najczęściej uŜywamy biblioteki Swing. Prześledźmy program tworzący najprostsze puste okno o określonych rozmiarach. ProsteOkno.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20.
import javax.swing.*; public class ProsteOkno { public static void main(String args[]) { Okno ramka = new Okno(); ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ramka.show(); } } class Okno extends JFrame { public Okno() { setSize(SZEROKOSC, WYSOKOSC); } public static final int SZEROKOSC = 400; public static final int WYSOKOSC =300; }
W programie tym występują dwie klasy. Klasa Okno rozszerza klasę JFrame i za pomocą konstruktora zmienia domyślny rozmiar ramki 0x0 pikseli na 400x300 pikseli. Zmiana rozmiaru ramki dokonywana jest za pomocą metody setSize (linia 16). W klasie ProsteOkno w metodzie main tworzony jest obiekt ramki (linia 6). Domyślnie ramka nie jest wyświetlania na ekranie. Aby ją wyświetlić naleŜy wywołać metodę show (linia 8). WaŜną czynnością przy programowaniu aplikacji okienkowych jest oprogramowanie sytuacji gdy uŜytkownik zamyka okno. Jeśłi chcemy aby po zamknięciu okna aplikacja zakończyła swoje działanie musimy uŜyć polecenia z linii 7, które informuje, Ŝe aplikacja po zamknięciu okna ma zakończyć swoje działanie. PoniŜej przedstawiono wynik działania programu.
W następnym przykładzie rozbudujemy klasę wyświetlającą puste okno i wzbogacimy ją o kilka elementów. Będziemy chcieli wypozycjonować okno na środku ekranu, ustalić jego rozmiar na połowę rozdzielczości ekranu oraz umieścić tytuł okna i "podmienić" ikonkę w lewym górnym rogu ekranu. ProsteOkno2.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26.
import javax.swing.*; import java.awt.*; public class ProsteOkno2 { public static void main(String args[]) { Okno2 ramka = new Okno2(); ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ramka.show(); } } class Okno2 extends JFrame { public Okno2() { Toolkit InformacjeSystemowe = Toolkit.getDefaultToolkit(); Dimension rozmiarEkranu = InformacjeSystemowe.getScreenSize(); int wysEkranu = rozmiarEkranu.height; int szerEkranu = rozmiarEkranu.width; setSize(szerEkranu / 2, wysEkranu / 2); setLocation(szerEkranu / 4, wysEkranu / 4); Image rys = InformacjeSystemowe.getImage("zsti.gif"); setIconImage(rys); setTitle("Okno centralnie na środku ekranu"); } }
W powyŜszym programie naleŜy uzyskać informację o aktualnej rozdzielczości ekranu. W tym celu wywołamy metodę getScreenSize klasy Toolkit. Metoda ta zwraca rozmiar ekranu w postaci obiektu klasy Dimension (linia 17). Obiekt ten posiada dwie właściwości, dzięki którym zapamiętujemy wysokość i szerokośc ekranu w odpowiednich zmiennych (linie 18, 19). W linii 21 pozycjonujemy okno na środku ekranu za pomocą metody setLocation. W linii 22 za pomocą metody getImage zmieniamy domyślną ikonę "filiŜanki kawy" na przygotowaną przez nas (ikonę zawartą w pliku zsti.gif o rozmiarze 20x20 pikseli), natomiast
ROZDZIAŁ VI. APLIKACJE OKIENKOWE w linii 24 definiujemy napis jaki ma pokazać się na pasku tytułowym okna. PoniŜej przedstawiono efekt działania programu.
Okno wyświetla się na środku ekranu
2. Umieszczanie informacji w oknie – praca z panelami W następnym przykładzie zajmiemy się wyświetlaniem informacji w oknie. W poprzednich przykładach definiowaliśmy klasę Okno, która rozszerzała klasę JFramę (klasa JFrame rozszerza z kolei klasę Frame). W Javie ramki są przede wszystkim pojemnikami graficznymi – kontenerami – do przechowywania innych komponentów, takich jak teksty, przyciski, menu itp. Zazwyczaj więc umieszczać je będziemy w innym komponencie o nazwie panel, który później dołączony zostanie do ramki. Ramka składa się z 4 powierzchni. Z punktu widzenia programisty najwaŜniejsza jest twz. powierzchnia zawartości (z j. ang. content pane) – to do niej dołączać będziemy inne komponenty. Konstrukcja ta wygląda następująco: Container powierzchniaZawartosci = getContentPane(); Component x = …………; // tu definiujemy odpowiedni komponent powierzchniaZawartosci.add(x); // tu dodajemy komponent do powierzchni zawartości
PoniŜej przedstawiono program wyświetlający w oknie napis "Programowanie w Javie". TestNapisu.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.
import javax.swing.*; import java.awt.*; import java.awt.Font; public class TestNapisu { public static void main(String args[]) { OknoTestNapisu ramka = new OknoTestNapisu(); ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ramka.show(); } } class OknoTestNapisu extends JFrame {
public OknoTestNapisu() { Toolkit InformacjeSystemowe = Toolkit.getDefaultToolkit(); Dimension rozmiarEkranu = InformacjeSystemowe.getScreenSize(); int wysEkranu = rozmiarEkranu.height; int szerEkranu = rozmiarEkranu.width; setSize(szerEkranu / 2, wysEkranu / 2); setLocation(szerEkranu / 4, wysEkranu / 4); Image rys = InformacjeSystemowe.getImage("zsti.gif"); setIconImage(rys); setTitle("Programowanie w Javie"); PanelTestNapisu panel = new PanelTestNapisu(); Container powZawartosci = getContentPane(); powZawartosci.add(panel); } } class PanelTestNapisu extends JPanel { public void paintComponent(Graphics g) { super.paintComponent(g); Font czcionka = new Font("Sans Serif",Font.BOLD,20); g.setFont(czcionka); g.drawString("Programowanie w Javie", POZ_X, POZ_Y); } public static final int POZ_X = 200; public static final int POZ_Y = 180; }
NajwaŜniejszą zmianą w powyŜszym przykładzie w stosunku do poprzedniego (ProsteOkno2.java) jest utworzenie obiektu panel (linia 26) klasy PanelTestNapisu. Klasa ta rozszerza klasę JPanel i redefiniuje metodę paintComponent, która jest odpowiedzialna za wszystkie operacje rysowania w Javie. Za kaŜdy razem, gdy okno będzie musiało zostać ponownie narysowane ta metoda zostanie wywołana automatycznie. Ponowne rysowanie ma miejsce w przypadku zmiany rozmiaru okna, przemieszczenia go na ekranie, zminimalizowania i ponownego przywrócenia, w przypadku gdy inne okno zasłoniło nasze okno, itp. Jeśli chcemy "ręcznie" wymusić odmalowanie okna, naleŜy wywołać metodę repaint, która automatycznie spowoduje ponowne odmalowanie okna. Metoda paintComponent pobiera jeden parametr – obiekt g klasy Graphics (linia 33). W obiekcie g klasy Graphics przechowywane są wszystkie informacje dotyczące wyświetlania tekstów i rysunków, czcionek, kolorów itp. Aby wyświetlić tekst na ekranie tworzymy nowy obiekt klasy Font i konstruktorze podajemy jego parametry: nazwę czcionki, atrybuty i rozmiar (linia 36). Następnie na rzecz obiektu g klasy Graphics wykonujemy metodę setFont, podając jako parametr outworzony wcześniej obiekt czcionki (linia 37). Wyświetlenie napisu na ekranie w ściśle określonym połoŜeniu odbywa się poprzez wywołanie metody drawString (linia 38). PoniŜej przedstawiono wynik działania programu.
{ super.paintComponent(g); Font czcionka = new Font("Sans Serif",Font.BOLD,20); g.setColor(new Color(220,70,40)); g.setFont(czcionka); g.drawString("Test Figur Geometrycznych", POZ_X, POZ_Y); Graphics2D g2 = (Graphics2D)g; double lewyX = 50; double gornyY = 50; double szerokosc = 540; double wysokosc = 300; g2.setPaint(Color.RED); Rectangle2D pros = new Rectangle2D.Double(lewyX, gornyY, szerokosc, wysokosc); BasicStroke linia = new BasicStroke(3.0f, BasicStroke.CAP_ROUND, BasicStroke.CAP_ROUND); g2.setStroke(linia); g2.draw(pros); Ellipse2D elipsa = new Ellipse2D.Double(); elipsa.setFrame(pros); g2.setPaint(Color.BLUE); g2.draw(elipsa); g2.draw(new Line2D.Double(lewyX, gornyY, lewyX+szerokosc, gornyY+wysokosc)); double srodekX = pros.getCenterX(); double srodekY = pros.getCenterY(); double promien = 150; Ellipse2D okrag = new Ellipse2D.Double(); okrag.setFrameFromCenter(srodekX, srodekY, srodekX+promien, srodekY+promien); g2.setColor(Color.GREEN); g2.draw(okrag); } public static final int POZ_X = 200; public static final int POZ_Y = 30; }
W linii 28 ustalamy nowy kolor dla naszego okna za pomocą metody setBackground. MoŜna wykorzystać jeden z predefiniowanych kolorów systemowych lub utworzyć nowy obiekt koloru podając w konstruktorze jego parametry, w postaci 3 liczb symbolizujących składowe RGB. Podobnie postępujemy z ustaleniem kolorów czcionki (linia 39) oraz linii, którymi będą rysowane obiekty rysunkowe: linia, prostokąt, elipsa i okrąg (linie 47, 54, 62). Aby działać na obiektach klasy Graphics2D naleŜy utworzyć obiekt tej klasy. W tym celu rzutujemy obiekt g do klasy Graphisc2D i tworzymy obiekt g2 (linia 42). Na tym obiekcie będziemy wykonywać dalsze operacje. W linii 48 tworzymy obiekt o nazwie pros klasy Rectangle2D i konstruujemy go podając współrzędne lewego górnego naroŜnika oraz wysokość i szerokość. W następnej linii tworzymy obiekt, w którym definiujemy grubość i styl linii oraz przekazujemy go metodzie setStroke (linia 50). W następnych liniach konstruujemy obiekty reprezentujące: elipsę wpisaną w prostokąt (linia 52, 53), ukośną linię (linia 56) oraz okrąg (linia 60). W kaŜdym z powyŜszych przykładów nieco inaczej następuje konstruowanie obiektów i przekazywanie ich metodzie draw. PoniŜej przedstawiono efekt działania programu.
4. Obsługa zdarzeń Ostatnim przykładem aplikacji okienkowych będzie program, w którym zastosowano tzw. obsługę zdarzeń. Projektując aplikację obsługującą zdarzenia takie jak np. kliknięcie myszką musimy najpierw stworzyć panel wypełniony przyciskami, a następnie zbudować obiekty słuchaczy, które będą słuchaczami akcji tych przycisków. Jeśli uŜytkownik kliknie którykolwiek z przycisków w tym panelu, przypisanych do tego przycisku obiekt słuchacza otrzyma obiekt klasy ActionEvent, który przekaŜe informację, Ŝe przycisk został naciśnięty. Następnie obiekt słuchacza spowoduje np. zmianę koloru panelu. PoniŜej przedstawiono program z zastosowaniem obsługi zdarzeń. TestObslugiZdarzen.java 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30.
import java.awt.*; import java.awt.event.*; import javax.swing.*; public class TestObslugiZdarzen { public static void main(String[] args) { RamkaObslugiZdarzen ramka = new RamkaObslugiZdarzen(); ramka.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); ramka.show(); } } class RamkaObslugiZdarzen extends JFrame { public RamkaObslugiZdarzen() { Toolkit InformacjeSystemowe = Toolkit.getDefaultToolkit(); Dimension rozmiarEkranu = InformacjeSystemowe.getScreenSize(); int wysEkranu = rozmiarEkranu.height; int szerEkranu = rozmiarEkranu.width; setSize(szerEkranu / 2, wysEkranu / 2); setLocation(szerEkranu / 4, wysEkranu / 4); Image rys = InformacjeSystemowe.getImage("zsti.gif"); setIconImage(rys); setTitle("Test obsługi zdarzeń"); PanelPrzyciskow panel = new PanelPrzyciskow(); panel.setBackground(new Color(250,250,250)); Container powZawartosci = getContentPane(); powZawartosci.add(panel);
} public static final int SZEROKOSC = 300; public static final int WYSOKOSC = 200; } class PanelPrzyciskow extends JPanel { public PanelPrzyciskow() { JButton przyciskZolty = new JButton("śółty"); JButton przyciskNiebieski = new JButton("Niebieski"); JButton przyciskCzerwony = new JButton("Czerwony"); JButton przyciskZielony = new JButton("Zielony"); add(przyciskZolty); add(przyciskNiebieski); add(przyciskCzerwony); add(przyciskZielony); DzialanieKoloru dzialanieZoltego = new DzialanieKoloru(Color.yellow); DzialanieKoloru dzialanieNiebieskiego = new DzialanieKoloru(Color.blue); DzialanieKoloru dzialanieCzerwonego = new DzialanieKoloru(Color.red); DzialanieKoloru dzialanieZielonego = new DzialanieKoloru(Color.green); przyciskZolty.addActionListener(dzialanieZoltego); przyciskNiebieski.addActionListener(dzialanieNiebieskiego); przyciskCzerwony.addActionListener(dzialanieCzerwonego); przyciskZielony.addActionListener(dzialanieZielonego); } private class DzialanieKoloru implements ActionListener { public DzialanieKoloru(Color k) { kolorTla = k; } public void actionPerformed(ActionEvent zdarzenie) { setBackground(kolorTla); repaint(); } private Color kolorTla; } }
Na uwagę zasługuje klasa PanelPrzyciskow. W tej klasie tworzone są cztery obiekty klasy JButton, które stanowić będą obiekty 4 przycisków. W konstruktorze tych obiektów podawany jest napis, jak ma się pokazać na przycisku (linie 40 – 43). Następnie wywoływana jest czterokrotnie metoda add, która umieszcza obiekty przycisków w panelu (linie 44 – 47). W liniach od 48 d 55 tworzymy cztery obiekty dla kaŜdego z kolorów i czynimy je obiektami słuchaczy dla przycisków. Na przykład jeśli klikniemy w przycisk oznaczony napisem "Czerwony" zostanie wywołana metoda actionPerformed dla obiektu dzialanieCzerwonego. Konstruktor obiektów klasy DzialanieKoloru "ustawi" prywatne pole kolorTla i przypisze do niego wartość Color.red (linia 62). Następnie w metodzie actionPerformed wywołana zostanie metoda setBackground, która powoduje zmianę koloru tła na czerwony (linia 67) oraz metoda repaint przerysowująca okno (linia 68). PoniŜej przedstawiono działanie programu zawierającego obsługę zdarzeń.
Rozdział VII Tworzenie apletów Apletem będziemy nazywać niewielki program napisany w języku Java w taki sposób by mógł zostać wczytany przez przeglądarkę internetową i uruchomiony w środowisku JVM komputera, na którym funkcjonuje przeglądarka. Aplety były i są wykorzystywane głównie do tworzenia: • efektów graficznych wzbogacających wystrój stron WWW, m.in. animacji • "cienkich klientów" aplikacji internetowych • interaktywnych prezentacji, np. zjawisk fizycznych • narzędzi pomocniczych, np. klientów IRC-a lub czata WaŜną cechą apletów zwiększającą bezpieczeństwo, ale ograniczającą funkcjonalność, jest ich odseparowanie od zasobów lokalnego komputera, tj. tego, na którym uruchomiona jest przeglądarka. Niepodpisany cyfrowo aplet nie ma dostępu do systemu plików, nie moŜe teŜ łączyć się z innym serwerem niŜ ten, z którego został pobrany. Program NetBeans, oprócz tworzenia aplikacji, umoŜliwia tworzenie i uruchamianie apletów w języku Java. Aby utworzyć aplet w programie NetBeans naleŜy z menu File wybrać New Project …a następnie z listy Categories: wybrać Java, natomiast z listy Projects: wybrać Java Application.
PoniewaŜ w aplecie nie występuje metoda main, naleŜy odznaczyć pole Create Main Class w powyŜszym oknie. Następnie naleŜy utworzyć nowy plik z klasą rozszerzająca klasę JApplet.
W następnym kroku naleŜy podać nazwę klasy i jej lokalizację oraz zatwierdzić dokonany wybór poprzez kliknięcie w przycisk Finish.
1. Tworzenie prostego apletu PoniŜej podano przykład prostego apletu wyświetlającego napis w oknie przeglądarki. TestProstegoApletu.java
import java.awt.*; import javax.swing.*; public class TestProstegoApletu extends JApplet { public void init() { Container zawartosc = getContentPane(); JLabel napis = new JLabel("To jest aplet języka Java", SwingConstants.CENTER); zawartosc.add(napis); } }
W programie nie występuje metoda main. Zamiast niej występuje metoda init(), która wykonuje się jako pierwsza. W metodzie tej tworzony jest obiekt klasy JLabel i umieszczany jest w nim napis "To jest aplet języka Java" (linia 8). Następnie za pomocą metody add jest on dodawany do powierzchni zawartości (linia 9). W programie NetBeans moŜna testować działanie apletów za pomocą przeglądarki apletów. Aby to uczynić naleŜy zaznaczyć plik z klasą, która tworzy aplet w okienku Projects, a następnie z menu kontekstowego wybrać polecenie RunFile (Shift + F6).
Uruchomienie apletu PoniŜszy rysunek przedstawia efekt działania naszego apletu uruchomionego w przeglądarce apletów.
Widok apletu w przeglądarce apletów
Aby utworzony przez nas aplet uruchomić w przeglądarce stron WWW musimy napisać kod strony HTML i "osadzić" w nim nasz aplet. NetBeans tworzy taki kod i umieszcza go podfolderze o nazwie build zlokalizowanym w bieŜącym folderze projektu. PoniŜej przedstawiono listing kodu HTML oraz widok apletu w przeglądarce WWW.