1. Java
Transkrypt
1. Java
1. Java Jednym Java kojarzy się z prostymi apletami działającymi w środowisku przeglądarek WWW. Inni myślą o niej nieco abstrakcyjnie jako o świetnym języku programowania. Dla jeszcze innych będzie to narzędzie oprogramowania transakcji serwerowych lub bazodanowych. Wszystkie te punkty widzenia niewątpliwie mają racje bytu, ale Java jest czymś więcej niŜ tylko kolejnym jeŜykiem czy kolejnym narzędziem działania w sieci. MoŜna powiedzieć, Ŝe Java to — w tej chwili — najbogatsze środowisko uniwersalnych i standaryzowanych metod wykonywania wszelkiej dającej się pomyśleć działalności informatycznej. Java jako uniwersalny język programowania Oczywiście przede wszystkim Java jest uniwersalnym językiem programowania. Składniowe podobieństwo do C/C++ czyni ją łatwą do opanowania przez programistów znających te języki. Jednocześnie Java ma ambicje udoskonalania swoich wzorców. Javowy programista w zasadzie nie musi martwić się zarządzaniem pamięcią (w Javie funkcjonuje automatyczne odśmiecanie - ang. garbage collector, specjalny wątek, który w tle, niewidocznie i automatycznie, dba o usuwanie przydzielonych wcześniej, a nie uŜywanych obszarów pamięci). Java nie dopuszcza arytmetyki wskaźnikowej, która pozwala na odwoływanie się do dowolnych obszarów pamięci i jest częstą przyczyną błędów. W Javie nie ma wskaźników, są za to referencje, które mogą albo odnosić się do istniejącego obiektu, albo mają wartość „null" (co oznacza, Ŝe do Ŝadnego obiektu akurat się nie odnoszą). Ścisła kontrola typów na etapie kompilacji pozwala unikać prostych błędów, a konwersje przeprowadzane w fazie wykonania są bezpieczne, bowiem nigdy nie moŜe zaistnieć sytuacja przekształcenia danych do niewłaściwego dla nich typu (chodzi oczywiście o typy obiektowe, poprawność konwersji typów prostych jest gwarantowana przez kompilator). Wymuszana przez kompilator obsługa wyjątków czyni programowanie w Javie jeszcze bardziej bezpiecznym i niezawodnym, a wbudowane w jeŜyk podstawowe elementy współbieŜności umoŜliwiają łatwe tworzenie i synchronizowanie równolegle działających wątków. Niewątpliwie jednak najwaŜniejszą cechą Javy jako „czystego jeŜyka" jest jej obiektowość. Ogólnie oznacza to, iŜ programy pisze się w Javie łatwiej i bardziej niezawodnie niŜ w językach nieobiektowych. Niestety, Java nie jest językiem w pełni obiektowym. Występują w niej bowiem konstrukcje nieobiektowe (np. typy proste), co powoduje pewne niespójności syntaktyczne i semantyczne. Większość innych waŜnych cech Javy, o których była mowa wyŜej, wynika z wysokich wymogów bezpieczeństwa stawianych językowi przez jego twórców. Coś za coś - często oznacza to pewne ograniczenie swobody i elastyczności programisty, a takŜe (czasem nadmierne) zwiększanie pracochłonności pisania kodu. Zalety Javy jako czystego języka programowania mogą być dyskusyjne. Ale nie dlatego warto Javy się uczyć, Ŝe jest to język idealny (czy w ogóle takie istnieją?). DuŜo waŜniejsza - moim zdaniem - jest jej uniwersalność we wszelkich zastosowaniach informatycznych. Uniwersalność zapewniana przez wieloplatformowość Javy oraz wynikającą stąd moŜliwość stworzenia przebogatych standardowych ..bibliotek" na tyle zintegrowanych z samą Javą, Ŝe praktycznie będących jej synonimem. Wieloplatformowość Javy Java jest językiem interpretowanym, co umoŜliwia wykonywanie „binarnych" kodów Javy bez rekompilacji praktycznie na wszystkich platformach systemowych. Kod źródłowy (pliki z rozszerzeniem java) jest kompilowany przez kompilator .Tavy do kodu bajtowego (B-kodu, pliki z rozszerzeniem .class), ten ostatni zaś jest interpretowany przez tzw. wirtualną maszynę Javy - JVM (jest to program i/lub odpowiednie biblioteki), zainstalowaną na danej platformie systemowej lub wchodzącą w skład przeglądarki WWW. kod kompilacja ładowanie JVM źródłowy -------------------> B-kod -----------------> wykonanie (Win Unix OS/2 ...) .java) javac (.class) Oznacza to, teoretycznie, Ŝe raz napisany i skompilowany program będzie działał :ak samo na wszystkich platformach systemowych. Idea wręcz doskonała (jak wiele %wysiłku i kosztów pochłania przenoszenie programów z jednej platformy na drugą). Jej praktyczna realizacja (mimo wielu trudności) jest coraz bliŜsza i coraz bardziej kusząca (nieunikniona mniejsza efektywność i większa zasoboŜerność działania aplikacji javowych w porównaniu z natywnymi jest równowaŜona przez rozwój sprzętu). Sama wieloplatformowość języka interpretowanego nie jest czymś nadzwyczajnym. Ale twórcy Javy wyciągnęli z tej jej cechy bardzo konsekwentne wnioski. Stworzyli mianowicie bogaty zestaw standardowych bibliotek i narzędziowych interfejsów programistycznych (API), które umoŜliwiają w jednolity, niezaleŜny od platformy sposób programować graficzne interfejsy uŜytkownika (GUI), dostęp do baz danych, działania w sieci. Podstawowy (ogromny zresztą) zestaw takich bibliotek nazywa się Java Core API (albo JDK, albo Java 2 SDK). Oprócz tego wprowadzono prosty mechanizm, nazywany Java Extension Framework, który umoŜliwia rozszerzanie standardowego pakietu o nowe (teŜ standardowe!) biblioteki. Java jako uniwersalne środowisko programowania GUI Java - w swoich standardowych bibliotekach - dostarcza łatwych w uŜyciu i niezaleŜnych od platformy środków programowania graficznych interfejsów uŜytkownika. Proste, nieco surowe komponenty wizualne od wielu juŜ lat moŜna było łatwo uzyskać za pomocą części javowego API, nazywanej AWT (Abstract Windowing Toolkit). Były one jednak zbyt ubogie dla powaŜnych aplikacji, ponadto ich wygląd zaleŜał od platformy systemowej. Pojawił się więc projekt Swing, mający na celu głównie wzbogacenie istniejących i dodanie nowych elementów GUI oraz uniezaleŜnienie wyglądu komponentów od platformy systemowej. Swing, zrealizowany początkowo jako dodatek do wersji Javy 1.1, następnie wszedł w skład tzw. JFC (Java Foundation Classes) - integralnej części platformy Java 2 (wersje 1.2.x i 1.3). JFC obejmuje AWT wraz ze wzbogaconą grafiką dwuwymiarową (Graphics2D), Swing oraz mechanizmy przeciągnij i upuść (ang. drąg and drop) w aplikacjach Javy i na styku tych aplikacji z natywnymi aplikacjami platformy systemowej. Java jako uniwersalne środowisko dostępu do baz danych W skład standardu Javy wchodzi JDBC API (Java Database Connectivity API) -zestaw środków umoŜliwiających łączenie się aplikacji i apletów javowych z (niemal) dowolnymi relacyjnymi bazami danych (systemami zarządzania relacyjnymi bazami danych) i wykonywanie na nich operacji bazodanowych. Środki te są łatwe w uŜyciu, opierają się bowiem na powszechnym standardzie SQL -języka programowania relacyjnych baz danych. Niestandardowy pakiet JavaBlend udostępnia narzędzia łatwego tworzenia apli-•:icji biznesowych, integrujących obiekty Javy z relacyjnymi bazami danych. UmoŜ-!;-.'. ia to realizację podejścia obiektowego w środowisku relacyjnych baz danych. Java jako uniwersalne środowisko programowania multimediów W Java Core API znajdziemy na pewno uniwersalne środki przetwarzania: • grafiki i obrazów (2D), • dźwięków i muzyki (m.in. pliki WAV, AU, MIDI). Dotychczasowe standardowe rozszerzenia Javy, to: • Java 3D (tworzenia i przetwarzania grafiki trójwymiarowej), • Java Media Framework (przetwarzania zaawansowanych formatów multimedialnych - m.in. filmy, codec, RealStream), mogą niedługo wejść do podstawowego standardowego API. Jeśli jako multimedia potraktować telewizję i telefon, to i tu Java dostarcza odpowiednich interfejsów programistycznych: Java TV API oraz JavaPhone API. Java jako uniwersalne środowisko programowania w sieci (klientserwer) Java zawiera standardowe środki tworzenia: • apletów - programów wykonujących się w środowisku przeglądarki i umoŜliwiających: — interakcję z uŜytkownikiem w rozbudowanym GUI, — transakcje klient-serwer, w tym - poprzez JDBC - bazodanowe, • serwletów - zapewniających obsługę i zarządzanie transakcjami po stronie serwera; standardowe rozszerzenie: Java Servlet API, • aplikacji „wolno stojących", mogących sięgać do Internetu i intranetu za pomocą wbudowanych w Córę API „bibliotek" sieciowych. Istnieje standardowe rozszerzenie Javy słuŜące do obsługi poczty elektronicznej JavaMail API), a niedawno powstała nowa platforma komunikacyjna - o nazwie Zaplet - pozwalająca na grupową pracę w sieci w czasie rzeczywistym oraz komunikację przez e-mail. Oparta na Javie technologia Java Server Pages (JSP) umoŜliwia: • tworzenie dynamicznych stron WWW, • separację wyglądu stron od dynamicznie zmieniającej się treści, • łatwe programowanie serwera, niezaleŜne od sprzętu i platformy. Java jako środowisko programowania w systemach rozproszonych W standardzie Javy zapewniono komunikację z rodzimymi programami platformy systemowej (JNI Java Native Interface) oraz środki komunikowania się obiektów w środowiskach rozproszonych . Z kolei RMI (Remote Method lnvocation) zapewnia komunikację pomiędzy obiektami javowymi, funkcjonującymi w równoległych procesach wykonywanych w środowisku rozproszonym, np. na dwóch róŜnych komputerach sieci. Interakcję obiektów javowych i obiektów realizowanych w innych językach programowania zapewnia implementacja przez Javę standardu CORBA (Common Object Reąuest Broker Architecture, a ściślej IIOP/ORB). Oznacza to, Ŝe Java moŜe być językiem tworzenia tzw. middleware - oprogramowania pośredniczącego i integrującego działanie aplikacji napisanych w róŜnych językach oraz na róŜnych platformach systemowych i sprzętowych. Java jako środowisko budowania programów z gotowych komponentów Koncepcja budowania programu z gotowych cegiełek, komponentów „ponownego uŜytku" (ang. reusablc components) znalazła w Javie urzeczywistnienie w postaci specyfikacji JavaBeans. Bean znaczy ziarno, a JavaBean jest właśnie komponentem ponownego uŜytku (ziarnem javy). Komponenty takie (wizualne lub odzwierciedlające logikę) mogą być łatwo wykorzystywane przy budowie duŜych aplikacji. Wbudowanie ziarna w aplikację odbywa się zwykle w pewnym środowisku programistycznym, a programowanie polega na: umieszczeniu (załadowaniu) ziarna, połączeniu go z aplikacją i ewentualnie dostosowaniu jego właściwości. Enterprise Java Beans (EJB) jest zestawem ziaren i środków implementacji logiki biznesowej, działających w systemach rozproszonych z obsługą transakcji bazodanowych i hurtowni danych. Przy budowie programów uŜywane są gotowe ziarna ze składnic „problemowych" (np. ubezpieczenia, banki etc.) oraz środki EJB, umoŜliwiające łatwe tworzenie nowych ziaren. Java jako środowisko przetwarzania dokumentów XML XML (Extended Markup Language) jest rozszerzalnym językiem znacznikowym, pozwalającym na opisywanie struktury i treści dokumentów oraz separowanie treści od jej prezentacji (w przeciwieństwie, HTML określa tylko wygląd dokumentu i nie moŜe być rozszerzony — tzn. zestaw znaczników jest stały). XML staje się obecnie waŜnym środkiem komunikacji biznesowej i wymiany dokumentów. Java okazała się - ze względu na swą obiektowość i wieloplatformowość - doskonałym językiem do przetwarzania dokumentów XML. Gotowe środki przetwarzania XML wchodzą w standard Javy (Enterprise Edition). Oprócz tego dostępne są biblioteki zewnętrzne zrealizowane w Javie. Mikro-Java Do oprogramowania obsługi sprzętu elektronicznego (np. urządzeń domowych, konsumpcyjnych) o słabych parametrach informatycznych stworzono w Javie standardową technologię JINI. Jest to technologia połączeń „impromptu" - połączeń sieciowych między składnikami bez instalacji i interwencji. Programy są interpretowane przez niewielką, specjalną maszynę wirtualną Javy KJVM przeznaczoną do urządzeń o ekstremalnie słabych parametrach pamięciowych. Java do „maszynek do kawy" jest dostępna jako platforma Java 2 Micro Edition, przejmująca doświadczenia - takŜe dalej rozwijanych - interfejsów programistycznych PersonalJava i EmbeddedJava. Wersje Javy Pierwsze, powszechnie dostępne wersje Javy były numerowane 1.0.x. Ubogi zestaw komponentów GUI, zły model obsługi zdarzeń - to ich główne charakterystyki. Pomyślane głównie jako środowisko budowy apletów, tak naprawdę nie nadawały się do budowy większych aplikacji (ani teŜ jakichś bardziej uŜytecznych apletów). Nowe wersje, numerowane 1.1.x, wprowadziły kilka ogromnie waŜnych zmian i dodatków, m.in. nowy model obsługi zdarzeń, moŜliwości dynamicznego kształtowania działania programu oraz JavaBeans. Pojawił się teŜ Swing z nowymi komponentami. Wersje 1.1.x były prawdziwym przełomem. Następna generacja - Java 1.2.x - nie była juŜ tak rewolucyjna. Faktycznie zintegrowała istniejące juŜ i działające w Javie 1.1.x rozwiązania, dodając nowe, ciekawe, uŜyteczne (ale juŜ nie tak rewolucyjne) elementy, m.in. GraphicsZD i kolekcje. MoŜna jednak powiedzieć, Ŝe w tym momencie Java dojrzała, co wyraziło się w zmianie nazewnictwa. W tej chwili mówi się o platformie Java 2, a interfejs programistyczny zmienił swoją nazwę z JDK (Java Developer Kit) na Java 2 SDK (Software Developer Kit). Platforma Java 2 ma swoje trzy edycje: standardową, biznesową i mikro. W kaŜdej z nich mamy kolejne wersje Javy. 2. Wprowadzenie do obiektowości Języki obiektowe posługują się pojęciem obiektu i klasy. Zacznijmy od definicji. Obiekt - to konkretny lub abstrakcyjny byt, wyróŜnialny w modelowanej rzeczywistości, posiadający: • nazwę (ewentualnie), • określone granice, • atrybuty (właściwości), • skojarzony z dopuszczalnymi operacjami, które mogą na nim działać - zatem mogący świadczyć określone usługi. Usługa - to określone działanie (zachowanie) obiektu, które jest on zobowiązany przejawiać. Obiekty współdziałają ze sobą wymieniając komunikaty. Komunikat - to wąski i dobrze określony interfejs, opisujący współzaleŜność działania obiektów. Komunikaty zwykle Ŝądają od obiektów wykonania określonych usług. Klasa - to opis takich cech grupy podobnych obiektów, które są dla nich niezmienne 1 np. zestaw atrybutów i metod, czyli usług, które mogą świadczyć). PowyŜsze definicje stanowią abstrakcyjne odzwierciedlenie cech rzeczywistości. Gdybyśmy mieli w języku programowania podobne pojęcia, to moglibyśmy ujmować projekt rozwiązania rzeczywistego problemu i jego oprogramowanie w języku adekwatnym do problemu. I to zapewniają języki obiektowe. Jest to ich bardzo waŜna cecha, znacznie ułatwiająca tworzenie oprogramowania. Programowanie polega na przetwarzaniu danych. Dane zawsze mają określony typ, a typ to nic innego jak rodzaj danych i działania, które na nich moŜna wykonać. Z pragmatycznego punktu widzenia moŜemy więc powiedzieć, Ŝe klasa to typ, jej definicja opisuje właściwości typu danych (równieŜ funkcjonalne, tzn. jakie operacje -a dostępne na danych tego typu). Języki obiektowe pozwalają na definiowanie własnych klas - własnych typów danych, co właśnie oznacza programowanie w języku problemu. O obiektach moŜemy myśleć jako o egzemplarzach określonych klas. MoŜemy mieć np. klasę urządzeń elektrycznych o następujących atrybutach: szerokość, wysokość, stan (włączone-wyłączone) oraz udostępniających usługi: włączania i wyłączania. Tak jest w rzeczywistości. I tak samo moŜemy to zapisać w języku obiektowym, np. w Javie: class ElDev { int width, height; <-- atrybuty: szerokość, wysokość, stan boolean isOn; void on() C isOn = true; ) <— usługa on (włącz) void off() C isOn = false;3 <— usługa off (wyłącz) } Gdy mamy dwa obiekty - egzemplarze klasy urządzeń elektrycznych, oznaczane a i b, to moŜemy symulować w programie sekwencję działań: włączenie urządzenia a, włączenie urządzenia b, wyłączenie urządzenia a za pomocą komunikatów posyłanych do obiektów, np. w Javie (czy C++): a.on(); // obiekcie a włącz się b.on(); // obiekcie b włącz się a.off(); // obiekcie a wyłącz się (W rzeczywistości „komunikat" moŜe polegać na tym, Ŝe ktoś podchodzi do urządzania i wciska przełącznik). Oprócz odzwierciedlenia w programie „jeŜyka problemu", abstrakcja obiektowa ma jeszcze jedną waŜną przewagę nad ujęciami nieobiektowymi. Mianowicie, zwykle atrybuty obiektu nie są bezpośrednio dostępne. W programie z obiektami „rozmawiamy" za pomocą komunikatów, obiekty same „wiedza najlepiej", jak zmieniać swoje stany. Dzięki temu nie moŜemy nic nieopatrznie popsuć, co więcej, nie moŜemy zaŜądać od obiektu usługi, której nie udostępnia. Dane (atrybuty) są ukryte i są traktowane jako nierozdzielna całość z usługami. Nazywa się to hermetyzacją (enkapsulacją) i oznacza znaczne zwiększenie odporności programu na błędy. Podejście obiektowe umoŜliwia ponowne wykorzystanie juŜ gotowych klas przy tworzeniu klas nowych, co znacznie ogranicza nakłady pracy przy kodowaniu, a takŜe chroni przed błędami. Jest to równieŜ odzwierciedlenie rzeczywistych sytuacji. Na przykład komputer jest niewątpliwie urządzeniem elektrycznym. Jest obiektem klasy ElDev. Ale komputery (oprócz określonych w klasie ElDev atrybutów: wysokość, szerokość, stan: włączony-wyłączony) mają jakieś swoje specyficzne, wyspecjalizowane cechy. Stanowią więc podklasę klasy urządzeń elektrycznych. Tak jest w rzeczywistości. A w programie moŜemy to odzwierciedlić za pomocą koncepcji dziedziczenia klas. Klasa dziedzicząca inną przejmuje jej właściwości i ewentualnie dodaje własne, wyspecjalizowane. Dzięki temu w klasie dziedziczącej moŜemy skupić się na specyficznych cechach jej obiektów, wiedząc Ŝe podstawowe atrybuty i funkcjonalność zostały juŜ określone w klasie dziedziczonej. Na przykład tworząc klasę Komputer, dziedziczącą klasę urządzeń elektrycznych nie musimy od nowa zapisywać wszelkich cech i operacji na urządzeniu elektrycznym (np. nie musimy oprogramowywać metod on() czy off()). Musimy tylko dodać cechy wyspecjalizowane, np. dla komputera - usługę wykonania jakiegoś programu. Oczywiście program będzie obiektem klasy Program, a w komunikacie do obiektu-komputera powinniśmy podać jako argument obiektprogram do wykonania. Dziedziczenie klasy ElDev przez klasę Komputer i dostarczenie nowej usługi (metody) run moŜemy zapisać w Javie tak (słowo extends oznacza tu dziedziczenie): class Komputer extends ElDev { void run(Program p) { if (isOn()) wykonanie_programu_p; } } a następnie uŜyć nowej klasy Komputer w programie: Komputer a, b, c; Program x, y, z; ... a.on(); a.run(x); ... a.off();