0. Literatura Literatura podstawowa: Wykład pierwszy Bruce Eckel Thinking in Java, Helion, Gliwice 2001 (lub nowsze wydanie) Cay S. Horstmann, Gary Cornell Core Java 2 Podstawy, Helion, Gliwice 2003 Literatura uzupełniająca: Cay S. Horstmann, Gary Cornell, Core Java 2 Techniki Zaawansowane, Helion, Gliwice 2005 1. Krótka historia języka Java Prace nad językiem Java rozpoczęły si ę w roku 1990, w ramach wewnętrznego projektu firmy SUN Microsystems. Początkowym celem tego projektu było stworzenie urządzania PDA ( Star7 ). Podczas jego realizacji postanowiono stworzyć język programowania, w którym pisane byłyby aplikacje dla tego urządzenia. Osob ą, która wniosła największy wkład w rozwój tego języka by ł James Gosling. On równie ż nada ł temu językowi jego pierwotn ą nazw ę, Oak od dębu, który rós ł za oknami jego biura. Za pomysłodawc ę tego języka należy jednak uzna ć innego pracownika firmy SUN, który w artykule pt. Future przedstawi ł idee opracowania języka łączącego cechy języków C (głównie składnia) i Mesa (obiektowo ść). Kiedy okazało si ę, że sprzeda ż urządze ń PDA nie przyniesie spodziewanych zysków, zdecydowano że opracowany na ich potrzeby język programowania zostanie przekształcony w język pozwalający na tworzenie aplikacji dla nowego, szybko rozwijającego si ę medium Internetu. Wraz z przeznaczeniem języka zmieniono równie ż jego nazw ę i tak w roku 1996 pojawiła si ę Java w wersji 1.0. W chwili obecnej dostępna jest wersja 5.0 (trwaj ą prace nad wersj ą 6, a w planach jest 7). Java stała się rozbudowanym językiem programowania ogólnego przeznaczenia. 2. Najważniejsze cechy Javy Składnia podobna do składni języków C/C++ - aby ułatwi ć migracj ę programistom piszącym w językach C/C++ (nadal najpopularniejsze języki programowania). Kod źródłowy programu napisanego w Javie przypomina kod programu napisanego w języku C++, jednakże jest on bardziej czytelny 1. Obiektowo ść język Java podobnie jak C++ jest językiem hybrydowym, który pozwala miesza ć kilka różnych styli programowania (używając fachowej terminologii pozwala na programowanie multiparadygmatowe), jednakże w Javie położono większy nacisk na obiektowo ść ni ż w C++. Dokładniejsze informacje na temat omawianego pojęcia pojawi ą si ę w następnych wykładach. Mnogo ść bibliotek Java posiada szereg gotowych komponentów, które mog ą posłuży ć do rozwiązania typowych problemów programistycznych (tworzenie GUI, złożonych struktur danych, komunikacji przez sie ć itp.). Przenośno ść poniewa ż Java została zaprojektowana z myśl ą o Internecie należało rozwiąza ć problem uruchamiania napisanych w niej programów na wielu różnych platformach jakie s ą podłączone do sieci. Problemem może okaza ć si ę nie tylko architektura komputera na którym ma pracowa ć aplikacja, ale również system operacyjny jaki jest na tym komputerze zainstalowany. Inżynierowie z firmy SUN rozwiązali te problemy przy pomocy tzw. maszyny wirtualnej. Kod źródłowy programu napisanego w Javie jest kompilowany nie do kodu maszynowego, lecz do kodu bajtowego maszyny wirtualnej, która wykonuje ten program. W chwili obecnej takie maszyny wirtualne s ą dostępne na większo ść popularnych platform (Windows, Linux, Solaris i inne systemy uniksowe, a także telefony komórkowe i systemy wbudowane w tych dwóch ostatnich przypadkach maszyna wirtualna nie musi by ć oprogramowaniem, może by ć zaimplementowana sprzętowo). Powyższy opis wskazuje na to, że Java jest w dużej mierze językiem interpretowanym. Ma to swoje zalety maszyna wirtualna stanowi warstw ę pośrednicząc ą pomiędzy systemem operacyjnym, a aplikacj ą, co pozwala na wykrycie nieprawidłowości w działaniu tej ostatniej oraz zabezpieczenie przed skutkami tych nieprawidłowości pozostałych aplikacji uruchomionych w systemie oraz wady wykonanie przez interpreter (maszyn ę wirtualn ą) aplikacji jest wolne, a więc Java nie nadaje si ę do zastosowa ń, w których czas wykonywania oblicze ń jest krytyczny, jak np.: aplikacje czasu rzeczywistego. 2 1 2 Jest to moja subiektywna opinia rozumiem, e s osoby które mog my le inaczej Nale y wspomnie o kompilatorach, które pozwalaj na bezpo redni kompilacj kodu Javy do kodu maszynowego. Niestety w tym przypadku tracimy ca ł ochron jak zapewnia nam maszyna wirtualna 1
Prostota 3 i bezpieczeństwo Java jako język nowoczesny zapewnia środki pozwalające na pisanie bezpiecznych programów zarówno pod względem tajności jak i niezawodności. Posiada ona biblioteki i narzędzia pozwalające na szyfrowanie danych przetwarzanych przez aplikacje, bąd ź aplety (aplet jest form ą aplikacji, która jest uruchamiana w środowisku przeglądarki www, a nie bezpośrednio w systemie komputerowym). Pozwala również podpisywa ć cyfrowo aplety. Aby zapewni ć niezawodno ść tworzonych aplikacji język wymusza na programiście inicjalizacj ę zmiennych i obsług ę sytuacji wyjątkowych. Java używa równie ż bezpieczniejszej formy wskaźników referencji. Aby rozwiąza ć problem wycieków pamięci wprowadzono specjalny mechanizm (ang. garbage collector), który usuwa z pamięci nieużywane obiekty. Wprowadzono równie ż wiele rozwiąza ń, które ułatwiaj ą rozwiązywanie niektórych do ść złożonych zagadnie ń programistycznych, jak np. obsługa wątków. Dokumentacja wraz ze środowiskiem Javy można pobra ć ze strony: http://java.sun.com obszern ą (cho ć nie dość szczegółow ą) dokumentacj ę dotycząc ą zarówno środowiska, jak i języka programowania. 3. Program typu Hello World Oto program, który wypisuje na ekranie napis dobrze znany każdemu początkującemu programiście: public class Hello { public static void main(string[] args) { System.out.println("Hello World!"); Przedstawiony kod źródłowy należy umieści ć w pliku Hello.java, skompilowa ć poleceniem javac Hello.java. W wyniku kompilacji zostanie utworzony plik Hello.class. Aby uruchomi ć program musimy wyda ć polecenie java Hello. Uwaga: Nazwa pliku i wielko ść liter w tej nazwie ma znaczenie (wyjaśnienie w następnym akapicie). Słowo kluczowe class oznacza, że będziemy deklarowa ć klas ę. Klasa w terminologii obiektowej definiuje typ obiektu. Klasa ta jest klas ą publiczn ą (nie ograniczamy do niej nikomu dostępu, uzyskujemy to poprzedzając słowo class słowem kluczowym public) i nazywa si ę Hello. Klasa ta zawiera metodę 4 o nazwie main, która jest metod ą statyczn ą (słowo kluczowe static), co oznacza, że nie trzeba tworzy ć obiektu takiej klasy, aby t ę metod ę wywoła ć (szczegóły będ ą omówione później), publiczn ą i która nie zwraca żadnej wartości, ale jako parametry wejściowe pobiera tablic ę elementów typu String, które zawieraj ą parametry przekazane programowi z linii polece ń. Metoda main wypisuje na ekran napis Hello World, za pomoc ą metody println, która jest zdefiniowana w obiekcie out, który jest części ą klasy System. Przepisując powyższy program należy pamięta ć o tym, że Java jest językiem rozpoznającym wielko ść liter. Nazwa pliku musi by ć taka sama, jak nazwa klasy publicznej. 4. Proste typy danych Większo ść zmiennych w Javie jest tworzona dynamicznie, w obszarze pamięci programu zwanym stert ą. Wyjątkiem są zmienne o prostych typach, które wymieniono w tabeli 5 poniżej. Nazwa typu Warto ść minimalna Warto ść maksymalna Rozmiar boolean flase true - byte -128 127 8 bitów char Unicode 0 Unicode 2 16-1 16 bitów short -2 15 2 15-1 16 bitów int -2 31 2 31-1 32 bity long -2 63 2 63-1 64 bity float IEEE 754 6 IEEE 754 32 bity 3 4 5 6 W chwili obecnej, kiedy dost pna jest wersja 5.0 j zyka Java argument o prostocie staje si dyskusyjny. Metoda w Javie w du y stopniu jest odpowiednikiem funkcji w j zyku C o ró nicach opowiem na przyszłych wykładach Tabela sporz dzona na podstawie Thinking in Java Warto okre lona w tym standardzie 2
Nazwa typu Warto ść minimalna Warto ść maksymalna Rozmiar double IEEE 754 IEEE 754 64 bity void - - - Z powyższej tabeli wynika, że w Javie wszystkie typy mogące przechowywa ć liczby (typy numeryczne) s ą typami znakowymi. Zmienne tych typów deklarujemy według tego samego schematy co w języku C, z tym że nie musz ą być 7 deklarowane na początku bloku, lecz tam, gdzie s ą potrzebne. Zasięg zmiennej jest ograniczony do bloku w którym została zadeklarowana, dodatkowo nie jest możliwa poniższa deklaracja: { int a; { int a; //W tym bloku nie mog ą by ć widoczne obie zmienne o takiej samej nazwie 5. Operatory i wyrażenia Java posiada szereg operatorów pozwalających budowa ć wyrażenia i dokonywa ć operacji na wartościach zwartych w zmiennych. Poniżej przedstawiono tabel ę opisując ą priorytety tych operatorów (operatory w pierwszym wierszu mają najwyższy priorytet). + (nic nie robi), - (zmiana znaku na przeciwny), ++ (inkrementacja), -- (dekrementacja) * (mnożenie), / (dzielenie), % (modulo), + (dodawanie), - (odejmowanie), << (przesunięcie w lewo), >> (przesunięcie w arytmetyczne w prawo), >>> (przesunięcie logiczne w prawo) > (mniejsze), < (większe), >= (mniejsze lub równe), >= (większe lub równe), == (równe),!= (różne) && (iloczyn logiczny), (suma logiczna), & (iloczny bitowy), (suma bitowa),! (negacja logiczna), ~ (negacja bitowa), ^ (różnica symetryczna) Z1>Z2?A:C (operator trójargumentowy) = (przypisanie, równie ż w postaci *=, += itd.) Operator dodawania jest przeciążony tak, aby było możliwe łączenie za jego pomoc ą łańcuchów. W Javie wartość wyrażenia jest automatycznie promowana do typu int lub double (wyjątkiem jest tu typ long). Jeśli w wyrażeniu użyjemy zmiennej lokalnej (automatycznej) 8, która nie została wcześniej zainicjalizowana kompilator zgłosi błąd czasu kompilacji. Podobnie, jeśli w instrukcji przypisania po lewej stronie (l-warto ść) występuje zmienna o mniejszym typie ni ż zmienna lub wyrażenie występujące po prawej stronie (p-warto ść) tej instrukcji, to równie ż otrzymamy błąd czasu kompilacji, chyba, że dokonamy jawnego rzutowania 9. W przypadku operatorów && i możemy spotka ć si ę ze zjawiskiem skracania oblicze ń. Jeśli mamy kilka wyraże ń logicznych połączonych operatorem && i pierwsze z nich jest fałszywe, to nie jest ustalana warto ść pozostałych, tylko warto ść całego wyrażenia jest określana jako false. Podobna sytuacja zachodzi w przypadku operatora. Operator >>> dokonuje przesunięcia logicznego w prawo, natomiast >> dokonuje przesunięcia arytmetycznego w prawo. Zasada działania operatora trójargumentowego jest następująca: 10 jeśli warunek Z1>Z2 jest prawdziwy, to zwracana jest warto ść A (lub, jeśli zamiast zmiennej jest tam umieszczone wyrażenie, to jest obliczana i zwracana jego warto ść). W przeciwnym przypadku zwracana jest warto ść C (lub tak jak wyżej warto ść wyrażenia). 6. Inicjalizacja zmiennych prostych typów Zazwyczaj zmiennej prostego typu możemy nada ć warto ść stosując instrukcj ę przypisania. W niektórych przypadkach może si ę okaza ć, że kompilator nie jest w stanie poprawnie przypisa ć typu wartości jak ą chcemy zapisa ć do zmiennej. Możemy takich sytuacji unikn ąć stosując odpowiednie znaczniki. Jeśli liczba zaczyna si ę od znaków 0x, oznacza to, że 7 8 9 10 Standard ISO C99 pozwala równie na takie deklarowanie zmiennych w j zyku C S to wszystkie zmienne deklarowane wewn trz metod Rzutowania dokonuje si w ten sam sposób jak w j zyku C Nawi zuj c do jego zapisu w tabeli. 3
jest zapisana w kodzie szesnastkowym. Rozpoczęcie liczby znakiem zera oznacza, że jest zapisana w kodzie ósemkowym. Zakończenie liczby znakiem l lub L oznacza, że jest to warto ść typu long, natomiast zakończenie jej znakiem f lub F oznacza, że jest to warto ść typu float, z kolei zakończenie liczby znakiem d lub D oznacza, że jest to warto ść typu double. W przypadku wartości zmiennoprzecinkowych można stosowa ć zapis wykładniczy np.: 4e-4, co czytamy cztery razy dziesi ęć do potęgi minus czwartej. 7. Instrukcje sterujące Tylko wyjątkowo proste programy wykonuj ą si ę zawsze w ten sam sposób. Zaawansowane aplikacje wymagają instrukcji, które pozwoliłyby sterowa ć kolejności ą wykonywanych w programie instrukcji. W Javie większo ść tych instrukcji ma taki sam zapis, jak w języku C, ale ich sposób działania nie zawsze jest taki sam. Podstawow ą różnic ą jest to, że wszystkie wyrażenia warunkowe w Javie musz ą by ć typu boolean, co pozwala wyeliminowa ć często spotykany w językach C i C++ błąd polegający na umieszczeniu w warunku instrukcji przypisania (=), zamiast operatora porównania (==). Najprostsz ą instrukcj ą spośród instrukcji sterujących jest instrukcja if. Jej schemat ogólny można zapisa ć następująco: if(warunek) instrukcja1; else instrukcja2; Jeśli warunek zawarty w nawisach okrągłych będzie prawdziwy, to wykonana zostanie instrukcja pierwsza, natomiast jeśli ten warunek będzie fałszywy, to wykonana zostanie instrukcja druga. Cz ęść else nie jest obligatoryjna i możemy ją pomin ąć. Jeśli chcemy, aby w wyniku spełnienia warunku wykonanych było kilka instrukcji, to umieszczamy je w nawiasach klamrowych {, to samo odnosi si ę do części else. Instrukcja warunkowa różni si ę tym od operatora trójargumentowego, że w przeciwieństwie do tego ostatniego nie zwraca wartości. Jeśli musimy w programie rozpatrzy ć kilkanaście warunków, to bardziej wygodn ą konstrukcj ą ni ż instrukcja warunkowa może okaza ć si ę instrukcja wielokrotnego wyboru, której schemat ogólny przedstawia si ę następująco: switch(selektor) { case warto ść _1: instrukcja_1;break; case warto ść _2: instrukcja_2;break; case warto ść _3: instrukcja_3;break; case warto ść _4: instrukcja_4;break;... default: instrukcja_n; Selektor musi by ć wartości ą całkowit ą lub wyrażeniem, które po obliczeniu daje tak ą warto ść. Równie ż wartości po słowie kluczowym case musz ą by ć wartościami całkowitymi. Po dwukropku możemy umieści ć dowoln ą ilo ść instrukcji, ale należy je zakończy ć instrukcj ą brake, w przeciwnym przypadku zostan ą wykonane równie ż instrukcje dla przypadku znajdującego si ę poniżej (czasem jest to pożądane zachowanie i programiści celowo pomijaj ą instrukcj ę brake). Jeśli selektor nie przyj ął żadnej z uwzględnionych wartości, to wykonywane s ą instrukcje umieszczone za słowem kluczowym default. W Javie istniej ą trzy rodzaje instrukcji iteracyjnych, czyli pozwalających na powtarzanie pewnej grupy instrukcji określon ą ilo ść razy. Pierwsz ą z nich jest instrukcja for: for(zmienna_sterują ca=warto ść_począ tkowa; wyraż enie; krok) instrukcja; Jeśli chcemy, aby for obejmowała większ ą ilo ść instrukcji, musimy je umieści ć w nawiasach klamrowych. Zmienna sterująca może by ć zadeklarowana wewnątrz instrukcji for, tam gdzie jest inicjalizowana, wówczas będzie dostępna dla instrukcji, które znajduj ą si ę wewnątrz pętli. Można równie ż uży ć kilku zmiennych sterujących równocześnie. Pętla for powtarza instrukcje określon ą ilo ść razy. Często nie znamy ilości iteracji, które musimy wykona ć, ale znamy warunek, który musi by ć zachowany, aby można było kontynuowa ć wykonanie pętli. W takiej sytuacji możemy uży ć dwóch pozostałych pętli: oraz while(warunek) instrukcja; do instrukcja; while(warunek); 4
W przypadku instrukcji while warunek kontynuacji jest sprawdzany przed wykonaniem pętli, natomiast w przypadku do while warunek jest sprawdzany po wykonaniu instrukcji. Jeśli checmy, aby w pętli było wykonywanych kilka instrukcji jednocześnie, to musimy je umieści ć w nawiasach klamrowych. Podobnie jak w języku C możemy uży ć polecenia break do przerwania wykonywania pętli i instrukcji continue do przerwania bieżą cej iteracji. Java nie posiada słowa kluczowego stosując instrukcje brake i continue w połączeniu z etykietami: goto, ale można uzyska ć efekt podobny do jego działania public class Etykiety { public static void main(string[] args) { ety1: for(int i=1; i<20;i++) { System.out.println("i: "+i); W programie zaprezentowano użycie etykiety wraz z instrukcją continue. Kiedy zmienna j osiągnie warto ść 6, wówczas przerywane jest wykonanie pętli wewnętrznej i wykonywana jest pętla zewnętrzna. Jak ju ż zostało wspomniane wyżej etykiet można używa ć równie ż z instrukcj ą brake. for(int j=1; j<20; j++) { if(j==6) continue ety1; if(j%2==0) continue; System.out.println("j: "+j); 5