plik


ÿþJzyk Java: Podstawy, Programowanie, Zastosowania Java 3 1. Jzyk Java Pocztki jzyka Java sigaj roku 1990, gdy Bill Joy napisaB dokument pod tytuBem  Further , w którym sugerowaB in|ynierom Sun Microsystems stworzenie obiektowego [rodowiska w oparciu o C++. Dokument ten miaB pewien wpByw na twórców projektu Green (James Gosling, Patrick Naughton i Mike Sheridan). W roku 1991 w ramach projektu Green opracowano w jzyku C kompilator oraz interpretator wynalezionego przez Goslinga jzyka OAK (Object Application Kernel), który miaB by narzdziem do oprogramowania  inteligentnych konsumenckich urzdzeD elektronicznych. Poniewa| nazwa  OAK okazaBa si zastrze|ona, zmieniono j na  Java . Obecnie nale|y raczej mówi o [rodowisku Java, na które skBada si: 1. Obiektowy jzyk Java, którego skBadnia wykazuje znaczne podobieDstwo do skBadni jzyka C++. Nazwa pliku z programem zródBowym w jzyku Java, ma posta  nazwa.java , gdzie  nazwa musi by nazw zdefiniowanej w tym pliku klasy. Je|eli plik  nazwa.java zawiera definicje wielu klas, a w[ród nich jedn klas publiczn, to  nazwa musi by nazw tej klasy publicznej. 2. Kompilator, który przetwarza program  nazwa.java na tak zwany B-kod (bytecode, J-code), zapisywany automatycznie w plikach z rozszerzeniem nazwy  .class . B-kod jest przeno[n postaci programu, która mo|e by zinterpretowana przez odpowiedni maszyn wirtualn, to jest  urzdzenie logiczne , na którym bdzie wykonywany program binarny. 3. Specyfikacje maszyny wirtualnej Java (JVM  Java Virtual Machine) i plików klas. JVM mo|na uwa|a za abstrakcyjny komputer, który wykonuje programy, zapisane w plikach z rozszerzeniem nazwy  .class . Maszyna wirtualna mo|e by implementowana na rzeczywistych komputerach na wiele sposobów, na przykBad jako interpretator wbudowany w przegldark WWW (np. Netscape), lub jako oddzielny program, który interpretuje pliki  nazwa.class . Mo|e to by tak|e implementacja polegajca na przeksztaBceniu  tu| przed rozpoczciem fazy wykonania  pliku z B-kodem na program wykonalny, specyficzny dla danej maszyny. Mechanizm ten mo|na okre[li jako tworzenie kodu wykonalnego w locie (ang. Just-In-Time, np. kompilator JIT firmy Symantec). Interpretatory B-kodu, tj. ró|ne maszyny wirtualne, s tak|e czsto napisane w jzyku Java. 4. Biblioteka Javy. Zrodowisko jzyka Java zawiera bogat bibliotek, a w niej zbiór skBadników dla prostego, niezale|nego od platformy graficznego interfejsu u|ytkownika. Rysunek 4-1 ilustruje usytuowanie [rodowiska programowego jzyka Java, posadowionego na dowolnej platformie sprztowo- programowej komputera (platforma sprztowo-programowa oznacza sprzt komputera i jego system operacyjny). a) b) MyProgram.java Program w jzyku Java Java API Klasa System Maszyna wirtualna (JVM) Platforma sprztowo-programowa Zrodowisko wykonawcze Rys. 1-1. Usytuowanie systemu Java Pokazany w cz[ci a) rysunku blok Java API (Application Programming Interface) reprezentuje klasy, interfejsy i obiekty wchodzce w skBad aktualnej maszyny wirtualnej, któr zwykle okre[la si jako platform jzyka Java (Java Platform). Umo|liwiaj one programom jzyka Java na dostp do zasobów komputera. Mo|e to by dostp (wzgldnie) systemowo niezale|ny (implementowany przez klas System w pakiecie JDK) i na dostp systemowo zale|ny (implementowany przez klas Runtime, reprezentujc [rodowisko wykonawcze w pakiecie JDK), jak pokazano w cz[ci b) rysunku 4-1. 4 Jzyki obiektowe Tak wic programy u|ytkownika mo|na kompilowa na dowolnej platformie sprztowo-programowej, na której posadowiono kompilator jzyka Java. Otrzymany w wyniku kompilacji B-kod mo|na traktowa jako zbiór instrukcji kodu dla dowolnej implementacji maszyny wirtualnej, jak pokazano na rysunku 4-2. MyProgram.java Kompilator Edytor MyProgram.class Interpretator Interpretator SUN - Solaris PC - Windows 95/NT Rys. 1-2. Przetwarzanie programów u|ytkownika 1.1. Elementarny program: tekst zródBowy, kompilacja, interpretacja Java wprowadza swoist terminologi dla swoich konstrukcji syntaktycznych i jednostek (moduBów) kompilacji. Programem w jzyku Java jest aplikacja (application) lub aplet (applet). Aplikacja jest programem samodzielnym, za[ aplet jest programem wbudowanym (np. w przegldark WWW). Ka|da aplikacja musi zawiera dokBadnie jeden moduB zródBowy nazywany moduBem gBównym aplikacji, którego klasa zawiera publiczn funkcj klasy (funkcje takie s poprzedzane sBowem kluczowym static) main. Tekst zródBowy najprostszego programu mo|e mie posta: //plik Hello.java public class Hello { public static void main(String args[]) { System.out.print("Hello, World!\n"); } //end main } // end Hello Dla skompilowania powy|szego programu jego tekst zródBowy nale|y umie[ci w pliku o nazwie Hello.java. ZakBadajc, |e dysponujemy systemem JDK z kompilatorem javac, program skompilujemy poleceniem: javac Hello.java Udana kompilacja wygeneruje plik z B-kodem o nazwie Hello.class, zawierajcy sekwencj instrukcji dla interpretatora JVM. Kod ten wykonujemy przez wywoBanie interpretatora o nazwie java poleceniem: java Hello Interpretator wyszuka plik o nazwie Hello.class, ustali, czy klasa Hello zawiera publiczn metod statyczn main i wykona instrukcje zawarte w bloku main. Zauwa|my przy okazji, |e w jzyku Java wszystkie staBe, zmienne i funkcje s elementami skBadowymi klas; nie ma wielko[ci globalnych, definiowanych poza klas. Ponadto nie deklaruje si metod (funkcji) skBadowych jako rozwijalnych (inline) bdz nie  decyzja nale|y do kompilatora. W przykBadowym programie do metody main jako parametr jest przekazywana (z wiersza rozkazowego) tablica obiektów (BaDcuchów) klasy String; metoda main nie zwraca wyniku (typem zwracanym jest void), za[ warto[ci parametru arg[0] jest pierwszy po nazwie programu spójny cig znaków. CiaBo main zawiera jedn instrukcj System.out.print("Hello, World!\n"); (W jzyku Java ka|da instrukcja koDczy si [rednikiem, który peBni rol symbolu terminalnego). SBowo System jest nazw klasy w standardowym [rodowisku jzyka. Klasa System zawiera statyczny obiekt skBadowy typu PrintStream o nazwie out; wywoBanie System.out oznacza Java 5 pisanie do standardowego strumienia wyj[ciowego. Klasa PrintStream zawiera szereg przeci|eD metody o nazwie print; jedno z nich przyjmuje parametr typu String. Kompilator automatycznie tBumaczy literaB staBy "Hello, World\n" na odpowiedni obiekt klasy String; odno[nik (referencja) do tego obiektu jest przekazywana do metody System.out.print(). Metoda print() generuje jeden wiersz wyj[ciowy i powraca do metody main, która koDczy wykonanie. 1.2. Klasy: definicja, dziedziczenie, tworzenie obiektów Klas Javy mo|na traktowa jako wzorzec i jednocze[nie generator obiektów. Jako wzorzec klasa zapewnia hermetyzacj (zamknicie w jednej jednostce syntaktycznej) danych i metod oraz ukrywanie informacji, które nie powinny by widoczne dla u|ytkownika. Jako generator zapewnia tworzenie obiektów za pomoc operatora new, którego argumentem jest konstruktor klasy. Definicja klasy ma posta: Deklaracja klasy { CiaBo klasy } Deklaracja klasy skBada si w najprostszym przypadku ze sBowa kluczowego class i nazwy klasy. Przed sBowem kluczowym class mo|e wystpi jeden ze specyfikatorów: abstract, public, final, lub dwa z nich, np. public abstract, public final. Specyfikator abstract odnosi si do klas abstrakcyjnych, które nie mog mie wystpieD, za[ final deklaruje, |e dana klasa nie mo|e mie podklas. Brak specyfikatora oznacza, |e dana klasa jest dostpna tylko dla klas zdefiniowanych w tym samym pakiecie. Specyfikator public mówi, |e klasa jest dostpna publicznie. Klasa abstrakcyjna mo|e zawiera metody abstrakcyjne (bez implementacji, poprzedzone sBowem kluczowym abstract; w miejscu ciaBa metody abstrakcyjnej wystpuje [rednik). Po nazwie klasy mog wystpi frazy:  extends nazwa_superklasy oraz  implements nazwy_interfejsów . Fraza  extends nazwa_superklasy mówi, |e klasa dziedziczy (zawsze publicznie) od klasy nazwa_superklasy, za[  implements nazwy_interfejsów deklaruje, |e w danej klasie zostan zdefiniowane metody, zadeklarowane w implementowanych interfejsach. Je|eli dana klasa implementuje wicej ni| jeden interfejs, wtedy nazwy kolejnych interfejsów oddziela si przecinkami. Podklasa klasy abstrakcyjnej zawierajcej metody abstrakcyjne mo|e podawa definicje metod abstrakcyjnych. Podklasa podajca te definicje staje si klas konkretn, tj. mo|e mie wystpienia. Ka|da klasa, która odziedziczy metod abstrakcyjn, ale nie dostarczy jej implementacji, sama staje si klas abstrakcyjn, a jej definicja tak|e musi by poprzedzona sBowem kluczowym abstract. Uwaga. W jzyku Java ka|da klasa dziedziczy od predefiniowanej klasy Object. Zatem, je|eli w definicji klasy nie wystpuje fraza extends, to jest to równowa|ne niejawnemu wystpieniu w tej definicji frazy  extends Object . Zauwa|my, |e oprócz sBowa kluczowego class i nazwy klasy wszystkie pozostaBe elementy w deklaracji klasy s opcjonalne. Je|eli nie umie[cimy ich w deklaracji, to kompilator przyjmie domy[nie, |e klasa jest niepubliczn, nieabstrakcyjn i niefinaln podklas predefiniowanej klasy Object. CiaBo klasy jest zamknite w nawiasy klamrowe i mo|e zawiera zmienne skBadowe (to jest pola lub zmienne wystpienia), zmienne klasy (statyczne, tj. poprzedzone sBowem kluczowym static), konstruktory i metody oraz funkcje klasy (statyczne). Nazwa ka|dej zmiennej skBadowej, zmiennej klasy, metody lub funkcji klasy musi by poprzedzona nazw typu (np. boolean, double, char, float, int, long, void). Przed nazw typu mo|e wystpi jeden ze specyfikatorów dostpu: private (dostp tylko dla elementów klasy, np. private double d;), protected (dostp tylko w podklasie, nawet je[li podklasa nale|y do innego pakietu; nie dotyczy zmiennych klasy) lub public (dostp publiczny). Brak specyfikatora oznacza, |e dany element jest dostpny tylko dla klas w tym samym pakiecie. Po specyfikatorze dostpu mo|e wystpi sBowo kluczowe final. SBowo final przed nazw typu zmiennej wystpienia lub zmiennej klasy deklaruje jej niemodyfikowalno[ (np. public static final int i = 10;), za[ w odniesieniu do metody oznacza, |e nie mo|e ona by redefiniowana w podklasie (np. public final void f(int i) {/* ... */ }). 6 Jzyki obiektowe Dostp do elementów klasy uzyskuje si za pomoc operatora kropkowego. Je|eli element danej klasy (zmienna lub metoda) przesBania (overrides) jaki[ element swojej superklasy, to mo|na si do niego odwoBa za pomoc sBowa kluczowego super, jak w poni|szym przykBadzie: class ASillyClass /* Deklaracja klasy */ { static final int MAX = 100; /** Definicja staBej */ boolean aVariable;/* Deklaracja zmiennej wystpienia */ static public int x = 10; //Definicja zmiennej klasy void aMethod() { //Definicja metody aVariable = true;// Instrukcja przypisania } // end aMethod } // end aSillyClass class ASillerClass extends ASillyClass { boolean aVariable; void aMethod() { aVariable = false; super.aMethod(); /* WywoBanie metody superklasy */ System.out.println(aVariable); System.out.println(super.aVariable); } // end aMethod } // end ASillerClass Klasy i omawiane ni|ej interfejsy s typami referencyjnymi (odno[nikowymi). Warto[ciami zmiennych tych typów s odno[niki do warto[ci lub zbiorów warto[ci reprezentowanych przez te zmienne. Np. instrukcja ASillyClass oob; jedynie powiadamia kompilator, |e bdziemy u|ywa zmiennej oob, której typem jest ASillyClass. Do zmiennej oob mo|emy przypisa dowolny obiekt typu ASillyClass utworzony za pomoc operatora new: oob = new ASillyClass(); W powy|szej instrukcji argumentem operatora new jest generowany przez kompilator konstruktor ASillyClass() klasy ASillyClass, który inicjuje obiekt utworzony przez operator new. Operator new zwraca odno[nik do tego obiektu, po czym przypisuje go do zmiennej oob. Je|eli dana klasa nie zawiera deklaracji konstruktorów, to kompilator dostarcza konstruktor domy[lny z pustym wykazem argumentów, który w swoim bloku wywoBuje konstruktor super() jej bezpo[redniej nadklasy. Wezmy dla ilustracji definicj klasy Point: public class Point { int x, ,y; } Jest ona równowa|na definicji public class Point { int x, ,y; public Point() { super(); } } z niejawnym wywoBaniem dostarczanego przez kompilator konstruktora superklasy, od której bezpo[rednio dziedziczy klasa Point. Podobne, niejawne wywoBania konstruktora super() s wykonywane w drzewach dziedziczenia. Rozpatrzmy nastpujcy program: //plik Super1.java class Point { int x,y; Point() { x=1;y=2; } } class CPoint extends Point { public int color = 0xFF00FF; } public class Super1 { public static void main(String args[]) { CPoint cp = new CPoint(); System.out.println("cp.color= " + cp.color); System.out.println("cp.x= " + cp.x); }//end main }//end Super1 Instrukcja CPoint cp = new CPoint(); tworzy nowe wystpienie klasy CPoint. Najpierw jest przydzielany obszar w pamici dla obiektu cp, aby mógB przechowywa warto[ci x oraz y, po Java 7 czym pola te s inicjowane do warto[ci domy[lnych (tutaj zero dla ka|dego pola). Nastpnie jest woBany konstruktor Cpoint(). Poniewa| klasa CPoint nie deklaruje konstruktorów, kompilator automatycznie dostarczy konstruktor o postaci CPoint(){super();}, który wywoBa konstruktor klasy Point bez argumentów, tak jakby zamiast super() napisano: Point(){super();x=1;y=2; }. W hierarchii dziedziczenia konstruktor super() mo|e by wywoBywany jawnie, jak w przykBadzie poni|ej: //plik Super2.java class Point { int x,y; Point(int x, int y) { this.x = x; this.y = y; } } class CPoint extends Point { static final int WHITE = 0, BLACK = 1; int color; CPoint(int x, int y) { this(x,y,WHITE); } CPoint(int x, int y, int color) { super(x,y); this.color=color; } } public class Super2 { public static void main(String args[]) { int a = 10, b = 20; CPoint cp = new CPoint(a,b); System.out.println("cp.color= " + cp.color); System.out.println("cp.x= " + cp.x); }//end main }//end Super2 Zmienna this w definicji konstruktora klasy Point jest odno[nikiem (referencj), identyfikujcym obiekt, na rzecz którego wywoBuje si konstruktor. Tak wic lewa strona instrukcji this.x = x identyfikuje pole x obiektu klasy Point, za[ prawa strona jest warto[ci argumentu x, któr inicjuje si to pole. Natomiast sBowo kluczowe this w definicji dwuargumentowego konstruktora klasy CPoint sBu|y do wywoBania konstruktora trójargumentowego tej klasy w instrukcji this(x,y,WHITE). Zatem w instrukcji CPoint cp = new CPoint(a,b); konstruktor CPoint(int,int) wywoBuje ze swojego bloku (instrukcja this(x,y,WHITE);) drugi konstruktor, CPoint(int,int,int), dostarczajc mu argument WHITE. Drugi konstruktor woBa konstruktor superklasy, przekazuje mu wspóBrzdne x oraz y, a nastpnie inicjuje pole color warto[ci WHITE. Uwaga. instrukcja { this(argumenty);musi by pierwsz instrukcj w ciele konstruktora lub metody; to samo dotyczy instrukcji super(argumenty);. Dostp do zmiennych skBadowych klasy (statycznych) jest mo|liwy bez tworzenia obiektów tej klasy. Np. dla klasy ASillyClass mo|emy napisa instrukcj: System.out.println(ASillyClass.x);. Gdyby w klasie ASillyClass zdefiniowa statyczn funkcj klasy, np. public static void bMethod(){/*instrukcje */} to w takiej funkcji nie istnieje odno[nik this, a zatem |adna z jej instrukcji nie mo|e si bezpo[rednio odwoBa do niestatycznej skBadowej x; odwoBanie byBoby mo|liwe jedynie przez zadeklarowanie zmiennej odno[nikowej do klasy ASillyClass i zainicjowanie jej odno[nikiem do utworzonego za pomoc operatora new nowego obiektu, jak pokazano w poni|szej sekwencji instrukcji: ASillyClass ob = new ASillyClass(); System.out.println(ob.x);. 1.3. Interfejsy Konstrukcja o postaci interface nazwa { /* Deklaracje metod i definicje staBych */ } 8 Jzyki obiektowe jest w jzyku Java typem definiowanym przez u|ytkownika. Deklaracja metody skBada si z sygnatury (sygnatura metody zawiera typ zwracany, nazw metody i typy argumentów) i terminalnego [rednika. Poniewa| interfejs mo|e zawiera jedynie deklaracje metod i definicje staBych, odpowiada on klasie abstrakcyjnej z zadeklarowanymi publicznymi polami danych i metodami abstrakcyjnymi. W zwizku z tym w definicji interfejsu zabrania si u|ywania specyfikatorów private i protected, za[ u|ycie specyfikatorów abstract i public jest zbyteczne. Wezmy dla przykBadu dwa interfejsy PlaneLike i BoatLike interface PlaneLike { void takeOff(); float kmph(); } interface BoatLike { void swim(); float knots(); } i zdefiniujmy ich implementacje w klasach Plane i Boat, które dziedzicz od wspólnej superklasy Vehicle: class Vehicle {} class Plane extends Vehicle implements PlaneLike { /* Plane must implement kmph(), takeOff() */ public void takeOff() { System.out.println("Plane is taking off"); } public float kmph() { return 600; } } class Boat extends Vehicle implements BoatLike { /* Boat must implement knots(),swim() */ public void swim() { System.out.println("Boat is swimming"); } public float knots() { return 20; } } Poprawne bd wówczas deklaracje Plane biplane = new Plane(); biplane.takeOff(); Boat vessel = new Boat(); vessel.swim(); a tak|e deklaracje PlaneLike aircraft = new Plane(); aircraft.takeOff(); BoatLike motorboat = new Boat(); motorboat.swim(); ZaBó|my teraz, |e chcieliby[my skonstruowa klas SeaPlane, której obiekty powinny si zachowywa w pewnych okoliczno[ciach jak pojazdy wodne, za[ w innych jak pojazdy powietrzne. W jzyku, który wyposa|ono w mechanizm dziedziczenia mnogiego (np. C++) klasa SeaPlane miaBaby dwie superklasy: Plane i Boat, jak pokazano w cz[ci a) rysunku 1-3. Java 9 a) b) Vehicle Vehicle Plane Boat Plane Boat SeaPlane interface SeaPlane BoatLike interface PlaneLike Rys. 1-3. a) Graf dziedziczenia mnogiego dla SeaPlane. b) Graf dziedziczenia pojedynczego dla SeaPlane W jzyku Java podobny efekt mo|na osign poprzez implementacj w klasie SeaPlane obu interfejsów, t.j. PlaneLike i BoatLike (cz[ b rysunku 4-3): class SeaPlane extends Vehicle implements PlaneLike, Boatlike { /** SeaPlane must implement kmph(), takeOff(), knots(), swim() */ } Dla osignicia po|danego zachowania si obiektów klasy SeaPlane mogliby[my umie[ci w gBównym module zródBowym Multi1.java nastpujcy kod: public class Multi1 { public static void main(String args[]) { Boat vessel = new Boat(); Plane biplane = new Plane(); System.out.println("Let's starting!"); PlaneLike ref1 = new SeaPlane(biplane); ref1.takeOff(); System.out.println(ref1.kmph()); BoatLike ref2 = new SeaPlane(vessel); ref2.swim(); System.out.println(ref2.knots()); } } Jednak ze wzgldu na wielokrotn u|ywalno[ kodu lepszym rozwizaniem bdzie taka definicja klasy SeaPlane, która wykorzystuje mechanizm delegacji, tj. bezpo[redniej wspóBpracy z klasami Plane i Boat: class SeaPlane extends Vehicle implements PlaneLike, BoatLike { // define a Plane and Boat instance variables // i.e. collaborate with Plane and Boat classes private Plane itAsPlane; private Boat itAsBoat; //Konstruktor SeaPlane(Plane itAsPlane) { this.itAsPlane=itAsPlane; } //Konstruktor 10 Jzyki obiektowe SeaPlane(Boat itAsBoat) { this.itAsBoat=itAsBoat; } // forward the messages to the appropriate collaborator public float kmph() { return itAsPlane.kmph(); } public void takeOff() { itAsPlane.takeOff(); } public float knots() { return itAsBoat.knots(); } public void swim() { itAsBoat.swim(); } } Interfejs nie mo|e dziedziczy klas, ale mo|e dziedziczy dowolnie wiele interfejsów. Np. korzystajc z podanych wy|ej definicji mogliby[my utworzy interfejs interface SeaPlaneLike extends PlaneLike, BoatLike{ public long SPEED_LIMIT = 1000; } i wykorzysta go w klasie SeaPlane, implementujc metody zadeklarowane w interfejsach PlaneLike i BoatLike. 1.4. Pliki zródBowe i pakiety Program jzyka Java mo|e si skBada z wielu niezale|nie kompilowalnych moduBów zródBowych, w których umieszcza si definicje klas oraz interfejsów. ModuBy zródBowe s przechowywane w plikach o nazwie Nazwa.java, gdzie Nazwa jest nazw klasy publicznej; pliki te stanowi jednostki kompilacji. Je|eli w pliku Nazwa.java zdefiniowano tylko jedn klas, to w wyniku kompilacji tego pliku powstaje plik wynikowy Nazwa.class. Je|eli program jest aplikacj, to w zestawie moduBów zródBowych musi si znalez dokBadnie jeden moduB zródBowy (moduB gBówny aplikacji) z klas publiczn, która zawiera publiczn i statyczn funkcj main (ka|dy inny moduB zródBowy mo|e zawiera klas z funkcj main, je|eli nie jest to klasa publiczna). ModuB zródBowy, w którym definicje klas oraz interfejsów poprzedzono deklaracj pakietu o postaci package nazwa_pakietu; staje si pakietem. Deklaracja pakietu rozszerza przestrzeD nazw programu i pozwala na lepsze zarzdzanie programem wielomoduBowym. Je|eli moduB zródBowy nie zawiera deklaracji pakietu, to nale|y on do tzw. pakietu domy[lnego (pakietu bez nazwy). Np. zadeklarowana wcze[niej klasa Hello, umieszczona w pliku Hello.java nale|y do pakietu domy[lnego. Pakiety s [ci[le powizane z katalogami, w których umieszcza si moduBy zródBowe i pliki wynikowe. ZaBó|my np., |e w katalogu c:\mike (Win 95 DOS) umieszczono gBówny plik zródBowy aplikacji Student.java o postaci: import myprog.pakiet1.HiGrade; import myprog.pakiet1.LoGrade; Powy|sze dwie deklaracje importu mo|na zastapi jedn: import myprog.pakiet1.* public class Student { int i = 10; public static void main(String args[]) { System.out.println("Hello, I am here!"); HiGrade highgrade = new HiGrade(); highgrade.printgrade(); LoGrade lowgrade = new LoGrade(); lowgrade.printgrade(); } } Plik zawiera definicj klasy Student, poprzedzon deklaracj importu klas HiGrade i LoGrade. Plik ten mo|e zosta skompilowany wywoBaniem kompilatora javac z katalogu nadrzdnego w stosunku do katalogu mike\myprog\pakiet1; je|eli plik Student.java umieszczono w katalogu mike, to wywoBanie bdzie miaBo posta: javac Student.java. Je|eli pliki HiGrade.java i LoGrade.java maj posta: Java 11 package myprog.pakiet1; public class HiGrade { int i = 10; public void printgrade() { System.out.println("My grades are higher than " + i); } } class Empty{} oraz package myprog.pakiet1; public class LoGrade { int i = 3; public void printgrade() { System.out.println("My grades are lower than " + i); } } to zostan utworzone cztery pliki wynikowe: Student.class w katalogu javaprog oraz HiGrade.class, LoGrade.class i Empty.class, a wywoBanie interpretatora java Student spowoduje wyprowadzenie na ekran napisu: Hello, I am here! My grades are higher than 10 My grades are lower than 3 Uwaga. Deklaracja importu nie oznacza wBczania do pliku Student.java tekstu zawartego w plikach HiGrade.java i LoGrade.java. Natomiast pozwala ona u|ytkownikowi klasy Student u|ywa skrótowych nazw: np. zamiast pisa myprog\pakiet1\HiGrade highgrade = new mike\myprog\pakiet1\HiGrade(); mogli[my napisa krótko: HiGrade highgrade = new HiGrade();. Gdyby[my chcieli u|ywa równie| klasy Empty (lub innych klas pakietu pakiet1), to deklaracja importu miaBaby posta: import mike.myprog.pakiet1.*. W jzyku Java wa|na jest tak|e kolejno[ deklaracji:najpierw deklaracja pakietu, po niej deklaracje importu, po czym definicje klas. Zauwa|my, |e gdyby umie[ci w pliku LoGrade.java definicj pakietowej funkcji wystpienia, na przykBad void msg() { System.out.print("This is a package method\n"); } to funkcj t mo|na byBoby wywoBa z ciaBa klasy HiGrade, na przykBad w funkcji pf: public void pf() { LoGrade lg = new LoGrade(); lg.msg(); } Fukcja pf jest publiczna, zatem jest dostpna nie tylko dla klas pakietu myprog.pakiet1, lecz tak|e poza tym pakietem. Z funkcji main klasy Student mo|na j, przykBadowo, wywoBa poleceniem: highgrade.pf();. Zauwa|my te|, |e deklarujc msg jako funkcj klasy LoGrade static void msg(){System.out.print("This is a package method\n");} mogliby[my j wywoBa z ciaBa klasy HiGrade bez tworzenia referencji do obiektu klasy LoGrade, np. public void pf() { LoGrade.msg(); } 1.5. Polimorfizm Polimorfizm mo|emy okre[li jako wirtualizacj operacji; jest to mo|liwo[ dynamicznego (póznego, realizowanego w fazie wykonania) wizania nazwy operacji do wielu implementacji (metod) tej operacji w ró|nych klasach pozostajcych w relacji dziedziczenia. Wizaniu towarzyszy mechanizm wyboru konkretnej implementacji. Wybór implementacji zale|y od nazwy metody oraz od typu dynamicznego tego obiektu, dla którego zostaBa wywoBana operacja, a nie od typu zmiennej, wskazujcej ten obiekt. 12 Jzyki obiektowe Zauwa|my, |e przeci|anie operacji nie prowadzi do polimorfizmu; w tym przypadku wizanie, dopasowanie parametrów wywoBania operacji do okre[lonej sygnatury i wybór implementacji s statyczne, poniewa| s wykonywane w fazie kompilacji. Musz wówczas istnie ró|nice w sygnaturach operacji (w typie wyniku i/lub w typach parametrów wej[ciowych), a kryterium wyboru implementacji zale|y od tych ró|nic. W jzyku Java wszystkie deklaracje metod, które nie s metodami klasy, ani metodami finalnymi, mo|na traktowa jako operacje wirtualne. Tak wic definicja metody o danej sygnaturze w superklasie mo|e by przesBonita przez definicj metody o tej samej sygnaturze w podklasie. W rezultacie kompilator nie mo|e zwiza nazwy metody z jej implementacj (istniej co najmniej dwie implementacje o takich samych sygnaturach). Wizanie mo|e si odby dopiero w fazie wykonania; wówczas interpretator okre[la typ dynamiczny obiektu na którym zostaje wywoBana operacja i wi|e t operacj z wBa[ciw dla danego obiektu implementacj. Ilustracj wywoBania polimorficznego pokazuje poni|szy prosty przykBad. //Plik Polimorf.java class Base { public void msg() { System.out.println("Base class method"); } } class Derived extends Base { public void msg() { System.out.println("Derived class method"); } } public class Polimorf { int i = 10; public static void main(String args[]) { Base b1 = new Base(); b1.msg(); b1 = new Derived(); if(b1 instanceof Derived) System.out.println("Derived"); b1.msg(); } } Metoda msg() ma dwie implementacje: w klasie Base i w klasie Derived. Odno[nik (referencja) b1 do klasy Base jest najpierw inicjowana obiektem klasy Base, a wic instrukcja b1.msg(); wywoBa metod tej klasy. Nastpnie odno[nikowi b1 zostaje przypisany obiekt klasy Derived, co spowoduje, |e nastpna instrukcja b1.msg(); wywoBa implementacj metody msg() zdefiniowan w klasie Derived. Instrukcja if wykorzystujca operator instanceof sBu|y do sprawdzenia, jaki jest typ dynamiczny obiektu b1. Wynikiem wykonania programu bdzie nastpujcy wydruk: Base class method Derived Derived class method 1.5. Klasy zagnie|d|one Klasy, jak ju| powiedziano, mog nale|e do pakietów nazwanych lub nienazwanych. Poczwszy od wersji 1.1 jzyka Java wprowadzono mo|liwo[ definiowania klas wewntrznych (inner classes) jako elementów skBadowych innych klas; mo|na je definiowa albo lokalnie wewntrz ciaBa klasy zewntrznej, albo (anonimowo) jako wyra|enie w bloku. Takie zagnie|d|one klasy posiadaj kilka wBasno[ci, które czyni je u|ytecznymi: " Nazwy klasy wewntrznej nie mo|na u|y na zewntrz jej zasigu, za wyjtkiem nazwy kwalifikowanej. Pomaga to w strukturalizacji klas w obrbie pakietu. Java 13 " Kod klasy wewntrznej mo|e wykorzystywa proste nazwy z zasigów otaczajcych, w tym zarówno skBadowe klasy, jak i skBadowe wystpienia klas otaczajcych oraz zmienne lokalne otaczajcych bloków. Klasy wewntrzne s elementami kombinacji struktury blokowej i programowania opartego o klasy; wprowadzono je po raz pierwszy w jzyku Beta. Wykorzystanie struktury blokowej oraz klas wewntrznych uBatwia programi[cie wiza ze sob obiekty Javy, poniewa| klasy mog by definiowane w pobli|u obiektów, którymi manipuluj, i mog bezpo[rednio u|ywa nazw, których potrzebuj. Ponadto programista mo|e definiowa klas wewntrzn jako statyczny element dowolnej klasy otaczajcej. Jednak klasa wewntrzna nie mo|e deklarowa |adnej ze swoich skBadowych ze sBowem kluczowym static, poniewa| ciaBo klasy wewntrznej jest w zasigu klasy otaczajcej. W rezultacie zmienne statyczne dla klasy wewntrznej musz by umieszczane w klasie otaczajcej. Z tego samego powodu nie mo|na w klasie wewntrznej deklarowa statycznych inicjatorów dla pól klasy. Klasy zewntrzne oraz statyczne klasy wewntrzne nazywa si klasami wysokiego poziomu. Ró|ni si one od niestatycznych klas wewntrznych tym, |e mog u|ywa bezpo[rednio jedynie swoje wBasne zmienne wystpienia. Je|eli klasa wewntrzna posiada nazw, mo|e by deklarowana ze sBowami kluczowymi private, protected, final, lub abstract. Natomiast klasy anonimowe s prywatne w bloku, w którym s zadeklarowane, poniewa| nie mog by wykorzystane na zewntrz tego bloku. Zagnie|d|anie klas w ten wBa[nie sposób pozwala dowolnej klasie wysokiego poziomu  dla logicznie powizanych klas poziomu ni|szego  uzyska podobn do pakietu organizacj, w której wszystkie klasy maj peBny dostp do pól prywatnych. W podanym ni|ej przykBadzie klasa wewntrzna zostaBa zadeklarowana jako klasa niestatyczna Inner z wBasnym konstruktorem i wBasn zmienn skBadow y. //Plik Outer1.java public class Outer1 { public int x; public Outer1(int i) { x = i; } class Inner { public int y; public Inner(String s, int j) { y = j; System.out.println(s+j); }; }//end Inner public static void main(String args[]) { Outer1 ref1 = new Outer1(10); System.out.println("ref1.x = " + ref1.x); Outer1.Inner ref2 = ref1.new Inner("ref2.y = ", 20); System.out.println("ref2.y = " + ref2.y); } }//end Outer1 Wprowadzenie klas zagnie|d|onych nie spowodowaBo zmian w przetwarzaniu plików z B-kodem przez maszyn wirtualn Javy, tj. przez interpretator, ani w standardowych bibliotekach klas, a nowa cecha jzyka zostaBa uwzgldniona w nowych wersjach kompilatorów. Uwzgldniono j w ten sposób, |e nazwy klas wewntrznych s przeksztaBcane tak, aby unikn konfliktów z innymi nazwami w ró|nych zasigach. Nazwy s kodowane przez kompilator, który bierze ich posta zródBow, kwalifikuje je kropkami, po czym zmienia ka|d kropk po nazwie klasy na znak dolara ( $ ). Tak wic po kompilacji pliku zródBowego  Outer1.java otrzymamy dwa pliki z B-kodem:  Outer1.class oraz  Outer1$Inner.class . Oczywi[cie interpretacji poddamy plik  Outer1.class . Niestatyczn klas wewntrzn wykorzystuje si wtedy, gdy tworzony jest obiekt klasy zewntrznej; jak pokazano wy|ej, argumentem operatora new jest jest konstruktor klasy wewntrznej, wywoBywany na odno[niku do obiektu klasy zewntrznej. Nastpny przykBad ilustruje deklaracj statycznej klasy wewntrznej: 14 Jzyki obiektowe //plik Outer2.java public class Outer2 { public int x; public Outer2(int i) { x = i; } static class Inner { public int y; public Inner(int j) { y = j; }; }//end Inner public static void main(String args[]) { Outer2 ref1 = new Outer2(10); System.out.println("ref1.x = " + ref1.x); Outer2.Inner ref2 = new Outer2.Inner(20); System.out.println("ref2.y = " + ref2.y); } }//end Outer2 W tym przypadku argumentem operatora new jest jest konstruktor klasy wewntrznej, wywoBywany na skBadowej statycznej (Outer2.Inner) klasy zewntrznej. Kompilator, podobnie jak w poprzednim przykBadzie, utworzy dwa pliki z B-kodem:  Outer2.class oraz  Outer2$Inner.class . Je|eli nie ma potrzeby tworzenia obiektu klasy zewntrznej, wówczas zarówno klas wewntrzn, jak i funkcje skBadowe klasy zewntrznej mo|na zadeklarowa jako statyczne. Konstrukcje tego typu wykorzystywane s w Javie prawie wszdzie tam, gdzie klasa wewntrzna implementuje interfejs. Ilustracj tego stwierdzenia jest kolejny przykBad. //Plik Outer3.java interface InnerInt{ String wyswietl(); }//end of InnerInt interface public class Outer3 { public static int x=10; static class Inner implements InnerInt{ private int y; public Inner(int j) { y=j; System.out.println(wyswietl()); }//end of ctor public String wyswietl(){ return (new String("Inner.y = "+y)); } }//end Inner public static InnerInt foo(int i){ return (new Inner(i)); } public static void main(String args[]) { System.out.println("Outer3.x = " + Outer3.x); Outer3.foo(20); } }//koniec public class Outer3 W bloku main publiczna, statyczna funkcja foo() klasy zewntrznej, wywoBywana z argumentem 20, zwraca odno[nik typu interfejsowego InnerInt, inicjowany odno[nikiem do tworzonego w instrukcji return obiektu klasy Inner. Mogli[my tak uczyni, poniewa| klasa Inner jest nie tylko odrbnym typem, lecz tak|e implementuje typ InnerInt. W rezultacie kompilator utworzy trzy pliki z B-kodem:  Outer3.class ,  Outer3$Inner.class oraz  InnerInt.class . Java 15 Poniewa| typ Inner jest wykorzystywany w definicji klasy zewntrznej tylko jeden raz, mo|na, dla uzyskania bardziej zwizBego kodu, zrezygnowa z wprowadzania jego nazwy do przestrzeni nazw programu, a implementacj interfejsu InnerInt umie[ci bezpo[rednio w wyra|eniu new instrukcji powrotu z funkcji foo(). Konstrukcja taka, bdc implementacj interfejsu, jest oczywi[cie klas; poniewa| jednak nie wystpuje tutaj nazwa klasy, nazywamy j klas anonimow. Poni|ej zaprezentowano odpowiedni kod, w którym blok, zaczynajcy si nawiasem klamrowym po InnerInt() jest ciaBem klasy anonimowej, faktycznie identycznym z ciaBem klasy Inner z poprzedniego przykBadu. //plik Outer4.java interface InnerInt{ StringBuffer wyswietl(); }//end InnerInt public class Outer4 { public static int x=10; public static InnerInt foo(final int i) { return new InnerInt() { private int y = i; public StringBuffer wyswietl() { return (new StringBuffer("Outer4.foo(20).wyswietl()= " +y)); }//end wyswietl() };//end anonymous }//end foo public static void main(String args[]) { System.out.println("Outer4.x = " + Outer4.x); System.out.println(Outer4.foo(20).wyswietl()); }//end main() }//end Outer4 Zwrómy uwag na ostatni instrukcj w funkcji main(). Argument metody println() jest wyra|eniem otrzymanym w wyniku wywoBania na klasie Outer4 funkcji foo(), która zwraca obiekt typu InnerInt. Na obiekcie tym jest wywoBywana funkcja wyswietl(), która zwraca wynik typu StringBuffer, a wic typu akceptowanego przez metod println(). Zdefiniowana tutaj klasa anonimowa ma nastpujce wBasno[ci: " Mo|e mie inicjatory pól, ale nie mo|e mie konstruktora. " Je|eli klasa anonimowa zostaBa wyprowadzona z interfejsu I, to faktyczn jej superklas jest Object, a klasa tylko implementuje interfejs I, bez |adnych rozszerzeD. PrzeksztaBcanie nazw przez kompilator spowoduje teraz utworzenie nastpujcych plików z B-kodem:  Outer4.class ,  Outer4$1.class oraz  InnerInt.class . Plik  Outer4$1.class odpowiada klasie anonimowej. W jego nazwie liczba 1 (numer klasy anonimowej) zostaBa dodana przez kompilator dla otrzymania unikatowej nazwy, która zostanie przekazana do konsolidatora. Istnienie klas zagnie|d|onych wymaga pewnej zmiany w nazwach kwalifikowanych przy definiowaniu zmiennych typu klasy wewntrznej oraz hierarchii dziedziczenia. Istotne zmiany to:  Inicjowanie zmiennych odno[nikowych typu klasy wewntrznej sBowem kluczowym this, odpowiadajcym bie|cemu obiektowi klasy zewntrznej.  Kwalifikowanie dziedziczenia od klasy wewntrznej jej nazw, umieszczan po nazwie klasy zewntrznej i kropce. Ilustracj tego sposobu kwalifikacji nazw jest podany ni|ej przykBad. class Vehicle { class Wheel { String hubcapType; float radius; }//end class Wheel Wheel leftWheel = this. new Wheel(); 16 Jzyki obiektowe Wheel rightWheel = this. new Wheel(); Wheel extra; static void thirdWheel(Vehicle car) { if (car.extra == null) { car.extra = car. new Wheel(); }//end if }//end thirdWheel() public static void main(String args[]) { System.out.println("Vehicle = " ); }//end main() }//end class Vehicle //KoBo ze szprychami class WireRimWheel extends Vehicle.Wheel { WireRimWheel(Vehicle car, float wireGauge) { car. super(); }//end of constructor WireRimWheel() }//end class WireRimWheel class Auto extends Vehicle { } W wyniku kompilacji zostan utworzone cztery pliki z B-kodem:  Vehicle.class ,  Vehicle$Wheel.class ,  WireRimWheel.class oraz  Auto.class . 1.6. ObsBuga wyjtków Wyjtki pozwalaj zachowa kontrol nad przebiegiem wykonania funkcji (metod), a tak|e pojedynczych instrukcji zawartych w funkcjach. Wyjtek jest zdarzeniem, które pojawia si podczas wykonania i rozrywa normaln kolejno[ wykonania instrukcji. W jzyku Java istnieje bardzo rozbudowana hierarchia (drzewo) predefiniowanych klas wyjtków, których superklas jest klasa Throwable, a gBównymi gaBziami drzewa s klasy Error i Exception. Cz[ wyjtków nale|y do grupy tzw. wyjtków weryfikowalnych (checked exceptions): kompilator sprawdza, czy program zawiera procedury obsBugi dla ka|dego wyjtku z tej grupy. Natomiast wyjtki klasy Error i jej podklas nale| do grupy wyjtków nieweryfikowalnych (unchecked exceptions), poniewa| mog one wystpi w wielu punktach programu i powrót z nich jest trudny lub wrcz niemo|liwy. Do grupy wyjtków nieweryfikowalnych nale| te| wyjtki klasy RuntimeException (podklasa Exception) i jej podklas, poniewa| zadeklarowanie w programie takich wyjtków nie mogBoby znacznie pomóc w ustaleniu (przez kompilator) poprawno[ci programów. Dla obsBugi wyjtków weryfikowalnych wprowadzono cztery sBowa kluczowe: throw, throws, try, catch i finally. SBowo kluczowe throw sBu|y do jawnego zgBaszania wyjtków nieweryfikowalnych i wystpuje w instrukcji throw o skBadni throw wyra|enie;gdzie wyra|enie musi oznacza zmienn lub warto[ typu referencyjnego do klasy Throwable lub jej podklas. ZgBoszenie wyjtku w instrukcji throw spowoduje natychmiastowe opuszczenie bloku lub funkcji zawierajcego instrukcj throw i znalezienie instrukcji try, której fraza catch przechwyci zgBoszony wyjtek. Je|eli nie ma takiej instrukcji try, zostanie wywoBana metoda UncaughtException i wykonanie programu (lub wtku) zostanie zakoDczone. Fraza:throws klasa_wyjtków mo|e wystpi w nagBówku funkcji (metodzie wystpienia, konstruktorze, funkcji klasy), np. public staic void main(String args[]) throws Exception {/*...*/} void printNumber(int number) throws WrongNumberException {/*...*/} Fraza throws klasa_wyjtków oznacza, |e dana funkcja mo|e zgBasza jedynie wyjtki podanej klasy. Je|eli wykonanie pewnej instrukcji programu mo|e spowodowa powstanie wyjtkowego zdarzenia, to musi ona by ujta w blok instrukcji try, po którym musz wystpi procedury obsBugi wyjtku majce posta frazy catch i bezpo[rednio po catch (opcjonalnie) frazy finally. SkBadnia tej konstrukcji ma posta: try {I}catch(arg1 e1) {I} catch(arg2 e2) {I} ... catch(argn en) {I} ... finally {I} gdzie I oznacza instrukcje, arg1 .. argn  klasy wyjtków, e1 ... en  odno[niki do tych klas. Blok catch nale|y traktowa jako ciaBo procedury obsBugi wyjtku nale|cego do klasy argi. Java 17 Je|eli funkcja/metoda zawiera instrukcj try, to wyjtki mog by zgBaszane wyBcznie w bloku try. Po zgBoszeniu wyjtku sterowanie opuszcza kod, który zgBosiB wyjtek i przechodzi do pierwszej w kolejno[ci procedury catch; je|eli ta nie obsBuguje wyjtku zgBoszonej klasy, jest on przekazywany do nastpnej. Blok frazy finally (je[li wystpuje) jest wykonywany zawsze gdy koDczy si wykonanie instrukcji try i to nawet wtedy, gdy wykonanie try zostaje gwaBtownie przerwane. Prosty program, który jedynie ilustruje skBadni zgBaszania i obsBugi wyjtków mo|e wyglda nastpujco: //plik TestEx.java import java.io.*; public class TestEx { public TestEx() {} final int CONSTANT = 10; void ff() throws IOException { try { System.out.println("I was here, within try statement."); if(CONSTANT > 0) throw new IOException("CONSTANT should be negative"); } catch(IOException exc) { System.err.println("Caught IOException: "+ exc.getMessage()); } finally { System.out.println("And now I am in finally blok"); } }//end ff public static void main(String args[]) throws IOException { TestEx te = new TestEx(); te.ff(); }//end main }//end class TestEx Podany ni|ej przykBad definiuje klas ListOfNumbers, wywoBujc z pakietów Javy dwie metody klas, które mog zgBosi wyjtki. import java.io.*; import java.util.Vector; public class ListOfNumbers { private Vector victor; private static final int size = 10; public ListOfNumbers () { victor = new Vector(size); for (int i = 0; i < size; i++) victor.addElement(new Integer(i)); } public void writeList() { PrintWriter p = null; try { System.out.println("Entering try statement"); p = new PrintWriter(new FileOutputStream("OutFile.txt")); for (int i = 0; i < size; i++) p.println("Value at: " + i + " = " + victor.elementAt(i)); } catch (ArrayIndexOutOfBoundsException e) { System.err.println("Caught ArrayIndexOutOfBoundsException: " + 18 Jzyki obiektowe e.getMessage()); } catch (IOException e) { System.err.println("Caught IOException: " + e.getMessage()); } finally { if (p != null) { System.out.println("Closing PrintWriter"); p.close(); } else { System.out.println("PrintWriter not open"); } } } public static void main(String args[]) { ListOfNumbers lst = new ListOfNumbers(); lst.writeList(); }//end main }//end ListOfNumbers Konstruktor ListOfNumbers() tworzy obiekt klasy Vector o dziesiciu elementach bdcych warto[ciami od 0 do 9. W klasie ListOfNumbers zdefiniowano tak|e metod writeList(), która zapisuje ten cig liczb do pliku tekstowego OutFile.txt. Metoda writeList() wywoBuje dwie metody, które mog zgBosi wyjtki:  konstruktor klasy FileOutputStream, który zgBasza IOException je|eli z jakiego[ powodu nie mo|e otworzy pliku: p = new PrintWriter(new FileOutputStream("OutFile.txt"));  metod elementAt() klasy Vector, która zgBasza wyjtek ArrayIndexOutOfBoundsException je|eli przekazana do niej warto[ indeksu jest zbyt maBa (liczba ujemna) lub zbyt du|a (wiksza ni| liczba elementów zawartych aktualnie w obiekcie klasy Vector). Instrukcje System.err.println wykorzystuj komunikaty generowane przez metod getMessage klasy Throwable (lub jej podklas), która podaje dodatkowe informacje o zaistniaBym bBdzie. Je|eli na dysku jest wystarczajco du|o miejsca na zapisanie pliku OutFile.txt, to program zaBo|y taki plik z zawarto[ci: Value at: 0 = 0 ... Value at 9 = 9 oraz wyprowadzi na ekran dwa wiersze tekstu: Entering try statement Closing PrintWriter 1.7. Zarzdzanie pamici Jzyk Java jest wyposa|ony w mechanizm zbierania nieu|ytków (garbage collection). System wykonawczy Javy automatycznie zwraca przydzielony obiektowi obszar pamici gdy stwierdzi, |e do danego obszaru nie odnosi si ju| |adna referencja. 1.8. WspóBbie|no[ Program Javy jest z reguBy wykonywany w obrbie jednego procesu, którego stos mo|e by wykorzystywany przez wiele wspóBbie|nych wtków programu (wtkiem nazywa si sekwencyjny przepByw sterowania w procesie, który wykonuje dany program). Nawet najprostsza aplikacja, która wy[wietlaBa napis "Hello, World!", miaBa dwa wtki wykonania: wtek gBówny (main thread) wykonujcy kod tej aplikacji oraz kolektor nieu|ytków. Je|eli maszyna wirtualna jest wieloprocesorowa, wtki mog by wykonywane wspóBbie|nie; na komputerze jednoprocesorowym wspóBbie|no[ mo|e by emulowana (np. w systemie Windows 95) przez przydzielanie poszczególnym wtkom pewnej liczby kwantów czasu procesora. W tym drugim przypadku jest realizowana tzw. wielowtkowo[ wywBaszczeniowa (preemptive), która nie dopuszcza Java 19 do  zagBodzenia (starving) wtków o niskich priorytetach. Priorytet jest liczb z przedziaBu 1..10; je|eli priorytet nie zostanie ustawiony jawnie (funkcj setPriority klasy Thread), to nowy wtek przejmie priorytet wtku, który go utworzyB. Uwaga. ZagBodzenie mo|e si zdarzy wtedy, gdy jeden lub wicej wtków w programie jest blokowanych przed dostpem do pewnego zasobu i wskutek tego nie mog biec dalej. KraDcow postaci zagBodzenia jest zakleszczenie lub impas (deadlock). Impas pojawia si wtedy, gdy dwa lub wicej wtków czeka na warunek, który nie mo|e by speBniony; typowym przykBadem jest sytuacja, gdy istniej dwa wtki i ka|dy z nich czeka na wykonanie czego[ przez partnera. Wykonanie metody start (public synchronized void start()) na rzecz utworzonego wcze[niej obiektu klasy Thread powoduje utworzenie wtku. Przebieg wykonania wtku zale|y od implementacji metody run (public void run()), wywoBywanej niejawnie przez system tu| po utworzeniu wtku. ZakoDczenie wykonania metody run() powoduje niejawne wywoBanie metody stop (public static final void stop()), która niszczy wtek. Stanami wtków mo|na sterowa przez wywoBania finalnych metod wystpienia suspend i resume (zawieszenie i wznowienie wtku zawieszonego), wait i notify (wstrzymanie i uwolnienie wtku wstrzymanego), wywoBania finalnych metod synchronizowanych join() i join(long millisec), które powoduj wstrzymanie wykonywania wtku a| do zniszczenia go przez inny wtek oraz przez wywoBania metod klasy: public static void sleep(long millisec), która powoduje u[pienie wtku na podany okres czasu i public static void yield(), która oddaje dostp do procesora innemu wtkowi (o ile taki istnieje). Ponadto mo|na wywoBa metod public final boolean isAlive() dla stwierdzenia, czy wtek istnieje. Uwaga. Ze wzgldu na zdarzajce si bBdy przy blokowaniu i zwalnianiu zasobów oraz mo|liwe zakleszczenia wtków w obowizujcej obecnie wersji JDK1.2 nie zaleca si stosowania metod resume(), stop() i stop(Throwable obj). Wtek Javy mo|e by tworzony na dwa sposoby: albo jako obiekt podklasy, która dziedziczy od klasy Thread (klasa java.lang.Thread zawiera metody, które kontroluj i synchronizuj poszczególne wtki), albo jako obiekt klasy, która implementuje interfejs Runnable (java.lang.Runnable). W obu przypadkach nale|y poda implementacj metody run() zadeklarowanej w interfejsie Runnable. Pierwszy sposób ilustruje poni|szy przykBad. //plik Thread1.java public class Thread1 extends Object { public static void main(String args[]) { Thread x = new MyThread("Fastthread"); Thread y = new MyThread("Slow thread"); x.setPriority(Thread.MAX_PRIORITY); x.start(); y.start(); }//end main() }//end Thread1 class MyThread extends Thread { protected String name = "not initialized"; public MyThread(String nameString) { name = nameString; } public void run() { for(int i =1;i<=10;i++) { try { Thread.currentThread().sleep(300); }//end try catch(InterruptedException e) { } //end catch System.out.println(name+"continues... "+i); }//end for System.out.println(name+" is DONE!! "); }//end run() }//end MyThread 20 Jzyki obiektowe W przykBadzie utworzono dwa wtki, x i y, przy czym jeden z nich (x )ustawiono na najwy|szy osigalny priorytet. Ka|dy wtek bdzie wykonywany oddzielnie, ale wtek x zakoDczy dziaBanie wcze[niej. Drugi sposób implementuje interfejs Runnable: //plik TwoThreads public class TwoThreads extends Object { public static void main(String args[]) { MyClass xx = new MyClass(); MyClass yy = new MyClass(); Thread x = new Thread(xx); Thread y = new Thread(yy); x.setPriority(Thread.MAX_PRIORITY); x.start(); y.start(); }//end main() }//end TwoThreads class MyClass implements Runnable { public void run() { for(int I=0;I<=10;I++) { System.out.println("Thread progress="+I); } System.out.println("Thread completed"); } } 1.9 Synchronizacja wtków W podanych wy|ej przykBadach wtki byBy niezale|ne i asynchroniczne. Inaczej mówic, ka|dy wtek zawieraB wszystkie dane i metody potrzebne dla jego wykonania i nie wymagaB |adnych zewntrznych zasobów lub metod. Ponadto przebieg ka|dego wtku miaB wBasny rytm, niezale|ny od stanu, czy aktywno[ci drugiego, biegncego wspóBbie|nie. Istnieje jednak wiele sytuacji, gdy oddzielne, wspóBbie|nie wykonywane wtki wspóBdziel pewne dane i musz uwzgldnia stany i aktywno[ci innych wtków. Powszechnie znanym modelem programistycznym takich sytuacji jest model producent/konsument, w którym producent generuje strumieD danych pobieranych nastpnie przez konsumenta. PrzykBadem praktycznym mo|e by program, w którym jeden wtek (producent) zapisuje dane do pliku, podczas gdy drugi wtek czyta dane z tego samego pliku. Innym przykBadem mo|e by pisanie znaków na klawiaturze: wtek producenta umieszcza naci[nicia klawisza w kolejce zdarzeD, a wtek konsumenta odczytuje zdarzenia z tej samej kolejki. Jeszcze innym przykBadem mo|e by wysyBanie znaków do tego samego strumienia (np. do System.out) z kilku wspóBbie|nie wykonywanych wtków. Widzimy, |e podane przykBady wykorzystuj wspóBbie|ne wtki, które dziel wspólny zasób: w pierwszym wspóBdziel plik, a w drugim kolejk zdarzeD, w trzecim ten sam strumieD. Poniewa| wtki wspóBdziel wspólny zasób, musz by w jaki[ sposób synchronizowane (np. w trzecim przykBadzie przy braku synchronizacji BaDcuchy znaków pochodzce z ró|nych zródeB mog by bezsensownie przemieszane). Segmenty kodu programu, które |daj dostpu do tego samego obiektu z dwóch oddzielnych, wspóBbie|nych wtków, nazywa si sekcjami krytycznymi. W jzyku Java sekcj krytyczn mo|e by blok lub metoda; identyfikuje si je sBowem kluczowym synchronized. W przypadku bloku mamy instrukcj synchronized o skBadni synchronized ( Wyra|enie ) Blok w której Wyra|enie musi by typu referencyjnego, a Blok jest instrukcj grupujc, objt nawiasami klamrowymi. Instrukcja synchronized przejmuje wzajemnie wykluczajc blokad na rzecz wykonywanego wtku, wykonuje Blok, po czym zwalnia blokad. Inaczej mówic, wykonanie instrukcji synchronized powoduje przydzielenie wtkowi podanego Bloku jako sekcji krytycznej, a po wykonaniu go na rzecz obiektu identyfikowanego przez Wyra|enie, zwolnienie sekcji. Ilustracj wykorzystania instrukcji synchronized mo|e by poni|szy prosty program: //plik TestSynchro Java 21 class TestSynchro { public static void main(String[] args) { TestSynchro t = new TestSynchro(); synchronized(t) { synchronized(t) { System.out.println("made it!"); }//end internal synchronized statement }//end external synchronized statement }//end main }//end TestSynchro który wydrukuje napis made it! Metoda jest synchronizowana je|eli w jej nagBówku umieszczono sBowo kluczowe synchronized. Synchronizowana metoda operujca na obiekcie pewnej klasy automatycznie nakBada blokad na ten obiekt przed wykonaniem jego ciaBa (funkcji, metod) i automatycznie zwalnia blokad przy powrocie, podobnie jak instrukcja synchronized. Tak wic segment kodu class Test { int count; synchronized void bump() { count++; } static int classCount; static synchronized void classBump() { classCount++; }//end synchronized method }//end class Test jest równowa|ny segmentowi class BumpTest { int count; void bump(){ synchronized (this){ count++; }//end synchronized statement }//end bump() static int classCount; static void classBump() { try { synchronized (Class.forName("BumpTest")) { classCount++; }// end synchronized statement }//end try catch (ClassNotFoundException e) { //... }//end catch }//end classBump }//end BumpTest Wymieniona  blokada (lock) jest w programie wielowtkowym zwizana z obiektem, na którym wtek ma wykonywa pewne operacje; jest ona czsto nazywana monitorem obiektu. Do czasu zwolnienia monitora, zostanie zablokowane wykonanie ka|dego innego wtku, który podejmie prób wywoBania (na rzecz tego samego obiektu), dowolnej metody sychronizowanej danej klasy. Zauwa|my, |e w klasie Test metoda classBump() jest statyczna (jest metod klasy). Zatem, mimo i| metoda ta jest synchronizowana, mo|e by jednocze[nie wywoBywana na rzecz wielu obiektów, a wic blokada nie bdzie efektywna. Dla uniknicia mo|liwo[ci jednoczesnego wykonywania pewnej operacji na tym samym obiekcie (w szczególno[ci zawierajcym metody statyczne) przez dwa ró|ne wtki dobr praktyk jest definiowanie klas tak, aby byBy przygotowane na u|ycie wspóBbie|ne, jak ilustruje to poni|szy kod: //plik Box.java 22 Jzyki obiektowe public class Box { private Object boxContents; public synchronized Object get() { Object contents = boxContents; boxContents = null; return contents; }//end get public synchronized boolean put(Object contents) { if (boxContents != null) return false; boxContents = contents; return true; }//end put } Ka|de wystpienie klasy Box ma pewn zawarto[ zmiennej wystpienia, która utrzymuje referencj do dowolnego obiektu. W rezultacie mo|na wBo|y obiekt do pudeBka (Box) wywoBaniem metody put(), która zwróci false je|eli pudeBko jest ju| peBne. Podobnie mo|na wyj obiekt z pudeBka wywoBaniem metody get(), która zwróci null je|eli pudeBko jest puste. Gdyby put() i get() nie byBy synchronizowane i dwa wtki wykonywaByby te metody na tym samym obiekcie klasy Box w tym samym czasie, wtedy wykonanie programu dwuwtkowego mogBoby przebiega w sposób przez nas nieoczekiwany. 1.10. Obiekty sieciowe Komputery w sieci Internet komunikuj si ze sob albo poprzez TCP (Transport Control Protocol) albo poprzez User Datagram Protocol (UDP). Uwaga. Nazw TCP okre[la si zwykle protokóB (zbiór zasad wedBug których odbywa si komunikacja w sieci komputerowej); TCP/IP (gdzie IP jest akronimem od Internet Protocol) jest warstwowym zestawem protokoBów i odpowiada siedmiowarstwowemu modelowi ISO/OSI (Open Systems Interconnection) z warstwami: fizyczn(1), Bcza danych(2), sieciow(3), transportow(4), sesji(5), prezentacji(6) i aplikacji(7). Np. ProtokóB IP jest implementacj warstwy (3), za[ TCP i UDP implementuj warstw (4) modelu ISO/OSI, jak pokazano w tabeli 1.1. Tabela 1.1 Zale|no[ pomidzy modelem ISO/OSI a TCP/IP Warstwa ISO/OSI TCP/IP 7 Aplikacji Aplikacji: SMTP, HTTP, FTP, RPC, TELNET, 6 Prezentacji RLOGIN, inne usBugi 5 Sesji DNS, LDAP 4 Transportowa Transportowa: TCP/UDP, IGMP 3 Sieciowa Midzysieciowa: IP, ICMP, protokoBy rutingu 2 Acza danych Interfejs sieciowy: ARP, RARP, LLC 802.2, Ethernet 802.3 1 Fizyczna Fizyczna dla ró|nych mediów Piszc program  sieciowy w jzyku Java nie musimy deklarowa, czy |damy komunikacji via TCP czy UDP, poniewa| zdefiniowane w pakiecie java.net klasy dostarczaj [rodki dla niezale|nej od systemu komunikacji w sieci; klasy URL, URLConnection, Socket i ServerSocket korzystaj z TCP, a klasy DatagramPacket, DatagramSocket i MulticastSocket korzystaj z UDP. Tym niemniej warto pamita, |e powszechnie u|ywane protokoBy: Telnet i wirtualnego terminala odpowiadaj warstwie 5 i cz[ciowo 6, za[ FTP (File Transfer Protocol) odpowiada warstwom 6 i 7 modelu ISO/OSI. Zauwa|my te|, |e HTTP (Hypertext Transfer Protocol), jest aplikacj (warstwa (7) modelu ISO/OSI. Gdy u|ywamy HTTP do czytania z pewnego lokalizatora URL (Uniform Resource Locator) danych z pliku w formacie HTML (HyperText Markup Language), otrzymywane dane musz wystpi w tej samej kolejno[ci, w której byBy przesyBane, co wymaga niezawodnego kanaBu komunikacji punkt-punkt, jaki zapewnia protokóB poBczeniowy TCP. Z kolei UDP, bezpoBczeniowy protokóB przesyBania niezale|nych pakietów danych (datagramów) pomidzy dwoma aplikacjami w Java 23 sieci, jest wystarczajcy dla takich aplikacji, jak np. program ping, czy te| programu podajcego aktualny czas. Komputery w sieci s identyfikowane przez 32-bitowe adresy IP, za[ biegnce na danym komputerze sieciowym procesy  poprzez 16-bitowe numery portów (port mo|na uwa|a za utrzymywan przez system kolejk danych, które maj by dostarczane do danego procesu wykonujcego pewien program). Na przykBad programowi wykorzystujcemu protokóB HTTP przydziela si zwyczajowo port o numerze 80. Programy odbieraj lub wysyBaj dane poprzez wizane z numerami portów gniazda (sockets). Gniazdo, definiowane przez warstw transportow modelu ISO/OSI, reprezentuje punkt koDcowy poBczenia pomidzy programami wykonywanymi na komputerach sieciowych w systemie dostawca- odbiorca (klient-server); jest to interfejs programowy umo|liwiajcy aplikacjom dostp do protokoBów TCP i UDP i wymian danych poprzez sie pracujc pod kontrol protokoBów TCP/IP. Program serwera wykonywany na konkretnej maszynie ma przypisane do pewnego numeru portu gniazdo, poprzez które  nasBuchuje ewentualnego |dania nawizania Bczno[ci przez klienta. Je|eli klient zna adres komputera sieciowego, na którym jest wykonywany serwer oraz numer portu, do którego serwer jest doBczony, to mo|e przesBa takie |danie. Serwer akceptuje poBczenie, a nastpnie tworzy dla klienta nowe gniazdo, zwizane z innym numerem portu, poniewa| na pierwotnym gniezdzie musi nadal prowadzi  nasBuch |daD poBczenia. Po stronie klienta, gdy uzyska potwierdzenie poBczenia, tworzone jest odpowiednie gniazdo (zwizane z lokalnym numerem portu na maszynie klienta), poprzez które mo|e prowadzi komunikacj z serwerem. W pakiecie java.net klasy Socket i ServerSocket sBu| do komunikacji w oparciu o protokóB poBczeniowy TCP, za[ klasy DatagramSocket, DatagramPacket oraz MulticastSocket s wykorzystywane do komunikacji UDP. Klasy: URL oraz URLConnection i URLEncoder sBu| do nawizania Bczno[ci z World Wide Web (WWW). Komunikacja, która wykorzystuje te klasy, reprezentuje wy|szy poziom abstrakcji, poniewa| korzystaj one midzy innymi z implementacji gniazd. Poni|ej pokazano przykBad aplikacji, która wykorzystuje klasy URL i URLConnection dla dostpu do zasobu sieciowego (pliku tekstowego  abc ) WWW zlokalizowanego pod adresem www.task.gda.pl/java/. //plik URLTest.java import java.net.*; import java.io.*; //import java.util.*; public class URLTest { public static void main(String[] args) { URL url; try { url = new URL("http://www.task.gda.pl/java/abc"); URLConnection uc = url.openConnection(); BufferedReader d = new BufferedReader(new InputStreamReader(uc.getInputStream())); //DataInputStream dis = new //DataInputStream(uc.getInputStream()); String line = d.readLine(); System.out.println(line); }//end try catch (Exception e) { e.printStackTrace(); } }// end main }// end URLTest W programie wykorzystano konstruktor URL(String). Klasa URL jest wyposa|ona w cztery publiczne konstruktory: public URL(String spec) throws MalformedURLException  tworzy obiekt URL z podanej reprezentacji obiektu klasy String, lub zgBasza wyjtek, je|eli BaDcuch  spec podaje nieznany protokóB. Dla danego protokoBu (http, file, ftp) jest przyjmowany domy[lny numer portu. Numer portu mo|na te| poda jawnie, np. http://www.task.gda.pl:80/java/abc. 24 Jzyki obiektowe public URL(URL context, String spec) throws MalformedURLException  tworzy obiekt URL przez parsing (wydzielenie) specyfikacji  spec w obrbie zadanego kontekstu. public URL(String protocol, String host, int port, String file) throws MalformedURLException  tworzy obiekt URL z podanego protokoBu, nazwy komputera, numeru portu i nazwy pliku. public URL(String protocol, String host, String file) throws MalformedURLException  tworzy absolutny obiekt URL z podanego protokoBu, nazwy komputera i nazwy pliku; przyjmuje port domy[lny dla danego protokoBu. 2. Aplety - programy Javy na stronach WWW. Aplet jest niewielkim programem Javy przeznaczonym do uruchamiania w obrbie innej aplikacji - przegldarki WWW lub Java Applet Viewer. Najprostszy aplet drukujcy jedno zdanie na ekranie mo|e mie nastpujc posta: HelloWorld.java import java.applet.*; import java.awt.*; public class HelloWorld extends Applet { public void init() { add(new Label("Hello World!")); } } Podobnie jak aplikacj, kompilujemy aplet poleceniem: javac HelloWorld.java w wyniku czego otrzymamy plik ze skompilowan klas o nazwie HelloWorld.class. Nastpnie tworzymy prost stron HTML zawierajc znacznik <applet> wywoBujcy aplet Javy i otwieramy t stron przegldark WWW. HelloWorld.html <html> <head> <title>HelloWorld</title> </head> <body> <h1>Aplet HelloWorld</h1> <applet code=HelloWorld.class width=200 height=50> </applet> </body> </html> Wynik dziaBania apletu mo|emy równie| obejrze u|ywajc przegldarki apletów dostarczanej przez Suna razem ze [rodowiskiem JDK: appletviewer HelloWorld.html Ka|dy aplet tworzony jest jako podklasa klasy java.applet.Applet, dostarczajcej interfejs do [rodowiska, w obrbie którego jest on uruchamiany. Java 25 java.lang.Object java.awt.Component java.awt.Container java.awt.Panel java.applet.Applet Rys. 2-1. Hierarchia dziedziczenia dla klasy Applet. W cyklu |ycia apletu wystpuj cztery istotne zdarzenia. Gdy one nastpuj, wywoBywane s odpowiednie metody klasy Applet, które mog by przesBonite przez metody zdefiniowane w jej podklasie, jak w poni|szym przykBadzie: public class MyApplet extends Applet { . . . public void init() { . . . } public void start() { . . . } public void stop() { . . . } public void destroy() { . . . } . . . } Metody te s wywoBywane przez [rodowisko, w którym uruchamiany jest aplet, w momentach wystpienia nastpujcych zdarzeD: init - po zaBadowaniu apletu (lub jego przeBadowaniu) w celu jego zainicjowania, start - w momencie uruchamiania apletu, po jego zaBadowaniu lub po ponownym odwiedzeniu strony zawierajcej aplet, stop - w momencie zatrzymywania pracy apletu, gdy opuszczana jest strona lub nastpuje wyj[cie z przegldarki, destroy - przed wyj[ciem z przegldarki. init start stop destroy Rys. 2-2. Cykl |ycia apletu. 26 Jzyki obiektowe Aplet nie musi przesBania wszystkich z tych metod, mo|e tylko niektóre albo |adnej. W metodzie init powinno si zamieszcza kod, który normalnie powinien by zawarty w konstruktorze klasy. Jednak w momencie wykonywania konstruktora klasy apletu nie ma gwarancji, |e jest ju| zdefiniowane caBe jego [rodowisko. Dlatego takie zadania jak na przykBad utworzenie wtków apletu czy jednokrotne zaBadowanie obrazów wykorzystywanych przez aplet powinny by zawarte wBa[nie w metodzie init. W metodach start i stop mo|na na przykBad odpowiednio uruchamia i zatrzymywa animacj tak, |eby w czasie gdy u|ytkownik nie oglda strony z apletem niepotrzebnie nie zu|ywa zasobów komputera. Aplet dziedziczy metody interfejsu u|ytkownika z nadrzdnych klas AWT (Abstract Window Toolkit) Component, Container i Panel. Z klasy Component dziedziczy metody paint i update, które odpowiadaj za graficzn reprezentacj apletu na stronie przegldarki. Metody te aplet mo|e przesBoni: class MyApplet extends Applet { . . . public void paint(Graphics g) { . . . } . . . } Aplet jest podklas klasy Container, mo|e wic zawiera inne obiekty klasy Component, takie jak klawisze, etykiety, listy wyboru itd. Jak w innych obiektach klasy Container wzajemne rozBo|enie komponentów kontrolowane jest poprzez klas LayoutManager. Z klasy Component aplet dziedziczy równie| metody obsBugi zdarzeD. Zdarzenia s generowane gBównie przez komponenty interfejsu graficznego u|ytkownika. Komponenty bdce zródBem zdarzeD rejestruj jedn lub wicej klas delegowanych do obsBugi zdarzenia: someComponent.addActionListener(instanceOfMyClass); W deklaracji klasy obsBugujcej zadarzenie specyfikujemy, |e implementuje ona przynajmniej jeden z interfejsów pochodnych od EventListner (np. ActionListner, MouseListner, KeyListner, WindowListner itd.): public class MyClass implements ActionListener { a w jej definicji implementujemy metod obsBugujc zdarzenie: public void actionPerformed(ActionEvent e) { ... // kod reagujcy na zdarzenie typu ActionEvent } Ka|de zródBo zdarzeD mo|e mie wiele klas delegowanych do jego obsBugi. Jedna klasa mo|e te| obsBugiwa wiele ró|nych zródeB zdarzeD. Aplety s uruchamiane w [rodowisku przegldarki, która narzuca im pewne ograniczenia zwizane z zachowaniem bezpieczeDstwa. Ró|ni si one nieco pomidzy ró|nymi przegldarkami. Aplet [cignity do przegldarki poprzez sie: " nie mo|e czyta i pisa do plików znajdujcych si na komputerze, który go wykonuje, " nie mo|e tworzy poBczeD sieciowych do komputerów innych ni| ten, z którego zostaB [cignity, " nie mo|e uruchamia |adnych programów na komputerze, który go wykonuje, " mo|e czyta tylko wybrane parametry systemowe, " nie mo|e Badowa bibliotek ani definiowa metod w kodzie maszynowym. Ograniczeniem (cho nie zwizanym z bezpieczeDstwem) jest równie| graficzny interfejs u|ytkownika apletu. Aplet mo|e przedstawia swoj reprezentacj graficzn tylko w obrbie prostokta na stronie WWW o z góry zadanych wymiarach, bdz w postaci generowanych okienek, które ró|ni si od tych generowanych przez aplikacje. Pliki skBadajce si na aplet: klasy, pliki z grafikami, dzwikami i inne pliki pomocnicze mog by poBczone w jeden plik o formacie Java Archive (JAR), co pozwala uzyska wiele korzy[ci: " bezpieczeDstwo - zawarto[ pliku JAR mo|na podpisa cyfrowo; dziki temu mog by zBagodzone niektóre z wcze[niej wymienionych ograniczeD zwizane z dostpem do lokalnych zasobów dyskowych oraz z peBnym dostpem do sieci, Java 27 " skrócenie czasu Badowania - caBy aplet mo|e [cignity przez przegldark w jednej transakcji HTTP bez konieczno[ci otwierania nowego poBczenia dla ka|dego pliku, " kompresja - pliki s kompresowane zgodnie z formatem ZIP. Do obsBugi plików JAR sBu|y standardowe narzdzie jar zawarte w pakiecie JDK. Sposób jego u|ycia jest analogiczny do programu tar z systemu Unix. Operacja Polecenie jar cf jar-file input-file(s) Tworzenie pliku JAR jar tf jar-file Ogldanie zawarto[ci pliku JAR jar xf jar-file Rozpakowywanie pliku JAR Uruchamianie apletu spakowanego w postaci <applet code=AppletClassName.class pliku JAR archive="JarFileName.jar" width=width height=height> </applet> Uwaga. Internet Explorer u|ywa wBasnego standardu kompresji - CAB. Netscape Communicator obsBuguje format JAR.. Znacznik <applet> na stronie HTML mo|e mie wicej parametrów ni| podane wcze[niej w prostym przykBadzie. Bardziej zBo|one wywoBanie mo|e mie nastpujc posta: <applet code=AppletSubclass.class codebase= directory/ width=anInt height=anInt align=left> <param name=parameter1Name value=aValue> <param name=parameter2Name value=anotherValue> Wymagana jest przegldarka obsBugujca aplety Javy! </applet> Domy[lnie przegldarka szuka klas apletu oraz plików skompresowanych w tym samym katalogu, z którego zostaB [cignity plik HTML zawierajcy znacznik <applet>. Mo|na jednak wskaza inne miejsce podajc parametr codebase. Warto[ci parametru mo|e by [cie|ka wzgldna wobec strony HTML, [cie|ka bezwzgldna lub w ogólno[ci dowolny URL. Klasy apletu mog wic by [cigane z innego serwera ni| strona HTML. Opcje width i height okre[laj rozmiary prostokta na stronie przegldarki, w obrbie którego wizualizowany jest aplet. Opcja align okre[la poBo|enie apletu, podobnie jak dla znacznika <img>: left, right, top, texttop, middle, absmiddle, baseline, bottom, absbottom. Do apletu mo|na przekazywa parametry definiujc znaczniki <param> w obrbie znacznika <applet>. Warto[ci tych parametrów mo|na nastpnie odczytywa w kodzie apletu wywoBujc metod klasy Applet public String getParameter(String name) Opcjonalny tekst w obrbie znacznika <applet> jest pisany w okienku przegldarki, gdy ta nie potrafi obsBugiwa Javy lub obsBuga zostaBa wyBczona. Kod apletu wykonywany jest przez maszyn wirtualn Javy zaimplementowan w przegldarce. Jednym ze staBych niedomagaD tego modelu dystrybucji kodu jest to, |e wersje Javy wspierane przez przegldarki nie nad|aj za najnowszymi wersjami wprowadzanymi przez firm Sun. Aby cz[ciowo rozwiza ten problem Sun opracowaB moduB rozszerzajcy (ang. plug-in) przegldarki (obecnie tylko dla Netscape Navigator i Internet Explorer pod Windows), który zapewnia wykorzystanie najnowszej wersji bibliotek jzyka Java. Na skutek niejednolitego sposobu wywoBania takiego moduBu ze strony HTML i jego zBo|onej postaci najwygodniej jest skorzysta z programu HTMLConverter, który zamienia wystpienia zanacznika <applet> na odpowiadajcy mu kod wywoBujcy moduB rozszerzajcy Javy. 28 Jzyki obiektowe 3. Standardowe klasy Javy. W skBad JDK 1.2 wchodz nastpujce pakiety: java.applet, java.awt, java.beans, java.io, java.lang, java.math, java.net, java.rmi, java.security, java.sql, java.text, java.util, javax.accessibility, javax.swing, org.omg. Zostan one omówione pokrótce, najpierw te najcz[ciej wykorzystywane. W pakiecie java.lang zdefiniowana jest klasa Object, która jest klas nadrzdn wobec wszystkich innych klas Javy. Pakiet zawiera tak|e klasy opakowujce (kopertowe) zmienne podstawowych typów jzyka Java takie jak Boolean, Byte, Integer, Long, Double, Character itd., definiujc u|yteczne metody operujce na zmiennych tych typów, metody konwersji pomidzy typami, zamian na BaDcuchy znaków i inne. Klasa Math zawiera metody wykonujce podstawowe operacje numeryczne takie jak funkcje eksponencjalne, logarytmiczne, trygonometryczne. W pakiecie java.lang zawarte s dwie klasy obsBugujce BaDcuchy znaków: String i StringBuffer. Klasa String u|ywana jest do przechowywania i wykonywania operacji na staBych BaDcuchach; po utworzeniu obiektu tej klasy nie mo|na zmieni jego warto[ci. Klasa ta zawiera metody do sprawdzania poszczególnych znaków, porównywania BaDcuchów, wyodrbniania podBaDcuchów, tworzenia kopii z zamian na maBe albo du|e litery. Klasa StringBuffer implementuje BaDcuchy znaków, które mog by zmieniane. Podstawowe metody tej klasy to append dodajca znaki na koDcu bufora i insert wstawiajca znaki w okre[lonym miejscu. Ka|dy obiekt przydziela bufor na przechowywany BaDcuch znaków. Je|eli caBkowita dBugo[ BaDcucha wzro[nie powy|ej rozmiaru bufora, automatycznie przydzielany jest wikszy. Dostp do zasobów systemowych mo|na uzyska poprzez niezale|ne od systemu API zdefiniowane w finalnej klasie System oraz zale|ne od systemu API zawarte w Runtime. Mo|na uzyska dostp do parametrów systemowych, standardowych strumieni: wyj[ciowego, wej[ciowego i bBdów, metod Badowania bibliotek, odczytu czasu komputera, szybkiego kopiowania tablic itd. Klasa Thread definiuje wtki programu Javy pozwalajce na jego wspóBbie|n prac. Pakiet java.io definiuje klasy implementujce operacje wej[cia-wyj[cia. W pakiecie tym (jak równie| i w innych) wystpuj klasy i metody pochodzce z JDK 1.0 równolegle z nowymi klasami wprowadzonymi wraz z wej[ciem JDK 1.1. Pozostawiono stare klasy w celu zapewnienia zgodno[ci dla dawniej pisanych programów. Czsto przestarzaBe (deprecated) konstrukcje s odradzane i proponowane s ich udoskonalone odpowiedniki. Podstawowymi klasami pozwalajcymi czyta i pisa z plików, BaDcuchów znaków i innych strumieni, s: Reader wraz z podklasami BufferedReader, CharArrayReader, InputStreamReader, FileReader, StringReader oraz Writer wraz z podklasami BufferedWriter, CharArrayWriter, OutputStreamWriter, FileWriter, PrintWriter, StringWriter. Ich starsze odpowiedniki to InputStream i OutputStream wraz z ich podklasami. StrumieD wej[ciowy znaków mo|e by dzielony na jednostki logiczne - tokeny, poprzez skonstruowanie na nim obiektu klasy StreamTokenizer. Mo|na zdefiniowa skBadni, wedBug której wyró|niane bd tokeny typu sBowo, liczba, znaczniki koDca linii i pliku oraz pomijane komentarze. Zdefiniowane s równie| klasy wspierajce obsBug struktury drzewa plików w systemie - File oraz czytanie i pisanie do plików o dostpie swobodnym - RandomAccessFile. W pakiecie java.util mo|na znalez m.in. szereg klas definiujcych ró|ne struktury danych przechowujce inne obiekty. Klasa Vector implementuje tablic obiektów, która mo|e rosn lub zmniejsza si w miar jak obiekty s dodawane lub usuwane. Tak jak w zwykBej tablicy dostp do jej elementów mo|e odbywa si poprzez caBkowity indeks, mo|na równie| szuka wystpienia obiektu w wektorze, którego warto[ jest równa podanemu. Wszystkie elementy wektora najwygodniej jest przeglda wykorzystujc interfejs Enumeration: Java 29 Vector v; for(Enumeration e = v.elements(); e.hasMoreElements() ;) System.out.println(e.nextElement()); Ka|dy wektor stara si optymalizowa zarzdzanie rozmiarem zajmowanej pamici. Gdy wektor zajmuje caB przydzielon pami, przed dodaniem kolejnego elementu jego rozmiar jest automatycznie zwikszany o warto[ capacityIncrement. Program mo|e jednak sam zwikszy rozmiar wektora przed wstawieniem du|ej porcji danych, aby unikn wielu realokacji. Podklas klasy Vector jest Stack realizujcy kolejk LIFO obiektów z metodami push i pop. Klasa Dictionary jest abstrakcyjnym rodzicem dowolnej klasy implementujcej odwzorowanie kluczy na warto[ci. Jej podklas jest Hashtable, której konstrukor posiada dwa parametry initialCapacity i loadFactor. Gdy liczba elementów w tablicy mieszajcej (hash table) osiga warto[ iloczynu tych parametrów, rozmiar tablicy jest automatycznie zwikszany i przeliczane s pozycje elementów. Wikszy wspóBczynnik wypeBnienia pozwala oszczdniej gospodarowa pamici kosztem dBu|szego czasu potrzebnego do wyszukiwania elementów. Efektywniej jest równie| zawczasu przydzieli odpowiedniej wielko[ci tablic, ni| potem zda si na automatyczne przeBadowywania. Poni|ej przedstawiono przykBad tablicy mieszajcej obiektów typu Integer posiadajcych nazwy jako klucze: Hashtable numbers = new Hashtable(); numbers.put("one", new Integer(1)); numbers.put("two", new Integer(2)); numbers.put("three", new Integer(3)); Aby wydoby element z tablicy mo|na posBu|y si nastpujcym kodem: Integer n = (Integer)numbers.get("two"); if(n != null) System.out.println("two = " + n); Obiekty przechowywane w tablicy mieszajcej musz implementowa metody hashCode i equals dziedziczone z klasy java.lang.Object. Przy u|yciu klasy BitSet mo|na tworzy zbiory bitów i wykonywa na nich operacje logiczne. Klasa StringTokenizer pozwalajca dzieli BaDcuchy znaków na tokeny jest znacznie prostsza w u|yciu ni| klasa java.io.StreamTokenizer. Okre[la si w niej tylko jakie znaki rozdzielaj kolejne tokeny, domy[lnie s to znaki z BaDcucha  \t\n\r , na przykBad: StringTokenizer st = new StringTokenizer("To jest tylko test"); while (st.hasMoreTokens()) System.out.println(st.nextToken()); Mo|na równie| znalez klasy obsBugujce daty - Date i Calendar, ustawiajce parametry specyficzne dla kraju, regionu lub jzyka - Locale, TimeZone. W pakiecie java.util.zip znajduj si klasy pozwalajce tworzy i czyta pliki skompresowane w formatach ZIP i GZIP. Pakiet java.net zawiera klasy realizujce poBczenia sieciowe zarówno na poziomie gniazd, jak i adresów URL wskazujcych zasoby w WWW. Podstawowe klasy to Socket, URL, URLConection. Poni|szy przykBad pokazuje jak z apletu mo|na w prosty sposób przej[ do wybranej strony WWW: try { URL task = new URL("http://www.task.gda.pl/"); getAppletContext().showDocument(task); 30 Jzyki obiektowe } catch (MalformedURLException e) {} // new URL() failed Aplety i aplikacje Javy komunikuj si z u|ytkownikiem wykorzystujc klasy z pakietu java.awt skBadajce si na graficzny interfejs u|ytkownika AWT (Abstract Window Toolkit). AWT dostarcza typowe komponenty graficzne takie, jak klawisze, pola do wprowadzania tekstu, listy wyboru itd. poprzez klasy Button, Checkbox, Choice, Label, List, Menu, Scrollbar, TextArea, TextField bdce pochodnymi klasy Component. Wykorzystujc klas Canvas, mo|na rysowa dowolne obrazy graficzne na ekranie, a po dodaniu odpowiedniej obsBugi zdarzeD mo|na zdefiniowa dowolny wBasny komponent. Wraz z JDK 1.1 zostaB wprowadzony nowy model obsBugi zdarzeD, który jest znacznie bardziej elastyczny i wydajny w porównaniu z modelem z JDK 1.0. Stary model dla zachowania zgodno[ci jest równie| obsBugiwany, cho jego u|ycie jest odradzane. W modelu 1.1 AWT zdarzenia s generowane przez zródBa, którymi mog by komponenty interfejsu u|ytkownika, myszka, klawiatura itd. Mo|e by wydelegowany jeden lub wicej odbiorców zdarzenia pochodzcego od okre[lonego zródBa, który jest obiektem dowolnej klasy implementujcej przynajmniej jeden z interfejsów obsBugi zdarzeD takich, jak ActionListener, KeyListener czy MouseListener. Zasad dziaBania tego modelu mo|na prze[ledzi w poni|szym przykBadzie: import java.applet.*; import java.awt.*; import java.awt.event.*; public class URLButton extends Applet implements ActionListener { public void init() { Button button = new Button("TASK Home"); add(button); button.addActionListener(this); } public void actionPerformed(ActionEvent event) { . . . } } W skBad JDK 1.2 zostaB wBczony pakiet javax.swing nazywany równie| Java Foundation Classes (JFC), znacznie rozszerzajcy mo|liwo[ci funkcjonalne interfejsu graficznego u|ytkownika. Pakiet ten zawiera znacznie wicej komponentów graficznych, pozwala dynamicznie imitowa znane [rodowiska graficzne (np. Windows, CDE/Motif), umo|liwia korzystanie z urzdzeD pomocniczych w odczytywaniu informacji (jak np. czytniki ekranu, wy[wietlacze Braille a), zawiera bogat bibliotek do tworzenia dwuwymiarowej grafiki, wspomaga technik  przecignij i upu[ pomidzy aplikacjami Javy i aplikacjami w danym systemie operacyjnym. Zastosowanie klas Applet i AppletContext z pakietu java.applet byBo ju| demonstrowane we wcze[niejszych przykBadach. Definiuj one [rodowisko, w którym uruchamiane s aplety. Pozwalaj równie| na komunikacj pomidzy apletami znajdujcymi si na tej samej stronie. Zrodowisko budowania niezale|nych od platformy, modyfikowalnych wizualnych komponentów JavaBeans API zawarte jest w pakiecie java.beans. Wykorzystujc przeznaczone do tego narzdzia programistyczne, mo|na wizualnie z komponentów konstruowa aplikacje, aplety, servlety lub komponenty zBo|one. Narzdzie tego typu pozwala wybra z zestawu potrzebny nam komponent, wstawi go do okienka programu, zmodyfikowa jego wygld i zachowanie, zdefiniowa interakcj z innymi komponentami; wszystko to nie piszc ani jednej linii kodu. JDBC API (Java DataBase Conectivity) zdefiniowane w pakiecie java.sql wprowadza jednolity standard dostpu do dowolnych relacyjnych baz danych. Klasy z tego pakietu implementuj poBczenia z baz danych, zapytania SQL, wyniki tych zapytaD itp. Dostp do bazy odbywa si za Java 31 po[rednictwem drivera, który mo|e by napisany caBkowicie w Javie i wtedy mo|e by np. [cignity jako cz[ apletu, mo|e by te| napisany z wykorzystaniem kodu maszynowego okre[lonej platformy, aby uzyska dostp do istniejcych ju| bibliotek dostpu do baz danych. Drivery JDBC mo|na podzieli na cztery kategorie: 1. Pomost JDBC-ODBC, który zapewnia dostp do bazy poprzez binarne drivery ODBC. 2. Driver w Javie zamieniajcy odwoBania JDBC na odwoBania do binarnego drivera dostpowego konkretnej bazy danych znajdujcego si na lokalnym komputerze. 3. CaBkowicie w Javie napisany driver komunikujcy si poprzez sie z oprogramowaniem po[redniczcym w dostpie do bazy (middleware). ProtokóB dostpowy zale|y od producenta tego oprogramowania, producent ten jest te| najcz[ciej dostawc odpowiedniego drivera JDBC. 4. CaBkowicie w Javie napisany driver komunikujcy si poprzez sie bezpo[rednio z serwerem bazy danych. Dostawc drivera czsto jest producent bazy danych. RMI (Remote Method Invocation) zawarty w java.rmi umo|liwia tworzenie rozproszonych aplikacji w Javie. Aplikacja taka zBo|ona jest z serwera, tworzcego obiekty, których metody mog by wywoBywane zdalnie; po utworzeniu obiektów aplikacja udostpnia odno[niki do nich i czeka na wywoBania ich metod przez klientów; klient [ciga odno[niki do zdalnych obiektów i wywoBuje ich metody. RMI zapewnia mechanizm, poprzez który odbywa si komunikacja pomidzy serwerem i klientem oraz przesyBane s dane w obie strony. W pakietach org.omg Javy 1.2 wsparto powszechnie przyjty standard modelu rozproszonych obiektów  CORBA (Common Object Request Brokerage Architecture). Pozwala on na komunikacj pomidzy obiektami bez wzgldu na platform systemu operacyjnego, ani u|yty jzyka programowania. W pakiecie java.math znajduj si klasy BigInteger i BigDecimal pozwalajce na tworzenie i operacje na liczbach caBkowitych dowolnej precyzji. BigInteger implementuje operacje arytmetyki modularnej, obliczanie najwikszego wspólnego podzielnika, generator liczb pierwszych, operacje na bitach itd. Z liczb zdefiniowanych w tej klasie korzysta pakiet java.security wprowadzajcy jednolity model kryptografii i ochrony danych. Znajduj si tam abstrakcyjne klasy definiujce kody zapewniajce integralno[ danych (message digests) oparte na jednokierunkowych funkcjach mieszajcych (one-way hash functions), podpisy cyfrowe oparte na parze kluczy jawnego i tajnego, zarzdzanie kluczami i certyfikaty. Jest to tylko ramowy szkielet koncepcji kryptograficznych, pod który producenci oprogramowania mog podBcza konkretne algorytmy i metody. Razem z JDK Sun dostarcza jedynie klasy do cyfrowego podpisywania dokumentów opartego na algorytmie DSA oraz obliczania kodów dokumentów metodami MD5 i SHA-1. W pakiecie java.text znajdziemy klasy obsBugujce ró|ne formaty danych tekstowych, np. DateFormat obsBugujcy daty w ró|nych standardach czy NumberFormat tworzcy i analizujcy ró|ne formaty liczb. 4. Servlety - programy Javy na serwerze WWW. Servlety s moduBami, które s uruchamiane wewntrz serwerów przetwarzajcych zapytania i generujcych odpowiedzi, takich jak np. rozszerzone o obsBug Javy serwery WWW. Rozszerzaj one funkcjonalno[ tych serwerów. Mo|na w uproszczeniu powiedzie, |e servlety dla serwerów s tym, czym aplety dla przegldarek. Servlety stanowi alternatyw dla skryptów CGI, umo|liwiajc Batw metod dynamicznego tworzenia dokumentów HTML. S one Batwiejsze do pisania dziki wykorzystaniu [rodowiska Javy. S równie| szybciej wykonywane, gdy| wywoBanie servletu odbywa si nie poprzez uruchomienie nowego procesu, co jest kosztowne ze wzgldu na czas procesora i zasoby pamiciowe, lecz jako wtek. Co wicej, kod wykonywalny dla servletu jest Badowany do serwera tylko raz, gdy po raz pierwszy |dana jest usBuga oferowana przez dany servlet lub automatycznie, gdy zostanie zmieniony kod servleta. Potem servlet pozostaje w pamici serwera i mo|e równolegle obsBugiwa wiele zapytaD z mo|liwo[ci komunikacji pomidzy nimi. 32 Jzyki obiektowe Klasy implementujce funkcje servletów znajduj si w pakiecie javax.servlet dostpnego z firmy Sun jako Java Servlet Development Kit. Zawieraj one abstrakcyjn klas GenericServlet oraz interfejs Servlet, które definiuj podstawowe wBasno[ci ogólnych servletów, czyli moduBów przetwarzajcych zapytania i generujcych odpowiedzi. Jednak najcz[ciej korzysta si z podklas znajdujcych si w pakiecie javax.servlet.http definiujcych servlety HTTP. Klasa HttpServlet posiada m.in. takie metody jak doGet i doPost obsBugujce typowe zapytania CGI, czy uniwersaln metod service obsBugujc wszystkie rodzaje zapytaD. Najprostszy servlet mo|e wyglda nastpujco: HelloWorldServlet.java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class HelloWorldServlet extends HttpServlet { public void doGet (HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); ServletOutputStream out = res.getOutputStream(); out.println("<html>"); out.println("<head><title>Hello World</title></head>"); out.println("<body>"); out.println("<h1>Hello World</h1>"); out.println("</body></html>"); } } Wikszo[ u|ytecznych servletów czyta parametry wej[ciowe przekazane im z przegldarki poprzez metody GET lub POST i na ich podstawie tworzy odpowiedni dokument HTML. Prosty przykBad takiego servletu przedstawiono poni|ej. Hello.java import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Hello extends HttpServlet { public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { res.setContentType("text/html"); PrintWriter toClient = res.getWriter(); toClient.println("<html><head>"); toClient.println("<title>Hello</title>"); toClient.println("</head>"); toClient.println("<h1>Hello " + req.getParameterValues("name")[0] + "!</h1>"); toClient.println("</body></html>"); toClient.close(); } } Powy|szy servlet mo|na wywoBa na kilka sposobów. Mo|na poda w przegldarce URL Java 33 http://www.task.gda.pl/servlet/Hello?name=Darek i wywoBa servlet przekazujc parametry metod GET. Mo|na na stronie HTML umie[ci formularz: <form action=http://www.task.gda.pl/servlet/Hello method=POST> Podaj swoje imi: <input type=text name=name> <input type=submit value=Wy[lij> </form> i wywoBa servlet przekazujc parametry metod POST. Mo|na równie| wykorzysta znacznik <servlet> na stronie HTML zapisanej w pliku z rozszerzeniem shtml. Hello.shtml ... <servlet code=Hello> <param name=name value=Darek> </servlet> ... Wtedy serwer WWW rozszerzony o funkcjonalno[ servletów zastpi na stronie HTML powy|szy znacznik wynikiem generowanym przez servlet Hello i tak przetworzon stron prze[le do przegldarki. Dostpnych jest ju| wiele serwerów WWW obsBugujcych servlety Javy. PrzykBadami mog by Java Web Server firmy Sun lub darmowy dla celów niekomercyjnych JRun firmy Live Software. Ten ostatni mo|e pracowa jako samodzielny serwer WWW, bdz jako moduB rozszerzajcy funkcjonalno[ innych znanych serwerów WWW np. Apache, Microsoft IIS, Netscape. 5. Podsumowanie Zalety jzyka Java: "  o|ywienie WWW - swego rodzaju  lingua franca Internetu " jzyk pozwala Batwo pisa aplikacje sieciowe " przeno[no[ - niezale|no[ od platformy dziki JVM; Java poprzez swój B-kod staje si najbli|sz aproksymacj (zbudowan raczaej z software ni| z hardware, chocia| anonsowane s ju|  Java chips ) jednego z najstarszych marzeD przemysBu komputerowego: prawdziwie uniwersalna maszyna wirtualna " prawie czysta implementacja paradygmatu obiektowego " usunicie arbitralnego pojcia wskaznika jak w C++ " wsparcie dla zbierania nieu|ytków " brak samodzielnych (tj. definiowanych poza klasami) funkcji zewntrznych " weryfikacja kodu w fazie kompilacji i w fazie wykonania na zgodno[ ze standardem jzyka " dynamiczne Badowanie klas (w locie) " biblioteki klas dla GUI, sieciowe i WWW Wady: " Brak definiowanych przez u|ytkownika przeci|onych operatorów " zBamanie zasad obiektowo[ci w standardowych bibliotekach klas: w klasach opakowaD (kopertowych), w klasach kolekcji i w klasach BaDcuchów " Komunikaty s rzadko polimorficzne i rzadko trafiaj na oczekiwan struktur dziedziczenia " brak klas parametryzowanych (genericity, templates) " dziedziczenie tylko pojedyncze " usunicie instrukcji assert znanej w C i C++ 34 Jzyki obiektowe " pogmatwana (zawikBana) struktura modularna z trzema wpBywajcymi wzajemnie na siebie koncepcjami (klasy, pakiety zagnie|d|one, pliki zródBowe). 6. Bibliografia [1] Cargill T. An Overview of Java for C++ Programmers. C++ Report, vo. 8/No. 2, pp. 46-49, 1996. [2] Lorenz M. Java as an Object-Oriented Language. SIGS Books & Multimedia, New York 1996. [3] Martin R. C++ and Java: A Critical Comparison. C++ Report, vo. 9/No. 1, pp. 42-49, 1997. [4] Jain P. and Schmidt D.C. Experiences Converting a C++ Communication Software Framework to Java. C++ Report, vo. 9/No. 1, pp. 51-66, 1997. [5] Gosling J., Joy B, Steele G. The Java Language Specification. Addison-Wesley, 1996, http://java.sun.com/docs/books/jls/. [6] The Java Tutorial. http://java.sun.com/docs/books/tutorial/, 1998. [7] JDK1.2 Documentation. http://java.sun.com/products/jdk/1.2/docs/, 1998. [8] Servlet Tutorial. http://www.task.gda.pl/java/ServletTutorial.html, 1998. 7. Programy - wiczenia 1. Plik Squares.java class Squares { /** Print out the squares of integers from 1 to 10 */ public static void main(String[] args) { int x = 1; System.out.println("Squares of integers from 1 to 10:"); while (x <= 10) { System.out.println(x * x); // print x squared x = x + 1; // add 1 to x } // end while } // end main } // end Squares 2. Plik StringDemo.java class StringsDemo { static public void main(String[] args) { String myName = "Archibald"; myName = myName + " Tuttle"; System.out.println("Name = " + myName); } } 3. Plik Child1.java class Parent { //accessible within package static int i = 10; //accessible within package public static void fp() { System.out.println("fp of Parent class"); } //end fp } //end Parent Java 35 public class Child1 extends Parent { private static String st = "I am Child1"; public static void main(String args[]) { fp();//call class function; same result as Parent.fp();//Only class name; same result as System.out.println(Parent.i); System.out.println(st); // super.fp(); // Doesn't work. Why? }//end main }//end Child1 4. Plik Inherit1.java class GrandFather { private int i = 10; void fp() { System.out.print("fp of Parent class\n"+"i= "+i); }//end fp }//end GrandFather class Father extends GrandFather { }//end Father class GrandSon extends Father { String st = "I am a grandson"; } // end GrandSon public class Inherit1 { public static void main(String args[]) { GrandSon gs = new GrandSon(); gs.fp(); System.out.println("\n"); if(gs instanceof GrandSon) System.out.println(gs.st); }//end main }//end Inherit1 5. Plik Inherit2.java class Parent { private int i = 10; void fp() { System.out.print("fp of Parent class\n"+"i= "+i); }//end fp }//end Parent class Descendant extends Parent { public void fp() { System.out.println("fp of Descendant class"); } //end fp public void fd() 36 Jzyki obiektowe { super.fp(); //call to Parent's fp } // end fd } // end Descendant public class Inherit2 { public static void main(String args[]) { Descendant ds = new Descendant(); ds.fp(); ds.fd(); }//end main }//end Inherit2 6. Plik Inherit3.java class Parent { private int i = 10; void fp() { System.out.print("fp of Parent class\n"+"i= "+i); }//end fp }//end Parent class Descendant extends Parent { public void fp() { System.out.println("fp of Descendant class"); } //end fp public void fd() { super.fp(); //call to Parent's fp } // end fd } // end Descendant class Kin extends Descendant { public void fp() { System.out.println("fp of Kin class"); } //end fp public void fk() { super.fd(); // call to Descendant's fp } // end fk } // end Kin public class Inherit3 { public static void main(String args[]) { Kin kn = new Kin(); kn.fp(); kn.fk(); }//end main }//end Inherit2 7. Plik PascalTriangle.java Java 37 import java.io.*; public class PascalTriangle { private int data[][]; /** Create a Pascal's triangle to specified depth. */ public PascalTriangle(int rows) { data = new int[rows][]; for (int row = 0; row < rows; row++) { data[row] = new int[row + 1]; if (row == 0) data[row][0] = 1; else for (int col = 0; col <= row; col++) { data[row][col] = 0; // if not on right edge, add node up and right if (col < row) data[row][col] += data[row - 1][col]; // if not on left edge, add node up and left if (col > 0) data[row][col] += data[row - 1][col - 1]; } } } /** Print this Pascal's triangle to given stream. */ public void print(PrintStream ps) { for (int i = 0; i < data.length; i++) { int[] row = data[i]; for (int j = 0; j < row.length; j++) ps.print(row[j] + " "); ps.println(); } } /** Create a Pascal's triangle of depth 12 and print it. */ public static void main(String[] args) { PascalTriangle pt = new PascalTriangle(12); pt.print(System.out); } } 8. Plik EasyIn.java // Simple input from the keyboard for all primitive types. ver 1.0 // Not thread safe, not high performance, and doesn't tell EOF. // It's intended for low-volume easy keyboard input. // An example of use is: // EasyIn easy = new EasyIn(); // int i = easy.readInt(); // reads an int from System.in // float f = easy.readFloat(); // reads a float from System.in import java.io.*; import java.util.*; 38 Jzyki obiektowe class EasyIn { static InputStreamReader is = new InputStreamReader( System.in ); static BufferedReader br = new BufferedReader( is ); StringTokenizer st; StringTokenizer getToken() throws IOException { String s = br.readLine(); return new StringTokenizer(s); } boolean readBoolean() { try { st = getToken(); return new Boolean(st.nextToken()).booleanValue(); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readBoolean"); return false; } } byte readByte() { try { st = getToken(); return Byte.parseByte(st.nextToken()); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readByte"); return 0; } } short readShort() { try { st = getToken(); return Short.parseShort(st.nextToken()); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readShort"); return 0; } } int readInt() { try { st = getToken(); return Integer.parseInt(st.nextToken()); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readInt"); return 0; } } long readLong() { try { st = getToken(); return Long.parseLong(st.nextToken()); } catch (IOException ioe) { Java 39 System.err.println("IO Exception in EasyIn.readLong"); return 0L; } } float readFloat() { try { st = getToken(); return new Float(st.nextToken()).floatValue(); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readFloat"); return 0.0F; } } double readDouble() { try { st = getToken(); return new Double(st.nextToken()).doubleValue(); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readDouble"); return 0.0; } } char readChar() { try { String s = br.readLine(); return s.charAt(0); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readChar"); return 0; } } String readString() { try { return br.readLine(); } catch (IOException ioe) { System.err.println("IO Exception in EasyIn.readString"); return ""; } } // This method is just here to test the class public static void main (String args[]){ EasyIn easy = new EasyIn(); System.out.print("enter char: "); System.out.flush(); System.out.println("You entered: " + easy.readChar() ); System.out.print("enter String: "); System.out.flush(); System.out.println("You entered: " + easy.readString() ); System.out.print("enter boolean: "); System.out.flush(); 40 Jzyki obiektowe System.out.println("You entered: " + easy.readBoolean() ); System.out.print("enter byte: "); System.out.flush(); System.out.println("You entered: " + easy.readByte() ); System.out.print("enter short: "); System.out.flush(); System.out.println("You entered: " + easy.readShort() ); System.out.print("enter int: "); System.out.flush(); System.out.println("You entered: " + easy.readInt() ); System.out.print("enter long: "); System.out.flush(); System.out.println("You entered: " + easy.readLong() ); System.out.print("enter float: "); System.out.flush(); System.out.println("You entered: " + easy.readFloat() ); System.out.print("enter double: "); System.out.flush(); System.out.println("You entered: " + easy.readDouble() ); } } 9. Plik Heritage.java /**Program krotko demonstruje mechanizm korzystania z interfejsow*/ /**Glowna klasa programu, tworzy pozostale*/ public class Heritage { public static void main (String[] args) { /*tworzymy obiekty i wywolujemy odpowiednie metody*/ Client our_client = new Client(); our_client.startingReport(); Server our_server= new Server (our_client); our_server.execute(5); } } /**Klasa klienta implementuje interfejs Message*/ class Client implements Message { int counter=0; /**zeruje licznik i wyswietla komunikat poczatkowy*/ public void startingReport() { counter=0; System.out.println ("To jest raport poczatkowy klienta"); System.out.println ("Counter="+counter); } /**Zwieksza licznik i wyswietla jego wartosc - podajac, ze klasa implementuje interfejs Message; zobowiazalismy sie, ze metoda o nazwie giveReport bedzie istniala*/ public void giveReport() { counter++; System.out.println ("Counter="+counter); Java 41 } } /**Klasa serwera korzysta z obiektu majacego zaimplementowany interfejs Message*/ class Server { /*Zwrocmy uwage, ze typem obiektu jest nazwa interfejsu*/ Message object; /**Konstuktor. Jako parametr podajemy dowolny obiekt majacy zaimplementowany interfejs Message; w naszym przypadku bedzie to Client*/ Server (Message object) { this.object=object; } /** Wywolujemy metode giveReport obiektu z interfejsem Message times razy */ public void execute (int times) { for (int k=0; k<times; k++) object.giveReport(); } } /**Interfejs Message, kazda klasa ktora go zaimplementuje musi posiadac metode giveReport*/ interface Message { /**Tylko zobowiazanie, ze kazda klasa ktora implementuje ten interfejs bedzie miala metode giveReport - jej dzialanie bedzie zalezec od danej klasy*/ void giveReport(); } 10. Plik Compare.java /**Program krotko demonstruje mechanizm wyjatkow w Java*/ import java.io.*; /**Klasa porownuje dwa pliki i zwraca rezultat porowanania na ekranie*/ public class Compare { /**glowna i jedyna metoda aplikacji*/ public static void main (String[] args) { /*nazwy plikow*/ String first_file = args[0]; String second_file = args[1]; /*obiekty reprezentujace pliki*/ RandomAccessFile first =null; RandomAccessFile second =null; /*Zawartosc plikow bedzie umieszczona w tych buforach*/ byte[] first_buffer; byte[] second_buffer; /*Dlugosci plikow*/ int first_size = -1; int second_size = -1; try { System.out.println ("Ten program porowna dwa pliki"); 42 Jzyki obiektowe System.out.println ("plik 1: "+first_file+" plik2: "+second_file); try { first = new RandomAccessFile(first_file, "r"); second = new RandomAccessFile(second_file, "r"); /*blok, w ktorym porownujemy*/ prawie_koniec:{ //etykieta first_size = (int)first.length(); second_size = (int)second.length(); /*najpierw porownujemy dlugosci*/ if (first_size!=second_size) { System.out.println ("Rozne pliki"); break prawie_koniec; } /*jesli dlugosci identyczne, wczytujemy pliki do pamieci*/ first_buffer = new byte [first_size]; second_buffer = new byte [second_size]; first.readFully (first_buffer, 0, first_size); second.readFully (second_buffer, 0, second_size); /*porownujemy zawartosc plikow*/ for (int i=0; i<first_size; i++) { if (first_buffer[i]!=second_buffer[i]) { System.out.println ("Rozne pliki"); break prawie_koniec; } } System.out.println ("Pliki identyczne"); } /*tutaj przechodzi break prawie_koniec*/ System.out.println ("---------------"); } /*przechwytujemy wyjatki zwiazane z operacjami I/O*/ catch (IOException e) { System.out.println ("Blad I/O"); } /*to sie zawsze wykona*/ finally { try { first.close(); second.close(); } /*podczas zamykania plikow ignorujemy wyjatki*/ catch (Exception ignored) { } System.out.println ("Koniec czesci wewnetrznej"); } } /*tu przechwytujemy wyjatki nie obsluzone w czesci wewnetrznej*/ catch (Exception e) { Java 43 System.out.println ("Wystapil nastepujacy wyjatek przechwycony w main"); System.out.println (e); System.out.println ("Uzycie programu: Compare pierwszy_plik drugi_plik"); } /*na koniec zawsze wyswietlamy krotki komunikat*/ finally { System.out.println ("Koniec dzialania programu"); } } //end main }// end Compare 11. Plik FileInfo.java import java.io.*; public class FileInfo { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { String path = args[i]; if (args.length > 1) System.out.println("Regarding \"" + path + "\":"); File file = new File(path); if(file.exists()) { System.out.println("This file exists."); System.out.println("It can" + (file.canRead() ? "" : "not") + " be read."); System.out.println("It can" + (file.canWrite() ? "" : "not") + " be written."); System.out.println("It is " + file.length() + " bytes long."); if(file.isFile()) { System.out.println("It is a normal file."); } else { System.out.println("It is a directory."); String[] contents = file.list(); if (contents.length == 0) System.out.println("It is empty."); else { System.out.println("It contains the following files:"); for (int j = 0; j < contents.length; j++) System.out.println("\t" + contents[j]); }//end else that belongs to if(contents.length==0) }// End else that belongs to if(file.isFile()) }// End if(file.exists()) else { System.out.println("This file does not exist."); } // End else that belongs to if(file.exists()) System.out.println(); }// End for }//End main }// End FileInfo

Wyszukiwarka

Podobne podstrony:
podstawy programowania java
zestawy cwiczen przygotowane na podstawie programu Mistrz Klawia 6
Podstawy Programowania Wersja Rozszerzona
Visual C 6 0 Podstawy programowania
matlab podstawy programowania
JP SS 2 algorytmy i podstawy programowania
Podstawy programowania II 2
podstawy programowania 5
Podstawy programowania  11 2013
podstawa programowa
podstawa programowa
Java Zadania z programowania z przykładowymi rozwiązaniami
Java?ektywne programowanie Wydanie II javep2
Podstawy Programowania
Delphi podstawy programowania rejestr systemowy
wychowanie fizyczne w nowej podstawie programowej
ćw 05 podstawy programowania

więcej podobnych podstron