Top Banner
Prvo predavanje upoznavanje s Javom Aplikacija Hello World kompiliranje i izvršavanje programa for -petlje operatori za increment i decrement naredbe za ispis Fibonaccijevi brojevi varijable i tipovi podataka komentari argumenti na komandnoj liniji klase , atributi i metode objekti razlikovanje objekata iste klase višestruko referenciranje objekta staticke varijable metode prenošenje argumenta u metodu vracanje vrijednosti iz metoda setter metode getter metode ista imena varijabli i metoda konstruktori skrivanje imena varijabli i kljucna rijec this polja Aplikacija Hello World class HelloWorld { public static void main (String args[]) { System.out.println("Hello World!"); } } Kompiliranje i izvršavanje programa Trisu koraka u stvaranjuprograma: 1. pisanjekoda 2. kompilacijaizvornogkoda 3.izvršavanjekompilirnogkoda Pod UNIXomkompilacijaiizvršavanjeizgledaovako: % javac HelloWorld.java % java HelloWorld Hello World % Na racunalu student.math.hr se Java kompajler(javac ), Java interpreter(java)i ostalialatinalazeu direktoriju /opt/java/bin, dakle dodajte taj direktoriju vašu $ PATH varijablu : % export PATH=$PATH:/opt/java/bin
339

Java Predavanje I

Jul 18, 2016

Download

Documents

Goran

Java predavanje I
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Java Predavanje I

Prvo predavanje upoznavanje sJavomAplikacija Hello World kompiliranje i izvršavanje programa for-petljeoperatori za increment i decrement naredbe za ispis Fibonaccijevi brojevivarijable i tipovi podataka komentari argumenti na komandnoj liniji klase ,atributi i metode objekti razlikovanje objekata iste klase višestrukoreferenciranje objekta staticke varijable metode prenošenje argumenta umetodu vracanje vrijednosti iz metoda setter metode getter metode ista imenavarijabli i metoda konstruktori skrivanje imena varijabli i kljucna rijec thispolja

Aplikacija Hello Worldclass HelloWorld { public static void main (String args[]) { System.out.println("Hello World!"); } }

Kompiliranje i izvršavanje programa

Trisu koraka u stvaranjuprograma:

1. pisanjekoda2. kompilacijaizvornogkoda3. izvršavanjekompilirnogkoda

Pod UNIXomkompilacijai izvršavanjeizgledaovako: % javac HelloWorld.java% java HelloWorldHello World%

Na racunalustudent.math.hr se Java kompajler(javac), Java interpreter(java) iostalialatinalazeu direktoriju/opt/java/bin, dakle dodajte taj direktoriju vašu$PATH varijablu: % export PATH=$PATH:/opt/java/bin

Page 2: Java Predavanje I

Pod Windowsimaslicno; mora se koristitiDOS-shell: C:> javac HelloWorld.javaC:> java HelloWorldHello WorldC:>

Pri tom opet varijablaPATH koja se definirau odgovarajucemretku datotekeautoexec.bat ilipomocu Start Settints System Environment Variables PATH

mora sadržavatiodgovarajucidirektorij, npr …;c:\jdk1.3.0_02\bin\; Primijetiteuporabu.java ekstenzijekod kompiliranja, aline i .class ekstenzijekodizvršavanja.

for-petljeclass Count { public static void main (String args[]) { int i; for (i = 0; i < 50; i=i+1) { System.out.println(i); } } }

Deklaracijavarijabliunutarpetlje

class Count { public static void main (String args[]) { for (int i = 0; i < 50; i = i+1) { System.out.println(i); } } }

Operatori za increment i decrement

Java imaoperatore ++ i -- kao C.

Page 3: Java Predavanje I

Increment: class Count { public static void main (String args[]) { for (int i = 0; i < 50; i++) { System.out.println(i); } } }

Decrement: class Count { public static void main (String args[]) { for (int i = 50; i > 0; i--) { System.out.println(i); } } }

Nardbe za ispis class PrintArgs { public static void main (String args[]) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } } } % java PrintArgs Hello there!Hellothere!%

Za ispisretka koristese metodeprintln(...) izklasePrintStream . U našemprogramu System.out.println() ispisujesadržajstandardnogoutput streamaSystem.out klaseSystem , u ovomslucajuargumenteizakojihslijediline-separatorovisano platformi([carriage return] (ASCII 13, \r) i [linefeed] (ASCII 10, \n)na Windowsima, [linefeed] na UNIXu, [carriage return] na Mac-u)

Page 4: Java Predavanje I

System.err.println(…) ispisujesadržajsa standardnogerror output streamaSystem.err.

Možete konkateniratiargumenteza println() pomocuznaka+, npr.

System.out.println("Ucitano je " + args.length + "argumenata s komandne linije");

Ako koristiteprint(…) umjestoprintln() onda nakon ispisanemaznakaza noviredak. Npr, System.out.print("Ucitano je ");System.out.print(args.length); System.out.print(" argumenata s komandne linije");System.out.println();

System.out.println() prekida linijui pokrece ispis. U praviluse ništanece ispisatinaekranudok god se ne pojaviznakza prijelomlinije.

Fibonaccijevi brojeviclass Fibonacci { public static void main (String args[]) { int low = 1; int high = 0; System.out.println(low); while (high < 50) { System.out.println(high); int temp = high; high = high + low; low = temp; } } }

Primjerpokazujuezbrajanje, while-petlju, relacije te deklaracijei pridruživanjevarijabli.

Variable i tipovi podataka

U javipostoji8 primitivnihtipovapodataka:

boolean

byte

short

Page 5: Java Predavanje I

int

long

float

double

char

Medutimpostojisamo 7 vrsta literala, a jedan medunjima(String) nijeprimitivnitippodataka:

boolean : true ilifalseint: 89, -945, 37865long: 89L, -945L, 5123567876Lfloat: 89.5f, -32.5f,double: 89.5, -32.5, 87.6E45char: 'c', '9', 't'String: "Ovo je string literal"

Ne postoje literalitipashort ilibyte.

String je referentni iliobjektni tip, ne primitivni. Medutim, java kompajlerimaposebnupodršku za Stringove, pa možeizgledatikao da je to primitivnitip.

class Variables { public static void main (String args[]) { boolean b = true; int low = 1; long high = 76L; long middle = 74; float pi = 3.1415292f; double e = 2.71828; String s = "Hello World!"; } }

Kommentari

Komentarise u Javioznacavajuna istinacinkao u C++. Sve izmedu/* i */ ce seignorirati, a u pojedinacnimlinijamabit ce odbaceno sve nakon // (do kraja linije).Takoder postojiposeban oblikkomentaraza javadoc alat za automatiziranodokumentiranjejava programa. Pišuse izmeduznakova/** i */. /** * Ovako se pisu komentari za javadoc */class HelloWorld { public static void main (String args[]) { /* Ispisujemo liniju Hello World */

Page 6: Java Predavanje I

System.out.println("Hello World!"); } // main metoda ovdje zavrsava } // HelloWorld program ovdje zavrsava

Komentarise evaluirajuu znakspace (praznina), a ne u ništa. Zato bi sljedeciprimjerizazvaogreškuu kompiliranju:

int i = 78/* Razdvoji broj na dva dijela */76;

Java ovo pretvarau pogrešnunaredbu int i = 78 76;

a ne u int i = 7876;

Argumenti na komandnoj linijiclass printArgs { public static void main (String args[]) { for (int i = 0; i < args.length; i++) { System.out.println(args[i]); } } }

Ime klase nije ukljucenou listuargumenata. Argumentise s komandnelinijeprenose uprogramkao polje stringova. Pocetna komponentasvakogpoljauvijekje nulta. Npr, % java printArgs Hello There

args[0] je string"Hello".args[1] je string"There".args.length je 2.

Sviargumentis komandnelinijeprenose se kao stringovi, nikadkao brojevi. Kasnijecetenaucitipretvaratistringoveu brojeve.

Klase, atributi i metode

Klasa je obrazac iliprototipkoji definiravarijablei metodezajednickesvimobjektimaneke vrste

Page 7: Java Predavanje I

Atribuitikažušto nekiobjekt jest.Metode kažušto nekiobjekt radi. class TwoDPoint { double x; double y; }

Da bistekompiliralitu klasu, spremiteje u datotekuTwoDPoint.java i otipkajte: % javac TwoDPoint.java

Primijetiteda ovo nije kompletanprogram. Ne možetega, naime, izvršitijer munedostajemain() metoda.

Objekti

Objekt je primjerak(instanca) klase.

Objekte možetekreiratipomocukljucnerijecinew izakoje slijeditzv. konstruktorklase . Sljedeciprogramkreiraobjekt tipaTwoDPoint i ispisujenjegoveatribute:

class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; // ovime smo deklarirali (ne i alocirali) objekt origin origin = new TwoDPoint(); // sada smo uz pomoc konstruktora alocirali (kreirali objekt) origin.x = 0.0; // Inicijaliziramo njegove atribute origin.y = 0.0; // Ispisujemo podatke o objektu origin System.out.println("Ishodiste ima koordinate " + origin.x + ", " + origin.y); } // kraj main() metode } // kraj OriginPrinter programa (klase)

Tocka . je tzv. separator pristupaclanovima. Pozivkonstruktorauzkljucnurijecnewpotreban je za alociranjeobjekta.

Staviteovuklasuu datotekuOriginPrinter .java u istomdirektorijukaoTwoDPoint.java, kompajlirajteje i izvršite(to je sada kompletanprogram):

% javac OriginPrinter .java% java OriginPrinter

Page 8: Java Predavanje I

Ishodiste ima koordinate 0.0, 0.0%

Razlikovanje objekata iste klase

Opcenito, klase ce imativišeod jednogobjekta. Za razlikovanjeobjekata unutaristeklase koristese referentnevarijable. Sljedeciprogramkreiradva razlicitaobjekta tipaTwoDPoint i ispisujenjihoveatribute. class TwoPointPrinter { public static void main(String[] args) { TwoDPoint origin; // deklariramo tocku origin TwoDPoint one; // deklariramo tocku one origin = new TwoDPoint(); // alociramo origin pomocu konstruktora klase one = new TwoDPoint(); // alociramo one pomocu konstruktora klase // postavljamo vrijednosti atributa origin.x = 0.0; origin.y = 0.0; one.x = 1.0; one.y = 0.0; // ispisujemo koordinate ovih dviju tocaka System.out.println("Ishodiste ima koordinate " + origin.x + ", " + origin.y); System.out.println("Tocka one ima koordinate " + one.x + ", " + one.y); } // kraj main() metode } // kraj TwoPointPrinter programa (klase)

Obrada: % javac TwoPointPrinter .java% java TwoPointPrinterIshodiste ima koordinate 0.0, 0.0Tocka one ima koordinate 1.0, 0.0%

Variableone i origin su dvijerazlicitereferentnevarijablekoje pokazujuna dvarazlicitaobjekta. Nije dovoljnosamo identificirativarijablukao clanaklase, vec trebaspecificiratina koji objekt u toj klasise ona referira.

Višestruko referenciranje objekta

Page 9: Java Predavanje I

Moguceje da dvijereferentnevarijablepokazujuna istiobjekt. Kad na nekiobjekt nepokazujeni jedna referentnavarijabla, on ce bitioznacenza uklanjanje(garbagecollection). Sljedeciprogramdeklariradvijereferentnevarijabletipa TwoDPoint, kreirajedan objekt tipaTwoDPointi pridružujetaj objekt objemavarijablama. Te se dvijevarijablesmatrajujednakima. class EqualPointPrinter { public static void main(String[] args) { TwoDPoint origin1; // deklariramo tocku origin1 TwoDPoint origin2; // deklariramo tocku origin2 origin1 = new TwoDPoint(); // alociramo origin1 pomocu konstruktora klase origin2 = origin1; // definiramo jos jednu referentnu varijablu za origin1 // Postavljamo vrijednosti atributa (samo za origin1) origin1.x = 0.0; origin1.y = 0.0; // print System.out.println("Tocka origin1 ima koordinate " + origin1.x + ", " + origin1.y); System.out.println("Tocka origin2 ima koordinate " + origin2.x + ", " + origin2.y); } // kraj main() metode } // kraj EqualPointPrinter programa (klase)

Obrada i izlaz: % javac EqualPointPrinter .java% java EqualPointPrinterTocka origin1 ima koordinate 0.0, 0.0Tocka origin2 ima koordinate 0.0, 0.0%

Primijetiteda su origin1 i origin2 dvijerazlicitereferentnevarijablekoje referencirajuistiobjekt tipapoint.

Staticke varijable

Statickavarijablaje varijablaklase , ona pripada klasi(samojklasi), a ne nekomobjektu (instanciklase). class Point { double x; double y; static double xorigin = 0.0;

Page 10: Java Predavanje I

static double yorigin = 0.0; } class PointPrinter { public static void main (String [] args) { System.out.println("Ishodiste je u tocki (" + Point.xorigin + ", " + Point.yorigin + ")"); } }

Obrada: % javac Point.java% javac PointPrinter .java% java PointPrinterIshodiste je u tocki (0.0, 0.0)%

Primijetiteda za ispisstatickihvarijablinijebilopotrebno kreiratikonkretniobjekt.Varijablamaklase pristupase pomocuimenaklase, a ne pomocuimenareferentnevarijable.

Metode

Metode kažušto nekiobjekt radi. class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } }

Primijetiteda se kljucnarijecthis koristikako bi se iznutrareferenciralavarijablakojapripada istojklasi. Sada možemopreraditiprogramOriginPrinterovako: class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.x = 0.0; origin.y = 0.0;

Page 11: Java Predavanje I

origin.print(); } }

Obrada: % javac OriginPrinter .java% java OriginPrinter(0.0, 0.0)%

Prenošenje argumenata u metodu

Dodat cemo klasiTwoDPoint još jednumetoduza ispis. class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } }

Primijetiteda su tu dvijerazliciteprint() metode. Jedna prihvacaargument, drugane.To je dozvoljenodok god listaargumenatarazrješujeovudvosmislenost. To se nazivaoverloading. Metoda System.out.println() takoder primjeroverloaded metode.Metoda main(String[] args) je non-overloaded metodakoja imapoljeStringova kao argumente. class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.x = 0.0; origin.y = 0.0; origin.print(); origin.print(5); } }

Page 12: Java Predavanje I

Izlaz: % javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)(0.0,0.0)(0.0,0.0)(0.0,0.0)(0.0,0.0)(0.0,0.0)%

Vracanje vrijednosti iz metoda

Još jednomcemo klasiTwoDPoint dodati novumetoduza ispis, getAsString() kojaza razlikuod prethodnedvijeimapovratnitip (return type) i vraca vrijednosttipaString. class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } String getAsString() { return "(" + this.x + "," + this.y + ")"; } }

Zato sad ovumetodumožemokoristitina svimmjestimagdje bi inacedošla vrijednosttipaString, npr, String s = origin.getAsString();System.out.println(s);

Ili, još bolje, System.out.println(origin.getAsString());

Sada možemojoš jednompreraditiklasuOriginPrinter :

Page 13: Java Predavanje I

class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.x = 0.0; origin.y = 0.0; System.out.println(origin.getAsString()); } }

Imamo: % javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)%

Setter metode

Takoder poznatei kao mutator metode, ove metodesamo postavljajuvrijednostivarijabli(obicnoprivatnih) unutarklase. class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } String getAsString() { return "(" + this.x + "," + this.y + ")"; } void setX(double value) { this.x = value; } void setY(double value) { this.y = value; } }

Page 14: Java Predavanje I

class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.setX(0.0); origin.setY(0.0); System.out.println(origin.getAsString()); } }

Imamoopet: % javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)%

Getter metode

Takoder poznatei kao accessor metode, ove metodesamo vracajuvrijednostivarijebliunutarklase. class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } String getAsString() { return "(" + this.x + "," + this.y + ")"; } void setX(double value) { this.x = value; } void setY(double value) { this.y = value; }

Page 15: Java Predavanje I

double getX() { return this.x; } double getY() { return this.y; } } class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.setX(0.0); origin.setY(0.0); System.out.println("(" + origin.getX() + "," + origin.getY() + ")"); } }

Još jednom: % javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)%

Ista imena varijabli i metoda

Java cak dozvoljavada varijablei metode imajuista imenatako dugodok se razlikujupolistiargumenatai povratnomtipu. Npr. klasiTwoDPoint koja sadržiattributex i ymožemododati i istoimeneaccessor metodebez opasnostiod dvoznacnosti: class TwoDPoint { double x; double y; void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } }

Page 16: Java Predavanje I

String getAsString() { return "(" + this.x + "," + this.y + ")"; } void setX(double value) { this.x = value; } void x(double value) { this.x = value; } void setY(double value) { this.y = value; } void y(double value) { this.y = value; } double getX() { return this.x; } double x() { return this.x; } double getY() { return this.y; } double y() { return this.y; } }

Sada možemoumjestosetX(value) koristitix(value), a umjestogetX() stavitix() ianalognoza y. tako da OriginPrintermožeizgledatii ovako: class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(); origin.x(0.0); origin.y(0.0); System.out.println("(" + origin.x() + "," + origin.y() + ")"); } }

Još jednom:

Page 17: Java Predavanje I

% javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)%

Konstruktori

Konstruktorislužeza instanciranjeklasa, dakle kreiranjeobjekata koji su instancenekeklase. To su posebne metodekoje imajuisto imekao njihovaklasa i ne vracajunikakvuvrijednost. Npr.: class TwoDPoint { double x; double y; TwoDPoint(double xvalue, double yvalue) { // konstruktor sa dva argumenta this.x = xvalue; this.y = yvalue; } void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } String getAsString() { return "(" + this.x + "," + this.y + ")"; } void setX(double value) { this.x = value; } void x(double value) { this.x = value; } void setY(double value) { this.y = value; } void y(double value) { this.y = value; } double getX() {

Page 18: Java Predavanje I

return this.x; } double x() { return this.x; } double getY() { return this.y; } double y() { return this.y; } }

U jednojklasimožebitii višekonstruktora. Svakikonstruktorzadaje po jedan nacinkreiranjaobjekata dane klase. class OriginPrinter { public static void main(String[] args) { TwoDPoint origin; origin = new TwoDPoint(0.0, 0.0); System.out.println("(" + origin.x() + "," + origin.y() + ")"); } }

Izlaz: % javac TwoDPoint.java% javac OriginPrinter .java% java OriginPrinter(0.0,0.0)%

Skrivanje imena varijabli i kljucnarijec this

Pomocukljucnerijecithis moguceje cak i argumentimakonstruktora(ilibilokojedrugemetode) davatiista imenakao varijablama. Npr.; TwoDPoint(double x, double y) { this.x = x; this.y = y; } void setX(double x) {

Page 19: Java Predavanje I

this.x = x;

KlasuTwoDPointmožemo, dakle preraditiovako: class TwoDPoint { double x; double y; TwoDPoint(double x, double y) { // konstruktor sa dva argumenta this.x = x; this.y = y; } void print() { System.out.println("(" + this.x + "," + this.y + ")"); } void print(int n) { for (int i = 0; i < n; i++) { System.out.println("(" + this.x + "," + this.y + ")"); } } String getAsString() { return "(" + this.x + "," + this.y + ")"; } void setX(double x) { this.x = x; } void x(double x) { this.x = x; } void setY(double y) { this.y = y; } void y(double y) { this.y = y; } double getX() { return this.x; } double x() { return this.x; } double getY() { return this.y; } double y() { return this.y;

Page 20: Java Predavanje I

} }

Kažemoda unutarmetode, deklaracijalokalnevarijableiliargumentasa istimimenomkao neka (member) varijablaskriva ilizasjenjuje(hides)tu varijablu. Ona se možereferenciratidodavanjemprefiksathis.

Polja

Polje je kolekcijavarijabliistogtipa. Npr. args[] u main() metodije poljeobjekatatipaString.

Zamislimoklasukoja brojipojavljivanjaznamenaka0-9. Pretpostavimoda želimotestiratida lije raspodjelabrojeva koje generirageneratorslucajnihbrojeva doistauniformna. Ako jest, sve znamenkabi trebaleimatipribližnoistufrekvencijunakonduljegvremena.

Napravitcemo poljendigits od 10 elemenata. Nultielementce pratitibrojpojavljivanjanula, prvielementbroj pojavljivanjajedinicaitd. Koristitcemo klasujava.util.Random. Za generiranjeslucajnihbrojeva koristitcemo metodunextDouble() izte klase.

import java.util.Random; class RandomTest { public static void main (String args[]) { int[] ndigits = new int[10]; double x; int n; Random myRandom = new Random(); for (int i = 0; i < 10; i++) { // inicijaliziranje polja ndigits[i] = 0; } for (long i=0; i < 100000; i++) { // testiranje generatora slucajnih brojeva x = myRandom.nextDouble() * 10.0; // novi slucajni broj izmedju 0 i 9 n = (int) x; // pretvaranje u cijeli broj ndigits[n]++; // biljezimo pojavu dobivenog slucajnog broja } for (int i = 0; i < 10; i++) { // ispis rezultata System.out.println(i+": " + ndigits[i]);

Page 21: Java Predavanje I

} } }

Ispismožeizgledatiotprilikeovako: % javac RandomTest.java% java RandomTest0: 99671: 98082: 100693: 100574: 99845: 99326: 100047: 101288: 99529: 10099%

U programusu trifor-petlje: jedna za inicijaliziranjepolja, drugaza izvodenjeodgovarajucihracunai treca za ispisrezultata. To je uobicajenou programimakojikoristepolja.

Page 22: Java Predavanje I

Drugo predavanjeproceduralna sintaksaPrimitivni tipovi podataka operatori razmak literali identifikatori kljucnerijeci separatori zbrajanje cijelih brojeva zbrajanje brojeva tipa doublemnoženje i dijeljenje neocekivani kvocijenti racunanje ostatka , moduloprioritet izvršavanja operatora zagrade miješanje tipova podataka automatskododjeljivanje tipova podataka (casting) pretvaranje stringova u brojeve podacitipa char Unicode naredbe za kontrolu toka naredba if ispitivanje jednakosti

klauzula else klauzula else if while petlja for petlja do while petljabooleovski podaci relacijski operatori prioritet izvršavanja relacijskih operatora

ispitivanje jednakosti objekata naredba break naredba continue labeliranepetlje naredba switch-case kondicionalni operator (? :) logicki operatoriprioritet izvršavanja logickih operatora deklariranje polja kreiranje poljainicijaliziranje polja metoda System.arraycopy () deklariranje , alociranje iinicijaliziranje dvodimenzionalnih polja višedimenzionalna i neuravnotežena polja

Primitivni tipovi podataka

Primitivnitipovipodataka u Javivrlosu slicnionimau C i C++. To su boolean , byte,short, int, long, float, double i char. Tipboolean je dodan u Javi.Implementacijaje medutimbitnoprocišcenana nekolikonacina.

1. Dok C i C++ ostavljajumnogestvariovisnimao mašinii kompajleru(npr. duljinuza int), Java specificirasve.

2. Java ne dopušta pretvaranjetipovaizmeduproizvoljnihvarijabli. Dopuštenojepretvaranjejedinomedunumerickimvarijablamate izmedupodklasa i nadklasaistogobjekta.

3. Sve numerickevarijableu Javisu oznacene.boolean

1-bit. Može poprimitivrijednostitrue ilifalse.

true i false su definiranekonstantejezikai nisuistošto i True i False, TRUE iFALSE, nulai ne-nula, 1 i 0 ilibilokoja druganumerickavrijednost. Ne možesepretvoritiniu jedan drugitip varijablenitise drugitipovimogupretvoritiuboolean .

byte

1 oznacenibyte (komplenentod 2). Pokrivavrijednostiod -128 do 127.short

2 bytea, oznacena(komplementod 2), -32,768 to 32,767int

4 bytea, oznacena(komplementod 2), od -2,147,483,648 do 2,147,483,647.Kao kod svihnumerickihtipova, moguceje pretvaranje(casting) u ostalenumericketipove(byte, short, long, float, double). Kod pretvaranjas

Page 23: Java Predavanje I

gubitkominformacija(lossy casts), npr int u byte, konverzijase obavljamoduloduljina kraceg tipa.

long

8 bytea oznacenih(komplementod 2), od -9,223,372,036,854,775,808 do+9,223,372,036,854,775,807.

float

4 bytea, IEEE754, od 1.40129846432481707e-45 do3.40282346638528860e+38 (positivniilinegativni).

Kao kod svihnumerickihtipova, moguceje pretvaranje(casting) u ostalenumericketipove(byte, short, long, int, double). Kod pretvaranjasgubitkominformacija(lossy casts), npr float u short, decimalnidio seodbacuje, i konverzijase obavljamoduloduljina kraceg tipa.

double

8 bytea IEEE754, od 4.94065645841246544e-324d do1.79769313486231570e+308d (positivnior negativni).

char

2 bytea, neoznacena, Unicode, od 0 do 65,535

Vrijednostitipachar nisuistošto i vrijednostitipabyte, int, short iliStrings .

Operatori

Page 24: Java Predavanje I

Operator Akcija

+ Zbrajanjebrojeva, konkatenacijastringova

+= Zbrajanjei pridruživanjebrojeva, konkatenacijai pridruživanjestringova

- Oduzimanje

-= Oduzimanjei pridruživanje

* Množenje

*= Množenjei pridruživanje

/ Dijeljenje

/= Dijeljenjei pridruživanje

| BitovskiOR

|= BitovskiOR i pridruživanje

^ BitovskiXOR

^= BitovskiXOR i pridruživanje

& BitovskiAND

&= BitovskiAND i pridruživanje

% Modulo(racunanjeostatka)

%= Moduloi pridruživanje

> Vece

>= Vece ilijednako

< manje

<= Manje ilijednako

! booleovskiNOT

!= razlicito

++ Povecavanjeza jedan

-- Smanjivanjeza jedan

>> Shift pomak bitovau desno, zajednosa znakom

>>= Shift pomak bitovau desno, zajednosa znakomi pridruživanje

<< Shift pomak bitovau lijevo

<<= Shift pomak bitovau lijevoi pridruživanje

>>> Neoznacenibitovskishiftu desno

>>>= Neoznacenibitovskishiftu desno i pridruživanje

&& BooleovskiAND

|| BooleovskiOR

== Booleovskajednakost

= Pridruživanje

~ BitovskiNOT

?: Uvjet

instanceof Provjera tipa

Page 25: Java Predavanje I

Razmak (white space)

Razmakje u praviluznak[space], koji dobijetekad pritisnete<spacebar> no u Javipostoje još 4 znakaza razmak: [horizontaltab], [formfeed], [carriagereturn] i [linefeed].Ovisnoo platformi, kad pritisnetetipku<return> ili<enter>, dobit cete [carriagereturn](MAC), [linefeed] (UNIX) ilioboje (DOS, Windows, VMS). To ce proizvestitvrdiprijelomlinijeu tekstu izvornogprograma.

Osimu literalimatipaString , jedan razmakje ekvivalentannizuuzastopnihrazmakabilokoje vrste.

UnutarliteralatipaString i char jedinidozvoljenirazmakje znak[space]. Umjestoznakova[horizontaltab], [formfeed], [carriagereturn] i [linefeed] morajuse stavljatiodgovarajuceescape-sekvence, npr. \t, \r, \f i \n. Ne možeterazlomitistringovako:

String poem = "Mary had a little lambwhose fleece was white as snowand everywhere that Mary wentthe lamb was sure to go.";

Umjestotoga trebate koristitiznakove\n i operator konkatenacije+, ovako: String poem = "Mary had a little lamb\n" +"whose fleece was white as snow\n" +"and everywhere that Mary went\n" +"the lamb was sure to go.";

Primijetiteda naredbe možeterazlomitikroz nekolikoredaka, jedinone možeteto ucinitisa literalimatipaString . Takoder primijetiteda \n funkcionirasamo na UNIX-u. Akoželitesvoj kod ucinitineovisnimo platformi, umjesto\n upotrijebitcete metoduSystem.getProperty("line.separator") koja ce vratitiodgovarajuciznakza danuplatformu. Pogledajtetakoder i metoduSystem.getProperties ().

Java nemasve escape-sekvence koje imaC. Osimvec spomenutih, to su još samo \b za[backspace] i \\ za sam [backslash]. No moguse koristitii \u sekvencekoje dozvoljavajuumetanjebilokojeg Unicodeznaka.

Literali

LiteralitipaString oznacavajuse dvostrukimnavodnicima, npr HelloWorld!”.Takoder, dva + dva je istošto i dvadva . Navodnici, medutimnisu dio literala.Vrijednostliterala HelloWorld!” je HelloWorld!, a ne HelloWorld!”. Takoderformatiranjeznakovanemautjecajana vrijednoststringa, dakle Hello World!” je istošto i HelloWorld!”.

Literalitipachar oznacavajuse jednostrukimnavodnicimai smijusadržavatitocno jednoslovo, npr. ¸ c je literaltipachar cijavrijednostje slovoc.

Page 26: Java Predavanje I

Booleovskiliteralisu true i false, a znaceistinui laž.

Brojevimogutakoder bitiliterali. Npr. 34 je literaltipaint i njegovaje vrijednostbroj34, dok je 1.5 literaltipadouble , a to su i 45.6, 76.4E8 (76.4 puta 10 na osmu) i-32.0.

Nadalje, 34L je literaltipalong i oznacavabroj 34, dok su 1.5F, 45.6f i 76.4E8Fliteralitipafloat.

Identifikatori

Identifikatori su imenavariabli, metoda, klasa, paketa i sucelja. Za razlikuod literalatonisusame stvarinegonacinnjihovogreferenciranja. U programuHelloWorldidentifikatorisu HelloWorld , String , args, main i System.out.println .

Identifikatorimorajubitisastavljeniod slova, brojeva i znakova_ (underscore) i $(dollarsign). Pocetno slovoidentifikatorasmijebitisamo slovo, _ ili$. Mala i velikaslovase razlikuju. Ime ne možesadržavatirazmak.

Ovo su primjerilegalnihvarijabliu Javi:

MyVariable

myvariable

MYVARIABLE

x

i

_myvariable

$myvariable

_9pins

andros

ανδρος

OReilly

This_is_a_very_long_variable_name

Sljedecihnekolikoprimjeranisu valjanaimenavarijabli:

My Variable // sadrzi razmak

9pins // pocinje brojem

a+c // + nije alfanumericki znak

testing1-2-3 // - nije alfanumericki znak

O'Reilly // ' nije alfanumericki znak

OReilly_&_Associates // & nije alfanumericki znak

Kljucne rijeci

Page 27: Java Predavanje I

Postoji50 rezerviranihkljucnihrijecikoje u Javi1.1 (51 u Javi1.2). U tablicije navedenonjih48 koje se stvarnokoriste.

Page 28: Java Predavanje I

Keyword Purpose

abstract Deklariraapstraktnuklasuilimetodu

boolean Deklarirabooleovskuvarijabluilipovratnitip (returntype)

break Prijevremeniizlazakizpetlje

byte Deklarirabyte varijabluilipovratnitip

case Jedna od granau naredbiswitch

catch Obrada iznimke

char deklarirachar variabluilipovratnitip

class Oznacavapocetak definiranjaklase

continue Prijevremenipovratak na pocetak petlje

default default akcijaza switchnaredbu

Do Pocetak do whilepetlje

double deklariradouble variabluilipovratnitip

Else Oznacavadio koda koji se izvršavaako uvjetu if naredbinijeistinit

extends Oznacavada je promatranaklasa potklasaneke drugeklase

FinalDeklarirada klasa ne možeimatipodklasuilida varijablailimetodanemožebit pregažena

finally Deklarirablok koda koji ce garantiranobitiizveden

Float deklarirafloat variabluilipovratnitip

For Pocetak for petlje

If Izvršavakod ako je uvjetistinit

implements Deklarirada promatranaklasa implementiradano sucelje

import Dopuštapristupklasiiligrupiklasa unutarpaketa

instanceof Ispitujeda lije objekt instancaneke klase

Int deklariraint (integer) variabluilipovratnitip

interface Oznacavapocetak definiranjasucelja

Long deklariralong (longinteger) variabluilipovratnitip

native Deklarirada je metoda implementiranau drugomprogramskomjeziku

New Alociranoviobject

packageDefinirapaket kojemupripada datoteka sa promatranimizvornimkodom

private Deklarirametoduilimembervarijablukao privatnu

protected Deklariraklasu, metoduilimembervarijablukao zašticenu

public Deklariraklasu, metoduilimembervarijablukao javnu

return Vraca vrijednostizmetode

Short deklarirashort (short integer) variabluilipovratnitip

static Deklarirada varijablailimetodapripada klasi, a ne objektu

Super Referencana roditeljapromatranogobjekta

switch Ispitujeistinitostnekolikomogucihuvjeta

synchronized Oznacavada je promatranidio koda osjetljivna threadovethis

Page 29: Java Predavanje I

Referencana sam promatraniobjekt

throw Odbacivanjeiznimke

throws Deklariraiznimkekoje metodaodbacuje

transient Varijablane smijebitiserijalizirana

try Pokušavaizvršitioperacijukoja možeeventualnoodbacitiiznimku

void Deklarirada metodane vraca nikakvuvrijednost

volatile Upozoravakompajlerda se varijablamijenjaasinhrono

while Pocetak whilepetlje

Još dvije, const i goto, rezerviranesu, alinisuimplementirane. To omogucujekompajleruboljekreiranjeporuka o pogreškamau slucajukriveupotrebe ovihuobicajenihkljucnihrijecijezikaC++ u Java programima.

Java 1.2 dodaje kljucnurijecstrictfp kojom se deklarirada metoda iliklasa mora bitiizvršenasa egzaktnomIEEE754 semantikom.

Primijetiteda true and false nisukljucnerijecinegobooleovskiliterali. Svejedno, ninjihne možetekoristitikao imenavarijabli.

Separatori

Separatoripomažuu definiranjustructureprograma. U programuHelloWorldkoristesezagrade, ( ), viticastezagrade, { }, tocka, ., tocka-zarez, ;.

Separator Svrha

( )Zatvaraargumenteu definicijamai pozivimametoda; podešava prioriteteizvršavanjau aritmetickimizrazima; okružujeumjetnopretvorenetipovepodataka (cast types); izdvajauvjetneizrazeu naredbamaza kontrolutoka

{ } Definirablokovekoda; automatskiinicijalizirapolja

[ ] Deklarirapolje tipova; izdvajavrijednostielemenatapolja

; Završavanaredbu

,Razdvajananizaneidentifikatoreu deklaracijamavarijabli; ulancavanaredbeu uvjetnomdijelufor petlje

.Selektiravarijabluilimetodunekogobjekta; separiraimenapaketa od imenapodpakete i imenaklasa

: Koristise nakon labelau petljama

Zbrajanje cijelih brojevaclass AddInts { public static void main (String args[]) {

Page 30: Java Predavanje I

int i = 1; int j = 2; int k; System.out.println("i je " + i); System.out.println("j je " + j); k = i + j; System.out.println("i + j je " + k); k = i - j; System.out.println("i - j je " + k); } }

Evo što se dogada kad izvršiteAddInts : % javac AddInts.java% java AddIntsi je 1j je 2i + j je 3i - j je -1%

Zbrajanje brojeva tipa double

Brojevitipadouble sadrže decimalnutocku . class AddDoubles { public static void main (String args[]) { double x = 7.5; double y = 5.4; double z; System.out.println("x je " + x); System.out.println("y je " + y); z = x + y; System.out.println("x + y je " + z); z = x - y; System.out.println("x - y je " + z); } }

Evo rezultata:

Page 31: Java Predavanje I

% javac AddDoubles.java% java AddDoublesx je 7.5y je 5.4x + y je 12.9x - y je 2.0999999999999996

Množenje i dijeljenje

Operatorimnoženjai dijeljenjasu * (množenje) i / (dijeljenje). class MultiplyDivide { public static void main (String args[]) { int i = 10; int j = 2; int k; System.out.println("i je " + i); System.out.println("j je " + j); k = i/j; System.out.println("i/j je " + k); k = i * j; System.out.println("i * j je " + k); } }

Rezultat: % javac MultiplyDivide .java% java MultiplyDividei je 10j je 2i/j je 5i * j je 20%

Realnibrojevitipa floati doublemnožese i dijelena istinacin. U slucajucjelobrojnogdijeljenja, rezultatse zaokružujeprema dolje. Npr. cjelobrojnodijeljenje10 sa 3 daje 3.

Neocekivani kvocijenti2/3 = 0 3/2 = 11/0 = ArithmeticException0/0 = ArithmeticException1.0/0.0 = Inf1.0/0 = Inf

Page 32: Java Predavanje I

0.0/0.0 = NaN (not a number)-1.0/0.0 = -InfInf + 1 = InfInf + Inf = InfInf - Inf = NaNInf/Inf = NaNNaN + anything = NaNNaN - anything = NaNNaN * anything = NaNNaN - anything = NaNNaN < NaN je falseNaN > NaN je falseNaN <= NaN je falseNaN >= NaN je falseNaN == NaN je falseNaN != NaN je true

Racunanje ostatka - modulo

Operator za racunanjeostatka dijeljenjadvajubrojeva (modulo) je %. class Remainder { public static void main (String args[]) { int i = 10; int j = 3; int k; System.out.println("i je " + i); System.out.println("j je " + j); k = i%j; System.out.println("i%j je " + k); } }

Izlaz: % javac Remainder.java% java Remainderi je 10j je 3i%j je 1%

Primijetiteda se operacijamodulomožeu Javiprimijenitii na realnebrojeve. Npr. 5.5 %1.5 je 1.

Prioritet izvršavanja operatora

Page 33: Java Predavanje I

Višeoperatora možebitiu istomizrazu:

int m = 1 + 2 + 3 + 4 + 5;

Sljedeciprogramracunaenergijuekvivalentnumasijednogelektronauzpomoc

EinsteinoveformuleE = mc2.

class mc2 { public static void main (String args[]) { double mass = 9.1096E-25; double c = 2.998E8; double E = mass * c * c; System.out.println(E); }}

Izlaz: % javac mc2.java% java mc28.18771e-08%

U slucajurazlicitihoperatora, prioritetje uobicajen: Sljedece trinaredbe su ekvivalentne int n = 1 - 2 * 3 - 4 + 5;int n = 1 - (2 * 3) - 4 + 5;int n= -4;

Unutardo sada spomenutihoperatora, operacijese izvršavajusljedecimprioritetom:

1. *, /, % Sva množenja, dijeljenjai modulood lijevana desno.2. +, - Sva zbrajanjai oduzimanjaod lijevana desno.3. = Pridruživanjedesne strane lijevoj

Zagrade

Zagradese koristeza mijenjanjeuobicajenogredosljedaoperacija. SljedeciprimjerpokazujepretvaranjeFahrenheitovihstupnjevau Celsiusovepo formuliC = (5/9) (F -32) gdje su C stupnjeviCelsiusaa F stupnjeviFahrenheita. Programispisujetablicukonverzijaizmedu0 i 300 stupnjevaFahrenheitaza svakih20 stupnjeva. // Ispisuje tablicu konverzije Fahrenheita u Celsiuse class FahrToCelsius { public static void main (String args[]) { double fahr, celsius; double lower, upper, step;

Page 34: Java Predavanje I

// donja granica temperaturne tablice lower = 0.0; // gornja granica temperaturne tablice upper = 300.0; // velicina koraka step = 20.0; fahr = lower; while (fahr <= upper) { celsius = (5.0 / 9.0) * (fahr-32.0); System.out.println(fahr + " F = " + celsius + " C"); fahr = fahr + step; } } }

Obrada i izlaz: % javac FahrToCelsius .java% java FahrToCelsius0.0 F = -17.77777777777778 C20.0 F = -6.666666666666667 C40.0 F = 4.444444444444445 C60.0 F = 15.555555555555557 C80.0 F = 26.666666666666668 C100.0 F = 37.77777777777778 C120.0 F = 48.88888888888889 C140.0 F = 60.0 C160.0 F = 71.11111111111111 C180.0 F = 82.22222222222223 C200.0 F = 93.33333333333334 C220.0 F = 104.44444444444444 C240.0 F = 115.55555555555556 C260.0 F = 126.66666666666667 C280.0 F = 137.77777777777777 C300.0 F = 148.88888888888889 C%

U ovomprogramunemamnogonovogu odnosuna prethodneprimjere, no pažnjuobratimona sljedeculiniju: celsius = (5.0 / 9.0) * (fahr-32.0);

To je prijevodformuleC = (5/9)(F - 32) gdje je dodana * za množenjejer Java nepodržavaimplicitnomnoženjefaktorau zagradama. Zagradese koristekao i u obicnojalgebri, za prilagodbupravilaprioriteta. Za operacijekoje koristeuobicajenearitmetickeoperatore (+, -, *, /), pravilaprioritetasu istakao i u obicnojalgebri.

Page 35: Java Predavanje I

Miješanje tipova podataka

Razlicititipovipodataka moguse pojavitiu istojnaredbi. Primjerpokazujeistovremenuupotrebuint i double. class IntAndDouble { public static void main (String args[]) { int i = 10; double x = 2.5; double k; System.out.println("i je " + i); System.out.println("x je " + x); k = i + x; System.out.println("i + x je " + k); k = i * x; System.out.println("i * x je " + k); k = i - x; System.out.println("i - x je " + k); k = x - i; System.out.println("x - i je " + k); k = i / x; System.out.println("i / x je " + k); k = x / i; System.out.println("x / i je " + k); } }

Izlaz: % javac IntAndDouble .java% java IntAndDoublei je 10x je 2.5i + x je 12.5i * x je 25.0i - x je 7.5x - i je -7.5i / x je 4.0x / i je 0.25%

Redoslijedmožeimatiutjecajana rezultatkad se tipovipodataka miješaju. Na primjer,

1 / 2 * 3.5 = 0.03.5 * 1 / 2 = 1.753.5 / 2 = 1.75

Page 36: Java Predavanje I

Kod miješanjatipovapodataka, uobicajenimatematickizakonikomutacijeopcenitonevrijede, posebno ne kad se miješajucjelobrojne(integer) i realne(floating point)vrijednosti.

1.0 / 2 * 3.5 = 1.753.5 * 1.0 / 2 = 1.751 / 2.0 * 3.5 = 1.753.5 * 1.0 / 2.0 = 1.75

Automatsko dodjeljivanje tipovapodataka (casting)

Ako int podijelimosa int dobijemoint.Ako double podijelimosa double dobijemodouble .Ako int podijelimosa double ilidouble sa double , dobijemodouble jer u slucajunejednakostitipovaJava težidodjeljivanjušto širegtipakako se sprijecilogubljenjeinformacija.

Pravilo:

· Ako je bilokoja varijablau aritmetickojbinarnojoperaciji(zbrajanje,oduzimanjemnoženje, dijeljenje, modulo) tipadouble onda Java tretiraobje vrijednostikao double .

· Ako nijedna nijedouble , alije jedna float, Java tretiraobje vrijednostikao float.

· Ako nijedna nijenifloat nidouble , alije jedna long, Java tretiraobjevrijednostikao long.

· Konacno, ako nijedna nijedouble , float nilong, Java tretiraobjevrijednostikao int, cak ako u jednadžbiuopce nemacijelihbrojeva.

Dakle, rezultatce bitidouble , float, long iliint, ovisnoo tipovimaargumenata.

U naredbipridruživanja, dakle ako postojiznakjednakosti, Java usporedujetip na lijevojstranisa konacnimtipomna desnoj strani. Tipna lijevojstraninece se promijeniti, alicese provjeritida livrijednostsa desne strane(double , float, int or long) odgovaratipuna lijevojstrani. Sve se možesmjestitiu double. Sve osimdouble možesesmjestitiu float. Svakicjelobrojnitip možese smjestitiu long, alifloat i double nemogu, dok se sve tipaint, short i byte možesmjestitiu int. Ako se desna stranamožesmjestitiu lijevu, pridruživanjese normalnoobavlja.

Pridruživanjevrijednostitipalong varijablamatipaint ilipak vrijednostitipadoublevarijablamatipafloat možeuzrokovatiproblemei kompajlervamtakva pridruživanjanece dopustitiosimako eksplicitnonavedeteda želitepretvaranje(casting). Prisilno

Page 37: Java Predavanje I

pretvaranjetipovaoznacavase navodenjemodgovarajucegtipau okruglimzagradamaneposrednoprije izrazakoji treba pretvoriti. Na primjer,

int i = (int) 9.0/4.0;

Kad se vrijednostpretvarau drugitip prijepridruživanja, nizoperacijase poduzimada bise desna strana skratila na pravuvelicinu. Za konverzijuizmedurealnih(floating point)i cijelihbrojeva (npr. int ililong), razlomljenidio se odbacuje (zaokružujena nulu). Toce proizvesticijelibroj. Ako je on dovoljnomalida stane u lijevustranu, pridruživanjejezavršeno. U suprotnom, ako je prevelik, bit ce mupridruženanajveca, a ako je premali,najmanjamogucavrijednostza odgovarajucitip.

Valjavoditiracunao tomeda prisilnopretvaranjemožeuzrokovatipogreške kojimacebitivrloteško uciu trag i zato ovumogucnosttreba koristitis oprezom.

Pretvaranje stringova u brojeve

Prilikomobrade korisnickoginputacesto je potrebno nekiString pretvoritiu int. Tose radi uzpomoc staticke metodeInteger.valueOf(String s) u kombinacijis(nestatickom) metodomintValue() koje pripadajuklasijava.lang.Integer . Npr.String "22" pretvorilibismou int 22 na sljedecinacin: int i = Integer.valueOf("22").intValue();

S tipovimadouble, float i long postupamoslicno, koristecistatickemetodeDouble.valueOf(String s), Float.valueOf(String s) i Long.valueOf(String s) u kombinacijis odgovarajucimmetodamadoubleValue(), floatValue() i longValue() koje pripadaju, respektivno, klasamajava.lang.Double ,java.lang.Float i java.lang.Long. String "22" pretvorilibismou long 22 ovako:

long l = Long.valueOf("22").longValue();

String "22.5" pretvorilibismou float ilidouble ovako:

double x = Double.valueOf("22.5").doubleValue();float y = Float.valueOf("22.5").floatValue();

RazlicitevalueOf() metoderelativnosu inteligentnei moguprepoznatiznakoveplusiminus, eksponentei ostaleuobicajenebrojcane formate. Medutim, ako kao argumentdobijunešto potpunone-numericko, npr. "Hello World", vjerojatnoce izbacitiNumberFormatException . Za sad još nisteucilikako baratatis iznimakamapa u svojimprogramimaizbjegavajtetakve situacije.

Preraditcemo sada programE = mc2 tako da o masiu kilogramimabude prihvacenkaokorisnickiinputsa komandnelinije. Ovaj postupak tipicanje za mnogeprograme.

class mc2 { public static void main (String args[]) {

Page 38: Java Predavanje I

double mass; double c = 2.998E8; // meters/second double E; mass = Double.valueOf(args[0]).doubleValue(); E = mass * c * c; System.out.println(E + " Joules"); }}

Obrada i rezultati: % javac mc2.java% java mc2 0.04564.098529824E15 Joules%

Primijetiteda ne bi bilodovoljnostaviti Mass = Double.valueOf(args[0]); // izostavljena je metoda doubleValue()

StatickametodaDouble.valueOf(args[0]) vratitce vrijednosttipaDouble , a tek cemetodadoubleValue() pretvorititu vrijednostu vrijednosttipadouble . Zato binavedenalinijaizazvalagreškuu kompajliranju: % javac mc2.javamc2.java:8: incompatible typesfound : java.lang.Doublerequired: double mass = Double.valueOf(args[0]); ^1 error%

Podaci tipa char

Podatak tipachar je pojedinacniznak, tj. slovo, brojka, tocka, tab, prazninai slicno.Literalitipachar su pojedinacniznakovizatvoreniunutarjednostrukihnavodnika, npr. char myCharacter = 'g';

Za znakovekoji se ne moguutipkatiJava osiguravaescape sekvence. To je backslashizkojeg slijedialfanumerickikod. Npr. '\n' je znakza novireda, '\t' je znakza tab, '\\' je sam backslash. Definiranesu sljedeceescape sekvence:

Page 39: Java Predavanje I

\b backspace

\t tab

\n linefeed

\f formfeed

\r carriagereturn

\" Dvostrukinavodnici, "

\' Jednostrukinavodnici, '

\\ backslash, \

Escape sekvencaza dvostrukenavodnikekoristise uglavnomu stringovimagdje bipojava navodnikainaceterminiralastring. Npr. System.out.println("And then Jim said, \"Who's at the door?\"");

Dvostrukinavodniciunutarjednostrukihbit ce prepoznatii bez escape sekvence. Npr.sljedeciredak je posve legalanu Javi. char doublequote = '"';

Unicode

Java koristiUnicodeskup znakova. Unicodeje dvobajtniznakovnikod koji reprezentiragotovosve znakoveu gotovosvimalfabetimai pismovnimsustavimasvijeta, ukljucujuciengleski, arapski, kineskii druge. Problemje, medutim, što mnogioperacijskisustaviiweb preglednicine podržavajuUnicode. Java ce uglavnompravilnotretiratiinputne-Unicodeznakova. Prvih128 znakovau Unicodetabliciidenticnisu sa uobicajenimASCII znakovima. Drugih128 znakovapodudara se sa gornjih128 znakovau ISOLatin1 proširenomASCII skupu. Ostalih65,280 predstavljaproblem.

PojedinacneUnicodeznakovemožetereferenciratikoristeciescape sekvancu\u izkojeslijedicetverocifreniheksadecimalnibroj. Npr.

\u00A9 © Znak za copyright

\u0022 " Dvostrukinavodnici

\u00BD 1/2 Razlomak½

\u0394 ∆ Velikogrcko delta

\u00F8 ø Malo o prekriženoznakomslash

Možete cak koristitipotpuneUnicodeznakovnenizoveza imenovanjevarijabli. Npr. String Mj\u00F8lner = "Hammer of Thor";

Naredbe za kontrolu toka

Page 40: Java Predavanje I

if

else

else if

while

for

do while

switch case

break

continue

Primijetiteda je goto je rezerviranarijecalinijeimplementirana. O obradi iznimakabitce rijecikasnije.

Naredba if

Primijetimoda smo se u klasiemc2 koristiliargumentoms komandnelinije, alinismoprovjeravalije lion uopce unešen. Sljedeciprogramispisujeprviargumentsa komandnelinije, aliprvo uzpomoc varijablearrayname.length provjeravaimaliargumenata.

class Hello { public static void main (String args[]) { if (args.length > 0) { System.out.println("Hello " + args[0]); } } }

System.out.println(args[0]) je ovdje umetnutaunutartesta, if (args.length

> 0) { }. Blokkoda unutarviticastihzagrada, System.out.println(args[0]), bitce izvršenako i samo ako je duljinapolja args veca od nule.

Argumentiza kondicionalnenaredbe kao što je if morajubitibooleovski, dakle izrazikojise evaluirajuna true ilifalse. Cjelobrojniargumentinisudopušteni.

% javac Hello.java% java Hello% % java Hello world!% Hello world!%

Ispitivanje jednakosti

Testiranjejednakostije nešto složenije. Ocekivalibisteda se za ispitivanjejesu lidvabroja jednakikoristiznakjednakosti=. Medutim, on je rezerviranza operator

Page 41: Java Predavanje I

pridruživanjapa je za ispitivanjejednakostiuvedennoviznak, dvostrukajednakost, ==.Taj je znakposudenizC-a.

Ta se dva znakagreškomlako moguzamijeniti, no kako u Javinisudozvoljenina istimmjestima, kompajlerce to otkriti. Ipak, sljedecasituacijamožebitiproblematicna:

boolean b = true; if (b = false) { System.out.println("b is false"); }

Da bi to izbjegli, nekiprogrameripišutestiranjeuvjetaovako: boolean b = true; if (false = b) { System.out.println("b is false"); }

Kako literalune možetepridružitinikakvuvrijednost, kompajlerce u tom slucajuotkritida je ste umjesto== napisali=.

Klauzula else

class Hello { public static void main (String args[]) { if (args.length > 0) { System.out.println("Hello " + args[0]); } else { System.out.println("Hello whoever you are."); } } } % javac Hello.java% java Hello% Hello whoever you are% % java Hello world!% Hello world!%

Klauzula else if

Naredba if nijeogranicenana samo dva slucaja. Kombiniranjemelse i if dobije seelse if kako bi se mogleispitatisve mogucnosti. Preradimosada Helloprogramtakoda barata sa 4 imenas komandnelinije.

Page 42: Java Predavanje I

class Hello { public static void main (String args[]) { if (args.length == 0) { System.out.println("Hello whoever you are"); } else if (args.length == 1) { System.out.println("Hello " + args[0]); } else if (args.length == 2) { System.out.println("Hello " + args[0] + " " + args[1]); } else if (args.length == 3) { System.out.println("Hello " + args[0] + " " + args[1] + " " + args[2]); } else if (args.length == 4) { System.out.println("Hello " + args[0] + " " + args[1] + " " + args[2] + " " + args[3]); } else { System.out.println("Hello " + args[0] + " " + args[1] + " " + args[2] + " " + args[3] + " and all the rest!"); } } } % javac Hello.java% java Hello% Hello whoever you are% % java Hello prvi drugi treci cetvrti% Hello prvi drugi treci cetvrti% % java Hello prvi drugi treci cetvrti peti% Hello prvi drugi treci cetvrti and all the rest!%

Ipak, takav nacinispitivanjabrzo postaje kompliciran. Postoje i bolja rješenja, kao štopokazujusljedeciprimjeri.

while petlja

class Hello { public static void main (String args[]) { int i; System.out.print("Hello "); // Ispis Hello

Page 43: Java Predavanje I

i = 0; // Inicijaliziramo brojac prolaza kroz petlju while (i < args.length) { // Testiramo i iteriramo System.out.print(args[i]); System.out.print(" "); i = i + 1; // Povecamo brojac prolaza za 1 } System.out.println(); // Zavrsimo liniju } } % javac Hello.java% java Hello% Hello% % java Hello prvi drugi treci cetvrti% Hello prvi drugi treci cetvrti%

for petlja

class Hello { public static void main (String args[]) { System.out.print("Hello "); // Ispis Hello for (int i = 0; i < args.length; i = i + 1) { // Testiramo i iteriramo System.out.print(args[i]); System.out.print(" "); } System.out.println(); // Zavrsimo liniju } } % javac Hello.java% java Hello% Hello% % java Hello prvi drugi treci cetvrti% Hello prvi drugi treci cetvrti%

Ponekad je u for petljipotrebno inicijaliziratii inkrementirativiševarijabliodjednom. Utom slucajuse inicijalizatorii inkrementoriodvajajuzarezimakao u sljedecemprimjeru: for (int i = 1, j = 100; i < 100; i = i+1, j = j-1) { System.out.println(i + j); }

Page 44: Java Predavanje I

Ipak, višestrukoispitivanjeuvjetana ovaj nacinnijedopušteno. Sljedecanaredbarezultiralabi porukomo greškiu kompilaciji: for (int i = 1, j = 100; i <= 100, j > 0; i = i-1, j = j-1) { // pogresno !!!

Za vi estruko ispitivanjeuvjetakoristebooleovskilogi ki operatori&& i || o kojima ebitirije i kasnije.

do while petlja

class Hello { public static void main (String args[]) { int i = -1; do { if (i == -1) System.out.print("Hello "); else { System.out.print(args[i]); System.out.print(" "); } i = i + 1; } while (i < args.length); System.out.println(); } } % javac Hello.java% java Hello% Hello% % java Hello prvi drugi treci cetvrti% Hello prvi drugi treci cetvrti%

Booleovski podaci

Svaka booleovskavarijablamožepoprimitijednuod dvijevrijednostitrue ilifalse.Primijetiteda te vrijednostinisuistošto i Stringovi"true" i "false", a nisuninumerickevrijednostikao 1 i 0. Takoder primijetiteda su rijecitrue i falserezerviranerijeciu Javi,nazivajuse booleovskiliteralii osjetljivesu na velikai malaslova. boolean test1 = true;boolean test2 = false;

Page 45: Java Predavanje I

Relacijski operatori

Java ima6 relacijskihoperatora koji usporedujudva broja i vracajubooleovskuvrijednost. To su <, >, <=, >=, ==, i !=.

x < y Manje Trueako je x manjeod y, inacefalse.

x > y Vece Trueako je x iveceod y, inacefalse.

x <= y Manje ilijednako Trueako je x manjeilijednako y, inacefalse.

x >= y Vece ilijednako Trueako je x vece ilijednako + y, inacefalse.

x == y Jednako Trueako je x jednako y, inacefalse.

x != y Nejednako Trueako je x razlicitood y, inacefalse.

Sljedeciprimjerikoda pokazjuuporaburelacijskihoperatora: boolean test1 = 1 < 2; // Trueboolean test2 = 1 > 2; // Falseboolean test3 = 3.5 != 1; // Trueboolean test4 = 17*3.5 >= 67.0 - 42; // Trueboolean test5 = 9.8*54 <= 654; // Trueboolean test6 = 6*4 == 3*8; // Trueboolean test7 = 6*4 <= 3*8; // Trueboolean test8 = 6*4 < 3*8; // False

To, medutimne ilustriratipicnuuporabubooleovskihvarijabli. U praksi se one gotovojedinokoristeu kondicionalnimnaredbamai ispitivanjimauvjetau petljama. Vec smovidjeliprimjer: if (args.length > 0) { System.out.println("Hello " + args[0]);}

gdje je args.length > 0 booleovskavrijednost, dakle true ilifalse. Zato možemotakoder pisati: boolean test = args.length > 0;if (test) { System.out.println("Hello " + args[0]);}

Prioritet izvr avanja relacijskihoperatora

Pogledateliprimjereu prethodnomodlomku, vidjet ete da se aritmetike operacijeobavljajuprijeuspore ivanja. Inace bi npr. boolean test8 = 6*4 < 3*8; // False

Page 46: Java Predavanje I

izazvalogreškuu kompiliranjujer 4 < 3 vraca false, a to se ne možemnožitisa 6 ili8.Relacijskioperatoriizvršavajuse nakon aritmetickih, a prijeoperatorapridruživanja.Operator == imanešto manjiprioritetnego<, >, <= i >=. Pogledajterevidiranutablicuprioriteta:

1. *, /, % Sva množenja, dijeljenjai modulood lijevana desno2. +, - Sva zbrajanjai oduzimanjaod lijevana desno3. <, >, >=, <= Sva usporedivanjamedusobnihvelicina4. ==, != Sva usporedivanjajednakostii nejednakosti5. = Pridruživanjedesne strane lijevoj

Na primjer: boolean b1 = 7 > 3 == true;boolean b2 = true == 7 > 3;b = 7 > 3;

Ispitivanje jednakosti objekata

Operatori<, >, <= i >= moguse primijenitijedinona brojeve i znakove. Ne mogusekoristitisa Stringovima, booleovskimvarijablamapoljima(arrays) kao nis drugimneprimitivnimtipovimaza koje nijedefiniranlinearniuredaj. Za jednakost== vrijedipraviloda je true jednako true i razlicitood false. Isto tako je Jack wentup the hillrazlicitood Jillwentup the hill. Medutim, pokušajte izvršitesljedeciprogram:

class JackAndJill { public static void main(String args[]) { String s1 = new String("Jack went up the hill."); String s2 = new String("Jack went up the hill."); if ( s1 == s2 ) { System.out.println("Stringovi su jednaki."); } else if ( s1 != s2 ) { System.out.println("Stringovi nisu jednaki."); } }}

Vidjetcete da je rezultat(neocekivano): Stringovi nisu jednaki.

To nijeono što ocekujemo. Da bismousporedivalistringoveiliobjekte bilokoje drugevrste, koristimose metodomequals(Object o) izpaketa java.lang.String .Pogledajmoispravnuverzijuprogramakoja ce raditionako kako ocekujemo. Razlozizaovo sežuprilicnoduboko u filozofijuJave i priroduobjekata kakvisu npr. stringovi. class JackAndJill {

Page 47: Java Predavanje I

public static void main(String args[]) { String s1 = new String("Jack went up the hill."); String s2 = new String("Jack went up the hill."); if ( s1.equals(s2) ) { System.out.println("Stringovi su jednaki."); } else { System.out.println("Stringovi nisu jednaki."); } }} % javac JackAndJill.java% java JackAndJillStringovi su jednaki.%

Naredba break

Naredba break uzrokujeizlazakizpetljeprijenego to uvjetza ulazaku sljede u iteracijupostane la an. Na primjer, u sljedecojvarijantiprogramaCountWheat koji racuna

parcijalnesumereda Si=1, ,64(2i) pri cemuse ispisujeporuka o pogreškii for

petljase prekida cimnastaneoverflow pa (2i) postane negativan. class CountWheat { public static void main (String args[]) { int total = 0; int grains = 1; for (int square=1; square <= 64; square++) { grains *= 2; if (grains <= 0) { System.out.println("Overflow: grains = " + grains); break; } total += grains; System.out.print(total + "\t "); if (square % 4 == 0) System.out.println(); } System.out.println("Gotovo!"); } }

Pogledajmoobradu i izlaz: % javac CountWheat.java

Page 48: Java Predavanje I

% java CountWheat2 6 14 3062 126 254 5101022 2046 4094 819016382 32766 65534 131070262142 524286 1048574 20971504194302 8388606 16777214 3355443067108862 134217726 268435454 5368709101073741822 2147483646 Overflow: grains = -2147483648Gotovo!%

Naredba break najcešcese koristiunutarnaredbe switch .

Naredba continue

Naredba continue vraca kontroluna pocetak najbližeunutarnjepetljekojom jeobuhvacena, ne izvršavajucipri tom ostatak naredbiu tijelupetlje. Ako je to for petlja,brojac se inkrementira. Sljedeciprimjerpokazujekako se možepreskocitiobrada parnihelemenatau polju:

for (int i = 0; i < m.length; i++) { if (m[i] % 2 == 0) continue; // obrada neparnih elemenata... }

U praksi se nardba continue ipak rjede koristijer se u vecinislucajevaproblemmožeriješitii bez nje. Prethodniprimjermogaoje izgledatii ovako: for (int i = 0; i < m.length; i++) { if (m[i] % 2 != 0) { // obrada neparnih elemenata... } }

Labelirane petlje

U praviluunutarugnjijedenihpetljinaredbe break i continue uzrokujunapu tanjenajunutarnjijepetljekoja ihobuhva a. Pogledajtesljedeciprimjerdvijeugniježdenepetlje: for (int i=1; i < 10; i++) { for (int j=1; j < 4; j++) { if (j == 2) break; System.out.println(i + ", " + j); }

Page 49: Java Predavanje I

}

Rezultatizvršavanjabio bi 1, 12, 13, 14, 15, 16, 17, 18, 19, 1

jer se unutarnjapetljaprekinesvakiput kad j postane 2, alise vanjskapetljaizvršidokraja. Ako želimoprekinutiobje petlje, labelirajmovanjskupetljui navedimotu labeluubreak naredbi: iloop: for (int i=1; i < 3; i++) { for (int j=1; j < 4; j++) { if (j == 2) break iloop; System.out.println(i + ", " + j); }}

Sada bi rezultatizvršavanjabio 1, 1

jer je j postao 2, a vanjskapetljaje prekinuta.

Naredba switch-case

Switch-case naredba je zapravokraticaza odredene vrste ifnaredbi. Pogledajmosljedecinizif naredbikoje se sve odnose na istuvelicinu: if (x == 0) doSomething0();else if (x == 1) doSomething1();else if (x == 2) doSomething2();else if (x == 3) doSomething3();else if (x == 4) doSomething4();else doSomethingElse ();

Ovaj bi se kod uzpomoc switch-case naredbe mogaozapisatiovako: switch (x) { case 0: doSomething0(); break; case 1: doSomething1(); break; case 2:

Page 50: Java Predavanje I

doSomething2(); break; case 3: doSomething3(); break; case 4: doSomething4(); break; default: doSomethingElse ();}

U ovomprimjerux mora bitivarijablailiizrazkoji se izracunavailipretvarau int bezgubitkainformacijaTo znacida varijablamora biti, odnosnoda izrazmora vracatirezultattipaint, byte, short ilichar. Izrazx usporedujese redom s vrijednostimanavedenimu svakojcase naredbidok se ne naidena podudarnost. U našemprimjeruse x

usporedujes literalima, alito takoder mogubitivarijableiliizrazikoji vracajurezultattipaint, byte, short ilichar. Ako se niu jednomslucajune pronade podudarnostizvršavase akcijanaznacenasa default .

Kad je podudarnostpronadena, izvršavase sve što slijedido kraja switch bloka ilinaredbe break. Uobicajenoje stavljatibreak naredbuna kraj svakogcase bloka kakobi se izbjegliraznineocekivaniefekti.

Kondicionalni operator (? :)

Vrijednostneke varijablecesto ovisisamo o tome je lineka booleovskavarijablaistinitailine. Npr. jedna od uobicajenihoperacijaje traženjemaksimumaizmedudvijevrijednostii pridruživanjete velicinenekoj varijabli: if (a > b) { max = a;}else { max = b;}

Kako je ovo cesta situacija, uvedenje kondicionalnioperator ? : kao kraticaza ovakvuif-else strukturu. Ovaj bismoprimjermoglipisatiovako:

max = (a > b) ? a : b;

pri cemuje (a > b) ? a : b; izrazkoji vraca jednuod dvijevrijednosti, a ilib,ovisnoo tome je liuvjet(a > b) istinitililažan. Ako je istinit, vraca se a, u suprotnomb.Uvjetmožebitibilokoji izrazkoji vraca booleovskuvrijednost.

Kondicionalnioperator funkcionirajedinokod pridruživanjavrijednostinekoj varijabli,korištenjavrijednostiza pozivanjemetode iliu nekimdrugimsituacijamakad je tipnjegovogdrugogi trecegargumentadefiniran. Pogledajmosljedeciprimjer: if (name.equals("Rumplestiltskin ")) {

Page 51: Java Predavanje I

System.out.println("Give back child");}else { System.out.println("Laugh");}

Ovo se ne može zapisatiovako: name.equals("Rumplestiltskin ") // ovo je primjer pogresne upotrebe operatora ?: ? System.out.println("Give back child") : System.out.println("Laugh");

Prijesvega, drugii treciargumentsu void (ne vracajuvrijednost). Takoder, nikakvopridruživanjene naznacujetip koji bi trebaloocekivatiza drugii trecioperator (iako seznada to ne možebitivoid).

Prviargumentmora vracatiregularnibooleovskitip, a drugii treciargumentmorajuvracativrijednostikoje su kompatibilnesa cijelimocekivanimpovratnimizrazom. Nikadne možetekoristitivoid metodekao argumentekondicionalnogoperatora.

Logicki operatori

Do sada uvedenirelacijskioperatori(<, <=, >, >=, !=) dovoljnisu za testiranjepojedinacnoguvjeta.Za ispitivanjevišestrukihuvjeta, moralibismokoristitivišeifnaredbi: if (x == 2) { if (y != 2) { System.out.println("Oba uvjeta su true."); }}

To, medutim, možebitinepregledno, a taj nedostatakrješavase uporabomlogickihoperatora &&, || i !.

Operator && je logickiand koji za dvijebooleovskevrijednostii vraca true ako i samoako su oba operanda true. Npr.

boolean b;b = 3 > 2 && 5 < 7; // b je trueb = 2 > 3 && 5 < 7; // b je sada false

Operator || je logickior koji za dvijebooleovskevrijednostivraca true ako je barjedan operand true. Npr. boolean b;b = 3 > 2 || 5 < 7; // b je trueb = 2 > 3 || 5 < 7; // b je i dalje trueb = 2 > 3 || 5 > 7; // now b je false

Page 52: Java Predavanje I

Operator ! je logickanegacijakoja za booleovskuvrijednostvraca true ako je operandfalse i obrunuto. Npr. boolean b;b = !(3 > 2); // b je falseb = !(2 > 3); // b je true

Ovi operatoriomogucujujednostavnjeispitivanjevišestrukihuvjeta. Naš prviprimjermožese sada zapisatimnogopreglednije: if (x == 2 && y != 2) { System.out.println("Oba uvjeta su true.");}

Prioritet izvršavanja logickihoperatora

Prilikomizvršavanjaoperatora && ili||, prvo se izracunavaizrazna lijevojstranioperatora. Pogledajmosljedeciprimjer: boolean b, c, d;b = !(3 > 2); // b je falsec = !(2 > 3); // c je trued = b && c; // d je false

Kad se izracunavaizrazd = b && c;, prvo se provjeravada lije b true. Ovjdjejebfalse, pa onda takoder b && c mora bitifalse bez obziraje lic true ilinije. Zato sevrijednostvarijablec u ovomizrazuuopce ne provjerava.

Na istinacin, kad Java naidena operator ||, pokušat ce skratitiizracunavanjecimustanovida je lijevioperand true, jer onda i cijelirezultatmora bititrue.

boolean b = (n == 0) || (m/n > 2); boolean b = (n != 0) && (m/n > 0);

Cak ako je n jednako nuli, nece se dogoditidijeljenjes nulomjer se lijevastranaprvaizraunava, a ako je istinita, onda se desna nece niracunati. Ova skracivanjanisuza Javutolikoznacajnakao za C jer u Javioba operanda za && i || morajubitibooleovskapa toreducirasporedne efektekoji oviseo tome jesu liilioperandistvarnoizracunati. Nosvejedno, moguceje eksplicitnospecificiratiracunanjeoba operanda, tj. izbjeciskracivanje. Ako želiteizracunavativrijednostibooleovskihizrazabez obzirana istinosnuvrijednostmožetese koristitioperatorima& i | (bitovskiand i bitovskior) umjesto&& i ||.Medutim, paziteda operandibuduzaistabooleovskijer ovioperatoriimajusvoj smisaoiza numericketipove, a znacenjeimje ondje posve drugacije.

Page 53: Java Predavanje I

Dodajmokonacnooperatore &&, ||, &, | i ? u tablicuprioriteta:

1. *, /, % Multiplikativnioperatori2. +, - Aditivnioperatori3. <, >, >=, <= Relacijskioperatori4. ==, != Usporedbe jednakostii nejednakosti5. & Bitovskiand6. | Bitovskior7. && Logickiand8. || Logickior9. ? : Kondicionalnioperator

10. = Operator pridruživanja

Deklariranje polja

Polja morajuimatiodredenitip, npr. byte, int, String ilidouble . Samo varijableodgovarajucegtipamogubitispremljeneu istopolje. Jedno poljene možeistodobnosadržavatirecimobrojeve i stringove. Polja morajukao i ostalevarijablebitideklarirana.Deklarirajuse dodavanjemuglatihzagrada[] kao sufikstipuvarijable. Na primjer: int[] k;float[] yt;String[] names;

Ovo znacida je k poljeint-ova, yt poljefloat-a, a names poljeString-ova. Uglatezagrademožetepo vlastitomizborudodati i varijabliumjestotipuilicak jednomi drugom. int k[];float yt[];String names[]; int[] k[];float[] yt[];String[] names[];

Kreiranje polja

Deklarirajucipolje samo smo reklikoje vrstevrijednostice polje sadržavati. Timega jošnismokreirali. Polja se kao i ostaliobjektiu Javikreirajupomocukljucnerijecinew.Varijablekoje smo maloprijedeklariralimožemokreiratiovako: k = new int[3];yt = new float[7];names = new String[50];

Brojeviu uglatimzagradamaspecificirajuduljinupolja, tj. Kolikoimakomponenatakojece sadržativrijednosti. Poljek možeimati3 broja tipaint, poljeyt možesadržati7

Page 54: Java Predavanje I

brojeva tipafloat, a poljenames možesadržati50 String-ova. Ovaj se korakponekad nazivaalociranjempolja jer se njimeizdvajapotrebna memorijaza polje.

Inicijaliziranje polja

Pojedinacnekomponentepolja referencirajuse imenompolja i cijelimbrojemkojipredstavljapozicijukomponenteunutarpolja. Ovi se brojevinazivajusubskriptimailiindeksimakomponentiu polju. Indeksisu cijelibrojevipocevšiod 0 (nula). Daklegoredeklariranopoljek imakomponentek[0], k[1] i k[2]. Buducida se pocinjeod nule,ne postojik[3]. Pokušaj referenciranjanepostojecekomponenterezultiratceodbacivanjemiznimkeArrayIndexOutOfBoundsException . Komponentepoljamoguse upotrebljavatikao i drugevarijablekoje nisukomponentepolja. k[0] = 2;k[1] = 5;k[2] = -2;yt[17] = 7.5f;names[4] = "Fred";

Ovaj se korak nazivainicijaliziranjempolja, preciznijeinicijaliziranjemkomponenatapolja. Pod inicijaliziranjempoljaobicnose podrazumijevainicijaliziranjesvihkomponenatapolja. Naravnoda za ioleveca poljanecemoinicijaliziratijednupo jednukomponentu, negocemo se poslužitipetljomkao u sljedecemprimjeru: float[] squares;squares = new float[101]; for (int i=0; i <= 100; i++) { squares[i] = i*i;}

Primijetimoda ce brojevitipaint kad budu spremljeniu ovo poljepostatifloat jer jepolje tako deklarirano.

Metoda System.arraycopy()

Kopiranjepoljanijenekitežak zadatak, alije efikasnijeako je implementiranou samomsustavu. Zato java.lang.System sadržistatickumetoduSystem.arraycopy() kojumožetekoristitiza kopiranjejednogpolja u drugo. Definiranaje ovako: public static void arraycopy(Object source, int sourcePosition , Object destination, int destinationPosition , int numberOfElements )

Metoda System.arraycopy() kopiranumberOfElements elemenataizpolaznogpojasource, pocevšis elementomna pozicijisourcePosition , na poljedestinationpocevšiod pozicijedestinationPosition . Poljedestination mora vec postojatiutrenutkupozivanjametodeSystem.arraycopy() jer ga ona sama nece kreirati.. Poljasource i destination morajubitiistogtipa. Na primjer,

Page 55: Java Predavanje I

int[] unicode = new int[65536]; for (int i = 0; i < unicode.length; i++) { unicode[i] = i; } int[] latin1 = new int[256]; System.arraycopy(unicode, 0, latin1, 0, 256);

Deklariranje, alociranje iinicijaliziranje dvodimenzionalnihpolja

Dvodimenzionalnapolja se deklariraju, alocirajui inicijalizirajuslicnokaojednodimenzionalna. Specificiratcete dvijedimenzijeumjestojedne i vjerojatnokoristitidvijeugniježdenepetlje. U sljedecemprimjeruse svakomelementudvodimenzionalnogpoljadodjeljujesumanjegovihindeksa. class FillArray { public static void main (String args[]) { int[][] matrix; matrix = new int[4][5]; for (int row=0; row < 4; row++) { for (int col=0; col < 5; col++) { matrix[row][col] = row+col; } } } }

Naravno, algoritamza punjenjepoljaovisiiskljucivoo namjenipojedinogpolja. Usljedecemprimjeruracunamojedinicnumatricuzadanevelicine(kvadratnumatricukojapo dijagonaliimajedinice, a ostalielementisu nule). class IDMatrix { public static void main (String args[]) { double[][] id; id = new double[4][4]; for (int row=0; row < 4; row++) { for (int col=0; col < 4; col++) { if (row != col) { id[row][col]=0.0; } else {

Page 56: Java Predavanje I

id[row][col] = 1.0; } } } } }

U dvodimenzionalnompoljuiznimkaArrayIndexOutOfBoundsException pojavljujese kad god prekoracitemaksimalniindeksbilopo recimabilopo stupcija.

Dvodimenzionalnopoljemožetetakoder deklarirati, alociratii inicijaliziratiu jednomkoraku, zadajucilistuinicijalnihvrijednostiunutarugniježdenihviticastihzagrada. Npr.jedinicna3x3 matricamožese zadatiovako:

double[][] ID3 = { {1.0, 0.0, 0.0}, {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0}};

Razmacii prijelomiredaka su iskljucivozbogprogramera. Sljedecizapisbio bi posveekvivalentanprethodnom: double[][] ID3 = {{1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{0.0, 0.0, 1.0}};

Višedimenzionalna polja ineuravnotežena polja

Ne moratese ogranicavatina dvodimenzionalnapolja. Java dopzšta poljaod 3, 4 ilivišedimenzija. Ipak, ako trebate višeod 3 dimenzijeza polje, vjerojatnokoristitepogrešnustrukturupodataka. Cak su i trodimenzionalnapolja rijetkaosimu programimazaznanstvenei inženjerskeaplikacije.

Sintaksaza trodimenzionalnapolja je direktnaekstenzijasintakseza dvodimenzionalna.Sljedeciprogramdeklarira, alocirai inicijalizirajedno trodimenzionalnopolje. U svakielementspremljenaje sumanjegovihindeksa.

class Fill3DArray { public static void main (String args[]) { int[][][] M; M = new int[4][5][3]; for (int row=0; row < 4; row++) { for (int col=0; col < 5; col++) { for (int ver=0; ver < 3; ver++) { M[row][col][ver] = row+col+ver; }

Page 57: Java Predavanje I

} } } }

Potrebna je dakle dodatna ugniježdenafor petljaza baratanjedodatnomdimenzijom.Sintaksaza još višedimenzijeje slicna. Java kao niC nemapravihvišedimenzionalnihpolja. Java simuliravišedimenzionalnapoljakoristecipolja cijisu elementidrugapolja. To znacida je moguceimatii neuravnoteženapolja, dakle poljau kojimadimenzijanijejednaka za sve retke. U praksi, medutim, takvestrukturevaljaizbjegavati.

Page 58: Java Predavanje I

Trece predavanje objekti i klaseObjektno orijentirano programiranje primjer: klasa Car kreiranje objekata uzpomoc operatora new separator pristupa clanovima . uporaba objekata unutarrazlicitih klasa inicijaliziranje atributa metode pozivanje metoda impliciranithis member varijable nasuprot lokalnim varijablama prenošenje argumenata umetodu prenošenje argumenata u metodu, primjer setter metode uporaba settermetoda, primjer vracanje vrijednosti iz metode vracanje nekoliko vrijednosti izmetoda uporaba getter metoda, primjer konstruktori uporaba konstruktoraogranicenja zaštita pristupa (access protection ) cetiri razine zaštite pristupa štotreba biti public , a što private? tri koristi od zaštite pristupa primjer zaštitepristupa promjena implementacije

Objektno orijentirano programiranje

U klasicnomproceduralnomprogramiranjupokušavase problemizrealnogsvijetaprikazatipomocumalogbroja unaprijeddefiniranihtipovapodataka: cijelihbrojeva,realnihbrojeva, stringovai eventualnopolja. U objektno orijentiranomprogramiranjukreiratemodelpromatranogsustavarealnogsvijeta. Klase su tipovikoje programerdefinirakako bi modeliraodijelovesustava.

Klasa je zamišljenakao prototip, nacrt iliidejaza svoje primjerke(instance). Možeteimaticijelei realnebrojeve i stringove, alitakoder imatei automobile, motocikle, ljude,zgrade, oblake, pse, andele, studente, tecajeve, bankovneracunei bilokakve tipovekojisu bitniza rješavanjezadanogproblema.

Klase specificirajupodatke i ponašanje, kako vlastito, tako i objekata koji se iznjihkreiraju. Klasa imadva dijela: atributei metode. Atributiopisujušto klasa jest. Metodeopisujušto klasa cini.

Koristeciprototipkoji klasa predstavlja, možetekreiratiproizvoljanbroj objekata, asvakiod njihje primjerak(instanca) klase. Razlicitiobjekti isteklase imajuisteatributeimetode, alivrijednostiatributabit ce opcenitorazlicite. Npr. Svi ljudiimajunekubojuociju, alise ona razlikujeod covjeka do covjeka.

S drugestrane, objekt neke klase imaistemetodekao i ostaliobjekti te klase, osimštometodeoviseo vrijednostimasvojihargumenatai objektovihatributa.

To se reflektirau runtime oblikuobjekta. Svakiobjekt imaodvojenblok memorijezasvoje atribute, alimemorijau kojoj su zabilježenemetodezajednickaje za sve objektedane klase.

Page 59: Java Predavanje I

Primjer: klasa Car

Pretpostavimoda želimonapisatiprogramza simulacijuprometakoji bilježiprolazakvozila. Na svakomvozilumožemopromatratisvojstvakao što je brzina, maksimalnabrzinai registarskaoznakakoja ga jednoznacnoidentificira. U tradicionalnimprogramskimjezicimaimalibismoopisalibismoto pomocudvijefloating point varijablei jednimstringom. U objektnoorijentiranomjezikukoristimokoncept klase da bismopodatke spakiraliu jedinstvenientitet, npr. ovako: class Car { String licensePlate ; // npr. "New York 543 A23" double speed; // u kilometrima na sat double maxSpeed; // u kilometrima na sat }

VarijablelicensePlate , speed i maxSpeed zovemovarijablamainstanci,varijablamaclanovimaili atributima. Atributinamkažušto neka klasa jest i koja sunjenasvojstva.

Objekt je specificnainstanca, primjerakneke klase, sa konkretnim(eventualnopromjenljivim) vrijednostimaatributa. Dok je klasa opcenitazamisao(blueprint) nekihobjekata, instancaje konkretniobjekt.

Kreiranje objekata uz pomocoperatora new

Da bismokreiralikonkretniobject neke klase, odnosnoinstanciraliklasu, koristimokljucnurijecnew izakoje slijedipozivtzv. konstruktoraklase. Pogledajmokako bismodeklariralii kreiralinovuvarijablutipaCar koju cemo nazvatic. Car c; c = new Car();

Prva rijec, Car, deklariratip varijablec. Klase su tipovipa kad varijablamadodjeljujemotipove, dodjeljujemoimzapravoklase te ihdeklariramona istinacinkaovarijablecijisu tipoviint, char, double itd.

Znak jednakostije operatorpridruživanja, a rijecnew je operatorkreiranja(instanciranja).

Na kraju, primijetimometoduCar(). Zagradenaznacujuda je to metoda, a ne tippodataka kao npr. rijecCar u prvomretku. To je konstruktor, metodakoja kreiranovuinstancuklase. O konstruktorimacet ucitiuskoro. Ako svojuklasui ne snabdijetekonstruktorima, kompajlerce umetnutisvoj default konstruktorbez argumenata.

Page 60: Java Predavanje I

Deklaracijutipa i kreiranjeinstanceobicnopišemou jednojnaredbi, npr.

Car c = new Car();

Separator pristupa clanovima .

Jednomkad ste kreiralinekiobjekt, potrebna vamje mogucnostpristupanjegovimclanovima(varijablamai metodama). Za to cete upotrijebitiseparator pristupa, tocku (.).Klasa Car imatriatributa:

licensePlate

speed

maxSpeed

Dakle, ako je c objekt tipaCar, c takoder imatriodgovarajucevarijable:

c.licensePlate

c.speed

c.maxSpeed

Koristiteihkao što bistekoristilibilokoju druguvarijablu. Na primjer: Car c = new Car(); c.licensePlate = "New York A45 636"; c.speed = 70.0; c.maxSpeed = 123.45; System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + "kilometara na sat.");

Separator . selektirapojedinogclana(varijablu, kao u ovomprimjeru, alitakoder imetodu) nekogobjekta po njegovomimenu.

Uporaba objekata unutar razlicitihklasa

Sljedeciprogramkreiranoviprimjerakautomobila(objekta klaseCar), dodjeljujevrijednostinjegovimvarijablamai ispisujerezultat. class CarTest { public static void main(String args[]) { Car c = new Car(); c.licensePlate = "New York A45 636"; c.speed = 70.0; c.maxSpeed = 123.45;

Page 61: Java Predavanje I

System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + "kilometara na sat."); } }

Ovaj programne zahtijevasamo klasuCarTest nego takoder i klasuCar. Da bistegamogliizvršiti, staviteklasuCar u datotekuCar.java., a klasuCarTest u datotekuCarTest.java. Obje datoteke neka buduu istomdirektoriju. Kompilirajteobjedatoteke na uobicajeninacini na kraju izvršiteCarTest . % javac Car.java% javac CarTest.java% java CarTestNew York A45 636 se krece brzinom od 70.0 kilometara na sat.%

Primijetiteda klasaCar nemamain() metodu, dakle ne možeteje izvršiti. Ona postojijedinotako da je pozivajudrugiprogramikoji imajuvlastitemain() metode.

Mnogeaplikacijekoje cete pisatikoristitce višeklasa. Uobicajenoje da se svaka klasastaviu svojuvlastitudatoteku. Uskoro cete naucitikoristitii pakete (packages) kakobistemogliorganiziratisvoje cesto korišteneklase unutarrazlicitihdirektorija. Za sadadržitesve datoteke sa izvornimprogramima(*.java) kao i one sa kompiliranimprogramima(*.class) unutarjednogdirektorija. Iako smo kompiliraliobje klaseodvojeno, dovoljnobi bilokompiliratisamo klasuCarTest jer ce kompajlervec sampronaciklasuCar.

Inicijaliziranje atributa

Atributise mogu(i najcešce trebaju) inicijaliziratiodmahcimsu deklarirani, istokao ilokalnevarijable. KlasuCar možemopreradititako da inicijaliziramonjeneattributeovako:

class Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat }

Sljedeciprogramkreiranoviautomobil(object tipaCar) i ispisujeodgovarajucepodatke. class CarTest2 { public static void main(String args[]) { Car c = new Car();

Page 62: Java Predavanje I

System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + "kilometara na sat."); } }

Rezultatizvršavanjabi bio % javac Car.java% javac CarTest.java% java CarTest se krece brzinom od 0.0 kilometara na sat.%

Metode

Tipovipodataka ne znacemnogoako ne možetes njimaništanapraviti. Zbog togapostoje metode. Dok atributikazjujušto klasa jest, metodekazujušto ona cini. Atributei metodenazivamozajednicimimenomclanovimaklase . Klase koje ste do sadaupoznaliimajuuglavnomsamo jednumetodu, main(). Medutim, opcenitoklase moguimatimnogorazlicitihmetoda. Na primjer, klasuCar možemosnabdjetimetodomkoja cesimulirativožnjumaksimalnombrzinom: class Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat void floorIt() { // ubrzanje do maksimalne brzine this.speed = this.maxSpeed; } }

Atributisu ostaliistikao prije, alisad je dodana metodakoju smo nazvalifloorIt().Pocinjekljucnomrijecivoid što je povratnitip (return type) te metode. Svaka metodamora imatipovratnitip koji možebitiilivoid ilinekitip podataka kao int, byte, float,String, iliklasa koju ste samidefinirali. Povratnitip pokazujevrstuvrijednostikoja cebitivracenapozivnojmetodinakonšto se pozvanametoda izvrši. Ako je povratnitip naprimjerint, onda tu metodumožetekoristitisvagdjegdje biste inacekoristililiteralilivarijablutipaint.Ako je povratnitipvoid, metodane vraca nikakvuvrijednost.

Ime ove metode je floorIt , a izanjegaslijedepraznezagrade. Kad bi ova metodaimalaargumente, onibi se naveliunutartihzagrada. Tijelometodenalazise unutarviticastihzagrada.

this.speed = this.maxSpeed;

Page 63: Java Predavanje I

Primijetiteda smo unutarklaseCar koristiliispred imenamembervarijablikljucnurijecthis to kako bismonaznacilida su to varijabletrenutnoaktivnogobjekta.

Pozivanje metoda

IzvanklaseCar, metodufloorIt() pozvatcete na istinacinkao što ste referenciraliattribute, dakle navodeciimeobjekta kojeg želite ubrzati i separator ., kao štopokazujesljedeciprimjer class CarTest3 { public static void main(String args[]) { Car c = new Car(); c.licensePlate = "New York A45 636"; c.maxSpeed = 123.45; System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); c.floorIt(); System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); } }

Izlaz: % javac Car.java% javac CarTest3.java% java CarTest3New York A45 636 se krece brzinom od 0.0 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.%

Metoda floorIt() je ugradenau klasuCar. Svaka metodau Java programumora, zarazlikuod C++ programa, pripadatinekoj klasi.

Implicirani this

UnutarklaseCar nijenužnododavatiimenimaatributaprefiksthis. jer se onpodrazumijeva. To je zato jer metodafloorIt() mora bitipozvanaod specificneinstanceklaseCar, a ta instancaznagdje su njenipodaci. Ilidrugimrijecima, svakiobjectizklase Car imasvojuvlastitufloorIt() metodu.

Page 64: Java Predavanje I

class Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } }

U pocetku, zbog jasnoce, preporucljivoje uvijekeksplicitnokoristitiprefiksthis, alikasnijese od toga možei odustati.

Member varijable nasuprot lokalnimvarijablama class Car { String licensePlate = ""; // member variabla double speed; = 0.0; // member variabla double maxSpeed; = 120.0; // member variabla boolean isSpeeding() { double excess; // lokalna variabla excess = this.maxSpeed - this.speed; if (excess < 0) return true; else return false; } }

Svidosadašnjiprogramibilisu vrlojednostavni. Svakije imaotocno jednuklasukoja jeimalapo jednumetodu, main(), i u njoj je bilasadržanasva programskalogikai njenevlastite, lokalne varijablekoje nisumoglebitireferenciraneizvanmetode.

S drugestrane, varijablelicensePlate , speed i maxSpeed klaseCar class, pripadajuobjektu tipaCar, a ne pojedinojmetodi. Definiranesu izvanbilokoje metode, aliunutarklase i nazivajuse membervarijableiliatributi(fields).

Member nijeistošto i membervarijablailiatribut. Memberiukljucujui attributei metode.

Prenošenje argumenata u metodu

Page 65: Java Predavanje I

Direktnopristupanjeatributimasmatrase lošomprogramerskomnavikom. Dobroobjektnoorijentiranoprogramiranjeprakticirapristuppoljimaiskljucivoputemmetoda.To vamomogucujeda promijeniteimplementacijuneke klase bez da ištamijenjateunjenomsucelju. To vamtakoder omogucujeugradivanjeraznihogranicenjana vrijednostiatributa.

Za to je potrebno imatimehanizamprenošenjainformacijau klasu, a to se radi pomocuargumenata. Na primjer, da bismodozvoliliostalimobjektimada mijenjajuvrijednostatributaspeed na nekomobjektu tipaCar, klasuCar možemosnabdijetimetodomkojucemo nazvatiaccelerate(). Ta metodane dozvoljavapojedinacnomautomobiluubrzavanjeiznadmaksimalnebrzineiliispod 0 km/h.

void accelerate(double deltaV) { this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; } }

Prva linijametodenazivase njenomsignaturom. Signaturavoid accelerate

(double deltaV) oznacavada metodaaccelerate() ne vraca nikakvuvrijednost, auzimajedan argumenttipadouble koji ce unutarte metodebitioznacenimenomdeltaV. Java prenosiargumentemetodamapo vrijednosti, ne po referenci.

Prenošenje argumenata u metodu,primjerclass Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; }

Page 66: Java Predavanje I

} } class CarTest4 { public static void main(String args[]) { Car c = new Car(); c.licensePlate = "New York A45 636"; c.maxSpeed = 123.45; System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); for (int i = 0; i < 15; i++) { c.accelerate(10.0); System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); } } }

Izlaz: % javac Car.java% javac CarTest4.java% java CarTest4New York A45 636 se krece brzinom od 0.0 kilometara na sat.New York A45 636 se krece brzinom od 10.0 kilometara na sat.New York A45 636 se krece brzinom od 20.0 kilometara na sat.New York A45 636 se krece brzinom od 30.0 kilometara na sat.New York A45 636 se krece brzinom od 40.0 kilometara na sat.New York A45 636 se krece brzinom od 50.0 kilometara na sat.New York A45 636 se krece brzinom od 60.0 kilometara na sat.New York A45 636 se krece brzinom od 70.0 kilometara na sat.New York A45 636 se krece brzinom od 80.0 kilometara na sat.New York A45 636 se krece brzinom od 90.0 kilometara na sat.New York A45 636 se krece brzinom od 100.0 kilometara na sat.New York A45 636 se krece brzinom od 110.0 kilometara na sat.New York A45 636 se krece brzinom od 120.0 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.%

Setter metode

Page 67: Java Predavanje I

Setter metode, zvanetakoder i mutator metode, imajuzadatak dodjeljivatiatributimavrijednostikoje se zadajuputemargumenata. Ove metodeu praviluvracajuvoid.Uobicajenoje koristitithis.name za referenciranjeatributai dodjeljivanjevrijednostiizistoimenogargumenta. Na primjer: class Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat // setter metoda za atribut licensePlate void setLicensePlate (String licensePlate ) { this.licensePlate = licensePlate ; } // setter metoda za atribut maxSpeed void setMaximumSpeed (double maxSpeed) { if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; } } }

Uporaba setter metoda, primjerclass CarTest5 { public static void main(String args[]) { Car c = new Car(); c.setLicensePlate ("New York A45 636"); c.setMaximumSpeed (123.45); System.out.println(c.licensePlate + " se krece brzinom od " + c.speed +

Page 68: Java Predavanje I

" kilometara na sat."); for (int i = 0; i < 15; i++) { c.accelerate(10.0); System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); } } }

Izlaz: % javac Car.java% javac CarTest5.java% java CarTest5New York A45 636 se krece brzinom od 0.0 kilometara na sat.New York A45 636 se krece brzinom od 10.0 kilometara na sat.New York A45 636 se krece brzinom od 20.0 kilometara na sat.New York A45 636 se krece brzinom od 30.0 kilometara na sat.New York A45 636 se krece brzinom od 40.0 kilometara na sat.New York A45 636 se krece brzinom od 50.0 kilometara na sat.New York A45 636 se krece brzinom od 60.0 kilometara na sat.New York A45 636 se krece brzinom od 70.0 kilometara na sat.New York A45 636 se krece brzinom od 80.0 kilometara na sat.New York A45 636 se krece brzinom od 90.0 kilometara na sat.New York A45 636 se krece brzinom od 100.0 kilometara na sat.New York A45 636 se krece brzinom od 110.0 kilometara na sat.New York A45 636 se krece brzinom od 120.0 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.%

Getter metode

Cesto je korisnoda metodavraca nekuvrijednostonoj klasikoja ju je pozvala. To seradi pomocukljucnerijecireturn na završetkutijelametode te naznakompovratnogtipa na njenompocetku. Na primjersljedecametodagetLicensePlate () vracatrenutacnuvrijednostatributalicensePlate u klasiCar.

String getLicensePlate () { return this.licensePlate ; }

Ovakve metodekoje samo vracajuvrijednostnekogatributanazivajuse getter iliaccessor metode. SignaturaString getLicensePlate () namkaže da metodagetLicensePlate () vraca vrijednosttipaString i ne tražinikakveargumente. Unutarmetode imamolinijureturn this.licensePlate ; koja vraca String sadržanu

Page 69: Java Predavanje I

atributulicensePlate onometko je metodupozvao. Povratnitip u return naredbimora odgovaratideklariranompovratnomtipuu signaturi.

Vracanje nekoliko vrijednosti izmetoda

Metoda ne moževratitivišeod jedne vrijednosti. Ne možetena primjervratitilicensePlate , speed i maxSpeed izistemetode. Moglibiste ih, naravno, složitiuobjekt neke vrste i njegavratiti, no to nijepravinacin. Pravilnobi bilodefiniratiodvojenemetode, getSpeed(), getMaxSpeed(), i getLicensePlate (), od kojihsvaka vracapo jednuodgovarajucuvrijednost.

class Car { String licensePlate = ""; // npr. "New York 543 A23" double speed = 0.0; // u kilometrima na sat double maxSpeed = 120.0; // u kilometrima na sat // getter (accessor) metode String getLicensePlate () { return this.licensePlate ; } double getMaxSpeed() { return this.maxSpeed; } double getSpeed() { return this.speed; } // setter metoda za atribut licensePlate void setLicensePlate (String licensePlate ) { this.licensePlate = licensePlate ; } // setter metoda za atribut maxSpeed void setMaximumSpeed (double maxSpeed) { if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed;

Page 70: Java Predavanje I

} if (this.speed < 0.0) { this.speed = 0.0; } } }

Uporaba getter metoda, primjerclass CarTest6 { public static void main(String args[]) { Car c = new Car(); c.setLicensePlate ("New York A45 636"); c.setMaximumSpeed (123.45); System.out.println(c.getLicensePlate () + " se krece brzinom od " + c.getSpeed() + " kilometara na sat."); for (int i = 0; i < 15; i++) { c.accelerate(10.0); System.out.println(c.getLicensePlate () + " se krece brzinom od " + c.getSpeed() + " kilometara na sat."); } } }

Primijetiteda više nema direktnogpristupaatributima!

Izlaz: % javac Car.java% javac CarTest5.java% java CarTest5New York A45 636 se krece brzinom od 0.0 kilometara na sat.New York A45 636 se krece brzinom od 10.0 kilometara na sat.New York A45 636 se krece brzinom od 20.0 kilometara na sat.New York A45 636 se krece brzinom od 30.0 kilometara na sat.New York A45 636 se krece brzinom od 40.0 kilometara na sat.New York A45 636 se krece brzinom od 50.0 kilometara na sat.New York A45 636 se krece brzinom od 60.0 kilometara na sat.New York A45 636 se krece brzinom od 70.0 kilometara na sat.New York A45 636 se krece brzinom od 80.0 kilometara na sat.New York A45 636 se krece brzinom od 90.0 kilometara na sat.New York A45 636 se krece brzinom od 100.0 kilometara na sat.New York A45 636 se krece brzinom od 110.0 kilometara na sat.New York A45 636 se krece brzinom od 120.0 kilometara na sat.

Page 71: Java Predavanje I

New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.New York A45 636 se krece brzinom od 123.45 kilometara na sat.%

Konstruktori

Konstruktorkreiranovuinstancuklase. On inicijalizirapotrebne varijablei obavljasveposlovekoji su potrebnida bi se klasa pripremilaza uporabu. Pogledajmoprimjer: Car c = new Car();

Ovdje je Car() konstruktorklaseCar. Konstruktorimauvijekisto imekao ipripadnaklasa.

Ako klasune snabdijemonikakvimkonstruktorom, Java osiguravajedan genericki, bezargumenata, tzv. noargs constructor, medutim, bolje je imativlastitekonstruktore. .Konstruktorse radi tako da se napišemetodakoja imaisto imekao iklasa. Zato se konstruktorklaseCar zoveCar().

Konstruktorinemajupovratnogtipa. Onizapravovracajuinstancusvoje klase, alito cineimplicitno, ne eksplicitno.

Sljedecametoda je konstruktorkoji inicijaliziravarijablukoja predstavljaregistarskuplocicu(licensePlate ) na prazanstring, brzinu(speed) na nulu, a maksimalnubrzinu(maxSpeed ) na 120.0 km/h.

Car() { this.licensePlate = ""; this.speed = 0.0; this.maxSpeed = 120.0; }

Još bolje, možetenapisatikonstruktorkoji primatriargumentai koristiihza inicijaliziranjeodgovarajucihvarijabli: Car(String licensePlate , double speed, double maxSpeed) { this.licensePlate = licensePlate ; this.speed = speed; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; if (speed > this.maxSpeed) this.speed = this.maxSpeed; if (speed < 0) this.speed = 0.0; else this.speed = speed; }

Ilimoždaželiteda inicijalnabrzinauvijekbude jedanaka nuli, a maksimalnabrzinairegistarskaplocicaspecificiraneargumentima:

Page 72: Java Predavanje I

Car(String licensePlate , double maxSpeed) { this.licensePlate = licensePlate ; this.speed = 0.0; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; }

Preradimojoš jednomklasuCar, tako da u njuugradimoove konstruktore: class Car { String licensePlate ; // npr. "New York 543 A23" double speed; // u kilometrima na sat double maxSpeed; // u kilometrima na sat Car() { this.licensePlate = ""; this.speed = 0.0; this.maxSpeed = 120.0; } Car(String licensePlate , double speed, double maxSpeed) { this.licensePlate = licensePlate ; this.speed = speed; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; if (speed > this.maxSpeed) this.speed = this.maxSpeed; if (speed < 0) this.speed = 0.0; else this.speed = speed; } Car(String licensePlate , double maxSpeed) { this.licensePlate = licensePlate ; this.speed = 0.0; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } // getter (accessor) metode String getLicensePlate () { return this.licensePlate ; } double getMaxSpeed() { return this.maxSpeed; } double getSpeed() { return this.speed; }

Page 73: Java Predavanje I

// setter metoda za atribut licensePlate void setLicensePlate (String licensePlate ) { this.licensePlate = licensePlate ; } // setter metoda za atribut maxSpeed void setMaximumSpeed (double maxSpeed) { if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; } } }

Uporaba konstruktora

Sljedeciprogram, CarTest7, koristitreciod navedenihkonstruktoraza inicijaliziranjeobjekata tipaCar umjestoda direktnopostavljavrijednosti. class CarTest7 { public static void main(String args[]) { Car c = new Car("New York A45 636", 123.45); System.out.println(c.getLicensePlate () + " se krece brzinom od " + c.getSpeed() + " kilometara na sat."); for (int i = 0; i < 15; i++) { c.accelerate(10.0); System.out.println(c.getLicensePlate () + " se krece brzinom od " + c.getSpeed() + " kilometara na sat."); } } }

Page 74: Java Predavanje I

Primijetiteda višene moratevoditiracunao atributimalicensePlate , speed imaxSpeed . Sve što trebate znatije kako konstruiratinoviprimjerakklaseCar i kakoispisatinjegovepodatke.

Postavljase pitanjejesu limetodesetLicensePlate () i setMaximumSpeed () zaistajoš potrebne kad se atributilicensePlate i maxSpeed postavljajuu konstruktorima.Odgovor ovisio tomeželimolidopustitinjihovomijenjanjejednomnakonšto je objektvec kreiran. Klase koje ne dopuštajupromjenuatributasvojihobjekata nakonšto sukreirani, nazivajuse nepromjenjivima(immutable). String je primjertakve klase. Nemožetepromijenitinjegovepodatke, možetesamo kreiratinoviobjekt tipaString .

Ogranicenja

Mogucnostimplementiranjaogranicenjajedan je od razlogaza davanjeprednostikorištenjukonstruktorai setter metodapred direktnimdohvacanjemvarijabli. Na primjer,u klasiCar važnoje osiguratida brzinanikadne bude veca od propisanemaksimalnebrzinei da nijedna ne bude manjaod nule.

Vec smo to vidjeliu primjerumetodeaccelerate() koja, na nacinkako je napravljena,nece pridijelitiautomobilubrzinuvecuod propisanemaksimalnebrzine.

void accelerate(double deltaV) { this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; } }

Takva se ogranicenjamoguugraditii u konstruktore. Na primjer, sljedecikonstruktor(treciu nizu) klaseCar osiguravada maksimalnabrzinane bude manjaod nule. Car(String licensePlate , double maxSpeed) { this.licensePlate = licensePlate ; this.speed = 0.0; if (maxSpeed >= 0.0) { this.maxSpeed = maxSpeed; } else { maxSpeed = 0.0; } }

Page 75: Java Predavanje I

Zaštita pristupa (access protection)

Globalnevarijablesu klasicniizvorpogrešaka u veciniprogramskihjezika. Nekanepoznatafunkcijaobicnopromijenivrijednostvarijabletamogdje programerto neocekuje.

Vecinaobjektnoorijentiranihjezika, Java takoder, omogucujezaštituvarijabliodmodifikacijeizvana. To vamdaje garancijuda ce vaša klasa ostatikonzistentnatako dugodok su njenevlastitemetodeu redu. Na primjer, u klasiCar željelibismobitisigurnida nijedan blok programskogkoda izneke drugeklase nece mocipromijenitivarijabluspeedtako da bude veca od maxSpeed. Želimopronacinacinda sljedeciprimjerkoda ucinimonelegalnim:

Car c = new Car("New York A234 567", 100.0); c.speed = 150.0;

Ovaj kod narušavauvjetkoji smo postavilina našuklasu. Želimoomogucitikompajleruda provede poštivanjetakvihuvjeta.

Klasa prezentiraprema vanjskomsvijetuodredenuslikusebe, tzv. sucelje. Ta slikakažeda klasa imaodredene metode i odredene atribute. Sve ostalo, ukljucjucidetaljniizgledifunkcioniranjemetoda je skriveno. Tako dugodok se ta slikane mijenja, programermožeslobodnomijenjatinacinna koji je ona implementirana. To izmeduostalogadozvoljavaprogrameruda mijenjai poboljšavaalgoritmekoje klasa koristibez bojaznida ce to na nekinepredvidljivnacinnarušitifunkcioniranjeklase. To se nazivaenkapsulacijom

Druginacinrazmišljanjao enkapsulacijije sljedeci. Zamislimoda klasa potpisuje«ugovor» sa ostalimklasamau programu. Taj ugovorkaže da klasa imaodredenejednoznacnoimenovanemetodesa zadanimtipovimaargumenatai povratnimtipovima.Ugovormožetakoder reci da klasa imaatributezadanogimenai zadanogtipa. Medutim,on ne kaže kako su te metode implementiranenitizabranjujepostojanjedrugihmetoda iatributakoje klasa moždakoristi. On samo garantiraprisutnostodredenihmetoda iatributapri cemune iskljucujeostalemetodeniatribute. Takav je ugovorimplementirankroz koncept zaštitepristupa.

Cetiri razine zaštite pristupa

Bilokoja dva razlicitaJava objekta mogujedan prema drugombitiu jednojod sljedecihrelacija:

Oba objekta su u istojklasiJedan objekt je u podklasiklase kojoj pripada drugiobjektOba objekta su u istompaketuNišta od navedenog(oba objekta su u nepovezanimklasamai razlicitimpaketima)

Page 76: Java Predavanje I

Ove relacijenisumedusobnoisklucive. Jedan objekt može, na primjer, bitiu podklasiklase drugogobjekta unutaristogpaketa.

Možete definiratikoji ce memberivaše klase, dakle atributii metode, bitidostupnidrugimobjektimaizsvake od ove cetirigrupeu odnosuna promatranuklasu.

· Želitelida bilokoji objekt možepozvatiodredenumetoduilipromijenitiodredeniatribut, oznacitcete taj memberkao public .

· Želitelida samo objekti izisteklase mogupozvatiodredenumetoduilipromijenitiodredeniatribut, oznacitcete taj memberkao private .

· Želitelipristupdozvolitisamo objektimakoji pripadajupodklasiilise nalazeunutaristogpaketa, oznacitcete ihkao protected .

· Konacno, želitelipristupdo odredenogmemberaomogucitisamo objektimaizistogpaketa, izostavitcete specifikacijupristupa. Taj default pristupnazivasepackage , alinemasvojukljucnurijec.

Po pretpostavci, sve klase koje pišetepripadajuistompaketu. Medutim, one nisuu istimpaketimasa Java klasamakao što je System iliApplet .

Atributimai metodamaoznacenimkao public možese pristupitis bilokojeg mjestaodakle je sam objekt vidljiv. Njihovbroj treba držatina minimumui onitrebajubitiuskopovezanisa kljucnomfunkcionalnošcuklase. Ne trebajuprikazivatidetaljeimplementacije. Osimrijetkihizuzetaka, atributtine bi trebalibitipublic .

Atributimai metodamaoznacenimkao private možepristupitijedinoobjekt sam ilidrugiobjekt isteklase (tzv. sibling).

Što treba biti public, a što private?

Klase su u pravilupublic .Varijablesu u praviluprivate .Konstruktorisu u pravilupublic .Getter i setter metodesu u pravilupublic .O ostalimmetodamatreba odlucivatiod slucajado slucaja.

Ova se pravilamogupo voljimijenjatiako za to postojirazlog. Medutim, dobro ihjeimatina umujer pokrivajuvelikuvecinuprakticnihpotreba.

Tri koristi od zaštite pristupa

Korištenjemogucnostizaštitepodataka osiguravatribitnekoristi:

1. Omogucujeuvodenjeogranicenjana stanjeobjekta

Page 77: Java Predavanje I

2. Osiguravajednostavnijekorisnickosucelje. Programerikorisnicine morajuznatisve što se nalaziunutarklase, dovoljnoimje da poznajujavne(public) segmente.

3. Odvaja suceljeod implementacije, cimese omogucujeda se jedno mijenjanezavisnood drugoga(zamislimonpr. da smo odlucilida registarskaplocica,licensePlate višene bude String nego instancanoveklaseLicensePlate ).

Primjer zaštite pristupa

Evo kako bi klasaCar u praksizaistaizgledala. Primijetiteda su sviatributisadaprivate , a možeimse pristupitijedinokroz metodekoje su deklariranekao public .To je uobicajeniobrazac za pisanjeklasa u Javi. class Car { private String licensePlate ; // npr. "New York 543 A23" private double speed; // u kilometrima na sat private double maxSpeed; // u kilometrima na sat public Car() { this.licensePlate = ""; this.speed = 0.0; this.maxSpeed = 120.0; } public Car(String licensePlate , double speed, double maxSpeed) { this.licensePlate = licensePlate ; this.speed = speed; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; if (speed > this.maxSpeed) this.speed = this.maxSpeed; if (speed < 0) this.speed = 0.0; else this.speed = speed; } public Car(String licensePlate , double maxSpeed) { this.licensePlate = licensePlate ; this.speed = 0.0; if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } // getter (accessor) metode public String getLicensePlate () { return this.licensePlate ; } public double getMaxSpeed() { return this.maxSpeed; }

Page 78: Java Predavanje I

public double getSpeed() { return this.speed; } // setter metoda za atribut licensePlate public void setLicensePlate (String licensePlate ) { this.licensePlate = licensePlate ; } // setter metoda za atribut maxSpeed public void setMaximumSpeed (double maxSpeed) { if (maxSpeed > 0) this.maxSpeed = maxSpeed; else this.maxSpeed = 0.0; } public void floorIt() { // ubrzanje do maksimalne brzine speed = maxSpeed; } public void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0; } } }

Pokušajmosada izneke drugeklase direktnopristupitiatributimaklaseCar da vidimošto ce se dogoditi:

class CarTest8 { public static void main(String args[]) { Car c = new Car("New York A45 636", 100.0); c.licensePlate = "New York A45 636"; c.speed = 0.0; c.maxSpeed = 123.45; System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat."); c.floorIt(); System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + " kilometara na sat.");

Page 79: Java Predavanje I

} }

Evo što bi se dogodiloako pokušate kompiliratiCarTest8 uzrevidiranuklasuCar:

% javac Car.java% javac CarTest8.javaCarTest8.java:7: Variable licensePlate in class Car not accessible from class CarTest8. c.licensePlate = "New York A45 636"; ^CarTest8.java:8: Variable speed in class Car not accessible from class CarTest8. c.speed = 0.0; ^CarTest8.java:9: Variable maxSpeed in class Car not accessible from class CarTest8. c.maxSpeed = 123.45; ^CarTest8.java:11: Variable licensePlate in class Car not accessible from class CarTest8. System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + ^CarTest8.java:11: Variable speed in class Car not accessible from class CarTest8. System.out.println(c.licensePlate + " is moving at " + c.speed + ^CarTest8.java:16: Variable licensePlate in class Car not accessible from class CarTest8. System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + ^CarTest8.java:16: Variable speed in class Car not accessible from class CarTest8. System.out.println(c.licensePlate + " se krece brzinom od " + c.speed + ^7 errors%

U mnogimslucajevimabit ce takoder metodakoje su private , protected iliimajudefault pristup. Zajednickise one nazivajunon-public metode.

U mnogimslucajevimaatributi(varijable) bit ce protected ilice imatidefault pristup, doksu, medutim, public varijablerijetke. Takva koncepcijaomogucujeprogramerimapromjenuimplementacijeklase i istovremenozadržavanjenepromijenjenogsuceljapremavanjskomsvijetu.

Page 80: Java Predavanje I

Promjena implementacije

Pretpostavimoda želimoprilagoditiklasuCar za uporabuu simulacijiprometavelikoggrada kao što je New York, gdje ce svakirealniautomobilna cestibitireprezentiranpojednimobjektomtipaCar. To je velikakolicinaobjekata i poželjnoje smanjitikolicinuzauzetememorije. Svakiobjekt tipaCar zauzimaoko 60 byteova, što najvišeovisioduljiniStringaza registarskuplocicu. Na numerickimvarijablamamožemouštedjeti8byteovapo objektuako floatumjestodouble, pri cemuce suceljeostatiisto: class Car { private String licensePlate ; // npr. "New York 543 A23" private float speed; // u kilometrima na sat private float maxSpeed; // u kilometrima na sat public Car() { this.licensePlate = ""; this.speed = 0.0F; this.maxSpeed = 120.0F; } public Car(String licensePlate , double speed, double maxSpeed) { this.licensePlate = licensePlate ; this.speed = (float) speed; if (maxSpeed > 0) this.maxSpeed = (float) maxSpeed; else this.maxSpeed = 0.0F; if (speed > this.maxSpeed) this.speed = (float) this.maxSpeed; if (speed < 0) this.speed = 0.0F; else this.speed = (float) speed; } public Car(String licensePlate , double maxSpeed) { this.licensePlate = licensePlate ; this.speed = 0.0F; if (maxSpeed > 0) this.maxSpeed = (float) maxSpeed; else this.maxSpeed = 0.0F; } // getter (accessor) metode public String getLicensePlate () { return this.licensePlate ; } public double getMaxSpeed() { return this.maxSpeed; } public double getSpeed() { return this.speed; }

Page 81: Java Predavanje I

// setter metoda za atribut licensePlate public void setLicensePlate (String licensePlate ) { this.licensePlate = licensePlate ; } // setter metoda za atribut maxSpeed public void setMaximumSpeed (double maxSpeed) { if (maxSpeed > 0) this.maxSpeed = (float) maxSpeed; else this.maxSpeed = 0.0F; } public void floorIt() { // ubrzanje do maksimalne brzine this.speed = this.maxSpeed; } public void accelerate(double deltaV) { // ubrzanje za zadani deltaV this.speed = this.speed + (float) deltaV; if (this.speed > this.maxSpeed) { this.speed = this.maxSpeed; } if (this.speed < 0.0) { this.speed = 0.0F; } } }

Buducida je suceljeostalo isto, ni jedna drugaklasa koja ovisio ovoj klasine mora semijenjatipa cak niponovnokompilirati. Ovdje bismomogliicidaljepa napravitivlastituklasuLicensePlate koja bi doz voljavaASCII znakoveod jednogbytea umjestoUnicodeznakovaod dva bytea i tako dalje.

Page 82: Java Predavanje I

Peto predavanje appletiHTML, jezik za oblikovanje web stranica - URL, jedinstvena adresa dokumentadijelovi URLa linkovi relativni URLovi applet Hello World što je applet?HTML oznaka <applet> - odabir pozicije na stranici alternativni tekstimenovanje appleta JAR arhive HTML oznaka <object > - velicina appletaHTML oznaka <param> - obrada nepoznatog broja parametara sigurnost appleta

što applet može ciniti? s kim applet može komunicirati ? koliko CPU vremenaapplet dobija ? sigurnost i social engineering sprecavnje hakerskih napada krozapplete Životni ciklus appleta metode init(), start(), stop() i destroy ()koordinatni sustav objekti klase Graphics crtanje linija crtanje pravokutnikapunjenje pravokutnika brisanje pravokutnika elipse i kružnice primjer,bullseye poligoni višestruke linije (polylines ) ucitavanje slika metodegetCodeBase () i getDocumentBase () prikaz slike u pravoj velicini skaliranje slika

boje sistemske boje fontovi odabir oblika i velicine fonta klasa FontMetrics

HTML - jezik za oblikovanje webstranica

HTMLznaciHyperTextMarkup Language. HTMLdatoteke su tekstualnedatoteke ukojimasu dijeloviteksta oznacenipomocu tagova (oznaika). Ekstenzijatakve datltekeje.htm ili.html. Evo primjerajedne jednostavneHTMLdatoteke: <html><head><title>Moj prvi HTML Document</title></head><body><h1>Zaglavlje velicine 1</h1> Ovdje se piše vidljivi dio dokumenta.Ovako se <STRONG>naglašava</STRONG> sadržaj. </body></html>

Elementikoji su zatvoreniu trokutastimzagradamakao <html>, <head>, and <title>

>zovuse oznake(tags). Oznake se mogupisativelikimilimalimslovima(nisucasesensitive).

Vecinaoznakaimazatvarackoji definiradoseg oznake. Zatvaracimaisto imekao ioznaka, alimuje dodan slash (/) nakonotvorenezagrade. Na primjer, </html>, </head>, i </title> su zatvaraci. Tekst izmedu<title> i </title>, Moj prvi HTMLdokument izgornjegprimjera, predstavljanaslovstranice.

Oznake se u pravilumogupisatiunutardrugihoznaka, alise ne mogupreklapati.

Page 83: Java Predavanje I

Neke oznakeimajudodatne atribute(to nijeistošto i atributiu Javi). Atributje imeizakojeg slijediznakjednakostii vrijednost, a zajednos oznakompobližeodreduje nacininterpretacijeteksta. Na primjer, da bismozaglavljeH1 centrirali, možemokoristitiatributALIGN i datimuvrijednostcenter; tj.

<h1 align="center">Zaglavlje velicine 1</h1>

Atributisu takoder case-insensitive. Dvostrukinavodnicioko vrijednostisu opcionalniosimako vrijednostsadržibjeline.Za potpunuinformacijuo HTML-u pogledajteHyperTextMarkup Languagena W3C - World Wide Web Consortium.

URL jedinstvena adresa dokumenta

URLje kraticaza uniformresource locator. To je pointerna odredeniresursna nekojlokacijina Internetu. Na primjer, http://student.math.hr/~vedris/ ilihttp://student.math.hr/~vedris/java/java-predavanje-05.htm su URLovi.

URLspecificiraprotokolza pristupposlužitelju, npr. ftp, http, imeposlužitelja, lokacijudatoteke na poslužiteljui eventualnolokacijunekogmjesta(sidro, anchor) unutardatoteke. Opci oblikURLaje

protocol://hostname[:port]/path/filename#section

Dijelovi URL-a

Protokol je uglavnomjedan od sljedecih:

file datoteka na lokalnomdiskuftp ftp poslužiteljhttp World Wide Web poslužiteljhttps secure http, Web poslužiteljsa zaštitompodatakagopher gopherposlužiteljmailto emailadresanews Usenetnewsgrouptelnet vezana serviszasnovanna Telnet-uWAIS WAIS poslužiteljrmi remotemethodinvocation

Hostname (imeposlužitelja) mora bitivaljanomrežnoimehosta na Internetu, a možebitii IP adresa, npr student.math.hr, www.ora.com or shock.njit.edu alii204.29.207.217 ili128.235.252.184.

Port (broj porta) je opcionalanZa http je default port 80.

Path (put do datoteke) pokazujeodredenidirektorijna poslužitelju. Formirase u odnosuna pocetnidirektorijservisa(server root, document root) koji ne mora biti(i obicno

Page 84: Java Predavanje I

nije) nužnopocetnidirektorij(root) sustavadatoteka (file system). Cijelisustavdatotekaobicnose ne otkrivajavnosti.

Filename (imedatoteke) pokazujena odredenudatotekuunutarnavedenogdirektorija.Na mnogimposlužiteljimauobicajenoje da se, ako je imedatoteke izostavljeno,podrazumijevadatoteka index.html. Na drugimace se dobitiispisdirektorija, a nekice poslatiporukuo pogreški.

Section (mjestounutardatoteke) referenciraimenovanosidro (anchor) unutarHTMLdokumenta. Ono se oznacavaovako:

<A NAME="xtocid1902914">Comments</A>

URLkoji pokazujena to sidro sadržinakon imenadatoteke još i imesidra ispredkojegje znak#, na primjerovako: http://metalab.unc.edu/javafaq/javafaq.html#xtocid1902914

Linkovi

Da bisteu HTMLdatotecinapravililinkod dijelateksta, zatvoritcete ga unutaroznaka<A> i </A>. Oznaci<A> dodat cete atributHREF i u njemunavestiurlna koji želiteusmjeritivaš link. Na primjer, Ovaj link pokazuje na <A HREF="http://student.math.hr/~vedris/java/java-predavanja/java-predavanje-05.htm">peto predavanje iz Jave</A> na PMF-u.

Vecinabrowsera ce tako oznacenitekst prikazatipodvuceno, u plavojililjubicastojboji,no to ovisio podešenostibrowsera. Klikanjemna taj dio teksta prikazatce se resurskojije navedenu pripadnomURLu.

Relativni URL-ovi

Whena web browser reads an HTMLdocument, it has a great deal of informationaboutthe document. Thisincludesthe protocolused to retrievethe document, the nameof thehost where the documentlives, and the path to thatdocumenton the host. Most of thisislikelyto be the same for manyof the URLsinthatdocument. RelativeURLsinherittheprotocol, hostname, and path of theirparent documentrather thanrespecifyingit ineach<A HREF> tag. Thusifanypiece of the URL is missing, it is assumedto be the same asthat of the documentinwhichthe URLis found. Sucha URL is calleda relative URL. Incontrast, a completelyspecifiedURLis calledan absoluteURL. Na primjer, akopregledavajucidokumenthttp://metalab.unc.edu/javafaq/books.html kliknetena sljedecihiperlink:

Page 85: Java Predavanje I

<a href="javafaq.html">the FAQ</A>

Browserce odrezatibooks.html sa završetkaizrazahttp://metalab.unc.edu/javafaq/books.html i ostavitihttp://metalab.unc.edu/javafaq/, a zatimpripojitijavafaq.html na završetakizrazahttp://metalab.unc.edu/javafaq/ dabi dobio http://metalab.unc.edu/javafaq/javafaq.html.

Ako relativnilinkpocinjesa /, onda je on relativanu odnosuna document root umjestona trenutnoaktivnudatoteku.. Znaci, ako prilikompregledavanjadatoteke http://metalab.unc.edu/javafaq/books.html kliknetena hiperlink

<a href="/boutell/faq/www_faq.html">

browser ce odbaciti/javafaq/javafaq.html i pripojiti/boutell/faq/www_faq.html na završetakizrazahttp://metalab.unc.edu/ da bi dobio http://metalab.unc.edu/boutell/faq/www_faq.html.

RelativniURLoviimajuraznihprednosti. Smanjujukolicinupotrebnogtipkanja, ališto jejoš važnije, omogucujupremiještanjecijelihstabalaHTMLdokumenatabez narušavanjanjihovihinternihlinkova

Applet Hello World

Jedan od razlogapopularnostiJave je mogucnostpisanjainteraktivnihappletana webu.ProgramHelloWorld nijebaš interaktivan, no pogledajmosvejednonjegovuweb verziju:

import java.applet.Applet; import java.awt.Graphics; public class HelloWorldApplet extends Applet { public void paint(Graphics g) { g.drawString("Hello world!", 50, 25); } }

Primjecujeteda je appletHelloWorld nešto složenijinegoaplikacija, a imai neštododatnogposla da bi ga se pokrenulo.

Najprijespremiteizvornikod u datotekuHelloWorldApplet .java. Kompilirajteje nauobicajeninacin. Dobitcete klasuHelloWorldApplet .class. Da biste je pokrenuli,potrebno je napravitiHTMLdokumentkoji ce sadržatinaš applet. Evo jednogtakvogdokumenta:

<HTML><HEAD><TITLE> HelloWorldApplet </TITLE></HEAD> <BODY>

Page 86: Java Predavanje I

Ovo je applet HelloWorld:<P><applet code="HelloWorldApplet .class" width="150" height="50"></applet></BODY></HTML>

Spremitetu datotekupod imenomHelloWorldApplet .html u istidirektorijgdje senalazidatoteka HelloWorldApplet .class. Pogledajtetu HTMLdatotekupomocunekogstandardnog(Java enabled) browsera kao što je Internet Explorer, Netscape iliApplet viewer koji se nalaziu JDK paketu. Vidjetcete stringHelloWorld unutarpravokutnikavelicine150x50 tocaka.

Ako je kompilacijaprošlabez pogreške, a ne viditestringHelloWorld, provjeriteda lijeklasa u istomdirektorijukao i HTMLdatoteka. Takoder buditesigurnida koristitedovoljnonovuverzijubrowsera, koja podržavaJavu. Ako niApplet Viewer ne vidivašapplet, pogreška je vjerojatnou appletu, a ne u browseru.

Što je Applet?

Appletje malaaplikacijakoja je zamišljenada se ne izvršavasamostalno, negounutardrugeaplikacije, tipicnounutarweb browsera. Klasa java.applet.Applet osiguravastandardnosuceljeizmeduappleta i njihoveokoline. Evo što se sve nazivaappletom:

malaaplikacijasigurniprogramkoji se izvršavaunutarweb browserapodklasa klasejava.applet.Appletinstancapodklase od java.applet.Applet

Ovo je hijerarhijanjenihnadklasa: java.lang.Object | +---java.awt.Component | +---java.awt.Container | +---java.awt.Panel | +---java.applet.Applet

HTML oznaka <APPLET>

Appletise u HTMLstranicuugradujupomocuoznaka<APPLET> i </APPLET>. Oznaka<APPLET> se ponaša licnokao <IMG>. Kompiliranaklasa koja sadržiappletovkodreferencirase pomocuatributaCODE. Njezinaje lokacijarelativnau odnosuna izvorni

Page 87: Java Predavanje I

HTMLdokument. Na primjer, ako pregledavatestranicuhttp://metalab.unc.edu/javafaq/index.html, a ta stranicareferenciraappletpomocuCODE="Animation.class", onda bi datoteka Animation.class trebalabitina adresihttp://metalab.unc.edu/javafaq/animation.class.

Medutim, suprotnood uobicajeneprakse, ako se appletnalazinegdjedrugdje, a ne uistomdirektorijukao i HTMLdokument, ne možeteu atributu<CODE> jednostavnonavestinjegovURL, negoumjestotoga moratekoristitijoš i atributCODEBASE u kojemcete navestidio URLakoji pokazujeput do appleta. Na primjer, da je HTMLstranicasnašimappletomHelloWorldApplet bilanapisanakao

<APPLET CODE="HelloWorldApplet .class" CODEBASE="classes" WIDTH=200 HEIGHT=200></APPLET>

onda bi browser pokušao tražitiklasuHelloWorldApplet .class u poddirektorijuclassesonogdirektorijau kojemse nalaziHTMLdokument. Takoder, ako napišemo <APPLET CODE="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200></APPLET>

onda ce browser pokušatinacinašuklasuna adresihttp://student.math.hr/~vedris/java/classes/HelloWorldApplet .class neovisnoo tomegdje seHTMLdokumentnalazi.

Ukratko, browser pokušavarekonstruiratiURLpo formuli(CODEBASE + "/" + CODE).Jednomkad je URLformiran, vrijedesva pravilao relativnimi apsolutnimURLovima.

Ekstenziju.classmožeteu atributuCODE izostavitii pisatisamo imeklase. Na primjer

<APPLET CODE="HelloWorldApplet " CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200></APPLET>

Ako appletnijeu default paketu, potrebno je pisatipuno imepaketa. Na primjer <APPLET CODE="hr.math.student.vedris.myApplets.HelloWorldApplet " CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200></APPLET>

U ovomslucajubrowser ce tražitiklasuna adresihttp://student.math.hr/~vedris/java/classes/hr/math/student/vedris/myApplets/HelloWorldApplet.class, pa strukturadirektorijana serverumora bitinapravljenau skladus hijerarhijompaketa.

AtributiHEIGHT i WIDTH rade na istinacinkao i kod oznakeIMG, odredujucivelicinupravokutnikakoji ce browser rezerviratiza prikazappleta. Velicinesu specificiraneupikselimai obaveznesu.

Page 88: Java Predavanje I

Odabir pozicije na stranici

Oznaka<APPLET> imanekolikoatributaza definiranjepozicijeappletana stranici.

AtributALIGN odreduje kako je appletovpravokutnikpozicioniranna straniceu odnosuna drugeelemente. Dozvoljenevrijednostiovogatributasu LEFT, RIGHT, TOP, TEXTTOP ,MIDDLE, ABSMIDDLE , BASELINE , BOTTOM i ABSBOTTOM . Atributje opcionalan.

U atributimaHSPACE i VSPACE moguceje odreditikolicinupraznogprostora (upikselima) izmeduappleta i okolnogteksta. I ovisu atributiopcionalni.

<applet code="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" width=200 height=200ALIGN=RIGHT HSPACE=5 VSPACE=10></APPLET>

AtributiALIGN, HSPACE , i VSPACE identicnisu onimakoji se koristeu oznaci<IMG>.

Alternativni tekst

Oznaka<APPLET> imai atributALT. Browserga koristiu slucajuako iznekograzloganemožeizvestiapplet. Na primjer, ako je u browseruiskljucenaopcijaza dozvoluizvodenjaJava appleta, trebao bi se prikazatitekst navedenu atributuALT. AtributALT jeopcionalan. <applet code="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" width=200 height=200ALIGN=RIGHT HSPACE=5 VSPACE=10ALT="Hello World!"></APPLET>

Ovimse atributomne koristestarijibrowserikoji uopce ne razumijuoznaku<APPLET>.Oni umjestotoga prikazujucistitekst koji se nalaziizmeduoznake<APPLET> i njenogzatvaraca, </APPLET>. S drugestrane, browserikoji su Java enabled ignoriratce tajtekst. Na primjer, sljedeciHTMLfragmentispisujestringHello World! svima, dakle iJava enabled i non-Java enabled browserima. <applet code="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" width=200 height=200ALIGN=RIGHT HSPACE=5 VSPACE=10ALT="Hello World!">Hello World!<P></APPLET>

Page 89: Java Predavanje I

Imenovanje appleta

Appletuse unutarweb stranicemožedati imekako bi mogaokomuniciratis drugimappletima. To se radi pomocuatributaNAME. Na primjer, <applet code="HelloWorldApplet .class" Name=Applet_01CODEBASE="http://student.math.hr/~vedris/java/classes" width=200 height=200ALIGN=RIGHT HSPACE=5 VSPACE=10ALT="Hello World!">Hello World!<P></APPLET>

JAR arhive

Sve slike, zvukovei klase koje su potrebne za izvršavanjevašegappletamožetespakiratiu JAR arhivui tako ihucitatiodjednom, a ne svakuposebno. Timesmanjujetebrojkonekcijakoje browser mora ostvaritida bi dobio sve što mutreba. Ako se appletovaklasa nalaziu takvoj arhivi, onda cete oznaci<APPLET> dodati još i atribut<ARCHIVE>.Na primjer:

<APPLET CODE=HelloWorldApplet CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200 ARCHIVE="HelloWorld.jar"><hr>Hello World!<hr></APPLET>

U ovomprimjeruappletovaklasa je i daljeHelloWorldApplet . Medutim, browser ceodgovarajucudatotekupotražitiu arhiviHelloWorld.jar a ne u zasebnojdatoteciHelloWorldApplet .class.

Arhivaje spakiranana nekiod uobicajenihnacina, na primjer:

% jar cf HelloWorld.jar HelloWorldApplet .class added manifestadding: HelloWorldApplet .class(in = 384) (out= 271)(deflated 29%)%

Želimolipogledatišto imau arhivi, možemoto ucinitiovako: % jar tf HelloWorld.jarMETA-INF/META-INF/MANIFEST.MFHelloWorldApplet .class%

Page 90: Java Predavanje I

HTML oznaka <OBJECT>

HTML4.0 uvodiumjestooznake<APPLET> novuoznaku<OBJECT>. UmjestoatributaCODE uvodise atributCLASSID . Na primjer: <OBJECT CLASSID="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200ALIGN=RIGHT HSPACE=5 VSPACE=10></OBJECT>

Atribut<OBJECT> omogucujei ukljucivanjeActiveXkontrolai drugihaktivnihelemenata,no za Javunamto ne treba. Podržavajuje samo najnovijeverzijebrowsera i smatrase dace oznaka<APPLET> bitijoš dosta vremenaaktualna.

Možete imatii obje oznake, jednuunutardruge, ovako:

<OBJECT CLASSID="HelloWorldApplet .class" WIDTH=200 HEIGHT=200CODEBASE="http://student.math.hr/~vedris/java/classes"><APPLET CODE="HelloWorldApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" WIDTH=200 HEIGHT=200></APPLET></OBJECT>

Browserikoji razumijuoznaku<OBJECT> ignoriratce sadržaj izmedunje i njenogzatvaraca, dok ce ga ostaliprikazati. ElementiPARAM su istiza obje oznake.

Velicina appleta

Velicinaprostora koju zauzimaappletdok se izvršavaunutarweb browsera zadanajeatributimaHEIGHTi WIDTHi sam applet je ne možepromijeniti. Medutim, možedoznatikolikaje ta velicina, što muje potrebno npr. da ne bi crtao izvanzadanogprostora.

Velicinaappletadoznajese pomocumetodegetSize() koju klasajava.applet.Applet nasljedujeod svoje nadklasejava.awt.Component . Ovametodavraca objekt tipajava.awt.Dimension . Takav objekt imadva atributatipaint, to su height i width. Pogledajmosljedeciprimjerappletakoji ispisujesvojedimenzije.

import java.applet.*; import java.awt.*; public class SizeApplet extends Applet { public void paint(Graphics g) { Dimension appletSize = this.getSize();

Page 91: Java Predavanje I

int appletHeight = appletSize.height; int appletWidth = appletSize.width; g.drawString("Applet je " + appletHeight + " pt visok i " + appletWidth + " pt sirok.", 15, appletHeight /2); } }

Prmijetitekako je ovdje visinaappletauzetau obzirkod odlucivanjagdje smjestititekst.Korištenjeappletovedimenzijeza odredivanjemjestaobjekata na stranicicesto jekorištenatehnika.

HTML oznaka <param>

Parametrise izHTMLdokumentaprenose appletimapomocupara NAME=VALUE i oznaci<PARAM> koja se smještaizmeduoznake<APPLET> i njenogzatvaraca. Unutarsamogappletavrijednostiproslijedeneputemoznake<PARAM> citajuse pomocumetodegetParameter () izklasejava.applet.Applet .

Sljedeciprogramdemonstriraispisstringovadobivenihsa HTMLstranice. Stringkoji seispisujeje ovdje vrijednostparametra"Message".

import java.applet.*; import java.awt.*; public class DrawStringApplet extends Applet { public void paint(Graphics g) { String inputFromPage = this.getParameter ("Message"); g.drawString(inputFromPage , 50, 25); } }

Na HTMLstraniciimatcemo parametar"Message" cijace vrijednostbitistring"Kakoste?". <HTML><HEAD><TITLE>DrawStringApplet </TITLE>

Page 92: Java Predavanje I

</HEAD> <BODY>Ovo je applet DrawStringApplet :<P><APPLET code="DrawStringApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH="300" HEIGHT="50"><PARAM name="Message" value="Kako ste?">Ova stranica ce biti vrlo dosadna ako vaš browser ne razumije Javu.</APPLET></BODY></HTML>

Promijenimolivrijednostparametra, applet ce ispisivatiodgovarajucistringbez potrebeda ga iznovakompiliramo.

Ovaj je appletvrloslicanappletuHelloWorldApplet . Medutim, umjestoda fiksnokodiramoporukukoju on ispisuje, ona ce bitiucitanau varijabluinputFromPageizravnoizklauzulePARAM u HTMLu.

MetodigetParameter () daje se kao argumentimeparametrasa HTMLstranice, a onace vratitinjegovuvrijednost. I argumenti povratnavrijednostsu stringovi. Ako jepotreban drugacijitip, moratcete osiguratipotrebne konverzije.

Oznaka<PARAM> stavljase izmedu<APPLET> i </APPLET>. Ona imasvoje atribute,NAME i VALUE koji identificirajunjegovoimei vrijednost. Oba se stavljajuu dvostrukenavodnikeako sadrže praznine.

Broj parametaranijeogranicen. Možete imatipo voljimnogooznaka<PARAM> kojeapplet i ne mora sve iskoristiti. Višakce bitina sigurannacinignoriran.

Obrada nepoznatog broja parametara

Ponekad je potrebno obraditinepoznatibroj parametara. U tom slucaju, parametritrebajubitiimenovanina nekipredvidljivnacin. Na primjer, <PARAM name="Line1" value="There once was a man from Japan"><PARAM name="Line2" value="Whose poetry never would scan"><PARAM name="Line3" value="When asked reasons why,"><PARAM name="Line4" value="He replied, with a sigh:"><PARAM name="Line5" value="I always try to get as many syllables into the last line as I can.">

Sljedeciprogramispisujeovaj tekst znajucinacinna koji su parametriimenovani("Line"+ numlines ).

Page 93: Java Predavanje I

Metoda paint() ispisujesvakistringna ekran, povecavajuciy pozicijuza 15 pikselasvakiput.

import java.applet.*; import java.awt.*; public class PoetryApplet extends Applet { String[] poem = new String[101]; int numlines; public void init() { String nextline; for (numlines = 1; numlines < poem.length; numlines++) { nextline = this.getParameter ("Line" + numlines); if (nextline == null) break; poem[numlines] = nextline; } numlines--; } public void paint(Graphics g) { int y = 15; for (int i=1; i <= numlines; i++) { g.drawString(poem[i], 5, y); y += 15; } } }

Ovako bi izgledaoHTMLdokument <HTML><HEAD><TITLE>PoetryApplet </TITLE></HEAD> <BODY>Ovo je applet PoetryApplet :<P><APPLET code="PoetryApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH="350" HEIGHT="100"><PARAM name="Line1" value="There once was a man from Japan"><PARAM name="Line2" value="Whose poetry never would scan"><PARAM name="Line3" value="When asked reasons why,"><PARAM name="Line4" value="He replied, with a sigh:"><PARAM name="Line5" value="I always try to get as many syllablesinto the last line as I can."> Ova stranica ce biti vrlo dosadna ako vas browser ne razumije Javu.

Page 94: Java Predavanje I

</APPLET></BODY></HTML>

Procesiranjeproizvoljnelisteparametarabez znanjao nacinuformiranjanjihovihimenazasad nijemoguce.

Sigurnost appleta

Suprotnoraširenommišljenju, Java appletisu sigurniza korisnikekoji surfajupointernetu. Nece vamse dogoditida vamapplet formatiradisk iliunesevirusu sustav.Zbog mehanizamavirtualnemašine, hvatanjaiznimakai tako dalje, Java appletiiaplikacijesu u praksi sigurnijiod tradicionalnihprogramskihjezika.

Appletiimajuugradenadodatna sigurnosnaogranicenjakako bi zaštitilikorisnikeodprogramerskihpogrešaka, alii od virusa. To je implementiranopomocuklasejava.lang.SecurityManager . Razlicitepodklase ove klase osiguravajurazlicitasigurnosnaokruženjana razlicitimvirtualnimmašinama. Loša strana toga je uvodenjeraznihrestrikcijana akcijekoje apletmožeciniti.

Što applet može ciniti?

Appletmože:

crtatislikena web stranicikreiratinoviprostor i crtatiu njegareproduciratizvukprimatiinputod korisnikapreko tastatureilimišaPovezivatise na server s kojeg je došao te slatii primatipodatke s tog servera.

Sve što s timogranicenjimamožeteucinitimoguceje ucinitiizappleta. S drugestrane,appletne može:

pisatipodatke na bilokoji disk na hostucitatipodatke s hostovogdiska bez korisnikovedozvole. U nekimokruženjima,npr Netscape, appletne možecitatipodatke s korisnikovogdiska cak niuzdozvolubrisatidatotekecitatiilipisatipo bilokojemblokumemorije, cak i u nezašticenimoperacijskimsustavimakao što je MacOS. Sav pristupmemorijistrogo je kontroliran.

Page 95: Java Predavanje I

povezivatise s hostovimana Internetu, osimsa hostoms kojeg dolazipozivatidirektnonative APIunositivirusena hostsrušitihostovsistem(smatrase da je tako, no tu tvrdnjutreba uzetis rezervom).

S kim applet može komunicirati?

Po pretpostavciappletmožeostvaritimrežnukonekcijusamo na stroj (file system) skojeg je ucitan. Taj sistemse zovecodebase. Appletne možekomuniciratis bilokojimstrojemna internetu. Sva komunikacijate vrstemora bitiposredovanapreko poslužitelja.

Razlogje taj što bi inaceappletmogaolansiratis neke mašinenapade na internumrežuorganizacije. To bi pogotovobio problemza mašineunutarfirewallakoje su obicnokonfiguriranetako da jedne drugimavjeruju. Takoder, to bi omogucilohakerimada lakšesakrijusvojupravulokaciju.

HotJava, Sunovappletvieweri InternetExplorer(aline i Netscape) dozvoljavajuvamdaappletudopustiteostvarivanjekonekcijana proizvoljnistroj, alito nijedefault opcija.

Koliko CPU vremena applet dobija?

Jedan od razlogaza briguoko zlonamjernihappleta je mogucnostpretjeraneuporabeCPU vremena, što je problemna, recimoMac-u, a nešto manjena WindowsNT iliSolaris. U svakomslucaju, appletmoženatjeratikorisnikada npr. prisilnougasibrowseršto možeuzrokovatiodredenigubitakpodataka.

Moguceje takoder da appletkoristiCPU vrijemeza svrhekoje nisuodmahvidljive. Naprimjer, nekipopularniappletmoželansirtinapad na password datotekupomocutzv.kineskelutrije. Ili, appletkoji simuliraneku igrumožeu backgroundulansiratithread kojipokušavaslucajnimpristupomrazbitienkripcijuneke datoteke. U tom slucajumogaobiostvaritikonekcijuprema svomserverui poslatikljucnatrag. Što je appletpopularniji, toje vjerojatnostpronalaženjakljucaveca. Ipak, Java kod se lako dekompilira, pa se takviappletimoguotkriti.

Sigurnost i social engineering

Suprotnopopularnomvjerovanju, vecinaprovalana kompjutorenijerezultatbriljantnihideja i velikogznanjanegorazlicitihoblikakrade passworda, od pretraživanjasmeca doprijevareputemlansiranjaprozora na kojempiše da je vezaprekinutapa se tražiupispassworda (pogledajteza primjerovaj TricksterApplet ). Takve aktivnostipoznatesupod nazivomsocial engineering., u slobodnomprijevodu"lovu mutnom".

Page 96: Java Predavanje I

Слика

Sprecavanje hakerskih napada krozapplete

Da bi se sprijeciletakve zabune, prozoriappletasu uvijeksnabdjeveninekomuocljivomporukomkao: "Warning: AppletWindow" ili"UnsignedJava AppletWindow." To,naravno, još uvijekne garantirada netko nece upisatisvoj password ne citajucišto pišena prozoru. Obrazovanjekorisnikana prvomje mjestuu racunalnojsigurnosti.

Životni ciklus appleta

1. broser ucitavaHTMLstranicui pronalazioznaku<APPLET>2. browser analiziraoznaku<APPLET> tražeciatributCODE i eventualnoCODEBASE .3. browser ucitava.classdatotekuappletasa prethodnopronadenogURLa4. browser konvertirabytoveu Java klasu, dakle objekt od java.lang.Class

object.5. browser instanciraappletovuklasukako bi formiraoobjekt-applet. To zahtijeva

da applet imakonstruktorbez argumenata.6. browser pozivaappletovuinit() metodu.7. browser pozivaappletovustart() metodu.8. dok se applet izvršava, browser mušalje informacijeo dogadajimakoji su mu

namijenjeni, npr. klikmišem, pritisakna tipkuitd. preko appletovehandleEvent() metode. Dogadajikoji rade update kažuappletuda se iznovaprikaže(repaint)

9. browser pozivaappletovustop() metodu.10. browser pozivaappletovudestroy() metodu.

Metode init(), start(), stop() idestroy()

Sviappletiimajusljedececetirimetode: public void init();public void start();

Page 97: Java Predavanje I

public void stop();public void destroy();

Imajuihjer ihimanjihovanadklasa, java.applet.Applet (pored ostalih, naravno). Unadklasisu one samo deklariranei ne cineništa, npr. public void init() {}

Podklase mogu(alii ne moraju) prekritiove metodekako bi ispunileodredene zadace uodredeno vrijeme. Na primjer, metodainit() je dobro mjestoza ucitavanjeparametaraizoznake<PARAM> jer ona ce bitipozvanaupravou trenutkukad se appletpocneizvršavati. because it's calledexactlyonce whenthe applet starts up. Buducida sudeklariraneu nadklasi, Web browser ce pozvatite metodekad mutrebaju, cak nineznajucijesu liimplementiraneu appletuiliu nadklasi. To je dobar primjerpolimorfizma.

Metoda start() se pozivabar jednomu appletovomživotnomciklusu, onda kad seapplet starta ilirestarta. Ponekad to možebitii višenego jednom. Mnogiappletinemajueksplicitnustart()metodunego je nasljedujuiznadklase. Najcešce se koristizastartanjethreadova koje ce applet trebatidok se izvršava.

Metoda stop() se pozivabar jednom, kad browser napustistranicukoja sadržiapplet.Kad se na njuopet vrati, pozvatce se metodastart(). Koristise za zaustavljanjezaustavljanjethreadovakoje appletkoristi. Kad je applet zaustavljen, ne bi trebao trošitiCPU cikluse.

Metoda destroy() se pozivatocno jednomu životnomciklusuappleta, upravoprijenegobrowser otpustiapplet. Koristise uglavnomza završnocišcenje. is calledexactlyonce inan applet's life, justbefore the browser unloadsthe applet. Thismethodisgenerallyused to performanyfinalclean-up.

U JDK appletvieweru, izboropcijeRestartpozivastop() i onda start(). OpcijaReloadpozivaredomstop(), destroy() i init(). (Normalnobi byte kodovitrebalibitiponovnoucitanizajednos HTMLdokumentom, no u Netscapeu postojiproblemstim.)

Appletovemetodestart() i stop() nemajuvezesa istoimenimmetodamaizklasejava.lang.Thread.

Vaš vlastitikod pozivatce povremenometodestart() i stop(). S drugestrane,pozivanjemetodainit() i destroy() nijedobra ideja. Browser (ilidrugaokolina) jetaj koji ce pozvatiove metode.

Koordinatni sustav

Java korististandardni, dvodimenzionalnisustavza racunalnugrafiku. Prvividljivipikselugornjemlijevomkutuappletovepodlogeje tocka (0, 0). Koordinatese povecavajuprema desno i prema dolje.

Page 98: Java Predavanje I

Слика

Objekti klase Graphics

Crtanjese u Javiobavljapomocuobjekata klasejava.awt.Graphics .

U pocetku cete koristitigrafickiobjekt koji se daje kao argumentmetodipaint(Graphics g)koju klasajava.applet.Applet nasljedujeod klasejava.awt.Container . Kasnijecete upoznatii ostaleobjekte klaseGraphics . Sve štosada budete naucilio crtanjuu appletimavrijedii za objekte kao što su paneli, okviri,gumbi, podlogeitd.

Svakiobjekt tipaGraphics imasvoj vlastitikoordinatnisustavi metodeza crtanjestringova, linija, pravokutnika, krugova, poligonai tako dalje. Crtanjeu Javipocinjeodpojedinacnogobjekta tipaGraphics . Pristuptom objektuostvarujetepreko metodepaint(Graphics g) u svomappletu.. Svakipozivmetodeza crtanjeizgledatceotprilikeovako:

g.drawString("Hello World", 0, 50)

gdje je g specificniobjekt tipaGraphics pomocukojeg crtate.

Zbog razumljivosti, g ce namuvijekznacitivec postojeciobjekt klaseGraphics .Naravnoda, kao i kod svake drugemetode, možetekoristitii drugaimenaza odredenikontekst, npr myGraphics iliappletGraphics i slicno.

Crtanje linija

Page 99: Java Predavanje I

Za crtanjeravnelinijepozovitemetodudrawline() cija je signatura: public abstract void drawLine(int x1, int y1, int x2, int y2)

Pozivase ovako: g.drawLine(x1, y1, x2, y2)

Pri tomesu (x1, y1) i (x2, y2) krajnjetocke linije, a g je objekt tipaGraphicspomocukojeg crtate. Pogledajmoprogramkoji ce nacrtatilinijudijagonalnoprekoappleta. import java.applet.*; import java.awt.*; public class SimpleLine extends Applet { public void paint(Graphics g) { g.drawLine(0, 0, this.getSize().width, this.getSize().height); } } <APPLET code="SimpleLine.class"HEIGHT="50" WIDTH="100">CODEBASE="http://student.math.hr/~vedris/java/classes"</APPLET>

Crtanje pravokutnika

Pravokutnikcrtate pomocuobjekta g izklaseGraphics i metodedrawRect() cija jesignatura: public void drawRect(int x, int y, int width, int height)

Pozivase ovako: public void drawRect(x, y, width, height)

Prva dva argumentasu koordinategornjeglijevoguglapravokutnika, dok su ostaladvanjegovaširinai visina. Sljedeciprogramcrta pravokutnikoko appleta.

Page 100: Java Predavanje I

import java.applet.*; import java.awt.*; public class RectangleApplet extends Applet { public void paint(Graphics g) { g.drawRect(0, 0, this.getSize().width - 1, this.getSize().height - 1); } } <APPLET code="RectangleApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="50" WIDTH="40"></APPLET>

Prisjetitese da je getSize().width širinapravokutnika, a getSize().height

njegovavisina.

Zašto crtamopravokutniksamo do getSize().height-1 i getSize().width-1?

Zato jer se lijevigornjiugaonalaziu tocki (0, 0), a ne u (1, 1). To znacida apletvelicine100 x 200 pikselaukljucujetocke s x-koordinatamaizmedu0 i 99, a ne izmedu0 i 100.Slicno, y-koordinatesu izmedu0 i 199 ukljucivo, a ne izmedu0 i 200.

Za crtanjekvadratane postojiposebmadrawSquare() metoda. Kvadrat je naprostopravokutnikkojemusu duljinai širinaiste.

Punjenje pravokutnika

Metoda drawRect() crta prazanpravokutnik. Ako ga želiteispuniti, koristitemetodufillRect() cija je signatura: public abstract void fillRect(int x, int y, int width, int height)

Sljedeciprogramcrta ispunjenipravokutniku centruappleta. Morat cemo razlikovativelicinupravokutnikaod velicineappleta. import java.applet.*; import java.awt.*; public class FillAndCenter extends Applet {

Page 101: Java Predavanje I

public void paint(Graphics g) { int appletHeight = this.getSize().height; int appletWidth = this.getSize().width; int rectHeight = appletHeight /3; int rectWidth = appletWidth/3; int rectTop = (appletHeight - rectHeight)/2; int rectLeft = (appletWidth - rectWidth)/2; g.fillRect(rectLeft, rectTop, rectWidth-1, rectHeight-1); } } <APPLET code="FillAndCenter .class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="50" WIDTH="40"></APPLET>

Brisanje pravokutnika

Nacrtanipravokutnikmožese izbrisatimetodomclearRect() cija je signatura: public abstract void clearRect(int x, int y, int width, int height)

Pogledajmoprogramkoji koristiovumetoduda bi prikazaobljeskanjepravokutnikanaekranu. import java.applet.*; import java.awt.*; public class Blink extends Applet { public void paint(Graphics g) { int appletHeight = this.getSize().height; int appletWidth = this.getSize().width; int rectHeight = appletHeight /3; int rectWidth = appletWidth/3; int rectTop = (appletHeight - rectHeight)/2; int rectLeft = (appletWidth - rectWidth)/2; for (int i=0; i < 1000000; i++) { g.fillRect(rectLeft, rectTop, rectWidth-1, rectHeight-1); g.clearRect(rectLeft, rectTop, rectWidth-1, rectHeight-1);

Page 102: Java Predavanje I

} } } <APPLET code="Blink.class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="50" WIDTH="40"></APPLET>

Ovo nije nacinkako se u praksi radi animacija, no to je najbolješto možemoucinitidokne naucimoraditis threadovima.

Elipse i kružnice

Elipsei kružnicecrtajuse pomocumetodedrawOval(), a punepomocumetodefillOval() cije su signature: public abstract void drawOval(int x, int y, int width, int height) public abstract void fillOval(int x, int y, int width, int height)

Argumentiovihmetodapredstavljajukoordinategornjeglijevoguglate širinui visinupravokutnikakojemuje elipsaupisana(pogledajtesliku)

Слика

Nema posebne metodeza crtanjekružnice. Kružnicaje naprostoelipsaupisanaukvadrat.

Java takoder sadržimetodeza crtanjepraznihi ispunjenihlukova. To su metodedrawArc() i fillArc(). Ponašajuse slicnokao drawOval() i fillOval().Signaturesu im:

public abstract void drawArc(int x, int y, int width,

Page 103: Java Predavanje I

int height, int startAngle, int arcAngle) public abstract void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle)

U pravokutnikse upisujenajvecimoguciluk. Lokacijalukaod 0 stupnjeva, kao i to da lije luknacrtanu smijerukazaljkena satu iliprotivnomje neovisnoo platformi.

Primjer bullseye

Ovo je jednostavniappletkoji crta nizispunjenih, koncentricnihkrugova, naizmjenicnocrvenihi bijelih. import java.applet.*;import java.awt.*; public class Bullseye extends Applet { public void paint(Graphics g) { int rectLeft, rectTop, rectHeight, rectWidth; int appletHeight = this.getSize().height; int appletWidth = this.getSize().width; for (int i=8; i >= 0; i--) { if ((i % 2) == 0) g.setColor(Color.red); else g.setColor(Color.white); // Centriramo pravokutnik rectHeight = appletHeight *i/8; rectWidth = appletWidth*i/8; rectLeft = appletWidth/2 - i*appletWidth/16; rectTop = appletHeight /2 - i*appletHeight /16; g.fillOval(rectLeft, rectTop, rectWidth, rectHeight); } } } <APPLET code="Bullseye.class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="100" WIDTH="100"></APPLET>

Page 104: Java Predavanje I

Klasa koja crta ovuslikuvelikaje 684 bytea. EkvivalentnaGIF slikaimalabi 1,850bytea, dakle gotovotriputa više.

Poligoni

U Javisu pravokutnicidefiniranipomocupozicijesvojeggornjeglijevogugla, visineiširine. Implicitnose podrazumijevada pravokutniknijerotiran. Ako jest, moramogasmatratispecijalnimslucajempoligona, tj. objekta izklase java.awt.Polygon .

Poligonisu definiranisvojimvrhovimabez dodatnihpretpostavkiosimda ležeudvodimenzionalnojravnini.OsnovnikonstruktorklasePolygon je

public Polygon(int[] xpoints, int[] ypoints, int npoints)

xpoints je poljekoje sadržix koordinatevrhovapoligona, a ypoints poljekoje sadržiy koordinatenjegovihvrhova. Oba polja trebajuimatiduljinunpoints . Pogledajmoprimjerkonstrukcijetrokutas pravimkutemu ishodištu:

int[] xpoints = {0, 3, 0};int[] ypoints = {0, 0, 4};Polygon myTriangle = new Polygon(xpoints, ypoints, 3);

Da biste taj trokut i nacrtali, možeteunutarsvojepaint() metodepozvatiizklasejava.awt.Graphics metodudrawPoligon() sa signaturom public void drawPolygon(Polygon p)

ovako : g.drawPolygon(myTriangle);

Na raspolaganjuvamje i drugaverzijametodedrawPolygon() koja imasignaturu: public abstract void drawPolygon(int[] xPoints, int[] yPoints, int nPoints)

a poziva se ovako : g.drawPolygon(xpoints, ypoints, xpoints.length);

Postoji takoder i polimorfnametodafillPolygon(). Sintaksaje ocekivana: g.fillPolygon(myTriangle);g.fillPolygon(xpoints, ypoints, xpoints.length());

Page 105: Java Predavanje I

Višestruke linije (polylines)

Java automatskizatvarapoligonekoje nacrta (desna slika).

Слика

Ako želitecrtatiotvorenepoligone(lijevaslika), koristitcete metodudrawPolyline ().

public abstract void drawPolyline (int[] xPoints, int[] yPoints, int nPoints)

Ucitavanje slika

Poligoni, elipse, linijei tekstovipokrivajuvelikidio grafickihpotreba. Ono što namjoštreba su slike. U Javito su GIF iliJPEG datoteke koje pokrivajuuglavnomsve.

Slikekoje se prikazujupomocuJava appletaucitavajuse s mrežepreko URLakojipokazujena datotekusa slikom. Mogubitispremljenena web poslužitelju, lokalnomdiskuilibilogdje kamo appletmožedoci preko URLa. Treba pazitida buduspremljenetamogdje ce ihkorisnikkoji gledaappletmocidohvatiti. URLkoji pokazujena vašlokalnidisk moždaradi dok testirateapplet, alimoždanece bitiod koristiza nekogatkodolazis mreže.

U praviluse, iako to nijenužno, slikestavljajuu istidirektorijgdje je applet iliu onaj gdjeje HTMLdatoteka. Staviteslikuu appletovdirektorijako ce se ona koristitiu sviminstancamaapleta, a u HTMLdirektorijako ce razliciteinstanceappletakoristitirazliciteslike. Treca mogucnostje stavitisve slikeu nekiposebnidirektoriji onda preko <PARAM>

oznakereci appletugdje su.

Ako znatetocan URLslike, možeteje ucitatipomocumetodegetImage():

URL imageURL = new URL("http://www.prenhall.com/logo.gif");java.awt.Image img = this.getImage(imageURL);

Iliu jednojnaredbi: Image img = this.getImage(new URL("http://www.prenhall.com/logo.gif"));

Metoda getImage() pripada klasijava.applet.Applet . Za URL objekte koristimoklasujava.net.URL. Provjeravajteu svojimprogramimada su te klase importiraneakoihkoristite.

Page 106: Java Predavanje I

Metode getCodeBase() igetDocumentBase()

Ako ne znatetocan URLslike, aliznatenjenoimei da se ona nalaziu istomdirektorijukao i applet, možetekoristitidruguvarijantumetodegetImage() koja uzimaURLi imedatoteke. KoristiteappletovumetodugetCodeBase() da dobijeteURLappletovogdirektorija: Image img = this.getImage(this.getCodeBase(), "test.gif");

Metoda getCodeBase() vraca objekt tipaURL koji pokazujena direktorijizkojeg jeappletdošao.

Konacno, ako je slikaspremljenau istomdirektorijukao i HTMLdatoteka, možeteuporabitiistumetodugetImage(), alijoj dajte getDocumentBase (). To ce vratitiURLkoji pokazujena direktoriju kojemse nalaziHTMLstranicakoja je pozvalaapplet.

Image img = this.getImage(this.getDocumentBase (), "test.gif");

Ako se slikaucitavas Interneta, možepotrajatidok se sva ne ucita. U praviluvas to nemora brinutii možeteje crtatiodmahnakonspajanjana nekiod spomenutihURLova.Java ce se sama pobrinutiza update kako podaci budustizali, bez vaše intervencije.

Sve slikekoje vaš appletkoristiucitajteu metodiinit(). Nemjte ihucitavatiunutarmetodepaint() jer ce se inacesvakiput kad se appletobnovislikeucitavatiizpocetka.

Prikaz slike u pravoj velicini

Jednomkad je slikaucitana, nacrtajteje u metodipaint() pomocumetodedrawImage() ovako: g.drawImage(img, x, y, io)

Pri tome je img objekt klaseImage koji ste vec ucitaliunutarmetodeinit(). Nadalje,x je apscisa, a y ordinatalijevoggornjeguglaslike. Argumentio je objekt klase kojaimplementirainterfaceImageObserver . Taj interfacepropisujekako Java rukujeasinhronimobnavljanjemslikekad se ona ucitavasa udaljenogracunala. Buducida klasajava.applet.Applet implementiraImageObserver za sad samo stavitekljucnurijecthis za odgovarajuciargumentmetodedrawImage() cimenaznacujeteda želitekoristitiImageObserver trenutnoaktivnogappleta.

Metoda paint() koja ne radi ništaosimcrtanjaslikeu pravoj velicini, pocevšiodgornjeglijevoguglaizgledalabi ovako:

public void paint(Graphics g) { g.drawImage(img, 0, 0, this);}

Page 107: Java Predavanje I

Skaliranje slika

Slikumožetei skaliratiunutarzadanogpravokutnikakoristecisljedecuverzijumetodedrawImage(): public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver io)

pri cemusu width i height dimenzijepravokutnikau koji želitesmjestitisliku. Ostaliargumentisu istikao i prije. Ako skaliranjenijeu skladus proporcijamaslike, on možeizgledatiizobliceno.

Da biste izbjegliizoblicenja, koristitemetodegetHeight() i getWidth() koje vamdaju pravuvelicinuslike. Tada je možeteskaliratina odgovarajucinacin. Na primjer, akoje želitesmanjitina cetvrtinu, postupilibisteovako:

g.drawImage(img, 0, 0, img.getWidth(this)/4, img.getHeight(this)/4, this);

Sljedeciprogramucitavaslikui povecavaje za zadanifaktor: import java.awt.*;import java.applet.*; public class MagnifyImage extends Applet { private Image image; private int scaleFactor; public void init() { String filename = this.getParameter ("imagefile"); this.image = this.getImage(this.getCodeBase(), filename); this.scaleFactor = Integer.parseInt(this.getParameter("scalefactor")); } public void paint (Graphics g) { int width = this.image.getWidth(this); int height = this.image.getHeight(this); int scaledWidth = width * this.scaleFactor; int scaledHeight = height * this.scaleFactor; g.drawImage(this.image, 0, 0, scaledWidth, scaledHeight , this); } } <APPLET CODE="MagnifyImage .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="MagnifyImage .jar"WIDTH=200 HEIGHT=200><param name="imagefile" value="java.gif"><param name="scalefactor" value=2></APPLET>

Page 108: Java Predavanje I

Metoda init() citadva parametraod kojihjedan daje imeslike, a drugifaktorpovecanja. Metoda paint() racunaomjerei zatimcrta sliku. Možda se pitatezašto se skaliranjeobavljau metodipaint() a ne vec u metodiinit()kad se velicinaslikeu pravilui onako ne mijenjadinamicki.

Razlogje taj što za vrijemeizvršavanjametodeinit() slikavjerojatnonece bitido krajaucitana, a u tom slucajumetodegetWidth() i getHeight() ce vratiti 1 i skaliranjeseuopce nece obaviti. Pokušajte to vidjetišto se dogada ako racunanjepremjestimoumetoduinit():

import java.applet.*;import java.awt.*; public class MagnifyImage extends Applet { Image theImage; int scaledWidth, scaledHeight ; public void init() { String filename = this.getParameter ("imagefile"); theImage = this.getImage(this.getDocumentBase (), filename); int scalefactor = Integer.valueOf(this.getParameter("scalefactor")).intValue(); int width = theImage.getWidth(this); int height = theImage.getHeight(this); scaledWidth = width * scalefactor; scaledHeight = height * scalefactor; } public void paint (Graphics g) { g.drawImage(theImage, 0, 0, scaledWidth, scaledHeight , this); } }

Boje

Boje su u Javiinstanceklasejava.awt.Color. Uvjeritese da ste importiralitu klasuprijenegokoristiteboje koje nisudefault. Nove boje možetekreiratikoristeciRGBtrojke kao kod web stranica. Na primjer: Color medGray = new Color(127, 127, 127);Color cream = new Color(255, 231, 187);Color lightGreen = new Color(0, 55, 0);

Page 109: Java Predavanje I

Nekolikonajcešcekorištenihboja dostupnesu i po imenu. To su:

Color.black

Color.blue

Color.cyan

Color.darkGray

Color.gray

Color.green

Color.lightGray

Color.magenta

Color.orange

Color.pink

Color.red

Color.white

Color.yellow

Boja nijesvojstvoodredenogpravokutnika, stringai slicno, nego je to dio objekta tipaGraphics koji obavljaodredena crtanja. Za promjenuboje potrebno je promijenitibojuvašegobjekta izGraphics . Tada ce sve što crtate poprimititu boju, do sljedecepromjene.

Kad se appletpocne izvršavati, njegovaboja je crna. Možete je promijenitistavljajucinpr. g.setColor(Color.red). Vratitcete je na pocetnuako pozoveteg.setColor(Color.black). Sljedecikod bi proizveoružicastistring, a izanjegazeleni:

g.setColor(Color.pink);g.drawString("This String is pink!", 50, 25);g.setColor(Color.green);g.drawString("This String is green!", 50, 50);

Primijetiteda ce sve nakonove zadnjelinijebitizeleno. Da bistese vratilina pocetnuboju, možetekoristitiki metodugetColor() na primjerovako: Color oldColor = g.getColor();g.setColor(Color.pink);g.drawString("This String is pink!", 50, 25);g.setColor(Color.green);g.drawString("This String is green!", 50, 50);g.setColor(oldColor);

Sistemske boje

U Javi1.1 i dalje, postojiklasajava.awt.SystemColor koja je podklasa odjava.awt.Color i omogucujekorištenjeboja native komponenata. Na primjer, akoželitepozadinuvašet appletaucinitiistomkao i pozadinuprozora, možeteu init()

metodipostupitiovako: public void paint (Graphics g) { g.setColor(SystemColor.control); g.fillRect(0, 0, this.getSize().width, this.getSize().height); }

Page 110: Java Predavanje I

Dostupnesu sljedecesistemskeboje:

SystemColor.desktop // Background color of desktop

SystemColor.activeCaption // Background color for captions

SystemColor.activeCaptionText // Text color for captions

SystemColor.activeCaptionBorder // Border color for captiontext

SystemColor.inactiveCaption // Background color for inactivecaptions

SystemColor.inactiveCaptionText // Text color for inactivecaptions

SystemColor.inactiveCaptionBorder // Border color for inactivecaptions

SystemColor.window // Background for windows

SystemColor.windowBorder // Color of window border frame

SystemColor.windowText // Text color inside windows

SystemColor.menu // Background for menus

SystemColor.menuText // Text color for menus

SystemColor.text // background color for text

SystemColor.textText // text color for text

SystemColor.textHighlight // background color for highlightedtext

SystemColor.textHighlightText // text color for highlightedtext

SystemColor.control // Background color for controls

SystemColor.controlText // Text color for controls

SystemColor.controlLtHighlight // Light highlight color forcontrols

SystemColor.controlHighlight // Highlight color for controls

SystemColor.controlShadow // Shadow color for controls

SystemColor.controlDkShadow // Dark shadow color for controls

SystemColor.inactiveControlText // Text color for inactivecontrols

SystemColor.scrollbar // Background color for scrollbars

SystemColor.info // Background color for spot-help text

SystemColor.infoText // Text color for spot-help text

Fontovi

Vidjeliste primjercrtanjateksta u appletuHelloWorldApplet . PozivatemetodudrawString() za objekt tipaGraphics . Toj metodidajete argumenttipaString kao ikoordinatex i y. Ako je g objekt tipaGraphics onda je sintaksasljedeca: g.drawString(String s, int x, int y)

Stringje ovdje tekst koji hocete ispisati. Integerix i y su koordinatedonjeglijevoguglateksta. Tekst ce bitiispisaniznadi desno od te tocke. Izuzetaksu slovasa indeksimakojimogubitiispisanii ispod crte.

Do sad smo koristilidefaultfont, no Java dozvoljavai izborfonta. Garantirase postojanjeseriffontakao što je Timeskojemuse pristupapreko imena"Serif", zatim

Page 111: Java Predavanje I

neproporcionalnogfontakao što je Courier, koji se referencirakao "Mono" i, konacno,sans seriffontakao Helveticakojemse pristupakao "SansSerif".

Sljedeciapplet ispisujelistudostupnihfontovana racunalugdje se izvršava. KoristisemetodomgetFontList() it klasejava.awt.Toolkit . Ova metodavraca poljestringovakoji sadrže imenadostupnihfontova. Svifontoviimplementiranina vašemracunalumoždai nisudostupniappletu.

import java.awt.*;import java.applet.*; public class FontList extends Applet { String[] availableFonts ; public void init () { Toolkit t = Toolkit.getDefaultToolkit (); availableFonts = t.getFontList(); } public void paint(Graphics g) { for (int i = 0; i < availableFonts .length; i++) { g.drawString(availableFonts [i], 5, 15*(i+1)); } } } <APPLET code="FontList.class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="200" WIDTH="100"></APPLET>

Odabir oblika i velicine fonta

Page 112: Java Predavanje I

Odabir oblikafontaje jednostavan. Kreiratenoviobjekt tipaFont. Zatimpozoveteg.setFont(Font f). Da biste instanciraliklasuFont uporabitekonstruktor: public Font(String name, int style, int size)

Ovdje je name imeodgovarajucefamilijefontova, npr. "Serif", "SansSerif", ili"Mono"dok je size velicinafontau tockama. U kompjutorskojgraficitocka je istošto i piksel.Nadalje, style je mnemonickakonstantaizjava.awt.Font koja kaže da lije tekstbold, italiciliobican. Te konstantesu Font.PLAIN, Font.BOLD, i Font.ITALIC .Sljedeciprogramispisujesve dostupnefontoveu prirodnomoblikui u 14 tocaka bold. import java.applet.*;import java.awt.*; public class FancyFontList extends Applet { String[] availableFonts ; public void init () { Toolkit t = Toolkit.getDefaultToolkit (); availableFonts = t.getFontList(); } public void paint(Graphics g) { for (int i = 0; i < availableFonts .length; i++) { Font f = new Font(availableFonts [i], Font.BOLD, 14); g.setFont(f); g.drawString(availableFonts [i], 5, 15*i + 15); } } } <APPLET code="FancyFontList .class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="200" WIDTH="100"></APPLET>

Klasa FontMetrics

Page 113: Java Predavanje I

Primijetiteda se tekst nece sam prebacivatiu noviredak, cak niako u njegastavite\n.Za takve tekstovepogodnijeje koristitikomponentekao što je TextAreao kojimaceteucitiposlije. Ipak, da bistedoznalikolikoprostora zauzimavaš tekst koristitcete objekteizklasejava.awt.FontMetrics .

Sljedeciprimjerproširujenaš appletDrawString . Ako tekst prelaziširinuappleta, on cese prelomitiu noviredak.

Da bismodobilimetrikutrenutacnoggrafickogobjekta, koristitcemo metodujava.awt.Graphics.getFontMetrics (). Iz klasejava.awt.FontMetricsprimijenitcemo na taj objekt metodustringWidth(String s) koja ce namvratitiširinustringa, a onda getLeading() da dobijemoodgovarajuciprored. Na raspolaganjuje još mnogometodakojimase utvrdujuvelicineteksta, no ove ce bitidovoljne.

Konacno, trebat ce namklasajava.util.StringTokenizer da bismostringrazbilinapojedinerijeci.

import java.applet.*; import java.awt.*; import java.util.*; public class WrapTextApplet extends Applet { String inputFromPage ; public void init() { this.inputFromPage = this.getParameter ("Text"); } public void paint(Graphics g) { int i = 0; int linewidth = 0; int margin = 5; StringBuffer sb = new StringBuffer (); FontMetrics fm = g.getFontMetrics (); StringTokenizer st = new StringTokenizer (inputFromPage ); while (st.hasMoreTokens ()) { String nextword = st.nextToken(); if (fm.stringWidth(sb.toString() + nextword) + margin < this.getSize().width) { sb.append(nextword); sb.append(' '); } else if (sb.length() == 0) { g.drawString(nextword, margin, ++i*fm.getHeight()); } else { g.drawString(sb.toString(), margin, ++i*fm.getHeight()); sb = new StringBuffer (nextword + " "); } }

Page 114: Java Predavanje I

if (sb.length() > 0) { g.drawString(sb.toString(), margin, ++i*fm.getHeight()); } } } <APPLET code="WrapTextApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"HEIGHT="200" WIDTH="100"><PARAM name="Text" value="Jako dugi tekst koji se treba prelomiti"></APPLET>

Page 115: Java Predavanje I

Šesto predavanje - komponenteŠto su komponente ? labele tri koraka u dodavanju komponente gdje je metodapaint()? metode klase Label buttoni akcije na buttonima primjer appleta saakcijom na buttonu razliciti obrasci za dogadaje višestruki ActionListenerimetode za buttone Action naredbe više buttona u istom appletu unutarnje klasekao EventListeneri tekstualna polja primjer tekstualnih polja u Javi TextAreaklasa TextComponent sucelje TextListener i klasa TextEvent klasa Canvas klasaChoice metode klase Choice klasa ItemListener klasa Checkbox dogadaji izklase Checkbox klasa CheckboxGroup primjer CheckboxGroup klasa Listmetode klase List dogadaji klase List klasa Scrollbar

Što su komponente?

Komponentesu sastavnicegrafickogkorisnickogsucelja(GUI, graphical userinterface).

U Javi, komponentesu podklase od java.awt.Component , a najcešcekorištenesu:

Canvas

TextField

TextArea

Label

List

Button

Choice

Checkbox

Frame

JButton

JLabel

JComboBox

JMenu

Sve komponentese iscrtavajusamostalno(bez pisanjaposebne paint() metode.

Labele

Najjednostavnijakomponentaje java.awt.Label. U sljedecemprimjeruje Label l

redak teksta koji je read-only. import java.applet.*; import java.awt.*; public class HelloContainer extends Applet { public void init() { Label l;

Page 116: Java Predavanje I

l = new Label("Hello Container"); this.add(l); } } <APPLET CODE="HelloContainer .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=100 HEIGHT=100></APPLET>

Kao i obicno, programzapocinjeteimportiranjempotrebnihklasa. U ovomslucajuto sujava.applet.Applet i java.awt.Label.

Naša klasa ce imatisamo jednumetodu, init(). Ona ce obavititri stvari. Deklariratceda je l labela, instanciratije pomocukonstruktoraLabel(String s) i dodati jerazmještaju(layout). Opcenito, to se ne mora obavitiuvijekunutarmetodeinit(), alinajcešcapraksa je upravotakva.

Tri koraka u dodavanju komponente public void init() { Label l; l = new Label("Hello Container"); this.add(l); }

Kljucnastvarkoju valjazapamtitio dodavanjukomponentiappletusu sljedecatrikoraka:

1. Deklariratikomponentu2. Inicijaliziratikomponentu3. Dodatikomponenturazmještaju(layout)

Prva dva koraka morajuse obavitiprilikomkreiranjainstancebilokoje klase, tako danamsamo trecikorak predstavljanovost.

Možete to napraviti, naravno, i u jednoj naredbi, na primjerovako:

this.add(new Label("Hello Container"));

Nedostatak ovogkraceg zapisaje taj što se izgubilareferencana labelu(varijablal).Ipak, labelese u pravilune mijenjaju, tako da uglavnomnijeposebna smetnja.

Page 117: Java Predavanje I

Gdje je metoda paint()

Primijetiteda u našemappletunemapaint(), a tekst se svejednoispisujena ekranu.Komponentese, naime, same iscrtavaju. Svakiput kad se container kao što je appletponovnoiscrta, on pozovene samo svojuvlastitupaint() metodu, nego i paint()metodesvihsvojihkomponenti. Klasa java.awt.Label imasvojuvlastitupaint()metodukoja znakako se treba iscrtati. O iscrtavanjukomponentine moratevoditiracunadok god ne kreiratevlastiteklase komponenatailiizmijeniteizgledsistemskihkomponenata.

Metode klase Label

Labelesu jednostavniobjektikoji imajutek nekolikokonstruktorai vlastitih, ako seizuzmuone koje su naslijedeneod java.awt.Component (kojoj je java.awt.Labelpodklasa). public final static int LEFT public final static int CENTER public final static int RIGHT public Label() public Label(String text) public Label(String text, int alignment) public void addNotify() public int getAlignment () public synchronized void setAlignment (int alignment) public String getText() public synchronized void setText(String text)

Vec smo vidjeliosnovnikonstruktorza labele. Možete takoder kreiratilabelukoristecikonstruktorLabel() bez argumenata, no to opcenitonemasmisla. Nadalje, možeteodreditida tekst bude poravnatlijevo, desno ilicentrirano, za što vamstojinaraspolaganjuodgovarajucikonstruktor: Label center = new Label("Ova labela je centrirana", Label.CENTER);Label left = new Label("Ova labela je lijevo poravnata", Label.LEFT);Label right = new Label("Ova labela je desno poravnata", Label.RIGHT);

Dvijesu metode izjava.awt.Label koje ce povremenobitipotrebne, a to su getText

() i setText(String s). One dozvoljavajuda doznatei promijenitetekst labeledokse applet izvršava. Na primjer, String s = l.getText();l.setText("Ovo je nova labela");

Page 118: Java Predavanje I

Buttoni

Buttonisu instanceklasejava.awt.Button koja je podklasa odjava.awt.Component . Buttonise kreirajupomocukonstruktoraButton(Stringlabel). On ce kreiratinovibuttonsa labelomkoja ce na njemubitiispisana. Kad gakreirate, možetega dodati razmještaju. Na primjer, Button b; b = new Button("My First Button"); this.add(b);

Sintaksaje gotovoidenticnakao za labelei vidjetcete da je takva i za ostalekomponentegrafickogsucelja. Jedinošto se mijenjasu konstruktori.

Kraci oblikje takoder isti:

add(new Button("My First Button"));

Evo jednogappletakoji sadržibutton:

import java.applet.*;import java.awt.*; public class FirstButton extends Applet { public void init () { this.add(new Button("Moj prvi Button")); } } <APPLET CODE="HelloContainer .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=100 HEIGHT=100></APPLET>

Akcije na buttonima

Za razlikuod labela, buttonicinenešto kad kliknetena njih. Kad miškliknena nekiobjekt tipaButton, onda ce on ispalitiobjekt tipaActionEvent . Da bistebilispremni

Page 119: Java Predavanje I

odgovoritina taj dogadaj, potrebno je buttonupridružitii odgovarajuciActionListener.Na primjer, Button beep = new Button("Beep"); add(beep); // dodajemo buttom razmjestaju beep.addActionListener (myActionListener ); // pridruzujemo buttonu action listener

Ovdje je myActionListener referencana objekt koji implementirasucelje(interface)java.awt.event.ActionListener . To suceljepropisujesamo jednumetodu:

public abstract void actionPerformed (ActionEvent e)

Objekt tipaActionListener ucinitce nešto s rezultatom, objektomtipaActionEventkojeg je ispaliobuttonnakonšto je zabilježioklikmišem. Na primjer, sljedecaklasa ce,kad dobijeActionEvent , proizvestibeep signal:

import java.awt.*;import java.awt.event.*; public class BeepAction implements ActionListener { public void actionPerformed (ActionEvent e) { Toolkit.getDefaultToolkit ().beep(); } }

Primjer appleta sa akcijom na buttonu

Sljedeciapplet imabuttonoznacenlabelomna kojoj piše "Beep". Buttonje na uobicajeninacindodan razmještaju, a metodaaddActionListener () propisujeda ce nabuttonoveActionEvente reagiratiodgovarajuciActionListener, u ovomslucajuobjektklaseBeepAction .

import java.applet.*;import java.awt.*;import java.awt.event.*; public class BeepApplet extends Applet { public void init () {

Page 120: Java Predavanje I

// Konstruiramo button Button beep = new Button("Beep"); // dodajemo button razmjestaju this.add(beep); // propisujemo da ce action evente koje ovaj button posalje // obraditi novi objekt klase BeepAction beep.addActionListener (new BeepAction()); } } <APPLET CODE="BeepApplet.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Beep.jar"WIDTH=100 HEIGHT=100></APPLET>

Razliciti obrasci za dogadaje

Glavnaje prednost Javinogmodeladogadaja je da se GUI možeodvojitiod ostalogkoda. Kako je ActionListener sucelje(interface), a ne klasa, on možebitiimplementirangdje god namodgovara. Na primjer, appletmožei sam obradivatisvojedogadaje, što cemo vidjetiizsljedecegprimjera: import java.applet.*;import java.awt.*;import java.awt.event.*; public class BeepApplet extends Applet implements ActionListener { public void init () { // Construct the button Button beep = new Button("Beep"); // add the button to the layout this.add(beep); // specify that action events sent by this // button should be handled by the applet itself beep.addActionListener (this); } public void actionPerformed (ActionEvent e) { Toolkit.getDefaultToolkit ().beep(); }

Page 121: Java Predavanje I

} <APPLET CODE="BeepApplet.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=100 HEIGHT=100></APPLET>

Višestruki ActionListeneri

Primijetiteda nisteogranicenina samo jedan listener po dogadaju. Na primjer, sljedeciprogramgenerirapet beep-ova svakiput kad pritisnetebutton. import java.applet.*;import java.awt.*;import java.awt.event.*; public class BeepFiveApplet extends Applet { public void init () { // Construct the button Button beep = new Button("Beep"); // add the button to the layout this.add(beep); // specify that action events sent by this // button should be handled by a new BeepAction object beep.addActionListener (new BeepAction()); beep.addActionListener (new BeepAction()); beep.addActionListener (new BeepAction()); beep.addActionListener (new BeepAction()); beep.addActionListener (new BeepAction()); } } <APPLET CODE="BeepFiveApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="BeepFive.jar"WIDTH=100 HEIGHT=100></APPLET>

Kad pritisnetebutton, on ce lansiratiActionEvent , a svakiod pet objekata klaseBeepAction dobit ce kopijutog dogadaja. Redosljedprimanjatihkopija nijespecificiran. Ako je vaše racunaloprebrzo da bisteculisvihpet beep-ova, dodajte unutarmetodeActionPerformed () izklaseBeepAction još i naredbu System.out.println("Beep");

Page 122: Java Predavanje I

Pogledateliappletpomocuappletviewera, mocicete pratitiispissvakiput kad pritisnetebuttoni vidjetida se akcijazaistadogada pet puta.

Metode za buttone

Buttonisu jednostavniobjekti. Uglavnomsve što trebate napravitis njimaje dodati ihurazmještaji pridružitiimActionListener . Na raspolaganjusu vami sljedecemetode: public void addNotify()public String getLabel()public synchronized void setLabel(String label)public void setActionCommand (String command)public String getActionCommand ()public void addActionListener (ActionListener l)public void removeActionListener (ActionListener l)

addNotify() kreira takozvani peer objekt za zadanibutton, tj. native maskukojaizgledakao WindowsbuttoniliMac buttoniliMotifbutton, no ona se rijetkodirektnopoziva.

Metode getLabel() i setLabel(String s) omogucujudohvacanjei mijenjanjeteksta koji se pojavljujena buttonuza vrijemeizvršavanjaappleta. Na primjer, za nekiButton b, možemoimati:

String s = b.getLabel();b.setLabel("Here's the new label");

Primijetiteda metodaunatocsugestivnomimenugetLabel() vraca objekt tipaString ,a ne Label.

Metode setActionCommand () i getActionCommand () modificirajukomandnistringkoji sa sobom nosiActionEvent . Po pretpostavcito je labelabuttona, alito se možepromijeniti. Na primjer, možetezadatibroj ponvljanjabeep signalakoji ce appletproizvestina klikmišem(pogledajteBeepFiveApplet ).

Metoda addActionListener () registriranekiobjekt kao onaj koji bi trebao primitiActionEvent koji ce Button ispaliti. Metoda removeActionListener () poništavaturegistraciju, tako da objekt tipaActionListener višenece primatiActionEvente kojebuttonispali.

Action naredbe

Metode setActionCommand () i getActionCommand () modificirajukomandnistringkoji putujeuzActionEvent . Po pretpostavci, to je labelabuttona, alito se možepromijeniti. Na primjer, možetena taj nacinproslijeditibroj ponaljanjabeep signalakojeapplet treba proizvesti. import java.applet.*;

Page 123: Java Predavanje I

import java.awt.*;import java.awt.event.*; public class BeepFiveApplet extends Applet { public void init () { // Construct the button Button beep = new Button("Beep"); // add the button to the layout this.add(beep); // specify that action events sent by this // button should be handled by the applet itself beep.addActionListener (new MultiBeepAction ()); beep.setActionCommand ("5"); } } class MultiBeepAction implements ActionListener { public void actionPerformed (ActionEvent ae) { int n; try { n = Integer.parseInt(ae.getActionCommand ()); } catch (NumberFormatException e) { n = 1; } Toolkit tk = Toolkit.getDefaultToolkit (); for (int i = 0; i < n; i++) tk.beep(); } } <APPLET CODE="BeepFiveApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="MultiBeep.jar"WIDTH=200 HEIGHT=200></APPLET>

Više buttona u istom appletu

Naravno, moguceje imativišeod jednogbuttonau appletu. Svakibuttonkoji ce izazvatinekuakcijumora registriratibar jedan objekt koji je ActionListener . RazlicitibuttonimoguregistriratirazliciteActionListener e , aliihmogui dijeliti. ActionListener i zabuttonemogupripadatiistojklasi, aline moraju. Ako dva buttonaregistrirajuistiActionListener , uobicajenoje koristitiactionkomanduda bismorazlikovaliakcije.

Page 124: Java Predavanje I

import java.applet.*;import java.awt.*;import java.awt.event.*; public class TwoButtons extends Applet { public void init() { MultiBeepAction mba = new MultiBeepAction (); // Construct the button Button beep = new Button("Beep Once"); // add the button to the layout this.add(beep); beep.addActionListener (mba); beep.setActionCommand ("1"); Button beepTwice = new Button("Beep Twice"); beepTwice.addActionListener (mba); beepTwice.setActionCommand ("2"); this.add(beepTwice); } } class MultiBeepAction implements ActionListener { public void actionPerformed (ActionEvent ae) { int n; try { n = Integer.parseInt(ae.getActionCommand ()); } catch (NumberFormatException e) { n = 1; } Toolkit tk = Toolkit.getDefaultToolkit (); for (int i = 0; i < n; i++) tk.beep(); } } <APPLET CODE="TwoButtons.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="TwoButtons.jar"WIDTH=200 HEIGHT=100></APPLET>

Page 125: Java Predavanje I

Unutarnje klase kao Event Listeneri

Uobicajenoje da klasa koja realiziraevent listener bude unutarnjaklasa. To se najcešceprimjenjujena prilagodenepodklase komponenatakoje želesame obradivatisvojedogadaje. import java.applet.*;import java.awt.*;import java.awt.event.*; public class TwoButtons extends Applet { public void init() { MultiBeepAction mba = new MultiBeepAction (); // Construct the button Button beep = new Button("Beep Once"); // add the button to the layout this.add(beep); // specify that action events sent by this // button should be handled by the MultiBeepAction mba beep.addActionListener (mba); beep.setActionCommand ("1"); Button beepTwice = new Button("Beep Twice"); beepTwice.addActionListener (mba); beepTwice.setActionCommand ("2"); this.add(beepTwice); } class MultiBeepAction implements ActionListener { public void actionPerformed (ActionEvent ae) { int n; try { n = Integer.parseInt(ae.getActionCommand ()); } catch (NumberFormatException e) { n = 1; } Toolkit tk = Toolkit.getDefaultToolkit (); for (int i = 0; i < n; i++) tk.beep(); } }} <APPLET CODE="TwoButtons.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="TwoButtonsIC .jar"

Page 126: Java Predavanje I

WIDTH=200 HEIGHT=100></APPLET>

Tekstualna polja

Klasa java.awt.TextField omogucujeugradnjumaske za unos i editiranjejedne linijeteksta. Korisnaje za jednostavneoperacijeunosamalihkolicinapodataka. Ima cetirikonstruktora:

public TextField() public TextField(String text) public TextField(int num_chars) public TextField(String text, int num_chars)

Zbog nacinana koji Java razmještatekst, konstruktorbez argumenatabi valjaloizbjegavati. Koristiteilionaj koji imaString ilizadajtebroj znakovakoje ce ta kucicasadržavati. Na primjer, TextField name = new TextField("Type your name here");TextField socialSecurity = new TextField(11);

Kad korisnikpritisnetipkureturnilienter unutarTextFielda, ispalise jedanActionEvent . Možete ga ulovitipomocuActionListener a, istokao u slucajubuttona. Imajtena umuda vecinakorisnikanijesvjesnada se nešto dogada tek onda kadpritisnureturnunutarTextFielda. Zato uvijekosigurajtei alternativninacinispaljivanjaActionEvent a, na primjerpomocubuttonailiretka na izborniku.

Metoda getText() vraca sadržajTextFielda. Metoda setText(String s) gamijenja.

Metoda setEditable() omogucujeda korisnikudozvoliteilizabranitemodificiranjesadržajaTextFielda.

Primjer tekstualnih polja u Javi

Sljedeciapplet cita tekst izjednogTextFielda i ispisujega velikimslovimau drugiTextField .

import java.applet.*;import java.awt.*;import java.awt.event.*; public class CapitalizeApplet extends Applet { private TextField input; private TextField output; public void init () {

Page 127: Java Predavanje I

// Konstruiramo tekstualna polja this.input = new TextField(40); this.output = new TextField(40); this.output.setEditable(false); Button b = new Button("Capitalize"); // dodajemo komponente u razmjestaj this.add(input); this.add(b); this.add(output); // odredjujemo da action evente koje salju // button ili input TextField budu obradjeni od // istog objekta tipa CapitalizerAction CapitalizerAction ca = new CapitalizerAction (input, output); b.addActionListener (ca); this.input.addActionListener (ca); // ActionEvents koje salje polje output se ignoriraju. } } class CapitalizerAction implements ActionListener { TextField in; TextField out; public CapitalizerAction (TextField in, TextField out) { this.in = in; this.out = out; } public void actionPerformed (ActionEvent ae) { String s = in.getText(); out.setText(s.toUpperCase()); } } <APPLET CODE="CapitalizeApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Capitalize.jar"WIDTH=500 HEIGHT=100></APPLET>

U ovomprogramukorištenje drugacijiobrazac za obradu dogadaja. KonstruktorklaseCapitalizerAction je iskorištenza prosljedivanjereferencirazlicitimkomponentamakoje metodaactionPerformed () modificira.

Page 128: Java Predavanje I

TextArea

Klasa java.awt.TextArea je podklasa od java.awt.TextComponent kojaosiguravamaskuza editiranjevišelinijateksta. Korisnaje za inputi output.

Слика

Na raspolaganjusu namcetirikonstruktora:

public TextArea() public TextArea(String text) public TextArea(int rows, int columns) public TextArea(String text, int rows, int columns) public TextArea(String text, int rows, int columns, int scrollbars)

Zbog nacinana koji Java rasporedujekomponente, izbjegavajtekorištenjekonstruktorabez argumenata. Radijepocnitesa onimkoji zadajeString ilibroj redaka i stupaca kojece ta površinazauzeti. Na primjer,

TextArea address = new TextArea("Upišite svoju adresu", 5, 80);

Po pretpostavci, TextAreas nemascrollbar. Možete ihdodati ako odgovarajucemkonstruktoruprenesetenekuod ovihkonstanti:

TextArea.SCROLLBARS_BOTH TextArea.SCROLLBARS_HORIZONTAL_ONLY TextArea.SCROLLBARS_NONE TextArea.SCROLLBARS_VERTICAL_ONLY

Na primjer,

TextArea instructions = new TextArea("", 15, 70, TextArea.SCROLLBARS_VERTICAL_ONLY);

Za razlikuod TextFielda, TextArea ne generiranikakavactionEvent kad korisnikpritisnereturnunutarpolja. Umjestotoga, linijase prekida, a kursor prenosiu novired.

No i nadalje, metodagetText() vraca tekst koji sadržiTextArea , a setText() gamijenja. Metoda setEditable() dopušta vamda odrediteda lice korisnikmocimijenjatisadržaj. Obje klase, TextField i TextArea , nasljedujusve ove metodeodsvoje nadklase, TextComponent .

Page 129: Java Predavanje I

Nadalje, tekst možetedodavatina kraj pomocumetodeappend(), umetatipomocumetodeinsert(), a zamijenitipomocumetodereplaceRange ():

public synchronized void insert(String text, int position)public synchronized void append(String text) public synchronized void replaceRange (String text, int start, int end)

Klasa TextComponent

I TextArea i TextField su podklase od java.awt.TextComponent . Ova klasasadržimetodekoje su zajednickeza obje klase, ukljucujucii nekolikometodakoje smovec vidjeli.: getText(), setText(), i setEditable(). Klasa TextComponent imatakoder i metodeza manipuliranjeselekcijomi kursoromte za procesiranjeTextEventa.

Selekcijase koristiza copy/paste alii za drugesvrhe. Prviznaku TextComponent i jeznakbroj 0; drugije znakbroj 1 i tako dalje.

public synchronized int getSelectionStart () public synchronized void setSelectionStart (int selectionStart ) public synchronized int getSelectionEnd () public synchronized void setSelectionEnd (int selectionEnd ) public synchronized void select(int selectionStart , int selectionEnd ) public synchronized void selectAll() public synchronized String getSelectedText ()

Kursor (caret) je mjestoinsertiranjateksta. Tamose pojavljujetekst kad ga korisnikutipka. Dvijesu metodekoje to reguliraju:

public void setCaretPosition (int position) public int getCaretPosition ()

Sucelje TextListener i klasaTextEvent

Klase TextArea i TextField moguinstaliratisuceljejava.awt.event.TextListener koje hvatadogadaje izklasejava.awt.event.TextEvent . TextComponent e ispaljujuTextEvente svakiput kadse njihovtekst promijeni. To se dogada uglavnomsvakiput kad korisnikpritisnetipkuunutarkomponente.

SuceljeTextListener propisujesamo jednumetodu, textValueChanged ():

public abstract void textValueChanged (TextEvent te)

Nekoj TextComponent i pridružujeteTextListener tako da pozovetenjenumetoduaddTextListener (). Na primjer,

Page 130: Java Predavanje I

TextArea password = new TextArea(24)password.addTextListener (new PasswordChecker ());

Ipak, u najvecembroju slucajevabit ce posve dovoljnoprocitatii postavititekst (get iset). Procesiranjeznakpo znakje relativnorijetkopotrebno.

Napomenimoda se TextListener uklanja pozivanjemmetoderemoveTextListener().

public void removeTextListener (TextListener tl)

Klasa Canvas

Klasa java.awt.Canvas definirapravokutnupovršinu(podlogu, pozadinu) po kojojmožetepisatii crtatikoristecimetode izklasejava.awt.Graphics . Klasa Canvas imasamo trimetode: public Canvas() public void addNotify() public void paint(Graphics g)

Podlogeuglavnomne instanciratedirektno. Umjestotoga pišetepodklasukoja cepregazitipaint() metodukako bistenacrta lislikukoju trebate. Na primjer, sljedecapodklasa od Canvas crta velikucrvenuelipsukoju možetedodati vašemappletu:

import java.awt.*; public class RedOval extends Canvas { public void paint(Graphics g) { Dimension d = this.getSize(); g.setColor(Color.red); g.fillOval(0, 0, d.width, d.height); } public Dimension getMinimumSize () { return new Dimension(50, 100); } public Dimension getPreferredSize () { return new Dimension(150, 300); } public Dimension getMaximumSize () { return new Dimension(200, 400); } }

Page 131: Java Predavanje I

Appletkoji koristikomponentenikakone bi smiopregazitimetodupaint() jer ce tozbognacinana koji Java rasporeduje komponenteizazvatinepredvidljiverezultate.Umjestotoga treba kreiratiobjekt tipaCanvas i sva crtanjaobavitipomocunjegovepaint() metode.

Podlogese dodaju apletimana istinacinkao i ostalekomponente. Na primjer,

public void init() { this.add(new RedOval()); }

Podlogeu pravilune ispaljujunikakvedogadaje, no poslijecete naucitikako se to možepromijeniti.

Klasa Choice

Klasa java.awt.Choice implementirapopup izborniksa fiksnompozicijom(postojitakoder i klasajava.awt.PopupMenu kod koje pozicijanijefiksnai pojavljujese kadkorisnikkliknei držidesnutipkumiša).

Слика

Kreiranjeizbornikaje nešto malokompleksnijeod kreiranjakomponentikoje smo dosada vidjeli. Imamo, naime, dodatnikorak, dodavanjepojedinacnihopcijau izbornik.Cijelipostupak izgledaovako:

1. DeklariratiChoice2. AlociratiChoice3. Dodatiopcije izborniku(alocirnomobjektu tipaChoice)4. Dodatiizbornikrazmještaju(layout)5. PridružitiItemListener izborniku

Na primjer, prva cetirikoraka moglabi izgledatiovako public void init() { Choice ch; ch = new Choice(); ch.addItem("1"); ch.addItem("2"); ch.addItem("3"); ch.addItem("4"); ch.addItem("5"); add(ch); }

Page 132: Java Predavanje I

Metode klase Choice

Klasa Choice imavišemetodaza dodavanje, uklanjanjei vracanjerazlicitihopcija sapopisa. Popis opcija se pocinjebrojitiod 0.

public int getItemCount () public String getItem(int index) public synchronized void add(String item) public synchronized void addItem(String item) public synchronized void insert(String item, int position) public synchronized void remove(String item) public synchronized void remove(int position) public synchronized void removeAll()

Ipak, uglavnomcete opcijeugraditiizbornikcimse appletpokrene i necete ihkasnijemijenjati.

Sljedecemetodecitajuilipostavljajutrenutacnoselektiranuopcijuizizbornika, dakleopcijukoja je u tom trenutkuvidljiva.

public synchronized void removeAll() public synchronized String getSelectedItem () public synchronized Object[] getSelectedObjects () public int getSelectedIndex () public synchronized void select(int position) public synchronized void select(String item)

Sucelje ItemListener i klasaItemEvent

Kad korisnikodabere novuopcijuu izborniku, onda izbornik(objekt tipaChoice)ispaljujedva dogadaja tipajava.awt.event.ItemEvent , jedan koji indicirada jepocetna opcijadeselektiranai drugi, da je selektirananovaopcija. Te dogadaje možeteprocesiratitako da instaliratesuceljejava.awt.event.ItemListener , a svomizbornikupridružiteodgovarajuciItemListener objekt koji ce hvatatispomenutedogadaje.

No imai drugihnacinada se to napravi. Na primjer, odabranuvrijednostizizbornikamožeteprovjeravatikad se dogodinekidrugidogadaj, na primjerpritisakna nekibutton.

Pogledajmo primjersljedecegappletakoji prikazujeizborniks brojevimaod d1 do 5.Korisnikbiranjembroja odreduje kolikoputa applet šaljebeep signal.

import java.applet.*;import java.awt.*;import java.awt.event.*;

Page 133: Java Predavanje I

public class MultiBeep extends Applet { public void init() { Choice ch; ch = new Choice(); ch.addItem("1"); ch.addItem("2"); ch.addItem("3"); ch.addItem("4"); ch.addItem("5"); this.add(ch); ch.addItemListener (new BeepItem()); } } class BeepItem implements ItemListener { public void itemStateChanged (ItemEvent ie) { if (ie.getStateChange () == ItemEvent.SELECTED) { String name = (String) ie.getItem(); Toolkit tk = Toolkit.getDefaultToolkit (); try { int n = Integer.parseInt(name); for (int i = 0; i < n; i++) tk.beep(); } catch (Exception e) { tk.beep(); } } } } <APPLET CODE="MultiBeep.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="BeepChoice.jar"WIDTH=200 HEIGHT=100></APPLET>

Klasa BeepItem implementirasuceljeItemListener . Ona pomocumetodeItemEvent.getStateChange () filtriradogadaje prouzrokovanedeselektiranjemopcija i proizvodibeep samo kad se opcija selektira. Konstantekoje namstoje naraspolaganjusu: ItemEvent.DESELECTED ItemEvent.ITEM_FIRST ItemEvent.ITEM_LAST ItemEvent.ITEM_STATE_CHANGED ItemEvent.SELECTED

Metoda ItemEvent.getItem() se koristida se dobije trenutnoselektiranaopcija. Kaoi prije, ako ne možetecutisve beepove, dodajte izanaredbitk.beep(); u klasi

Page 134: Java Predavanje I

BeepItem još i naredbuSystem.out.println("beep"); i pogledajteapplet saappletviewerom.

Klasa Checkbox

Klasa java.awt.Checkbox , se koristiza selektiranjeboolean vrijednosti. SvakiCheckbox imalabelukoja bi trebalareci korisnikušto pojediniCheckbox predstavlja.Na primjerCheckbox sa labelom"Olives" u appletuIngredients za narucivanjepizze(vididolje) bilabi cekiranaako korisnikželimasline, a u protivnomnecekirana.DodavanjeCheckboxa appletuje jednostavno. Deklarirajte, konstruirajtei dodajte: Checkbox c; c = new Checkbox("Pepperoni")); add(c);

Kao i obicno, ovo se moženapisatii u jednoj naredbi: add(new Checkbox("Pepperoni"));

Po pretpostavci, checkboxovisu necekiranikad se kreiraju. Ako želiteda nekiod njihbude odmahcekiran, koristitesljedecikonstruktor:

add(new Checkbox("Pepperoni", null, true));

Vrijednostnull je ovdje referencana CheckboxGroup i znacida ovaj Checkbox nespada u CheckboxGroup (vididalje).

SvakiCheckbox imaboolean vrijednost, bilotrue ilifalse. Kad je Checkboxcekiran, ta vrijednostje true. Kad je necekiran, ona je false. Toj vrijednostipristupatepomocuCheckboxovihmetodagetState() i setState(boolean b). Na primjer,

private void handleCheckbox (Checkbox c) { if (c.getState()) price += 0.50f; else price -= 0.50f; }

Dogadaji iz klase Checkbox

Kad Checkbox promijenistanje, što je u normalnimokolnostimarezultatkorisnikoveakcije, ispaljujese dogadaj tipajava.awt.event.ItemEvent . Taj dogadaj uglavnomignoriratei ispitujetestanjeCheckboxa direktnokad vamtreba. Ipak, ako želiteodmahznatito stanje, registriratcete uznjegaItemListener i u odgovarajucojklasiimplementiratisuceljejava.awt.event.ItemListener .

Page 135: Java Predavanje I

PripadniItemEvent je potpunoistikao i onaj za Choice . Taj se dogadaj zapravokoristiza indiciranjeselekcijai deselekcijau svimvrstamapopisa opcija, ukljucujucicheckboxove, radio buttone, choice, i liste.

Sljedeciprogramje appletkoji pita "What do youwanton yourpizza?" Kad je dodatakcekiran, cijenase povecavaza 50 centa. Kad se dodatak decekira, cijenase smanjujeza50 cdnta. Cijenaje pokazanau TextFieldu.

import java.applet.*;import java.awt.*;import java.awt.event.*; public class Ingredients extends Applet { TextField t; float price = 7.00f; public void init() { Checkbox c; this.add(new Label("What do you want on your pizza?", Label.CENTER)); this.t = new TextField(String.valueOf(price)); // so people can't change the price of the pizza t.setEditable(false); Pricer p = new Pricer(price, t); c = new Checkbox("Pepperoni"); this.add(c); c.addItemListener (p); c = new Checkbox("Olives"); c.addItemListener (p); this.add(c); c = new Checkbox("Onions"); c.addItemListener (p); this.add(c); c = new Checkbox("Sausage"); c.addItemListener (p); this.add(c); c = new Checkbox("Peppers"); c.addItemListener (p); this.add(c); c = new Checkbox("Extra Cheese"); c.addItemListener (p); this.add(c); c = new Checkbox("Ham"); c.addItemListener (p); this.add(c); c = new Checkbox("Pineapple"); c.addItemListener (p); this.add(c); c = new Checkbox("Anchovies"); c.addItemListener (p); this.add(c); this.add(t); }

Page 136: Java Predavanje I

} class Pricer implements ItemListener { TextField out; double price; public Pricer(double baseprice, TextField out) { this.price = baseprice; this.out = out; } public void itemStateChanged (ItemEvent ie) { if (ie.getStateChange () == ItemEvent.SELECTED) this.price += 0.50f; else this.price -= 0.50f; // Change the price this.out.setText(String.valueOf(price)); } } <APPLET CODE="Ingredients.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Pizza.jar"WIDTH=200 HEIGHT=200></APPLET>

Klasa CheckboxGroup

Checkbox grupesu kolekcijecheckboxakoje imajuspecijalnosvojstvoda unutargrupene možebiticekiranovišeod jednogcheckboxaistovremeno. TakvicheckboxoviizklaseCheckboxGroup se cesto zovuradio buttons. Checkboxovikoji pripadajuistojCheckboxGroup i ne moguse istovremenocekirati. Kad korisnikcekira jednog, sviostalise automatskidecekiraju.

Konstruktorza CheckboxGroup je trivijalan. Nema argumenatai cak ne moratedodavatitu komponentuappletujer ona nijedio korisnickogsuceljanegonaprostonacinuredenjacheckboxova.

CheckboxGroup cbg = new CheckboxGroup ();

Da bisteomogucilida se jedna grupacheckboxovaponaša kao radio buttons,konstruirajtesvakipojedinina ovaj nacin:

public Checkbox(String label, CheckboxGroup cbg, boolean checked)

Labelalabel pripada odredenomcheckboxu, a cbg je grupau koju stavljatetajcheckbox. Ona mora u tom trenutkuvec postojati.

Page 137: Java Predavanje I

Kad god želite, možeteprocitatiiliodreditikoji checkboxje cekiran, koristecise jednomod sljedecedvijemetode:

public Checkbox getSelectedCheckbox () public synchronized void setSelectedCheckbox (Checkbox box)

Primjer CheckboxGroup

Sljedeciprogrampitakorisnikakako želiplatitipizzu. Primijetiteda za razlikuodprethodnogprimjerau kojemje mogaoizabrativišedodataka na pizzu, sada možeodabrati tocno jedan nacinplacanja.import java.applet.*; import java.awt.*; public class PaymentMethod extends Applet { public void init() { this.add(new Label("How will you pay for your pizza?")); CheckboxGroup cbg = new CheckboxGroup (); this.add(new Checkbox("Visa", cbg, false)); this.add(new Checkbox("Mastercard", cbg, false)); this.add(new Checkbox("American Express", cbg, false)); this.add(new Checkbox("Discover", cbg, false)); this.add(new Checkbox("Cash", cbg, true)); // the default } } <APPLET CODE="PaymentMethod .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Pizza.jar"WIDTH=200 HEIGHT=200></APPLET>

U ovomprimjerunijebilonikakvihakcija. Ako želitedodati akcije, postupitejednakokao i u slucajubilokojeg drugogCheckboxa.

Klasa List

Listesa scrollbarom, objektiklasejava.awt.List, korisnesu za spremanjeduljihpopisa red po red. Elementilistesu stringovi. Na primjer,

Page 138: Java Predavanje I

Слика

Metode klase List

Noviobjekt tipaList kreiratejednimod sljedecihkonstruktora:

public List() public List(int numLines) public List(int numLines, boolean allowMultipleSelections )

Na primjer,

List l = new List(8, true);

Pri tome je numLines broj redaka koje želitevidjetina ekranui on je u pravilumanjiodbroja elemenatasame liste, dok je allowMultipleSelections argumentkojiodreduje moželikorisnikselektirativišeod jednogretka istovremeno(npr. pomocuShift-click).

Sljedecemetodedodaju retke na kraj liste:

public void add(String item) public void addItem(String item) // deprecated! Koristite prvu metodu

Sljedecedvijemetodedodaju retke na zadanupozicijuu listi:

public synchronized void add(String item, int index)

Page 139: Java Predavanje I

public synchronized void addItem(String item, int index) // deprecated!

Sljedecemetodeuklanjajuretke izliste:

public synchronized void removeAll() public synchronized void remove(String item) public synchronized void remove(int position) public synchronized void delItem(int position)

Sljedece metodedopuštajuvamda procitateodredene retke izliste: public int getItemCount () public String getItem(int index) public synchronized String[] getItems()

Možete takoder zamijenitiodredeniredak: public synchronized void replaceItem(String newValue, int index)

Ove metodeomogucujuvamda doznatekoje je retke korisnikselektirao::

public synchronized int getSelectedIndex () public synchronized int[] getSelectedIndexes () public synchronized String getSelectedItem () public synchronized String[] getSelectedItems () public Object[] getSelectedObjects ()

Množinskioblikovihmetodakoristitcete ako listadozvoljavavišestrukuselekciju. Da lije ona dozvoljena, ustanovitcete metodomisMultipleMode (), a to možetepromijenitipomocusetMultipleMode ().

public boolean isMultipleMode () public synchronized void setMultipleMode (boolean b)

Sljedecemetodeomogucujuvammanipuliranjeselektiranjem:

public synchronized void select(int index) public synchronized void deselect(int index) public boolean isIndexSelected (int index)

Sljedecedvijemetodeodredujuda lije redak na odredenomindeksuvidljivunutarkucice:

public int getVisibleIndex () public synchronized void makeVisible(int index)

ListEvents

Dogadaji klase List

Page 140: Java Predavanje I

Listscan firetwo separate types of events. Whena listitemis selectedor deselected, theList firesan ItemEvent . However, whenthe user doubleclickson a listitem, the Listfiresan ActionEvent . Therefore, youcan registerboth an ItemListener to processselectionsand/or an ActionListener to process doubleclicks. public void addItemListener (ItemListener l)public void removeItemListener (ItemListener l)public void addActionListener (ActionListener l)public void removeActionListener (ActionListener l)

The actioncommandinthe ActionEvent is the listitemwhichwas doubleclicked.

Klasa Scrollbar

Klase List, TextArea , i ScrollPane s imajugotovescrollbare. No ako želitescrollatinekidrugiobjekt, treba vamklasajava.awt.Scrollbar . Scrollbariimajupunoprimjena. Elementarnaje pomicanjevidljivogpodrucja. Takoder se mogukoristitizapostavljanjevrijednostiizmedudva zadanabroja. Ilimoguprolazitikroz višeekrana, kaou operacijamana bazamapodataka koje tražesukcesivneslogove.

Imamotrikonstruktora:

public Scrollbar()public Scrollbar(int orientation)public Scrollbar(int orientation, int value, int visible, int min, int max)

Argumentorientation je jedna od mnemonickihkonstanti, Scrollbar.HORIZONTALiliScrollbar.VERTICAL . Prema ocekivanju, one odredujuda lije scrollbarrazmještens lijevana desno iliodozgoprema dolje.

Sve vrijemeScrollbar imajednuan int vrijednost. To je pocetna vrijednostkojamora bitiizmeduminimalnei maksimalnekoje se zadajusa zadnjadva argumenta. Kad seScrollbar kreira, njegovapocetna vrijednostce bitivalue. Defaultje 0.

Argumentvisible predstavljavelicinuvidljivogdijelaskrolabilnepovršineu pikselima.To se koristikod pomicanjapo stranici.

DogadajkojiScrollbar ispaljujeje tipajava.awt.event.AdjustmentEvent . Klasakoja ce ga uhvatitimora implementiratisuceljejava.awt.event.AdjustmentListener . Ona mora implementiratimetoduadjustmentValueChanged () sa sljedecomsignaturom:

public void adjustmentValueChanged (AdjustmentEvent e)

Sljedeciprogramje appletkoji mijenjabroj u TextFieldu izmedu1 i 100 u ovisnostiopozicijioznakena scrollbaru. U praksibi taj broj, naravno, morao nešto predstavljati.

import java.applet.*; import java.awt.*;

Page 141: Java Predavanje I

import java.awt.event.*; public class Scrollie extends Applet implements AdjustmentListener { TextField t; Scrollbar sb; public void init() { int initialValue = 1; sb = new Scrollbar(Scrollbar.HORIZONTAL, initialValue , 1, 1, 100); sb.addAdjustmentListener (this); this.add(sb); this.t = new TextField(4); this.t.setText(String.valueOf(initialValue )); this.add(t); } public void adjustmentValueChanged (AdjustmentEvent e) { int val = sb.getValue(); this.t.setText(String.valueOf(val)); } } <APPLET CODE="Scrollie.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Page 142: Java Predavanje I

Sedmo predavanje - dogadajiProceduralni programi rep dogadaja (event queue ) dogadaji niske razine (lowlevel events) dogadaji visoke razine (high level events) hijerarhija klasadogadaja obrada dogadaja razliciti EventListeneri primjer uporabeMouseListenera dogadaji vezani uz tipke (key events) kodovi tipki razlicitetipke i njihovi kodovi modifikatori (modifier keys ) modifikatori uz tipke mišadogadaji vezani uz fokus (focus events) dogadaji vezani uz komponentu(component events) adapteri primjer uporabe adaptera apsorbiranje dogadaja

prebacivanje dogadaja s niske na visoku razinu rad s repom dogadaja

Proceduralni programi

Tradicionalno, proceduralniprogramiimajujedinstvenporedak izvršavanja. Kontrolaseprebacuje linearnood prve naredbe na drugu, od drugena trecu i tako dalje, saeventualnimpetljamai grananjima. Korisnikunosipodatke samo u tocno odredenimtrenucima, kad je racunalospremnoprimitite podatke.

Programikoji podržavajuGUI (GraphicalUser Interface) ne mogufunkcioniratina takavnacin. Korisnikumora bitiomogucenoda praktickiu svakomtrenutkukliknemišem,odabere stavkuizbornika, unesetekst i slicno.

Rep dogadaja (event queue)

Umjestoproceduralnog, GUI modelizahtijevajudogadajnipristup. Svaka korisnikovaakcija, bio to klik, pritisaktipke ilinešto drugo, stavljase u tzv. rep dogadaja(eventqueue), onako kako se dogadajipojavljuju. Uobicajenoje da se todogada na razinioperacijskogsustava. Programuklanjadogadaje izrepa i obraduje ih, jedan po jedan.Opcenito, jedna beskonacnawhile petljacitadogadaje izrepa, a dugackaswitchnaredba raspodjeljujeihodgovarajucimdijelovimaprogramakoji ce ihobraditi..

Ovisnoo arhitekturisustava, možemoimatijedan velikisistemskirep dogadaja ilipaksvaka aplikacijamožeimativlastitirep dogadaja. Operacijskisustavmora osiguratidapravidogadajistignudo pravihprograma.

U aplikacijamakojimase mibavimo, dakle u Java programima, svaka virtualnamašinaimajedan glavniAWT rep dogadaja. Takoder je gotovosigurnoprisutani native repdogadaja, no micemo promatratisamo Javinrep. Java programce jedinou tom repuvidjetidogadaje koje mušaljenative korisnickosucelje.

Page 143: Java Predavanje I

Dogadaji niske razine (low level events)

Dogadajiniskerazinepredstavljajudirektnukomunikacijus korisnikom. To možebitipritisakna tipku, klikanjemišemi slicno. Ukljucenesu sljedeceklase: java.awt.event.ComponentEvent

komponentapomaknuta, promijenjenajoj je velicinaitd. java.awt.event.FocusEvent

komponentadobilailiizgubilafokus java.awt.event.KeyEvent

tipkapritisnuta, tipkaotpuštenaitd. java.awt.event.MouseEvent

tipkamišapritisnuta, podignuta, kliknuta, mišpomaknut, mišpovucenitd. java.awt.event.ContainerEvent

komponentaje dodana kontejneruiliuklonjenaiznjega java.awt.event.WindowEvent

prozor aktiviran, deaktiviran, otvoren, zatvoren, ikonificiran, deikonificiran java.lang.Object | +--java.util.EventObject | +--java.awt.AWTEvent | +--java.awt.event.ComponentEvent | +--java.awt.event.InputEvent | | | +--java.awt.event.KeyEvent | | | +--java.awt.event.MouseEvent | +--java.awt.event.FocusEvent | +--java.awt.event.ContainerEvent | +--java.awt.event.WindowEvent

Dogadaji visoke razine (high levelevents)

Dogadajivisokerazineilisemantickidogadajisadrže u sebi znacenjekoje je pridijeljenokomponentikorisnickogsucelja. Klase koje ovdje igrajuulogusu: java.awt.event.ActionEvent

Page 144: Java Predavanje I

izvršenaje naredba java.awt.event.AdjustmentEvent

prilagodenaje vrijednost(npr. scrollbarom) java.awt.event.ItemEvent

stanjestavke se promijenilo java.awt.event.TextEvent

vrijednosttekstualnogobjekta se promijenila Na primjer, kad korisnikkliknemišemna buttoni zatimga otpusti, buttonce dobititriodvojenadogadaja nižerazine, tipaMouseEvent (jedan za pritisaktipke miša, mousedown, drugiza otpuštanjetipke, mouse up, trecieventualnoza povlacenjemiša, mousedrag, ako je nastupilo). Buttonce nakon toga ispalitijedan dogadaj višerazine, tipaActionEvent .

Ako korisnikkliknemišemna button, povucemišaizvanbuttonai onda ga otpusti, buttonce dobitidva odvojenadogadaja nižerazine(jedan za mouse down, drugiza mousedrag). U tom slucajuignoriratce ihi nece ucinitiništa.

Hijerarhija klasa dogadaja

Svaka klasa dogadaja visokerazinepodklasa je od java.awt.AWTEvent . java.lang.Object | +--java.util.EventObject | +--java.awt.AWTEvent | +--java.awt.event.ActionEvent | +--java.awt.event.ItemEvent | +--java.awt.event.AdjustmentEvent | +--java.awt.event.TextEvent | +---java.awt.event.ComponentEvent | +--java.awt.event.InputEvent | | | +--java.awt.event.KeyEvent | | | +--java.awt.event.MouseEvent | +--java.awt.event.FocusEvent | +--java.awt.event.ContainerEvent |

Page 145: Java Predavanje I

+--java.awt.event.WindowEvent

Obrada dogadaja

Za obradu dogadaja izrepa zaduženaje Java runtime. Posebno, ona osiguravada svakidogadaj niskerazinedospijedo odgovarajucekomponente. Ne moratese brinutikojoj jekomponentikoji dogadaj namijenjen. To sustavrješavaautomatski. Specijalno, runtimeprosljedujedogadaj metodiprocessEvent () klasejava.awt.Component :

protected void processEvent (AWTEvent e)

Metoda processEvent () prepoznajetip dogadaja i prosljedujega jednojod pet drugihmetoda izisteklase:

protected void processComponentEvent (ComponentEvent e) protected void processFocusEvent (FocusEvent e) protected void processKeyEvent (KeyEvent e) protected void processMouseEvent (MouseEvent e) protected void processMouseMotionEvent (MouseEvent e)

Svaka od tihmetodapokušavavidjetije lineki listener odgovarajucegtipa registriranzatu komponentu. Ako jest, dogadaj se prosljedujesvakomod registriranihlisteneranepredvidljivimporetkom.

Interno, ove metodekoristeobjekt tipajava.awt.AWTEventMulticaster kako bivodilepopis registracijalistenera uzsvakukomponentu.

Razliciti EventListeneri

Da bisteomoguciliodgovaranjena dogadaje koje komponentadobiva, pridružujetekomponenti(registrirate) event listener odgovarajucegtipa. Eventlistenerje svakiobjektkoji implementirasuceljejava.util.EventListener . AWT definiravišenjegovihpodsucelja, po jedno za svakitip dogadaja. Npr.:

java.awt.event.ComponentListener

java.awt.event.ContainerListener

java.awt.event.FocusListener

java.awt.event.KeyListener

java.awt.event.MouseListener

java.awt.event.MouseMotionListener

java.awt.event.WindowListener

java.awt.event.ActionListener

java.awt.event.AdjustmentListener

java.awt.event.ItemListener

java.awt.event.TextListener

java.awt.event.AWTEventListener

java.awt.event.HierarchyBoundsListener

java.awt.event.HierarchyListener

Page 146: Java Predavanje I

java.awt.event.InputMethodListener

Svako od tihsuceljadefiniradogadaje na koje eventlistenertog tipamora bitispremanodgovoriti. Na primjer, suceljeMouseListener deklarirasljedecemetode: public abstract void mouseClicked (MouseEvent e) public abstract void mousePressed (MouseEvent e) public abstract void mouseReleased (MouseEvent e) public abstract void mouseEntered (MouseEvent e) public abstract void mouseExited(MouseEvent e)

Kada, na primjer, komponentadobijedogadaj tipaMouseEvent , njenametodaprocessMouseEvent () provjeravanjegovID da bi ustanovilada lije miškliknut,pritisnut, otpušten, uvedeniliizveden. Tada pozivaodgovarajucumetoduu svakomregistriranomobjektukoji implementiraMouseListener .

Primjer uporabe MouseListenera

Na primjer, pretpostavimoda želimoappletkoji crta crvenikrugoko mjestagdjekorisnikkliknemišem. Prisjetitese da je java.applet.Applet podklasa odjava.awt.Component . Prema tome, da bi appletodgovaraona klikanjemišem, uznjegamora bitiregistriranodgovarajuciMouseListener . U takvimappletimanajjednostavnijeje da sam appletbude MouseListener . Koordinatnisustavse odnosina komponentukojoj je dogadaj namijenjen, ne nužnona cijeliapplet (no to je u ovomslucajuisto). import java.applet.*;import java.awt.*;import java.awt.event.*; public class Dots extends Applet implements MouseListener { int x; int y; int numClicks = 0; public void init() { this.addMouseListener (this); } public void mouseClicked (MouseEvent e) { x = (int) e.getX(); y = (int) e.getY(); numClicks = numClicks + 1; this.repaint(); } // You have to implement these methods, but they don't need // to do anything. public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited(MouseEvent e) {}

Page 147: Java Predavanje I

// paint the dots public void paint(Graphics g) { g.setColor(Color.red); if ( numClicks > 0 ) { g.fillOval(x, y, 30, 30); } } } <APPLET CODE="Dots.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=200></APPLET>

Dogadaji vezani uz tipke (Key Events)

Dogadaj (objekt) tipajava.awt.event.KeyEvent šaljese komponentiako korisnikpritisnetipkudok komponentaimafokus. Tisu dogadajipredstavljenipo jednomcjelobrojnomkonstantom:

KeyEvent.KEY_PRESSED Tipkaje pritisnuta

KeyEvent.KEY_RELEASED Tipkaje otpuštena

KeyEvent.KEY_TYPED Tipkaje pritisnutai zatimotpuštena

Uglavnomcete imatiposla sa ovimposljednjimdogadajemvezanimuz tipke,KeyEvent.KEY_TYPED.

Glavnastvarkoju obicnotrebate doznatiuznekiKeyEvent je koja je tipkapritisnuta. TuinformacijudobijetepomocumetodegetKeyChar():

public char getKeyChar()

Ona ce vamvratitiUnicodeznakkoji odgovarapritisnutojtipki.

Dogadajikao KEY_PRESSED iliKEY_RELEASED ne nose samo znak. Oni takoder imajuikod tipke. (Za razlikuod njih, dogadajiKEY_TYPED nemajukod, odnosno, kod imjenedefiniran). Ako za nekiKeyEvent trebate doznatikoja tipka je pritisnuta, a ne koji jeznakupisan, doznatcete to pomocumetodegetKeyCode():

public int getKeyCode()

Možete to i konvertiratiu lokaliziranistringkao na primjer"END", "F4" ili"Q" pomocustatickemetodeKeyEvent.getKeyText():

public static String getKeyText(int keyCode)

Page 148: Java Predavanje I

U praviluna dogadaje vezaneuz tipkeodgovarateu samojkomponenti, tako da uznjuregistriratenekiKeyListener . SuceljeKeyListener deklarirasljedecemetode, pojednuza svakitipKeyEventa.

public abstract void keyTyped(KeyEvent e) public abstract void keyPressed(KeyEvent e) public abstract void keyReleased(KeyEvent e)

Kodovi tipki

Nisusve tastaturenapravljenena istinacin. Mac imatipke za naredbe i opcije. PC imaAlt tipke. Neki imajutipkuWindows95, nekinemaju. Neki imajunumerickutastaturu,nekine. Emacsocekuje Meta tipkukoja rijetkozasebnopostoji, no obicnoje pridruženaEscape tipki(koju takoder neke tastaturenemaju). Nekonzistentnosttastaturaje je jedanod problemas kojimase cross-platform environment mora na nekinacinpozabaviti.

Klasa Java.awt.event.KeyEvent definiranešto višeod stotinuvirtualnihkodova zatipkekoji se mapirajuna razlicite, uvijekprisutne, tipke. KeyEvent.VK_0 doKeyEvent.VK_9 su istekao znakoviASCII '0' do '9' (0x30 - 0x39)

KeyEvent.VK_0

KeyEvent.VK_1

KeyEvent.VK_2

KeyEvent.VK_3

KeyEvent.VK_4

KeyEvent.VK_5

KeyEvent.VK_6

KeyEvent.VK_7

KeyEvent.VK_8

KeyEvent.VK_9

KeyEvent.VK_A do KeyEvent.VK_Z su istikao ASCII 'A' do 'Z'; dakle imamo,KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D,KeyEvent.VK_E, KeyEvent.VK_F itd.

Razlicite tipke i njihovi kodovi

Od interesasu i sljedecetipke, odnosnonjihovikodovi:

KeyEvent.VK_ACCEPTKeyEvent.VK_ADDKeyEvent.VK_ALTKeyEvent.VK_BACK_QUOTEKeyEvent.VK_BACK_SLASHKeyEvent.VK_BACK_SPACEKeyEvent.VK_CANCELKeyEvent.VK_CAPS_LOCKKeyEvent.VK_CLEAR

KeyEvent.VK_F4KeyEvent.VK_F5KeyEvent.VK_F6KeyEvent.VK_F7KeyEvent.VK_F8KeyEvent.VK_F9KeyEvent.VK_F10KeyEvent.VK_F11KeyEvent.VK_F12

KeyEvent.VK_NUMPAD4KeyEvent.VK_NUMPAD5KeyEvent.VK_NUMPAD6KeyEvent.VK_NUMPAD7KeyEvent.VK_NUMPAD8KeyEvent.VK_NUMPAD9KeyEvent.VK_OPEN_

Page 149: Java Predavanje I

KeyEvent.VK_CLOSE_BRACKETKeyEvent.VK_COMMAKeyEvent.VK_CONTROLKeyEvent.VK_CONVERTKeyEvent.VK_DECIMALKeyEvent.VK_DELETEKeyEvent.VK_DIVIDEKeyEvent.VK_DOWNKeyEvent.VK_ENDKeyEvent.VK_ENTERKeyEvent.VK_EQUALSKeyEvent.VK_ESCAPEKeyEvent.VK_F1KeyEvent.VK_F2KeyEvent.VK_F3

KeyEvent.VK_HOMEKeyEvent.VK_INSERTKeyEvent.VK_KANAKeyEvent.VK_KANJIKeyEvent.VK_LEFTKeyEvent.VK_METAKeyEvent.VK_MODECHANGEKeyEvent.VK_MULTIPLYKeyEvent.VK_NONCONVERTKeyEvent.VK_NUM_LOCKKeyEvent.VK_NUMPAD0KeyEvent.VK_NUMPAD1KeyEvent.VK_NUMPAD2KeyEvent.VK_NUMPAD3

KeyEvent.VK_PAGE_UPKeyEvent.VK_PAUSEKeyEvent.VK_PERIODKeyEvent.VK_PRINTSCREENKeyEvent.VK_QUOTEKeyEvent.VK_RIGHTKeyEvent.VK_SCROLL_LOCKKeyEvent.VK_SEMICOLONKeyEvent.VK_SEPARATERKeyEvent.VK_SHIFTKeyEvent.VK_SLASHKeyEvent.VK_SPACEKeyEvent.VK_SUBTRACTKeyEvent.VK_TABKeyEvent.VK_UNDEFINEDKeyEvent.VK_UP

Modifikatori (Modifier Keys)

Obje klase, KeyEvent i MouseEvent su podklase od java.awt.event.InputEvent .Njezinaglavnaulogaje testiranjedodatnihuvjetakao, na primjer, da lije ALTtipkabilapritisnutazajednos nekomdrugomtipkom, iliSHIFT tipka istovremenos mišemi slicno.

Sljedececetirimetodekažuvamda lije ilinijeodredena tipka bilapritisnutau trenutkukad je dogadaj poslan.

public boolean isShiftDown() public boolean isControlDown () public boolean isMetaDown() public boolean isAltDown()

Sve se one mogupozivatii uzMouseEvent i uzKeyEvent objekte.

Tu je takoder i metodagetWhen() koja vraca vrijemekad je dogadaj nastao. Vrijemeje dano u milisekundamaod ponoci1. sijecnja1970. UTC.

public long getWhen()

Klase java.util.Date i java.util.Calendar imajumetodepomocukojihtomožetekonvertiratiu obicandatumi vrijeme. No najcešcece vas zanimatisamovremenskarazlikaizmedudva dogadaja.

Modifikatori uz tipke miša

DogadajitipaInputEvent spremajuse kao int vrijednosti. Svakibit u takvombroju jeflag koji odgovaraodredenommodifikatoru. Vrijednostitihflagova su dane pomocuint konstantikoje su public final static unutar InputEvent klase:

Page 150: Java Predavanje I

InputEvent.SHIFT_MASK

InputEvent.CTRL_MASK

InputEvent.META_MASK

InputEvent.ALT_MASK

InputEvent.ALT_GRAPH_MASK

InputEvent.BUTTON1_MASK

InputEvent.BUTTON2_MASK

InputEvent.BUTTON3_MASK

Možete ihdoznatipomocumetodegetModifiers ():

public int getModifiers ()

Koristitebitovskioperator & kad želitetestiratida lije neki flag podignut. Na primjer,

if (e.getModifiers () & InputEvent.BUTTON2_MASK != 0) { System.out.println("Button 2 was pressed");}

Dogadaji vezani uz fokus (FocusEvents)

U svakomtrenutkutocno jedna komponentau appletuimafokus, odnosnomogucnostprimanjainputas tastatureilimiša. Dogadajiniskerazinebit ce, dakle, u tom trenutkuusmjereniprema toj komponenti.

Fokus je mogucepodesitina višenacina. Na primjer, kad korisnikpritisnetipkuTab,fokusce opcenitobitipremještens dotadašnjekomponentena sljedecu. Ako pritisneShift-Tab, fokusce se vratitina prethodnukomponentu. Ako selektirakomponentumišem, ona ce dobitifokus.

Bez obzirana koji nacinkomponentadobije iliizgubifokus, ona emitiradogadaj tipajava.awt.event.FocusEvent . Promjenafokusamožebitipermanentnailiprivremena.Permanentnapromjenanastajekad je fokusdirektnopremještens jedne komponentenadrugu, bilopozivanjemkomponentinemetoderequestFocus () iliakcijomkorisnika,npr. pomocuTab tipke. Privremenapromjenafokusanastajekao indirektnirezultatdrugeoperacije, na primjerdeaktiviranjaprozora. U tom slucajuoriginalnostanjefokusace bitiautomatskirestauriranokad se operacijazavršiiliprozor opet aktivira.

Metoda isTemporary() vraca true ako je promjenafokusaprivremena, a false akoje permanentna:

public boolean isTemporary()

Na dogadaje vezaneuzpromjenufokusamožeteodgovoritiako uzkomponentuinstaliratesuceljejava.awt.event.FocusListener . To suceljedeklariradvijemetode:

public abstract void focusGained(FocusEvent e) public abstract void focusLost(FocusEvent e)

Page 151: Java Predavanje I

Dogadaji vezani uz komponentu(Component Events)

Klasa java.awt.event.ComponentEvent je nadklasasvimklasamadogadaja kojesmo do sad vidjeli. Ona takoder imai nekolikosvojihvlastitihdogadaja koji vamomogucujuda reagiratekad se komponentaprikaže, sakrije, pomakneilijoj se promijenivelicina. Oni su reprezentiranikonstantama: ComponentEvent .COMPONENT_MOVED ComponentEvent .COMPONENT_RESIZED ComponentEvent .COMPONENT_SHOWN ComponentEvent .COMPONENT_HIDDEN

Kao i obicno, na te dogadaje možeteodgovaratiako uzsvojukomponenturegistrirateodgovarajuciobjekt izklase koja implementirasuceljejava.awt.event.ComponentListener . To suceljedeklariracetirimetode: public abstract void componentResized (ComponentEvent e) public abstract void componentMoved (ComponentEvent e) public abstract void componentShown (ComponentEvent e) public abstract void componentHidden (ComponentEvent e)

Klasa java.awt.event.ComponentEvent nemanekihvlastitihposebno korisnihmetoda, alimožetekoristitiraznemetode izklasejava.awt.Component kad želiteustanovitikamo je komponentapomaknutailina koju velicinuje preoblikovana.

Adapteri

Adapterisu klase koje implementirajupojedinasuceljatako da sve deklariranemetode izsuceljaprekrijumetodamakoje ne cineništa. AWT osiguravavišeadapterskihklasa zarazlicitevrsteEventListener a. To su:

ComponentAdapter

ContainerAdapter

FocusAdapter

KeyAdapter

MouseAdapter

MouseMotionAdapter

WindowAdapter

Na primjer, znamoda suceljeMouseListener deklarirasljedecihpet metoda: public abstract void mouseClicked (MouseEvent e) public abstract void mousePressed (MouseEvent e) public abstract void mouseReleased (MouseEvent e) public abstract void mouseEntered (MouseEvent e) public abstract void mouseExited(MouseEvent e)

Zato odgovarajuciadapter, java.awt.event.MouseAdapter izgledaovako:

Page 152: Java Predavanje I

package java.awt.event; import java.awt.*;import java.awt.event.*; public class MouseAdapter implements MouseListener { public void mouseClicked (MouseEvent e) {} public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited(MouseEvent e) {} }

Ako sada napravitepodklasuklaseMouseAdapter umjestoda direktnoimplementirateMouseListener , izbjecicete pisanjemetodakoje vamzapravone trebaju. Pregazitcetejedinoone metodekoje stvarnoželiteimplementirati. Adapterisu svojevrsnopojednostavnjenjeposla prilikomimplementiranjasucelja. Možete ihkoristitiako želite,alii ne morate.

Primjer uporabe adaptera

Ovdje imamoadapter za mišakoji proizvodibeep signalkad kliknetemišem. import java.applet.Applet; public class MouseBeepApplet extends Applet { public void init() { MouseBeeper mb = new MouseBeeper(); this.addMouseListener (mb); }} import java.awt.*;import java.awt.event.*; public class MouseBeeper extends MouseAdapter { public void mouseClicked (MouseEvent e) { Toolkit.getDefaultToolkit ().beep(); } } <APPLET CODE="MouseBeepApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="MouseBeep.jar"WIDTH=200 HEIGHT=200></APPLET>

Page 153: Java Predavanje I

Kad MouseBeeper ne bi bio podklasa od MouseAdapter morao bi izgledatiovako: import java.awt.*;import java.awt.event.*; public class MouseBeeper implements MouseListener { public void mouseClicked (MouseEvent e) { Toolkit.getDefaultToolkit ().beep(); } public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited(MouseEvent e) {} }

Apsorbiranje dogadaja

Ponekad je potrebno neke dogadaje zadržatikako ihkomponentane bi procesiralanauobicajennacin. Na primjer, programza izraduvizualnogsuceljamoždatreba dozvolitikorisnikupovlacenjemišapo ekranu. U tom slucajune želiteda obicanklikna tipkumišaaktiviratu funkciju. Zato komponentamožeapsorbirati(consume) dogadaje tipaInputEvent , dakle MouseEvent ilia KeyEvent , tako da pozovenjihovumetoduconsume():

public void consume()

Jednomkad je dogadaj (objekt) tipaInputEvent apsorbiran, izvornakomponentaganece procesirati, alice taj dogadaj svejednobitidistribuiransvimregistriranimlistenerima.

Prebacivanje dogadaja s niske navisoku razinu

Svakinative operacijskisustavi korisnickosucelješaljesamo dogadaje niskerazine.Ono nece poslatiActionEvent , TextEvent , ItemEvent iliAdjustmentEvent .Umjestotoga, svaka komponentakoja lansiratakve dogadaje prvo slušaodredenedogadaje niskerazine. Kad ugledaodgovarajucidogadaj ilikombinacijudogadaja niskerazine, ona ihapsorbirai lansiranovidogadaj visokerazine.

Rad s repom dogadaja

Page 154: Java Predavanje I

Klasa java.awt.EventQueue predstavljarep dogadaja koji cekaju na procesiranje.Možete kreirativlastiteinstanceove klase uzpomoc sljedecegkonstruktora:

public EventQueue()

Na primjer:

EventQueue MyQueue = new EventQueue();

Ipak, uglavnomce vas višezanimatisistemskirep dogadaja. Taj se kreiraautomatski.Možete dobitireferencuna njegapomocumetodegetSystemEventQueue () izklasejava.awt.Toolkit ovako:

EventQueue systemQueue = Toolkit.getDefaultToolkit ().getSystemEventQueue ();

Appletnece mocipozvatiovumetodua da pritomne generiraSecurityException .

Jednomkad dobijetereferencuna sistemskirep dogadaja, možetemanipuliratis njimpomocusljedecihmetoda:

public synchronized void postEvent(AWTEvent e) public synchronized AWTEvent getNextEvent () public synchronized AWTEvent peekEvent() public synchronized AWTEvent peekEvent(int n)

Metoda postEvent() omogucujevamda stavitedogadaj u rep. Metoda getNextEvent () vraca gornjidogadaj izrepa i uklanjaga odande. Metoda peekEvent() vraca gornjidogadaj izrepa, aliga ne uklanja. Metoda peekEvent(int n) vraca ntidogadaj izrepa.

Page 155: Java Predavanje I

Osmo predavanje razmještajkomponentiKontrola razmještaja komponenti razne implementacije layout managerarazmještaj tipa FlowLayout podešavanje poravnanja za FlowLayout razdvajanjekomponenti za FlowLayout razmještaj tipa BorderLayout razmještaj tipaCardLayout uporaba CardLayout razmještaja promjena karata razmještaj tipaGridLayout razmještaj tipa BridBagLayout razmještaj tipa GridBagConstraintsmreža (grid) za applet Calculator atributi gridx i gridy atributi gridwidth igridheight atribut fill atributi ipadx i ipady klasa Insets atribut anchoratributi weightx i weighty primjer za GridLayout rucno pozicioniranjekomponenti Kontejneri dvije vrste kontejnera paneli ugnježdeni paneliprozori (windows) okviri (frames) dogadaji vezani uz prozore primjer dogadajana prozorima kombiniranje appleta i aplikacija dijalozi metode za dijalogeprimjeri dijaloga pisanje podklasa klase Dialog

Kontrola razmještaja komponenti

Kontrolunad pozicijamakomponentikoje dodajete razmještajuomogucujevamsuceljejava.awt.LayoutManager . Buducida ne možeteunaprijedznatis kako velikompovršinomcete raditiilikakvogce ona bitioblika, kontrolace bitirelativna, dakleuglavnomcete odlucivatio tome treba lineka komponentabitiiznadiliispod druge,poravnatalijevoilidesno, aliu pravilunecete odredivatida se komponentatreba pojavitibaš u nekoj specificnojtocki.

Razne implementacije LayoutManagera

Suceljejava.awt.LayoutManager implementiranoje u višerazlicitihklasa, kao što su:

java.awt.FlowLayout

java.awt.BorderLayout

java.awt.CardLayout

java.awt.GridLayout

java.awt.GridBagLayout

Appletiilikontejneriimajumogucnostkoristitiove i druge layout managere da bi odluciligdje ce stavitikomponentekoje u njihdodajete. Klasa java.awt.FlowLayout rasporedujekomponentes lijevana desno dok imaprostora, a tada nastavljana istinacinu retku ispod. Svaka komponentau FlowLayout

razmještajudobijaupravoonolikoprostora kolikojoj minimalnotreba i ništaviše. Takavje razmještajkoristanza rasporedivanjebuttona, aliza mnogedrugestvarinije. On je

Page 156: Java Predavanje I

pretpostavljeni(default) razmještajza applete i panele(posebne kontejnereo kojimacemalokasnijebitirijeci).

Klasa java.awt.BorderLayout organiziraappletna sekcijeprema stranamasvijeta:North, South, East, West i Center. North, South, East i West su pravokutnicinarubovimaappleta. Oni se kontinuiranošireprema velicinikomponenatau njima. Center jeono što preostaneu središtu.

Klasa java.awt.CardLayout razbijaappletu skupinupovršina(karata) koje imajusvaka svoj vlastiterazmještaj. U svakomtrenutkusamo se jedna karta pojavljujenaekranu. Korisnikmožeprebacivatiizgledekrana s jedne na drugukartu, a svakaprikazujerazliciteskupovekomponenti. Obicnose to usporedujesa HyperCardom naMacu iliToolbookom on Windowsima. U Javi se to možekoristitikao serijamaskizaunospodataka ako sva poljane mogustatina ekran.

Klasa java.awt.GridLayout dijeliappletna odredenibroj redaka i stupaca te takoformiramrežucelijakao matricu. Kako se koja komponentadodaje, ona se smještausljedecuslobodnuceliju, pocevšiod lijevoguglaprema desno i prema dolje. Svakakomponentase podešava po velicinitako da pristajeu celiju. Takav razmještajce nekekomponentenepotrebnostisnuti, a neke razvuci, alije jako pogodanza razmještanjepanela.

Klasa java.awt.GridBagLayout daje najpreciznijiod svihAWT razmještaja.Razmještajje kao i GridLayout , alikomponentene morajubitiistevelicine. Svakakomponentamožezauzetijednuilivišecelija. Štaviše, komponentenisunužnosmješteneu celijepocevšiod gornjeglijevoguglanitise morajudodavatiprema desno i premadolje.

U jednostavnimappletimasa samo nekolikokomponentibit ce dovoljanjedanrazmještaj. U kompliciranijima, medutim, cesto cete razbitiappletna panele, rasporeditiihprema nekomrazmještaju, a onda svakipanelsnabdjetivlastitimlayout managerom zarasporedivanjekomponentiunutarnjega.

Razmještaj tipa FlowLayout

Klasa java.awt.FlowLayout rasporedujekomponentes lijevana desno dok imaprostora, a tada nastavljaistipostupak redak niže. Svaka komponentadobijaupravotolikomjestakolikojoj treba i ništaviše. Ovaj je tip razmještajanajkorisnijizarasporedivanjebuttona.

FlowLayout je pretpostavljeni(default) razmještajza java.awt.Panel koji jenadklasaod java.applet.Applet . Prema tome ne trebate ucinitiništaposebno dabisteFlowLayout kreiraliunutarappleta. Medutim, ako ga želitekoristitiunutarprozora,java.awt.Window, trebat ce vamodgovarajucikonstruktori.

Razmještajiimajukonstruktorekao i ostaleklase. Jedan od konstruktorazaFlowLayout je:

Page 157: Java Predavanje I

public FlowLayout()

Dakle, za kreiranjenovogobjekta tipaFlowLayout pišete:

FlowLayout fl;fl = new FlowLayout();

Kao i obicno, to se možeskratitina:

FlowLayout fl = new FlowLayout();

Appletucete reci koju specificnuinstancuklaseLayoutManager želitekoristiti, tako dataj objekt navedeteu appletovojmetodisetLayout(). Ovu metoduklasajava.applet.Applet nasljeduje, kao i mnogedruge, izklasejava.awt.Container .

this.setLayout(fl);

Metoda setLayout() se uglavnompozivau init() metodi. Uobicajenoje kreiratiprimjerakrazmještajadirektnounutarpozivametodesetLayout() ovako:

this.setLayout(new FlowLayout());

Podešavanje poravnanja zaFlowLayout

Poravnanjeza nekiFlowLayout zadajetepomocuodgovarajucegkonstruktora.Komponentesu u appletupo pretpostavcicentrirane. Možete umjestotoga odreditidabudu lijevoilidesno pozicionirane. Za to možetekoristitigotovekonstanteFlowLayout.LEFT, FlowLayout.RIGHT iliFlowLayout.CENTER prilikompozivanjakonstruktora, npr. this.setLayout(new FlowLayout(FlowLayout.LEFT)); this.setLayout(new FlowLayout(FlowLayout.RIGHT)); this.setLayout(new FlowLayout(FlowLayout.CENTER));

Pogledajmosljedeciprimjeru kojemse poravnanjezadaje pomocuparametraoznake<APPLET>. import java.applet.Applet; import java.awt.Button;import java.awt.FlowLayout; public class TapeDeckAlign extends Applet { public void init() { FlowLayout f; String align = getParameter ("align"); if (align == null) f = new FlowLayout(FlowLayout.CENTER); else if (align.equalsIgnoreCase ("left")) {

Page 158: Java Predavanje I

f = new FlowLayout(FlowLayout.LEFT); } else if (align.equalsIgnoreCase ("right")) { f = new FlowLayout(FlowLayout.RIGHT); } else f = new FlowLayout(FlowLayout.CENTER); setLayout(f); add( new Button("Play")); add( new Button("Rewind")); add( new Button("Fast Forward")); add( new Button("Pause")); add( new Button("Stop")); } } <APPLET CODE="TapeDeckAlign .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100><param name="align" value="left"></APPLET>

S parametromvalue="center", odnosno value="right" dobilibismocentriraniidesno pozicioniranirazmještaj.

Razdvajanje komponenti zaFlowLayout

VecinaLayoutManager a omogucujevamkontrolunad minimalnimvertikalnimihorizontalnimprostoromkoji razdvajakomponente. Za FlowLayout zadajeteželjeniprostor u pikseleima, putemodgovarajucihargumenatau konstruktoru:

public FlowLayout(int alignment, int hspace, int vspace);

Na primjer, da bistenapraviliFlowLayout sa deset pikselahorizontalnogi dvadesetpikselavertikalnograzmaka, sa lijevimporavnanjem, koristilibistesljedecikonstruktor:

FlowLayout fl = new FlowLayout(FlowLayout.LEFT, 20, 10);

Pogledajteprimjerappletakoji tako rasporedujebuttonenalikonimaza VCR: import java.applet.*; import java.awt.*; public class SpaceTapeDeck extends Applet {

Page 159: Java Predavanje I

public void init() { this.setLayout( new FlowLayout(FlowLayout.LEFT, 20, 10)); this.add( new Button("Play")); this.add( new Button("Rewind")); this.add( new Button("Fast Forward")); this.add( new Button("Pause")); this.add( new Button("Stop")); } } <APPLET CODE="SpaceTapeDeck .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=400 HEIGHT=100></APPLET>

Razmještaj tipa BorderLayout

Klasa java.awt.BorderLayout smještaobjekte na NORTH, SOUTH, EAST, WESTiliCENTERunutarappleta. Da bistekreiralinoviobjekt tipaBorderLayout , pozovite,slicnokao i za FlowLayout unutarmetodeinit() metodusetLayout() ovako: this.setLayout(new BorderLayout ());

U ovomtipurazmještajanemacentriranjani lijevogilidesnogporavnavanja, no možetedodati horizontalnei vertikalnerazmakemedukomponentama. Na primjer, zahorizontalnirazmakod 5 pikselai vertikalniod 10 piksela, stavilibismo: this.setLayout(new BorderLayout (5, 10));

Kad želitedodati komponentuna odredenustranu, možeteto ucinitina primjerovako: this.add(new Button("Start"), BorderLayout .SOUTH);

Kao što se izsljedecegprimjeramoževidjeti, sjevernai južnasekcijaprotežuse prekoappletas lijevana desno. Istocna i zapadnase protežuod dna sjevernedo vrhajužnesekcije. Ove cetirikomponentebit ce onolikovelikekolikoje potrebno da bi u njihstalekomponentekoje imdodijelite. Ono što ostane, bitice za centralnusekciju. Tocnevelicinesu nepredvidljive. Kao i tocan nacinpakiranjakomponentiunutarsekcija.

import java.applet.*; import java.awt.*; public class BorderButtons extends Applet { public void init() { this.setLayout(new BorderLayout (20, 10));

Page 160: Java Predavanje I

this.add(new Button("North"), BorderLayout .NORTH); this.add(new Button("South"), BorderLayout .SOUTH); this.add(new Button("East"), BorderLayout .EAST); this.add(new Button("West"), BorderLayout .WEST); this.add(new Button("Center"), BorderLayout .CENTER); } } <APPLET CODE="BorderButtons .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Razmještaj tipa CardLayout

Razmještajkoji implementiraklasajava.awt.CardLayout je maloneuobicajen. Onpretvaraappletu snop karata, od kojihsvaka potencijalnoimasvoj vlastitiLayoutManager . U svakomtrenutkuna ekranuje vidljivasamo jedna karta. Možeteprelazitis jedne karte na drugu, dovodecitako svakiput na ekran drugiskupkomponenti. Postojislicnostsa HyperCardom na Mac-u iliToolbookom naWindowsima. U Javise takav razmještajmožekoristitikao nizekrana za unosako svipodaci ne stanuna jedan. Ilise, ako treba prikazativišepodataka, moženapravitineštokao slide show.

Na primjer, pogledajtesljedeciapplet, CardTest , jedan od Sunovihstandardnihdemoappleta. Ovdje se koristiCardLayout za prebacivanjes jednograzmještajana drugi, pricemuse na razlicitenacinerasporedujuistibuttoni:

<APPLET CODE="CardTest.class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="CardTest.jar"WIDTH=400 HEIGHT=200></APPLET>

Page 161: Java Predavanje I

Uporaba CardLayout razmještaja

Ovaj razmještajkreiratepomocukonstruktoraCardLayout() ovako: this.setLayout(new CardLayout());

Na raspolaganjuvamje još jedan konstruktorkojimmožeteodreditirazmakmedukomponentama: this.setLayout(new CardLayout(3, 4));

U ovomprimjerukomponentece bitirazmaknute3 pixelahorizontalnoi 4 pixelavertikalno.

Svaka karta imaime. Nova karta se kreirakad dodate komponentukartikoja do tadanijeuvedena. Komponentedodajete tako da navedeteimekarte i instancukomponenteumetodiadd():

this.setLayout(new CardLayout());this.add("Pizza", new Label("How do you like your pizza?"));this.add("Pizza", new Button("OK"));this.add("Payment", new Label("How would you like to pay?"));this.add("Payment", new Button("OK"));this.add("Address", new Label("Delivery Instructions "));this.add("Address", new Button("Order"));

Cesto se karte imenujupo brojevima: this.setLayout(new CardLayout());this.add("1", new Label("First Card"));this.add("2", new Label("Second Card"));this.add("3", new Label("Third Card"));this.add("4", new Label("Fourth Card"));this.add("5", new Label("Fifth Card"));this.add("6", new Label("Sixth Card"));

Page 162: Java Predavanje I

Internose popis karata i njihovihimenaspremau objekt tipajava.util.Hashtable .To znacida nemagarantiranogiliugradenogredoslijedakarata. O tomeprogramtrebatesamivoditiracuna.

Promjena karata

U pravilusvakoj kartidodajete panelkoji imavlastitiLayoutManager . Svaka kartatreba bitisnabdjevenanekimuputnicamaza navigacijumedukartama. Sam AWT nemagotovogtakvogalata. Primijetitetakoder da jednukomponentumožetedodati na višeodjedne karte. To je korisno, na primjer, za kreiranjeChoice izbornikasa imenimasvihkarata kao navigacijskimpomagalom.

Sljedecihpet metodaklasejava.awt.CardLayout omogucujepromjenuaktivnekarte.U svimslucajevimatreba specificiratikontejnerunutarkojega prelazimos karte na kartu.To možebitiapplet, prozor ilipanelkoji je uredenu skladus timrazmještajem.

public void first(Container parent) public void next(Container parent) public void previous(Container parent) public void last(Container parent) public void show(Container parent, String name)

Razmještaj tipa GridLayout

Klasa java.awt.GridLayout specificirabroj redaka i stupaca u koje ce komponentebitismještene. Appletse razbijana matricujednako velikihcelija.

GridLayout je koristankad želiterazmjestitivišeobjekata slicnevelicine. Jako je dobarza sastavljanjelistecheckboxovailiradio buttonakao u appletuIngredients izšestogpredavanja. U sljedecemprimjerudonosimomaloizmijenjenuverzijutog appletapacemo checkboxoverasporeditiunutaršest redaka i jedne kolone, što ce appletudatimnogoboljii urednijiizgled. Uklonjenje kod za obradu dogadaja jer nijebitanza ovajprimjer.

import java.applet.*;import java.awt.*; public class Ingredients2 extends Applet { TextField t; double price = 7.00; public void init() { this.setLayout(new GridLayout(11,1)); this.add(new Label("What do you want on your pizza?", Label.CENTER)); this.add(new Checkbox("Pepperoni"));

Page 163: Java Predavanje I

this.add(new Checkbox("Olives")); this.add(new Checkbox("Onions")); this.add(new Checkbox("Sausage")); this.add(new Checkbox("Peppers")); this.add(new Checkbox("Extra Cheese")); this.add(new Checkbox("Ham")); this.add(new Checkbox("Pineapple")); this.add(new Checkbox("Anchovies")); this.t = new TextField("$" + String.valueOf(price)); this.t.setEditable(false); this.add(this.t); } /* ovdje dolazi kod za obradu dogadjaja koji je iz ovog primjera uklonjen */ } <APPLET CODE="Ingredients2.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=250></APPLET>

Razmještaj tipa GridBagLayout

Klasa java.awt.GridBagLayout daje mrežuza rasporedivanjekomponenti, slicnokao GridLayout , alidopušta da pojedinakomponentazauzmevišeod jedne celije.Takoder, ovdje se velicinacelijeprilagodavavelicinikomponente, a ne obrnuto, kao štosmo do sada navikli.Konstruktorza GridBagLayout je trivijalan, GridBagLayout () bez argumenata.Koristitega ovako:

Page 164: Java Predavanje I

GridBagLayout gbl = new GridBagLayout (); setLayout(gbl);

Za razlikuod konstruktoraza GridLayout() ovaj ne kaže kolikoredaka ilistupacatreba napraviti. To se odreduje prema celijamakoje vaš programreferencira. Ako stavitekomponentuu osmiredak i drugistupac, Java ce osiguratida bude bardevet redaka i tristupca (retci i stupcizapocinjuod nultog). Ako kasnijestavitekomponentuu deseti redaki cetvrtistupac, Java ce dodati odgovarajucibroj celija. Možete zamišljatikonacnumrežu, aliJava to ne mora znatikad kreirateGridBagLayout .

Za razlikuod vecineostalihrazmještaja, referencana objekt tipaGridBagLayout trebatce vamkasnijeu programupa ga, dakle necete kreiratianonimno, unutarpozivametodesetLayout().

Specifikacije GridBagConstraints

Svakoj komponentikoju kontroliraGridBagLayout pridruženje po jedan objekt izklasejava.awt.GridBagConstraints koji specificirapoložajunutarpovršinezaprikaz. Takav objekt zajednosa minimalnomi preferiranomvelicinomkomponenteodreduje gdje se i kako površinaza prikazsmještaunutarappleta.

Konstruktorza GridBagConstraints () je trivijalan:

GridBagConstraints gbc = new GridBagConstraints ();

Interakcijas objektomtipaGridBagConstraints odvijase preko jedanaestvarijabli(gridx, gridy, gridwidth , gridheight , weightx , weighty , achor, fill, insets ,ipadx, ipady) i petnaestmnemonickihkonstanti(RELATIVE , REMAINDER , NONE, BOTH,HORIZONTAL , VERTICAL , CENTER , NORTH, NORTHEAST , EAST, SOUTHEAST , SOUTH,SOUTHWEST , WEST, NORTHWEST ).

Pokazat cemo njihovuuporabuna primjeruappletaGridBagCalculatorApplet kojipredstavljamaskuza kalkulator.

<APPLET CODE="GridBagCalculatorApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" ARCHIVE="GridBagCalculator .jar" WIDTH=1 HEIGHT=1></APPLET>

Mreža (grid) za applet Calculator

Evo sada mrežekoju koristimoza razmještajkalkulatorovihkomponenti. Primijetiteda umrežiimavišecelijanegokomponentikalkulatora. Kalkulatorimajedan TextField i 18buttonarazlicitihvelicina. Neke komponentezauzetce višeod jedne celijemreže. Naprimjer, TextField koji predstavljakalkulatorovdisplay zauzetce cetiricelije, (0, 0),(1, 0), (2, 0), and (3, 0).

Page 165: Java Predavanje I

(0, 0) (1, 0) (2, 0) (3, 0)

(0, 1) (1, 1) (2, 1) (3. 1)

(0, 2) (1, 2) (2, 2) (3, 2)

(0, 3) (1, 3) (2, 3) (3, 3)

(0, 4) (1, 4) (2, 4) (3, 4)

(0, 5) (1, 5) (2, 5) (3, 5)

Za svakukomponentukreiratcemo po jedan objekt tipaGridBagConstraints. Na primjerza display, equals key i zero key imatcemo GridBagConstraints GBC_display = new GridBagConstraints (); GridBagConstraints GBC_bigequals = new GridBagConstraints (); GridBagConstraints GBC_0 = new GridBagConstraints ();

Nakon što postavimovrijednostiodgovarajucihatributa, taj cemo objekt pridružitikomponentipomocumetodesetConstraints () ovako: gbl.setConstraints (display, GBC_display); gb1.setConstraints (bigequals, GBC_bigequals; gbl.setConstraints (b0, GBC_0);

Atributi gridx i gridy

Atributigridx i gridy specificirajux i y "koordinate", tj. stupac i redak celijeu koju cedoci lijevigornjiugaokomponente. Gornjalijevacelijau našemprimjeruje celija(0, 0).Umjestoapsolutnihvrijednostimožemostavitii mnemonickukonstantuGridBagConstraints .RELATIVE koja kaže da ce komponentabitismještenaneposrednodesno (gridx) ilineposrednoispod (gridy) u odnosuna komponentukojaje prije toga posljednjabiladodana kontejneru.

Naš kalkulatorimadisplay u lijevomgornjemugluappleta. Prema tome, gridx i gridyprve komponente(to je TextField ) izgledatce ovako:

GBC_display.gridx = 0; GBC_display.gridy = 0;

Isto tako, na primjer, tipkaza znakjednakosti(equals key) imatce GBC_bigequals.gridx = 3; GBC_bigequals.gridy = 4;

Tipkaza znamenku0 (zero key) imatce GBC_0.gridx = 0; GBC_0.gridy = 5;

Page 166: Java Predavanje I

Atributi gridwidth i gridheight

Atributigridwidth i gridheight specificirajubroj celijau retku (gridwidth ) ilistupcu(gridheight ) koje ce komponentazauzeti. Ako ovdje upišemomnemonickukonstantuGridBagConstraints .REMAINDER , onda ce komponentazauzetisvepreostalecelijeu retku (za gridwidth ) ilistupcu(za gridheight ).

Kalkulatorovdisplay ce zauzeticetiricelijepo širinii jednupo visini, dakle imatcemo

GBC_display.gridwidth = 4; GBC_display.gridheight = 1;

Tipkaza znakjednakosti(equals key) je dvijecelijevisoki jednucelijuširok, dakle GBC_bigequals.gridwidth = 1; GBC_bigequals.gridheight = 2;

Tipkaza znamenku0 (zero key) imatce GBC_0.gridwidth = 2; GBC_0.gridheight = 1;

Atribut fill

Atributfill specificiranacinna koji komponentaispunjavaprostor koji joj je dodijeljen(u slucajuda je prostor veciod same komponente). Mnemonickekonstantekoje koristiteza postavljanjeove varijablesu:

GridBagConstraints .NONE: komponentane mijenjavelicinuGridBagConstraints .HORIZONTAL : Komponentace se protezatipreko cijeleširineprostora koji joj je dodijeljen, alinece promijenitisvojuvisinuGridBagConstraints .VERTICAL : Komponentace se protezatipreko cijelevisineprostora koji joj je dodijeljen, alinece promjijenitisvojuširinuGridBagConstraints .BOTH: Širinai visinakomponentebit ce prilagodenetakoda komponentazauzmecijeliprostor koji joj je dodijeljen

U našemprimjeruodredilismo da se displayširihorizontalno, a tipke (pogledajmonaprimjerzero key) u svimsmjerovima, dakle GBC_display.fill = GridBagConstraints .HORIZONTAL; GBC_0.fill = GridBagConstraints .BOTH;

Atributi ipadx i ipady

Svaka komponentaimaodredenuminimalnuširinui visinui ne možese smanjivatiispodtihvrijednosti. Ako su minimalnedimenzijekomponentevece od dimenzijapovršinekojejoj stoje na raspolaganju, bit ce prikazansamo dio komponente.

Page 167: Java Predavanje I

Atributiipadx i ipady dozvoljavajuvamda povecate te minimalnedimenzijetako da serubovimakomponentedoda nešto prostora . Na primjer, ako staviteipadx =2, to cegarantiratida je komponentanajmanje4 pikselaširaod svognormalnogminimuma. Unašemprimjeruto nijepotrebno.

Atribut Insets

Atributinsets je instancaklasejava.awt.Insets . On specificirarazmakizmedukomponentei rubovapovršinena kojoj je smještena. Za sve tipkeu našemkalkulatoruodredilismo da to bude 3 pikselasa svake strane(što osiguravada susjednetipkebudurazmaknuteza 6 piksela), pa imamona primjer GBC_bigequals.insets = new Insets(3, 3, 3, 3); GBC_0.insets = new Insets(3, 3, 3, 3);

Atribut anchor

Kad je komponentamanjenegoraspoloživapovršina, atributanchor specificirapoložajunutarcelijekamo komponentutreba staviti. Mnemonickekonstantekoje za to koristiteslicnesu onimaza BorderLayout . Tos u

GridBagConstraints .CENTER

GridBagConstraints .NORTH

GridBagConstraints .NORTHEAST

GridBagConstraints .EAST

GridBagConstraints .SOUTHEAST

GridBagConstraints .SOUTH

GridBagConstraints .SOUTHWEST

GridBagConstraints .WEST

GridBagConstraints .NORTHWEST

Pretpostavljenavrijednostje GridBagConstraints .CENTER . U našemprimjeruto nijeeksplicitnonavedenojer su komponentedovoljnovelikeu odnosuna raspoloživepovršine, tako da je centriranapozicijazadovoljavajuca.

Atributi weightx i weighty

Atributiweightx i weighty odredujukako su celijedistribuiraneunutarkontejneraakonjihovaukupnavelicinabude manjaod velicinekontejnera. Sa težinama0 (default) svecelijezauzimajunajmanješto mogui sve se sabijeprema centru. Sav dodatniprostor jeizguranprema rubovimakontejnera.

Primjer za GridBagLayout

Page 168: Java Predavanje I

Pogledajmosada kompletnuinit() metodasa razmještajemkalkulatorovihtipaka. public void init () { GridBagLayout gbl = new GridBagLayout (); setLayout(gbl); // Add the display to the top four cells GridBagConstraints GBC_display = new GridBagConstraints (); GBC_display.gridx = 0; GBC_display.gridy = 0; GBC_display.gridwidth = 4; GBC_display.gridheight = 1; GBC_display.fill = GridBagConstraints .HORIZONTAL; // add the text field TextField display = new TextField(12); gbl.setConstraints (display, GBC_display); add(display); // Add the clear button GridBagConstraints GBC_clear = new GridBagConstraints (); GBC_clear.gridx = 0; GBC_clear.gridy = 1; GBC_clear.gridwidth = 1; GBC_clear.gridheight = 1; GBC_clear.fill = GridBagConstraints .BOTH; GBC_clear.insets = new Insets(3, 3, 3, 3); // add the button Button clear = new Button("C"); gbl.setConstraints (clear, GBC_clear); add(clear); // Add the equals button GridBagConstraints GBC_equals = new GridBagConstraints (); GBC_equals.gridx = 1; GBC_equals.gridy = 1; GBC_equals.gridwidth = 1; GBC_equals.gridheight = 1; GBC_equals.fill = GridBagConstraints .BOTH; GBC_equals.insets = new Insets(3, 3, 3, 3); // add the = button Button equals = new Button("="); gbl.setConstraints (equals, GBC_equals); add(equals); // Add the / button GridBagConstraints GBC_slash = new GridBagConstraints (); GBC_slash.gridx = 2; GBC_slash.gridy = 1; GBC_slash.gridwidth = 1; GBC_slash.gridheight = 1; GBC_slash.fill = GridBagConstraints .BOTH; GBC_slash.insets = new Insets(3, 3, 3, 3);

Page 169: Java Predavanje I

// add the button Button slash = new Button("/"); gbl.setConstraints (slash, GBC_slash); add(slash); // Add the * button GridBagConstraints GBC_times = new GridBagConstraints (); GBC_times.gridx = 3; GBC_times.gridy = 1; GBC_times.gridwidth = 1; GBC_times.gridheight = 1; GBC_times.fill = GridBagConstraints .BOTH; GBC_times.insets = new Insets(3, 3, 3, 3); // add the button Button star = new Button("*"); gbl.setConstraints (star, GBC_times); add(star); // Add the 7 key GridBagConstraints GBC_7 = new GridBagConstraints (); GBC_7.gridx = 0; GBC_7.gridy = 2; GBC_7.gridwidth = 1; GBC_7.gridheight = 1; GBC_7.fill = GridBagConstraints .BOTH; GBC_7.insets = new Insets(3, 3, 3, 3); // add the button Button b7 = new Button("7"); gbl.setConstraints (b7, GBC_7); add(b7); // Add the 8 key GridBagConstraints GBC_8 = new GridBagConstraints (); GBC_8.gridx = 1; GBC_8.gridy = 2; GBC_8.gridwidth = 1; GBC_8.gridheight = 1; GBC_8.fill = GridBagConstraints .BOTH; GBC_8.insets = new Insets(3, 3, 3, 3); // add the button Button b8 = new Button("8"); gbl.setConstraints (b8, GBC_8); add(b8); // Add the 9 key GridBagConstraints GBC_9 = new GridBagConstraints (); GBC_9.gridx = 2; GBC_9.gridy = 2; GBC_9.gridwidth = 1; GBC_9.gridheight = 1; GBC_9.fill = GridBagConstraints .BOTH; GBC_9.insets = new Insets(3, 3, 3, 3);

Page 170: Java Predavanje I

// add the button Button b9 = new Button("9"); gbl.setConstraints (b9, GBC_9); add(b9); // Add the - key GridBagConstraints GBC_minus = new GridBagConstraints (); GBC_minus.gridx = 3; GBC_minus.gridy = 2; GBC_minus.gridwidth = 1; GBC_minus.gridheight = 1; GBC_minus.fill = GridBagConstraints .BOTH; GBC_minus.insets = new Insets(3, 3, 3, 3); // add the button Button minus = new Button("-"); gbl.setConstraints (minus, GBC_minus); add(minus); // Add the 4 key GridBagConstraints GBC_4 = new GridBagConstraints (); GBC_4.gridx = 0; GBC_4.gridy = 3; GBC_4.gridwidth = 1; GBC_4.gridheight = 1; GBC_4.fill = GridBagConstraints .BOTH; GBC_4.insets = new Insets(3, 3, 3, 3); // add the button Button b4 = new Button("4"); gbl.setConstraints (b4, GBC_4); add(b4); // Add the 5 key GridBagConstraints GBC_5 = new GridBagConstraints (); GBC_5.gridx = 1; GBC_5.gridy = 3; GBC_5.gridwidth = 1; GBC_5.gridheight = 1; GBC_5.fill = GridBagConstraints .BOTH; GBC_5.insets = new Insets(3, 3, 3, 3); // add the button Button b5 = new Button("5"); gbl.setConstraints (b5, GBC_5); add(b5); // Add the 6 key GridBagConstraints GBC_6 = new GridBagConstraints (); GBC_6.gridx = 2; GBC_6.gridy = 3; GBC_6.gridwidth = 1; GBC_6.gridheight = 1; GBC_6.fill = GridBagConstraints .BOTH; GBC_6.insets = new Insets(3, 3, 3, 3);

Page 171: Java Predavanje I

// add the button Button b6 = new Button("6"); gbl.setConstraints (b6, GBC_6); add(b6); // Add the + key GridBagConstraints GBC_plus = new GridBagConstraints (); GBC_plus.gridx = 3; GBC_plus.gridy = 3; GBC_plus.gridwidth = 1; GBC_plus.gridheight = 1; GBC_plus.fill = GridBagConstraints .BOTH; GBC_plus.insets = new Insets(3, 3, 3, 3); // add the button Button plus = new Button("+"); gbl.setConstraints (plus, GBC_plus); add(plus); // Add the 1 key GridBagConstraints GBC_1 = new GridBagConstraints (); GBC_1.gridx = 0; GBC_1.gridy = 4; GBC_1.gridwidth = 1; GBC_1.gridheight = 1; GBC_1.fill = GridBagConstraints .BOTH; GBC_1.insets = new Insets(3, 3, 3, 3); // add the button Button b1 = new Button("1"); gbl.setConstraints (b1, GBC_1); add(b1); // Add the 2 key GridBagConstraints GBC_2 = new GridBagConstraints (); GBC_2.gridx = 1; GBC_2.gridy = 4; GBC_2.gridwidth = 1; GBC_2.gridheight = 1; GBC_2.fill = GridBagConstraints .BOTH; GBC_2.insets = new Insets(3, 3, 3, 3); // add the button Button b2 = new Button("2"); gbl.setConstraints (b2, GBC_2); add(b2); // Add the 3 key GridBagConstraints GBC_3 = new GridBagConstraints (); GBC_3.gridx = 2; GBC_3.gridy = 4; GBC_3.gridwidth = 1; GBC_3.gridheight = 1; GBC_3.fill = GridBagConstraints .BOTH; GBC_3.insets = new Insets(3, 3, 3, 3);

Page 172: Java Predavanje I

// add the button Button b3 = new Button("3"); gbl.setConstraints (b3, GBC_3); add(b3); // Add the = key GridBagConstraints GBC_bigequals = new GridBagConstraints (); GBC_bigequals.gridx = 3; GBC_bigequals.gridy = 4; GBC_bigequals.gridwidth = 1; GBC_bigequals.gridheight = 2; GBC_bigequals.fill = GridBagConstraints .BOTH; GBC_bigequals.insets = new Insets(3, 3, 3, 3); // add the button Button bigequals = new Button("="); gbl.setConstraints (bigequals, GBC_bigequals); add(bigequals); // Add the 0 key GridBagConstraints GBC_0 = new GridBagConstraints (); GBC_0.gridx = 0; GBC_0.gridy = 5; GBC_0.gridwidth = 2; GBC_0.gridheight = 1; GBC_0.fill = GridBagConstraints .BOTH; GBC_0.insets = new Insets(3, 3, 3, 3); // add the button Button b0 = new Button("0"); gbl.setConstraints (b0, GBC_0); add(b0); // Add the . key GridBagConstraints GBC_decimal = new GridBagConstraints (); GBC_decimal.gridx = 2; GBC_decimal.gridy = 5; GBC_decimal.gridwidth = 1; GBC_decimal.gridheight = 1; GBC_decimal.fill = GridBagConstraints .BOTH; GBC_decimal.insets = new Insets(3, 3, 3, 3); // add the button Button bdecimal = new Button("."); gbl.setConstraints (bdecimal, GBC_decimal); add(bdecimal); }

Rucno pozicioniranje komponenti

Page 173: Java Predavanje I

Komponenteje mogucepostavitina tocno odredenupozicijuna ekranu, koristecikoordinateu pikselima, u odnosuna appletovpanel. To, medutim, imavišenedostataka.

Sve instancevašegappletanece imatipaneljednake velicine. Velicinumožetekontroliratisamo ako ce se appletpojavljivatijedinona vašimweb stranicama.Slobodnimprozorimakorisnicimogumijenjativelicinuu hodu. Ako koristitelayoutmanager, sve ce komponentebitiautomatskiprilagodenenovojveliciniprozora.Bez toga vrloje teško posticitakvo ponašanje.Komponentece na razlicitimplatformamazauzimatirazlicitekolicineprostora.Rucnopozicioniranjece imatismislau aplikacijamakoje su namijenjeneizvršavanjuna jednojodredenoj platformi. Appletinisupogodniza to.Rucnopozicioniranjekomponentitražimnogoposla, pogotovoako nematenaraspolaganjunekialatkoji ce automatiziratitaj proces.RazmještajGridBagLayout u kombinacijisa ugniježdenimpanelimadovoljanjeza sve efektekoje biste inacemogliposticirucnimpozicioniranjem.

Ako ipak želiterucnopozicioniratikomponente, onda prvo opozovitelayout managernaredbom: setLayout(null);

Nakon toga zadajtepozicijui velicinuza svakukomponentuunutarpaint() metode(reklismo da se to inacene radi!), tako da pozovetemetodesetLocation() andsetSize(): public void setLocation(int x, int y)public void setSize(int width, int height)

Ovdje su x i y koordinatelijevoggornjeguglakutijekoja omedujevašukomponentu, awidth i height su njenaširinai visinau pikselima.

Sljedeciapplet stavitce buttonvelicine30 x 40 piksela(tj. njegovlijevigornjiugao) utocku (25, 50):

import java.applet.*;import java.awt.*; public class ManualLayout extends Applet { private boolean laidOut = false; private Button myButton; public void init() { this.setLayout(null); this.myButton = new Button("OK"); this.add(this.myButton); } public void paint(Graphics g) { if (!this.laidOut) { this.myButton.setLocation(25, 50); this.myButton.setSize(30, 40); this.laidOut = true;

Page 174: Java Predavanje I

} } } <APPLET CODE="ManualLayout .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=100 HEIGHT=100></APPLET>

Što je Container?

Kontejnerje komponentakoja možesadržatidrugekomponente. On je uvijekinstancaklasejava.awt.Container koja je podklasa od java.awt.Component pa su daklekontejnerii samitakoder komponente.

Opcenito, komponentese nalazeu nekomkontejneru. Appletje primjerkontejnera, noto mogubitii prozori(windows), okviri(frames), dijalozi(dialogs) i paneli(panels).Kontejnerimogusadržavatidrugekontejnere.

Svakikontejnerimasvoj Layout manager koji odreduje nacinpozicioniranjakomponenataunutarkontejnera.

Ukratko, kontejnerisadrže komponente. Komponentesu pozicioniraneunutarkontejnerau skladusa pridruženimLayout managerom. Buducida su kontejneritakoderkomponente, onise mogunaciunutardrugihkontejnera. Primijetimoda appletiosiguravajuvec gotovkontejneri pretpostavljeniLayout manager. To je FlowLayout .

Dvije vrste Containera

Paket AWT definiraviševrstakontejneramedukojimecemo promotritipanelei prozore.

Paneli su podklase od java.awt.Panel. Panelse nalaziunutardrugogkontejnerailimoždaunutarbrowserovogprozora. Panelinisusamostalni. Appletisu primjerpanela.

Prozorisu podklase od java.awt.Window . Prozor je samostalan. Ima ihviševrsta,medunjimapromatratcemo okvire(frames) i dijaloge(dialogs). Okvirisu podklase odjava.awt.Frame. Predstavljajuobicne, prirodneprozore. Dialozisu podklase odjava.awt.Dialog. Dialogje privremeni, nestalniprozor koji postojisamo da preneseneke informacijeilipriminekiinputod korisnika.

Paneli

SvakiPanel je zapravogenerickiContainer cija je glavnaulogapodijelitiprikaznupovršinuu odvojenepravokutnedijelove. Buducida svakiPanel možeimatisvoj vlastiti

Page 175: Java Predavanje I

LayoutManager , s panelimamožeteucinitimnogotoga što inacene bistemoglisa samojednimLayout managerom.

Na primjer, pretpostavimoda želiteda se TextArea nalaziu centruappleta, a buttonispod nje, na "jugu":

To ne možeteposticis jednimjedinimLayout managerom. Na primjer, BorderLayoutbi proširioButton preko cijeleširinaappleta. S drugestraneFlowLayout ne bi ucinioda TextArea bude dovoljnovelika.

Umjestotoga, možetekreiratiappletkoji imaBorderLayout , a TextArea muse nalaziu centru. ZatimkreiratePanel, postavitenjegovLayoutManager na FlowLayout ,dodate buttontom panelui onda dodate paneljužnomdijeluappleta. Pogledajteprogram: import java.applet.*;import java.awt.*; public class PanelExample extends Applet { public void init() { this.setLayout(new BorderLayout ()); this.add("Center", new TextArea()); Panel p = new Panel(); p.setLayout(new FlowLayout(FlowLayout.CENTER)); p.add(new Button("OK")); this.add("South", p); } } <APPLET CODE="PanelExample .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=300 HEIGHT=200></APPLET>

U ovomje primjeruvažnorazlikovatidodavanjekomponenteappletu(add(...) ilithis.add(...)) od dodavanjakomponentepanelu(p.add(...)).

S drugestrane, nijevažnojeste liprvo dodalipanelappletupa onda buttonpaneluiliobrnuto.

Drugacesta uporaba panelaje za postavljanjenizacheckboxovakoji imajuGridLayouts jednimstupcem.

Ugniježdeni paneli

Page 176: Java Predavanje I

Ponekad je potrebno nekolikoinstanciistogLayoutManager a. Pogledajmoopet primjerkalkulatora.

S jedne strane izgledakao da ga je jednostavnoimplementirati. Tu su naprosto18buttonai TextField . S drugestrane, gotovosve tipke su jednake velicine, samo su dvijetipke i display nešto veci. Gotovobi se mogaokoristitiGridLayout , aliipak ne sasvim.Panelisu jedan od nacinarješavanjaovogproblema.

Evo sada ponovnokalkulatora, aliovogputa smo koristilisamoGridLayout iugniježdenepanele. Da lije to jednostavnijenegoGridBagLayout ilinije, stvar je ukusa. import java.applet.*;import java.awt.*; public class Calculator extends Applet { TextField screen; public void init () { this.setLayout(new GridLayout(3, 1, 3, 3)); Panel A1 = new Panel(); this.add(A1); Panel A2 = new Panel(); this.add(A2); Panel A3 = new Panel(); this.add(A3); A1.setLayout(new GridLayout(2, 1)); screen = new TextField(12); A1.add(screen); Panel B1 = new Panel(); B1.setLayout(new GridLayout(1, 4, 3, 3)); B1.add(new Button("C")); B1.add(new Button("=")); B1.add(new Button("/")); B1.add(new Button("*")); A1.add(B1); A2.setLayout(new GridLayout(2, 4, 3, 3)); A2.add(new Button("7")); A2.add(new Button("8")); A2.add(new Button("9")); A2.add(new Button("-")); A2.add(new Button("4")); A2.add(new Button("5")); A2.add(new Button("6")); A2.add(new Button("+")); A3.setLayout(new GridLayout(1, 2, 3, 3)); // 1, 2 and 0 Panel B2 = new Panel(); B2.setLayout(new GridLayout(2, 1, 3, 3)); // 1 and 2 Panel C1 = new Panel(); C1.setLayout(new GridLayout(1, 2, 3, 3));

Page 177: Java Predavanje I

C1.add(new Button("1")); C1.add(new Button("2")); B2.add(C1); B2.add(new Button("0")); // 3, . and = Panel B3 = new Panel(); B3.setLayout(new GridLayout(1, 2, 3, 3)); // 3 and . Panel C2 = new Panel(); C2.setLayout(new GridLayout(2, 1, 3, 3)); C2.add(new Button("3")); C2.add(new Button(".")); B3.add(C2); B3.add(new Button("=")); A3.add(B2); A3.add(B3); } public Insets insets() { return new Insets(5, 5, 5, 5); } /* Use 1.0 event handling since I need to run this inside today's web browsers. */ public boolean action(Event e, Object arg) { if (e.target instanceof Button) { screen.setText((String) arg); return true; } return false; } } <APPLET CODE="Calculator.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=150 HEIGHT=150></APPLET>

Prozori (windows)

Klasa java.awt.Window i njenepodklase omogucujuvamkreiranjesamostalnihprozora. Samostalniprozorisu cestiu aplikacijamakoje koje za komunikacijuskorisnikomkoristeAWT umjestokomandnelinije. Takoder osiguravajudodatniprostorza applete.

Klasa java.awt.Window je podklasa od java.awt.Container , alije nezavisnaodostalihkontejnera, tj. sam nijesadržanu drugimkontejnerima. Možete mudodavatikomponentekao što je Button iliTextField . Može imatisvoj vlastitiLayoutManager .

Page 178: Java Predavanje I

Možete crtatidirektnopomocunjegovepaint() metode. Sve što možeteraditiuappletovompanelu, možeteraditii u prozoru.

Uobicajenoje da se klasajava.awt.Window ne koristidirektno. Umjestotoga raditesnjenimpodklasama, npr. java.awt.Frame ilijava.awt.Dialog , ovisnoo tomeštotrebate. Frame je okvirkoji možeimatisvoj scrollbar, korisnikmumožemijenjativelicinuilipoložaji bit ce na ekranudok god korisnikazanimanjegovsadržaj.

Nasuprot tome, dijalognece imatiizbornike, obicnomuse ne možemijenjativelicinaiakose možepomicati. Njegova je ulogaprenošenjeodredene informacije(unosa) odkorisnikailipak upozoravanjena nešto. Vidljivje samo dok ne dobije odgovarajuciinputilidok korisnikne potvrdida je procitaoinformacijus njega.

Okviri (frames)

Okvirisu korisniza kompleksnijeaplikacije. Omogucujuvamodvajanjerazlicitihfunkcijailipodataka u razliciteprozore. Na primjer, aplikacijaza crtanjemožeimatinekolikorazlicitihslikas raznimstatusimazavršenostiu razlicitimprozorima. Ilimoždamožeimatijednusliku, aliu drugomprozorupaletus raznimcetkamai bojama. Svakiod tihprozorabio bi Frame.

Sve što vamtreba za kreiranjeokvirai rad s njimanalazise u klasijava.awt.Frame. Zakreiranjenovogokvirabez naslovneletvicekoristitcete konstruktorFrame() bezargumenata.

Frame f = new Frame();

Cešce ce ipak bitipotrebno dati okvirunaslov: Frame f = new Frame("My Window");

Okvirinasljedujuklasujava.awt.Container pa imdakle možetedodavatikomponente. Za razlikuod panelai appleta, pretpostavljeniLayoutManager za okvirejeBorderLayout , a ne FlowLayout . To, naravno, možetepromijenitipomocumetodesetLayout() na primjerovako: f.setLayout(new FlowLayout());

Okvirinasljedujui klasujava.awt.Component pa dakle imajumetodepaint() iupdate(). Ako želitecrtatiunutarokvirai procesiratidogadaje rucnokao u appletima,jednostavnokreirajtepodklasuod Frame i dodajte joj odgovarajucilistener. Gotovosvešto ste radilisa vlastitimpodklasamaod java.awt.Applet možetetakoder raditii sasvojimpodklasamaod java.awt.Frame.

Ipak, najcešcecete htjetikoristitikomponente. Da bistkomponentudodaliokviru, pozvatcete njegovumetodu add() istokao što st pozivaliappletovumetodu add(). Jedinarazlikaje što cete cesto trebatipozivatitu metoduizvanklaseFrame, tako da ce biti

Page 179: Java Predavanje I

potrebno dodati odgovarajuciprefikskoji pokazujena okvir. Drugimrijecima, ako imateokvirFrame f, trebat cete pozvati

f.add(new Button("OK");

umjestosamo this.add(new Button("OK"));

Naravno, to ovisiu kojoj ste klasikad pozivateadd(). Ako je pozivateizneke odpodklasa klaseFrame, onda to nece bitipotrebno.

Kako je pretpostavljenilayoutza frameBorderLayout , trebat ce specificiratida likomponentudodajete na North, South, East, West iliCenter. Evo primjerakoji pokazujekako se dodaje centriranalabelau centarokviraFrame f:

f.add("Center", new Label("This is a frame", Label.CENTER));

Ilif.add(new Label("This is a frame", Label.CENTER), BorderLayout .CENTER);

Velicinai pozicijabilokojeg danogokviraje nepredvidljivaako je ne specificirate.Velicinase zadaje pomocumetodesetSize() ovako: f.setSize(150,150);

Ta velicinane ukljucujenaslovnuletvicu, pa to treba zasebnouzetiu obzir. Da bistedoznalivisinunaslovneletviceza okvir, pozvatcete njegovumetoduinsets() ipogledatiatributtop rezultirajucegobjekta izjava.awt.Insets . To ce bitivisinanaslovneletvice. Imatcemo, dakle int TitleBarHeight = f.insets().top;

Postavljanjeokvirana željenupozicijuna ekranuobavljase pomocumetodesetLocation(int x, int y). Ovdje se x i y racunajuprema ekranu, ne premaappletu.

Kad se prozor kreira, on je u pocetku nevidljiv. Dodavanjekomponentidobro je obavitidok je prozor još nevidljiv, inacece korisnikmoratigledatiskakanje komponentiinepredvidljivopomicanjeprozora dok se slikane ustabili. Kad ste završilis dodavanjemkomponenti, uciniteokvirvidljivimtako da pozovetenjegovumetodushow():

f.show();

Dogadaji vezani uz prozore

Page 180: Java Predavanje I

Buducida je java.awt.Window podklasa od java.awt.Component , znacida objektitipaWindow mogulansiratidogadaje. Tidogadajisu objekti tipajava.awt.event.WindowEvent . To su:

WindowEvent.WINDOW_ACTIVATED

WindowEvent.WINDOW_CLOSED

WindowEvent.WINDOW_CLOSING

WindowEvent.WINDOW_DEACTIVATED

WindowEvent.WINDOW_DEICONIFIED

WindowEvent.WINDOW_ICONIFIED

WindowEvent.WINDOW_OPENED

Da bistemogliodgovaratina te dogadaje, morateuzobjekt tipajava.awt.Windowregistriratiodgovarajucilistener, dakle objekt neke klase koja implementirasuceljejava.awt.event.WindowListener . Ovo suceljepropisujesljedecemetode: public abstract void windowOpened (WindowEvent e) public abstract void windowClosing (WindowEvent e) public abstract void windowClosed (WindowEvent e) public abstract void windowIconified (WindowEvent e) public abstract void windowDeiconified (WindowEvent e) public abstract void windowActivated (WindowEvent e) public abstract void windowDeactivated (WindowEvent e)

Možete, naravno, koristitii odgovarajucijava.awt.event.WindowAdapter .

Primjer dogadaja na prozorima

Na primjer, prozorise ne zatvarajusamiod sebe nego ihmorateeksplicitnozatvoriti.Sljedecapodklasa od Frame koja odgovarana pokušaj zatvaranjatako da pozovemetodesetVisible(false) i dispose(). import java.awt.*;import java.awt.event.*; public class ClosableFrame extends Frame implements WindowListener { public ClosableFrame () { this.addWindowListener (this); } public ClosableFrame (String s) { super(s); this.addWindowListener (this); } public void windowClosing (WindowEvent e) { this.setVisible(false); this.dispose(); } public void windowOpened (WindowEvent e) {}

Page 181: Java Predavanje I

public void windowClosed (WindowEvent e) {} public void windowIconified (WindowEvent e) {} public void windowDeiconified (WindowEvent e) {} public void windowActivated (WindowEvent e) {} public void windowDeactivated (WindowEvent e) {} }

Možete je aktiviratina primjerpomocusljedecegappleta: import java.applet.Applet;import java.awt.*; public class ClosableFrameApplet extends Applet { public void init() { ClosableFrame cf = new ClosableFrame (); cf.setSize(150,150); cf.setLocation(100,100); cf.show(); } } <APPLET CODE="ClosableFrameApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="ClosableFrame .jar"WIDTH=200 HEIGHT=100></APPLET>

Kombiniranje appleta i aplikacija

Appletuje potreban okvirda bi se izvršavao. U praviluweb browser osiguravatakavokvir. No možetekreiratiinstancesvogappletaunutarnekogokviravaše vlastiteaplikacije. Na taj nacinmožetepisatikod koji je istovremenoi applet i aplikacija.

Da bi appletpretvoriliu aplikaciju, dodajte musljedecumain() metodu(ovdje jemyApplet imevašegappleta):

public static void main(String args[]) { myApplet a = new myApplet(); a.init(); a.start(); Frame appletFrame = new Frame("Applet Window"); appletFrame.add("Center", a); appletFrame.setSize(150,150); appletFrame.setLocation(100,100); appletFrame.show();

Page 182: Java Predavanje I

}

Redak 1 je deklaracijastandardnemain() metodakoju koristiteza aplikacijeskomandnelinije. Ako se applet izvršavaunutarweb browsera iliappletviewera, ta cemetodabitiignorirana. Izvršitce se samo ako appletpokrenetekao samostalniprogram.

Redak 3 kreira instancuvašegappleta. Tu trebate umjestomyApplet upisatipravo imesvogappleta.

Nakon toga, retci4 i 5 pozivajuappletovuinit() i start() metodu. To inaceradiweb browser za vas, aliako se programizvršavasamostalno, morateto samiuciniti.

Nakon što ste kreiraliaplet, treba vamFrame u koji cete ga smjestiti. Redak 7 to cinipomocuuobicajenogkonstruktoraFrame(). Ovdje možetepromijenitinaslovokviradaodgovaravašoj aplikaciji.

Redak 8 dodaje appletu taj Frame. Buducida je LayoutManager za Frame popretpostavciBorderLayout , applet ce bitidodan u centar. Sjetitese da jejava.applet.Applet podklasa od java.awt.Component pa je u redu dodati ga nanekiFrame.

Redak 9 zadaje velicinuza Frame. Ovdje smo stavili150 x 150 pixela. Ako se programizvršavakao applet, možetedobitite vrijednostiizparametarawidthi height, aliako seizvršavasamostalno, morateizmislitineke velicine. Možete iheventualnoucitatikaoargumentes komandnelinije.

Redak 10 postavljaFrame na poziciju(100, 100). Ako pozicijusamine zadate, ona cebitinepredvidljiva,

Redak 11 cinivaš Frame vidljivimi applet je sad spremanza izvršavanje, unutarbrowsera iliizvannjega.

Napomena: Cak i ako imajuFrame , appletiipak nisuistošto i aplikacije. Kadkonvertirateappletu aplikacijuna opisaninacin, morateosiguratida se programneoslanjana metodekoje imajusmislajedinou appletima. Na primjer, metodagetParameter () nemasmislaizvanappleta. Isto tako, argumentes komandnelinijemožeteucitavatisamo u aplikacijama. Nadalje, aplikacijeimajumanjesigurnosnihrestrikcijanegoappletipa programkoji dobro radi kao aplikacijamožeproizvestimnoštvosigurnosnihiznimaka(java.lang.SecurityException ).

Pogledajtekako to funkcionirana primjeruappletaDots izsedmogpredavanjakoji smoza ovusvrhumodificiraliu applet/aplikacijuDotsTest .

Dijalozi

Okvirisu korisnikao prozorikoji ce se neko vrijemezadržatina ekranu, na primjerusvrhueditiranjanekog teksta i slicno. Za razlikuod njih, dijalozikoje implementiraklasa

Page 183: Java Predavanje I

java.awt.Dialog, po prirodisu kratkotrajnii služesamo kao sredstvoza kratki inputiliupozorenjekorisniku.

Slicnokao java.awt.Frame, java.awt.Dialog je podklasa od java.awt.Window

pa dakle i od java.awt.Container i java.awt.Component . Prema tome, mnogotoga što znateo okvirimaprimjenjujese i na dijaloge. Možete ihpomicati, mijenjatiimvelicinui dodavatiimkomponenteskoro istokao i u slucajuokvira. Postoje, medutim,dvijebitnerazlike:

1. Okvir (frame) možeimatiletvicuizbornika(menu bar) dok dijalogto ne može2. Dijalogmožebitimodalan, dok okvirne može

O izbornicimacete naucitiu sljedecempredavanju. Za sada se zadržimona razliciizmedumodalnihi ne-modalnihdijaloga. Modalnidijalogblokirakomunikacijusa svimdrugimaplikacijamasve dok ne dobijeodgovarajuciinputod korisnika. Ne možese pomicatiine dozvoljavakorisnikuprijelazu drugiprozor istogprograma. Na nekimplatformamanedozvoljavacak i odlazaku prozore drugihprograma.

Sedamdesetihgodinaproširiose viruskoji bi periodickiprekidao korisnikovradpodizanjemprozorcicana kojemje pisalo"I WANT A COOKIE." Rad se mogaonastavititek kad bi korisnikupisaorijec"COOKIE" na što bi programrekao nešto kao"MMM, MMM, THATWAS GOOD." i tek tada vratiokontrolukorisniku.

Modalnidijalozise ponašajuprilicnoslicnotom virusu. Oni traže inputod korisnikai nedozvoljavajuda se ištadogodidok ga ne dobiju. Ne-modalnidijalozise podižu, alinesprecavajukorisnikada radi drugestvaridok su onividljivi. Buducida modalnidijalozidjelujuponešto iritirajuce, treba ihu praviluizbjegavati.

Metode za dijaloge

Buducida su dijalozikomponente, onimogu, kao i okviri, koristitimetodekao što susetLocation() ilisetSize(). Za dijalogeimamokonstruktorekoji imdaju iline dajunaslov, pa možemo, na primjer, staviti: Dialog d = new Dialog(new Frame(), false);

Prviargumentje parent frame za taj dijalog, dok je drugi tipaboolean i odreduje hocelidijalogbitimodalan(true) iline (false). Modalnidijalozisu modalniu odnosuna svojparent frame, dakle privremenosprecavajuunosu taj okvir, aline i u drugeokvire.

Ako za prviargumentstavitenull dijalogce izbacitiiznimku,java.lang.IllegalArgumentException .

Ako kreirateparent framedirektnounutarpozivakonstruktorakao u prethodnomprimjeru, dijalogne možebitiuistinumodalan.

Ima još i nekihmanjihrazlikaizmeduokvirai dijaloga, npr.:

Page 184: Java Predavanje I

1. Korisnikmožemijenjatipoložaji velicinuveciniokvira, dok dijalozimau pravilunemože.

2. Okviriobicnoimajunaslovneletvice, dok okvirinemaju.DijalogumožeteomogucitipromjenjivostvelicinepomocumetodesetResizable (): d.setResizable (true);

Možete mudati naslovnuletvicutako da ga kreiratepomocusljedecegkonstruktora:: Dialog d = new Dialog(new Frame(), "My Dialog Window", false);

Sve ostalemetode i postupciza dijalogeistesu kao i za okvire.

Primjeri dijaloga

Sljedeciprogramprikazujejednostavnine-modalnidijalogsa OK buttonomi beznaslovneletvice. import java.applet.*;import java.awt.*; public class DialogTester extends Applet { public void init() { Dialog myDialog = new Dialog(new Frame(), false); myDialog.setLocation(320,240); myDialog.add("North", new Label("Hello!")); myDialog.add("South", new Button("OK")); myDialog.pack(); myDialog.show(); } } <APPLET CODE="DialogTester .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=150 HEIGHT=150></APPLET>

Pisanje podklasa klase Dialog

Prethodniprimjerje bio maloumjetan. U pravilu, kreiratcete svoje vlastitepodklase odjava.awt.Dialog i i instanciratiihizglavnogprograma. Na primjer, jedan odjednostavnijihuobicajenihdijalogaje ispisporuke koju korisniktreba procitatii potvrditito pritiskomna OK button. Evo primjera: import java.awt.*;import java.awt.event.*;

Page 185: Java Predavanje I

public class YesNoDialog extends Dialog implements ActionListener { public YesNoDialog(Frame parent, String message) { super(parent, true); this.add("Center", new Label(message)); Panel p = new Panel(); p.setLayout(new FlowLayout()); Button yes = new Button("Yes"); yes.addActionListener (this); p.add(yes); Button no = new Button("No"); no.addActionListener (this); p.add(no); this.add("South", p); this.setSize(350,100); this.setLocation(100, 200); } public void actionPerformed (ActionEvent e) { this.setVisible(false); this.dispose(); } } import java.applet.Applet;import java.awt.*; public class AlertExample extends Applet { public void init () { Dialog d = new YesNoDialog(new Frame(), "Are you sure you want to start global thermonuclear war?"); d.show(); } } <APPLET CODE="AlertExample .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="AlertExample .jar"WIDTH=300 HEIGHT=200></APPLET>

Page 186: Java Predavanje I

Deveto predavanje izbornici,slike i zvukoviŠto je izbornik ? klase izbornika kreiranje izbornika primjer izbornikadogadaji vezani uz izbornike izbornicke kratice padajuci izbornici (popupmenus) slike kamo staviti slike? ucitavnje slika crtanje slika uporabapovratne vrijednosti metoda drawImage() primjer crtanja slika promjena velicineslike ustanovljavanje velicine slike paket java .awt.image SuceljaImageProducer , ImageObserver , ImageConsumer sucelje ImageConsumercekanje na ucitavanje slike prekrivanje metode imageUpdate () što je zapravoslika? operator << - kreiranje slika primjer kreiranja slika metoda getRGB()pretapanje boja filtriranje slika klasa RGBImageFilter primjer plavog filtraprimjer filtra sivih tonova filtri koji ovise o položaju filtri koji ovise oadjungiranim pixelima audio kontinuirana izvedba

Što je izbornik?

Java omogucujepostavljanjeizbornikana frameove(dijalozimase izbornicine mogudodavati). Za applete to i nijetako bitno, aliu aplikacijamaje najcešcenužno.

Izbornicisu sastavljeniod trihijerarhijskaelementaPrvielementje izbornickaletvica(menu bar) i sastojise od razlicitihizbornika. Nalazise na gornjemrubuekrana kodMacintoshailina gornjemrubuprozora kod WindowsailiMotifa.

Слика

Svaka izbornickaletvicasadržibar jedan izbornik(menu). Izbornicisu organiziranipoitemama. Cesto susrecemoFile, Edit i tako dalje.

Svakiizborniksadržibar jednuopciju(menu item). Opcije su obicnopojedinacneakcijekao Open, Print, Cut iliCopy. Opcije nisuprikazanedok izborniknijeaktivan. Dva ilivišeizbornikane mogubitiistodobnoaktivni.

Слика

Page 187: Java Predavanje I

Na primjerovaj Edit izbornikimaonemogucenuUndo opcijunakonkoje dolaziseparator, a iznjegaomoguceneopcijeCut, Copy, paste i Clear, zatimjoš jedanseparator pa omogucenaopcijaSelect All.

Klase izbornika

Paket AWT sadržinekolikoglavnihklasa za upravljanjeizbornicima:

java.awt.Menu

java.awt.MenuBar

java.awt.MenuItem

java.awt.PopupMenu

Da biste izbornikekoristiliu svojimaplikacijama, bit ce vampotreban bar jedanprimjerakizklaseMenuBar sa jednimilivišeprimjerakaklaseMenu, a za svakognekolikoprimjerakaMenuItem . IzborniciizklasePopupMenu se pojavljujukaosamostalnielement. Klasa java.awt.MenuComponent je zadnjanadklasasvihovihklasa, a ona je opetpodklasa od java.lang.Object . Prema tome, izbornickeletvice, izbornicii opcijenisukomponentei ne moguse dodavatikontejnerimana uobicajeninacin. java.lang.Object | +--java.awt.MenuComponent | +--java.awt.MenuBar | +--java.awt.MenuItem | +--java.awt.Menu | +--java.awt.PopupMenu

Primijetiteda su MenuBar i MenuItem podklase od MenuComponent . Menu je podklasaod MenuItem (ovo zvucimaloneobicno, aliizbornikeje zaistaopcija, samo se dodajeizbornickojletvici). Nadalje, MenuBar implementirasuceljejava.awt.MenuContainer .

Kreiranje izbornika

Izbornikeje poželjnopotpunoizgraditiprijenego ihprikažete. Tipicniredosljedjeovakav:

1. kreirajtenoviobjekt tipaMenuBar .2. kreirajtenoviobjekt tipaMenu.3. dodajte opcijeobjektu tipaMenu.4. ako je potrebno, ponovitekorake 2 i 3.

Page 188: Java Predavanje I

5. dodajte objekt tipaMenuBar objektu tipaFrame.Konstruktorikoji su vampotrebnisu jednostavni. Novi objekt tipaMenuBar kreiratceteovako: MenuBar myMenubar = new MenuBar();

Za kreiranjenovogobjekta tipaMenu koristitekonstruktorMenu(String title).Dodajte munaslovkoji želitedati izborniku. Na primjer, za kreiranjeizbornikaFile iEdit, napravite: Menu fileMenu = new Menu("File"); Menu editMenu = new Menu("Edit");

Opcije, MenuItemare kreirajuse slicno, pomocukonstruktoraMenuItem(Stringmenutext). Dajte mupotreban naslov, na primjer: MenuItem Cut = new MenuItem("Cut");

Objekte tipaMenuItem kreirateunutarodgovarajucihobjekata tipaMenu kojimapripadaju, istokao što ste komponentekreiraliunutarodgovarajucihrazmještaja.Izborniciimajuadd() metodekoje kao argumentuzimajuobjekte tipaMenuItem . Evokako bistenapraviliEdit izborniki dodalimuoipcijeUndo, Cut, Copy, Paste, Clear iSelect All: Menu editMenu = new Menu("Edit"); editMenu.add(new MenuItem("Undo")); editMenu.addSeparator (); editMenu.add(new MenuItem("Cut")); editMenu.add(new MenuItem("Copy")); editMenu.add(new MenuItem("Paste")); editMenu.add(new MenuItem("Clear")); editMenu.addSeparator (); editMenu.add(new MenuItem("Select All"));

Metoda addSeparator () dodaje horizontalnucrtu preko izbornika. Koristise zalogickorazdvajanjefunkcijana izborniku.

Kad kreirateizbornike, dakle objekte tipaMenu, dodat cete ihletvici, objektu tipaMenuBar koristeciMenuBarovumetoduadd(Menu m) ovako:

myMenubar.add(fileMenu); myMenubar.add(editMenu);

Konacno, kad je MenuBar gotov, dodat cete ga okviru, dakle objektu tipaFramekoristecise frameovommetodomsetMenuBar(MenuBar mb). Ako imateFrame f

onda bi to izgledaloovako: f.setMenuBar(myMenuBar);

Page 189: Java Predavanje I

Primjer izbornika

Aplikacijamožeimatimnogoopcija, cak i po višestotina. Sve njihstavitiu init()

metodubilobi neprakticno. Uobicajenoje kreiratiodvojenemetodekoje grade svakipojediniizborniki dodaju ihizbornickojletvici. Sljedeciprogramkreiradva standardnaizbornika, File i Edit. import java.applet.*;import java.awt.*; public class MenuTester extends Applet { public void init () { Frame f = new Frame("Prozor s izbornicima"); f.add("Center", new Label("Pogledajte izbornike", Label.CENTER)); f.setSize(this.getSize().width, this.getSize().height); f.setLocation(320,240); MenuBar myMenuBar = new MenuBar(); this.makeFileMenu (myMenuBar); this.makeEditMenu (myMenuBar); f.setMenuBar(myMenuBar); f.show(); } void makeEditMenu (MenuBar mb) { Menu editMenu = new Menu("Edit"); editMenu.add("Undo"); editMenu.addSeparator (); editMenu.add("Cut"); editMenu.add("Copy"); editMenu.add("Paste"); editMenu.add("Clear"); mb.add(editMenu); } void makeFileMenu (MenuBar mb) { Menu fileMenu = new Menu("File"); fileMenu.add("New"); fileMenu.add("Open..."); fileMenu.addSeparator (); fileMenu.add("Close"); fileMenu.add("Save"); fileMenu.add("Save As..."); fileMenu.addSeparator (); fileMenu.add("Page Setup..."); fileMenu.add("Print"); fileMenu.addSeparator (); fileMenu.add("Quit");

Page 190: Java Predavanje I

mb.add(fileMenu); } } <APPLET CODE="MenuTester.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Dogadaji vezani uz izbornike

Kad korisnikodabere opciju, izborniklansiraobjekt tipajava.awt.event.ActionEvent . Njega možepokupitibilokoji actionListener, dakleobjekt izklase koja implementirasuceljejava.awt.event.ActionListener koji smoregistriraliuzopciju, dakle objekt tipaMenuItem . Actionkomandakoju možemoprocitatimetodomgetActionCommand () sadržatce tekst opcije.

Na primjer, sljedeciapplet stavljatekst odabrane opcijeu tekstualnopoljetheChoice .

import java.applet.*;import java.awt.*;import java.awt.event.*; public class ActiveMenuTester extends Applet implements ActionListener { TextField theChoice = new TextField(20); public void init () { Frame f = new Frame("Prozor s izbornicima "); f.add("North", new Label("Pogledajte izbornike ", Label.CENTER)); f.add("South", theChoice); f.setSize(300, 200); f.setLocation(220,240); MenuBar myMenuBar = new MenuBar(); this.makeFileMenu (myMenuBar); this.makeEditMenu (myMenuBar); f.setMenuBar(myMenuBar); f.addWindowListener (new WindowCloser ()); f.show(); } protected void addItem(Menu m, String s) { MenuItem mi = new MenuItem(s); mi.addActionListener (this); m.add(mi);

Page 191: Java Predavanje I

} protected void makeEditMenu (MenuBar mb) { Menu editMenu = new Menu("Edit"); this.addItem(editMenu, "Undo"); editMenu.addSeparator (); this.addItem(editMenu, "Cut"); this.addItem(editMenu, "Copy"); this.addItem(editMenu, "Paste"); this.addItem(editMenu, "Clear"); mb.add(editMenu); } protected void makeFileMenu (MenuBar mb) { Menu fileMenu = new Menu("File"); this.addItem(fileMenu, "New"); this.addItem(fileMenu, "Open..."); fileMenu.addSeparator (); this.addItem(fileMenu, "Close"); this.addItem(fileMenu, "Save"); this.addItem(fileMenu, "Save As..."); fileMenu.addSeparator (); this.addItem(fileMenu, "Page Setup..."); this.addItem(fileMenu, "Print"); fileMenu.addSeparator (); this.addItem(fileMenu, "Quit"); mb.add(fileMenu); } public void actionPerformed (ActionEvent e) { theChoice.setText(e.getActionCommand ()); } class WindowCloser extends WindowAdapter { public void windowClosing (WindowEvent e) { Window w = (Window) e.getSource(); w.setVisible(false); w.dispose(); } } } <APPLET CODE="ActiveMenuTester .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="ActiveMenuTester .jar"WIDTH=200 HEIGHT=100></APPLET>

Page 192: Java Predavanje I

Izbornicke kratice

Izbornickekratice, poznatei pod nazivomakceleratoriilitipovniekvivalentinaredbe,obicnone ubrzavajuništa, alibuducida ihkorisnicivole, komercijalneaplikacijeihtrebajusadržavati.

Klasa java.awt.MenuShortcut predstavljatakve kraticeu Javi. Ima sljedecekonstruktore:

public MenuShortcut (int key) public MenuShortcut (int key, boolean useShiftModifier )

U oba slucajaargumentkey je zapravokeycode tipkekoja ce aktiviratitu opciju.

Ako je useShiftModifier postavljenna true, onda tipkashiftmora bitipritisnutadabi kraticaaktiviralaopciju. Po pretpostavci, useShiftModifier je false.

Da bisteopcijiizbornikapridružilikraticu, pozovitemetodusetShortcut() izklasejava.awt.MenuItem . Na primjer,

MenuShortcut pShortcut = new MenuShortcut (KeyEvent.VK_P); MenuItem mi = new MenuItem("Print..."); mi.setShortcut(pShortcut);

Kraticumožetedefiniratii pomocuodgovarajucegkonstruktoraMenuItem()ovako: MenuShortcut pShortcut = new MenuShortcut (KeyEvent.VK_P); MenuItem mi = new MenuItem("Print...", pShortcut);

KraticumožeteuklonitipomocumetodedeleteShortcut () izklasejava.awt.MenuItem , na primjer: mi.deleteShortcut ();

Padajuci izbornici (Popup Menus)

Vec smo se susrelis klaslomalreadyencounteredthe java.awt.Choice cijise objektiponašajukao padajuciizbornici, no imajufiksnulokaciju.

Klasa java.awt.PopupMenu class, on the other hand, is activatedwhenthe user holdsthe rightmousebuttonor otherwiseindicatesthat theywant to pop up a menu. Typicallythisis used for contextsensitivemenus.

Klasa java.awt.PopupMenu je podklasa od java.awt.Menu. Uglavnomje koristitekao i obicneizbornike. Stavke se dodaju metodomadd(), a na korisnikoveizboreodgovarase pomocuActionListener a instaliranogna MenuItem . Na primjer, da bistenapravilipadajuciizborniksa raznimURL-ovima, možetepostupitiovako:

Page 193: Java Predavanje I

PopupMenu pm = new PopupMenu(); MenuItem mi = new MenuItem("http://www.javasoft.com/"); mi.addActionListener (URLActionListener ); pm.add(mi); mi = new MenuItem("http://home.netscape.com/"); mi.addActionListener (URLActionListener ); pm.add(mi); mi = new MenuItem("http://metalab.unc.edu/javafaq"); mi.addActionListener (URLActionListener ); pm.add(mi); mi = new MenuItem("http://www.roaster.com/news/"); mi.addActionListener (URLActionListener ); pm.add(mi);

Medutim, padajuciizbornicine pripadajunekomodredenomMenuBaru. Umjestotoga,onise dodaju komponenti. Na primjer, za daniokvir, Frame f, instaliralibistePopupMenu pm u taj okvirtako da ga proslijeditemetodiadd() izklasejava.awt.Component , ovako: f.add(pm);

Primijetiteda to nijeona istaadd() metodakoju koristiteza dodavanjekomponenteokviru.

Tocan nacinpokretanjapadajucihizbornikaovisio platformi. Na primjer, naWindowsimase PopupMenu pokrece podizanjemdesne tipke miša. Na Motifusepokrece pritiskanjemdesne tipkemiša. Neovisnoo egzaktnojsekvencidogadaja kojapokrece padajuciizbornik, kad korisnikodabere nekuopciju, odnosnokad odabere nekiMenuItem , lansirase ActionEvent kojeg treba uhvatitiodgovarajucilistenerregistriranuz tu stavku.

Objekt tipaPopupMenu se možeuklonitiizkomponentetako da ga se proslijedikomponentinojmetodiremove(), na primjerovako:

f.remove(pm);

Uz jednukomponentumožebitiinstalirannajvišejedan padajuciizbornik. Ako jeinstaliranuzkontejner, onda ce trigeriizkomponenatakoje se nalazeu tom kontejnerutakoder pokretatipadajuce izbornikepod uvjetomda kontejnernemasvoj vlastitipadajuciizbornik.

Slike

Slikeu Javisu bitmapiraneGIF iliJPEG datoteke koje mogusadržavatiproizvoljnusliku.Možete ihkreiratibilokojimprogramomkoji je u stanjunapravitiGIF iliJPEG format.

Page 194: Java Predavanje I

Jednomkad su ucitaneu Javu, slikepostaju instanceapstraktneklasejava.awt.Image.Ta klasa imasljedece(apstraktne) metode:

public abstract int getWidth(ImageObserver observer) public abstract int getHeight(ImageObserver observer) public abstract ImageProducer getSource() public abstract Graphics getGraphics() public abstract Object getProperty(String name, ImageObserver observer) public Image getScaledInstance (int width, int height, int hints) public abstract void flush()

Najvecidio posla oko slikaobavljase ipak u drugimklasama, posebno ujava.awt.Graphics , java.awt.Component , i java.awt.Toolkit . Metodamaiztihklasa prosljedujeteobjekt tipaImage da bisteucitalii prikazalisliku.

Kamo staviti slike?

Skuje koje prikazujuJava appletiucitavajuse s weba preko URL-a koji pokazujenadatotekusa slikom. Appletkoji prikazujeslikumora poznavatitaj URL. Slikemogubitispremljenena web poslužitelju, lokalnomdiskuilibilogdje kamo appletmožesticipomocuURL-a. Paziteda slikestavljatetamogdje ihappletmožedohvatiti. URLkojipokazujena vaš lokalnidisk možebitiod koristidok razvijateapplet, aline možeposlužitinekometko dolazipreko weba.

Tipicno, slikese stavljajuu istidirektoriju kojemse nalaziapplet iliu onaj u kojem senalaziHTMLdocument. Iako to nijeobavezno, stavljanjeslikana nekuod tihlokacijajeobicnoprakticno. Staviteslikuzajednosa appletovomclassdatotekomako ce se onakoristitisa sviminstancamaappleta. Ilije staviteu HTMLdirektorijako ce razneinstanceappletakoristitirazneslike. Treca alternativaje stavitisve slikena zajednickulokacijuikoristitioznaku<PARAM> za dojavljivanjemjestagdje se one nalaze.

Ucitavanje slika

Ako znatetocan URLslikekoju želiteucitati, možeteto ucinitiovako: URL imageURL = new URL("http://student.math.hr/~vedris/java/images/sun.jpg");Image img = getImage(imageURL);

To se možezapisatii na kraci nacin: Image img = getImage(new URL( "http://student.math.hr/~vedris/java/images/sun.jpg"));

Metoda getImage() je izklasejava.applet.Applet pa ona funkcioniraunutarappleta. IzvanappletamožetekoristitimetodugetImage() izklasejava.awt.Toolkit .

Page 195: Java Predavanje I

URL imageURL = new URL("http://student.math.hr/~vedris/java/images/sun.jpg"); Image img = Toolkit.getDefaultToolkit .getImage(imageURL);

Ako ne znatetocan URLslike, aliznatenjenoimei znateda se nalaziu istomdirektorijukao i applet, koristitcete appletovumetodugetCodeBase() koja ce vamvratitiURLappletovogdirektorija: Image img = getImage(getCodeBase(), "sun.jpg");

Konacno, ako je slikau istomdirektorijukao HTMLdatoteka, koristitcete appletovumetodugetDocumentBase () koja ce vratitiURLdirektorijaHTMLstranice:

Image img = getImage(getDocumentBase (), "sun.jpg");

Ako se slikaucitavasa Interneta, to možepotrajati. U pravilune moratevoditiposebnogracunao tom i možeteiscrtatislikucimste je povezalisa URL-om. Java ce sama, bezvaše intervencije, prikazatislikucimpristignedovoljnopodataka za to.

Sve slikekoje applet treba ucitajtevec u init() metodi. Posebno, nemojteihucitavatiupaint() metodijer ce se tada ponovnoucitavatisvakiput kad appletnapravirepaint(), što ce drasticnosnizitiperformanse.

Slikukoja se koristiu sljedecimprimjerimamožeteskinutisa http://

student.math.hr/~vedris/java/images/sun.jpg.

Crtanje slika

Jednomkad ste slikuucitalis nekogURL-a, relativnoje jednostavnoiscrtatije. To ceteucinitiu paint() metodi, koristecinekuod metodadrawImage() izklasejava.awt.Graphics , npr. public boolean drawImage(Image img, int x, int y, ImageObserver io)

Ovdje je img memberklaseImage koji je u tom trenutkuvec ucita. Atributix i y sukoordinatelijevoggornjeguglaslike, dok je io instancaklase koja implementirasuceljejava.awt.image.ImageObserver .

To suceljepropisujekako Java rukujeasinhronimažuriranjemslike. Ono jeimplementiranou klasijava.awt.Component pa možeteza sada jednostavnostavitikljucnurijecthisu metodudrawImage(), cimecete naznacitida je sam applet taj koji ceobavitiposloveažuriranjaslike.

Metoda paint() ne radi ništadrugoosimcrtanjaslike, pocevšiod lijevoggornjeguglaimožeizgledatina primjerovako:

public void paint(Graphics g) { g.drawImage(img, 0, 0, this);

Page 196: Java Predavanje I

}

Pretpostavljamoda atributimg referenciraobjekt koji je prethodnovec bio inicijaliziran.

Uporaba povratne vrijednosti metodedrawImage()

Metoda drawImage() vraca vrijednosttipaboolean . Iako se na njucesto zaboravlja,ona vamkaže da lije slikauspješnonacrtanailinije. Ako jest, metodace vratititrue, uprotivnomfalse.

Na primjer, sljedeciappletucitavaslikus mreže. Dok se slikaucitava, applet ce nanjenommjestuprikazivatitekst "Slika se ucitava. Molim, pricekajte". Kadslikabude ucitanau potpunosti, applet ce je prikazati.

import java.awt.*;import java.applet.*;import java.awt.image.*; public class ImageDisplay extends Applet { Image picture; public void init() { this.picture = this.getImage(this.getCodeBase(), "sun.jpg"); } public void paint(Graphics g) { if(!g.drawImage(this.picture, 0, 0, this)) { g.drawString("Slika se ucitava. Molim, pricekajte", 25, 50); } } } <APPLET CODE="ImageDisplay .class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300></APPLET>

Primjer crtanja slika

Page 197: Java Predavanje I

U sljedecemprimjeruslikace se iscrtatiako je njenoimedobivenoizoznake<PARAM>, a u protivnombit ce ispisanaporuka "nema slike! ".

import java.awt.*;import java.applet.*; public class DisplayImage extends Applet { private Image picture; public void init() { String filename = this.getParameter ("imagefile"); if (filename != null) { this.picture = this.getImage(this.getCodeBase(), filename); } } public void paint(Graphics g) { if (this.picture != null) { g.drawImage(this.picture, 0, 0, this); } else { g.drawString("Nema slike!", 20, 20); } } } <APPLET CODE="DisplayImage .class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Promjena velicine slike

Ne moratese ogranicitina crtanjeslikesamo u njenojprirodnojvelicini. Sljedecavarijacijapaint() metodedopušta vamodredivanješirinei visineslike, slicnoprimjeruMagnifyImage izpredavanjao appletima(peto predavanje). public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver io) import java.awt.*;import java.applet.Applet; public class MagnifyImageDisplay extends Applet {

Page 198: Java Predavanje I

private Image picture; private double scalefactor; public void init() { String filename=this.getParameter ("imagefile"); if (filename != null) { this.picture = this.getImage(getCodeBase(), filename); } try { scalefactor = Double.valueOf( this.getParameter ("scalefactor")).doubleValue(); } catch (Exception e) { this.scalefactor = 1.0; } } public void paint (Graphics g) { if (this.picture != null) { int width = picture.getWidth(this); int height = picture.getHeight(this); int scaleWidth = (int) (width * scalefactor); int scaleHeight = (int) (height * scalefactor); g.drawImage(picture, 0, 0, scaleWidth, scaleHeight, this); } else { g.drawString("Missing imagefile PARAM element in HTML page", 10, 10); } } } <APPLET CODE="MagnifyImageDisplay .class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"><PARAM NAME="scalefactor" VALUE="0.5"></APPLET>

Ustanovljavanje velicine slike

Ako pravokutniku koji ucrtavateslikunijeproporcionalanvelicinislike, onda ona možebitiizoblicena.

Da bismoizbjeglinepravilnoskaliranjekoje dovodido izoblicenja, koristitcemo metodegetHeight() i getWidth() izklasejava.awt.Image kako bismodoznalivelicinu

Page 199: Java Predavanje I

slike. Tada je možemo, ako je potrebno, skaliratiproporcionalno. Na primjer, ovakobistesmanjilislikuna jednucetvrtinuizvorneširinei visine:

g.drawImage(img, 0, 0, img.getWidth(this)/4, img.getHeight(this)/4, this);

Pogledajmoprimjerkoji crta slikuu pravoj velicinibez obzirana velicinuappletovogpravokutnika:

import java.awt.*;import java.applet.Applet; public class FillWithImage extends Applet { private Image picture; public void init() { String filename = this.getParameter ("imagefile"); if (filename != null) { this.picture = this.getImage(this.getCodeBase(), filename); } } public void paint (Graphics g) { if (this.picture != null) { g.drawImage(this.picture, 0, 0, this.getSize().width, this.getSize().height, this); } else { g.drawString("Nedostaje PARAM imagefile u HTML dokumentu", 10, 10); } } } <APPLET CODE="FillWithImage .class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=700 HEIGHT=500><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Paket java.awt.image

Paket java.awt.image sadržiklase i suceljakoje omogucujukreiranjenovihslikafromscratch umjestoucitavanjai modificiranjavec postojecihslika.

Page 200: Java Predavanje I

Za nas ce bitizanimljivasljedecasuceljai sljedeceklase:

Sucelja

java.awt.image.ImageConsumer

java.awt.image.ImageObserver

java.awt.image.ImageProducer

Klase

java.awt.image.AreaAveragingScaleFilter

java.awt.image.ColorModel

java.awt.image.CropImageFilter

java.awt.image.DirectColorModel

java.awt.image.FilteredImageSource

java.awt.image.ImageFilter

java.awt.image.IndexColorModel

java.awt.image.MemoryImageSource

java.awt.image.PixelGrabber

java.awt.image.RGBImageFilter

java.awt.image.ReplicateScaleFilter

Sucelja ImageProducer,ImageObserver, ImageConsumer

Kad pozoveteappletovumetodugetImage(), slikase ne možeodmahpojaviti, vecmora proci neko vrijemeda se ona ucita. Vece slikeucitavatce se duže. Ako se slikaucitavasa Interneta, to možepotrajatijoš duže.

Umjestocekanja da se slikaucita, metodagetImage() se vraca odmah, moždai prijenegošto se vezas udaljenimracunalomuopce uspostavila. Ona vraca objekt tipaImage,alion inicijalnomoždane sadržinikakvepodaatke. Raznemetodeu paketu AWT kojekoristeslikeponašajuse u skladus tim. Na primjer, ako je samo gornjapolovicaslikedostupnau trenutkukad se pozoveneka od metodadrawImage() izklaseGraphics ,bit ce prikazanasamo ta gornjapolovica.

U meduvremenu, u pozadini, u odvojenomthreadu, nekiImageProducer, dakle objekt izklase koja implementirasuceljejava.awt.image.ImageProducer , popunjavaslikupixelimašto brže može. Kako višepixelapostane dostupno, bar za jedan redak, on ceobavijestitio tomesve ImageObservere koji su registriranida imajuinteresza tu sliku.

Kako nekiImageObserver registrirasvoj interesza sliku? Tako da ga se proslijedimetodikoja nešto radi sa slikom. Na primjer, sjetitese da metodedrawImage(), iz

Page 201: Java Predavanje I

klaseGraphics , te getWidth() i getHeight() izklaseImage primajuizmeduostalogai argumenttipaImageObserver .

Klasa java.awt.Component implementirasuceljeImageObserver pa to cinei svenjenepodklase. To znacida objekti tipaButton, TextArea, CheckBox, Panel, Applet, idrugimoguigratiuloguImageObserver a. Ipak, u pravilucete koristitionu komponentukoja u tom trenutkupokušavacrtatisliku.

SuceljeImageObserver propisujesamo jednumetodu, imageUpdate():

public abstract boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)

SuceljeImageProducer koristitu metoduda bi obavijestioImageObserver a da jepristiglojoš podataka o slicipa se njenprikazmožeosviježiti.

Sucelje ImageConsumer

Suceljejava.awt.image.ImageConsumer je manjeobicno. Dok ImageProducer

nekomImageObserver u samo kaže da je dio slikespreman, dotle zainteresiranomImageConsumer u daje stvarnepodatke o slici. SuceljeImageConsumer propisujesljedecemetode: public abstract void setDimensions (int width, int height) public abstract void setProperties (Hashtable props) public abstract void setColorModel (ColorModel model) public abstract void setHints(int hintflags) public abstract void setPixels(int x, int y, int width, int height, ColorModel model, byte[] pixels, int off, int scansize) public abstract void setPixels(int x, int y, int width, int height, ColorModel model, int[] pixels, int off, int scansize) public abstract void imageComplete (int status)

Cekanje na ucitavanje slike

Suceljejava.awt.image.ImageObserver omogucujevamnadziranjeprocesaucitavanja, tako da možeteinformiratikorisnikao statusuucitavanjai pocetikoristitislikucimbude spremna.

Kad nekiImageProducer primidodatne podatke za nekusliku, pozvatce metoduimageUpdate() kod svakogregistriranogklijenta. Pretpostavljena(default)imageUpdate() metodau klasijava.awt.Component osvježuje(repaints) prikazkomponentekad se slikapromijeni.

Page 202: Java Predavanje I

Ipak, varijablekoje su postavljenepomocumetodakao što getHeight() iligetWidth() ne ažurirajuse automatskipo pozivumetodeimageUpdate(). Morate ih, dakle, samiažuriratikod promjeneslikeako je potrebno.

Tocna kolicinapodataka koju nekiImageProducer dobijeprijenegopozovemetoduimageUpdate() je nepredvidljiva.

Prekrivanje metode imageUpdate()

PretpostavljenaimageUpdate() metoda izklasejava.awt.Component osvježujeprikazkomponentekad se slikapromijeni. Možete je, medutim, prekrititako da radinešto drugo. Na primjer, sljedeciapplet ispisujeporukuna statusnojlinijibrowsera dokpratiucitavanjeslike.

import java.awt.*;import java.applet.*;import java.awt.image.*; public class ImageStatus extends Applet implements ImageObserver { private Image picture; public void init() { String filename = this.getParameter ("imagefile"); if (filename != null) { this.picture = this.getImage(this.getCodeBase(), filename); } } public void paint(Graphics g) { if (this.picture != null) { g.drawImage(this.picture, 0, 0, this); } else { g.drawString("Nema slike", 20, 20); } } public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) { if ((infoflags & ImageObserver .ALLBITS) != 0) { showStatus("Slika ucitana"); this.repaint(); return false; }

Page 203: Java Predavanje I

else { showStatus("x: " + x + " y: " + y + " sirina: " + width + " visina: " + height); this.repaint(); } return true; } } <APPLET CODE="ImageStatus.class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Što je zapravo slika?

Slikaje pravokutnamrežapixela. Ona imakonacnuširinui visinukoje se moguizrazitibrojempixela. Svakipixelje kvadratickoji imafiksnuvelicinuna danomekranu. Velicinapixelamožeovisitio ekranii racunalu.

Svakipixelimanekuboju. Boja je 32-bitniinteger. Prvihosam bitovaodreduje udiocrveneboje, drugihosam udiozelene, a trecihosam udioplaveboje. Preostalihosampixelaodreduje transparentnostpixela.

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Transparency Red Green Blue

Svaka od ovihvrijednostimožese interpretiratikao neoznacenibyte izmedu0 i 255.Unutarneke boje, vecibrojevioznacavajusvijetliju(brighter), odnosnointenzivnijuboju.Tako crvenaboja vrijednosti0 nijeuopce crvena, dok je ona koja imavrijednost255intenzivnocrvena.

Trenutacnosu dostupnasamo dva stupnjatransparencije: potpunoneprozirno(255) ipotpunoprozirno(0). Vrijednostiod 1 do 254 interpretirajuse kao potpunoprozirno.

Razliciteboje dobijajuse miješanjemosnovnihtrijuboja u razlicitimomjerima. Naprimjer, umjerenosivaje zapravo127 crveno(red), 127 zeleno(green) i 127 plavo(blue):

255 127 127 127

Cista bijelaje 255 red, 255 green, 255 blue:

Page 204: Java Predavanje I

255 255 255 255

Cista crvenaje 255 red, 0 green, 0 blue:

255 255 0 0

Svijetlokrem je 255 red, 231 green, 187 blue:

255 255 231 187

Operator <<

Operator << pomicebitovecijelihbrojeva prema lijevo, bez znaka. To se možeprakticnoiskoristitiu kreiranjuboja. Pogledajmoopet primjerumjerenosiveboje:

255 127 127 127

Ovdje je transparentnost(alpha channel) 255 (11111111), dakle potpunoneprozirno,dok su kanaliza red, green, bluepostavljenina 127 (01111111). To znacida je bojapredstavljenacijelimbrojem11111111011111110111111101111111 odnosno-8,421,505. Naravno, cjelobrojnavrijednostnas ovdje ne zanima, bitnaje binarnareprezentacija.

Dakle, kako se kreirajuovakveboje?. Jednostavnoinicijalizirajtecijelebrojeve navrijednostikoje želiteza svakiod cetirikanala, uporabiteoperator << kojimcete izodvucina pravo mjestoi kombinirajtebitovskimOR operatorom, |. Taj operatorpostavljaodredenibit u rezultatuna 1 ako je on tako postavljenu bilokojem operandu.Na primjer, da bismokreiralicistuplavuboju, stavimo:

int alpha = 255 << 24;int red = 0 << 16;int blue = 255 << 8;int green = 0;int pureblue = alpha | red | green | blue;

Možete to zapisivatii krace, u jednomretku, npr: int pureblue = (255 << 24) | (0 << 16) | (255 << 8) | 0; //cista plavaint halfgrey = (255 << 24) | (127 << 16) | (127 << 8) | 127; //umjereno siva

Kreiranje slika

Page 205: Java Predavanje I

Kad znamoda su slikezapravomrežeintegera, ne bi trebalobititeško kreiratiih.Naravno, to se odnosina one slikekoje se mogukreiratialgoritamski.

Ima višenacinaza kreiranjeslike, tj. objekta tipaImage izsirovihbyteova.Najjednostavnijeje uporabitiklasujava.awt.image.MemoryImageSource . Onaimplementirasuceljejava.awt.image.ImageProducer kao i sve klase koje kreirajuslike. Njenikonstruktorisu:

public MemoryImageSource (int width, int height, int[] pixels, int offset, int scan) public MemoryImageSource (int width, int height, ColorModel cm, byte[] pixels, int offset, int scan) public MemoryImageSource (int width, int height, ColorModel cm, byte[] pixels, int offset, int scan, Hashtable props) public MemoryImageSource (int width, int height, ColorModel cm, int[] pixels, int offset, int scan) public MemoryImageSource (int width, int height, ColorModel cm, int[] pixels, int offset, int scan, Hashtable properties)

Za sada se koncentrirajmona prviod tihkonstruktora: Ovdje je width širinaslikeupixelima, height je njezinavisina, a pixels je cjelobrojnopoljekoje sadržistvarnepodatke slike. Svakibroj u tom poljuje 32-bitnavelicinakoja sadržiRGB-transparencyvrijednostza jedan pojedinacnipixel. Nadalje, offset je indexu tom poljuod kojegapocinjupodaci za tu sliku, a scan je broj pixelau svakomretku polja. Uglavnomce tajbroj bitijednak vrijednostiatributawidth.

Da bistekreiralisliku, prvo cete napunitipoljepodacimasame slike, a zatimpomocutogpoljakonstruiratinoviobjekt tipajava.awt.image.MemoryImageSource . Zatimcetetaj MemoryImageSource predatimetodicreateImage() izklasejava.awt.Component koja ce proizvestipraviImage objekt.

Primjer kreiranja slika

Pretpostavimoda želimonapravitislikuširoku100 pixelai visoku50 pixela, koja ce sesastojatiod ciste ljubicastepovršine. Vrlolijepaljubicastaboja dobije se sa. 217 red, 10green, 186 blue.

Cjelobrojnuvrijednostove boje formiratcemo ovako:

int red = 217;int green = 10;int blue = 186;int opaque = 255;

Page 206: Java Predavanje I

int purple = (opaque << 24 ) | (red << 16 ) | (green << 8 ) | blue;

Slikakoju želimoje 100 pixelaširoka i 50 pixelavisoka, pa ce namza njubitipotrebnopolje sa 100 * 50 = 5000 elemenata, dakle int[] pixels = new int[5000];

Sada možetepoljenapunitiljubicastimpixelima, npr. pomocuovakvefor petlje: for (int i=0; i < pixels.length; i++) pixels[i] = purple;

Sad imamopolje i možemokreiratiMemoryImageSource . MemoryImageSource purpleMIS = new MemoryImageSource (100, 50, pixels, 0, 50));

Pod pretpostavkomda smo u appletuilinekoj drugojpodklasiodjava.awt.Component , ucinitcemo sljedece:. Image purplebox = createImage(purpleMIS);

(Ako smo negdjedrugdje, trebat cemo pozivucreateImage() dodati prefix,odgovarajucureferentnuvarijablu.) Sada možemoslikunacrtatina uobicajennacin, kaoda smo je ucitalis mreže.

Jedan ImageProducer možetekoristitiza kreiranjevišeslika, a jedno poljepixelazakreiranjevišeobjekata tipaMemoryImageSource . Medutim, ako to radite, poljene bistesmjelimijenjatinakonšto je inicijalnokreirano.

Metoda getRGB()

Manipulacijubitovimane morateuvijekobavljatisami. Umjestotoga možetekreiratinoviobjekt tipajava.awt.Color i uporabitinjegovumetodugetRGB() da dobijeteodgovarajucuint vrijednost. Na primjer, Color purple = new Color(217, 10, 186) int p = purple.getRGB(); int[] pixels = new int[5000]; for (int i=0; i < pixels.length; i++) pixels[i] = p; MemoryImageSource purpleMIS = new MemoryImageSource (100, 50, pixels, 0, 50); theImage = createImage(purpleMIS);

Pretapanje boja

Slikakoja donosijednobojnupodlogukao štoje prethodna, možese kreiratii na višedrugihiefikasnijihnacinanegošto je manipuliranjepixelima. Medutim, neke je slikeipak

Page 207: Java Predavanje I

najjednostavnijenapravitibaš takvim,algoritamskimpristupom. Pogledajmosljedeciappletkoji kreiraslikuvelicine256 x 256

pixelana kojoj se pretapajucrvena, zelena, crna i žutaboja.

(Kvalitetaove slikeovisiu mnogomei o kvalitetimonitora.)

import java.applet.*;import java.awt.*;import java.awt.image.*; // Don't forget this! public class RGBlend extends Applet { private Image picture; public void init() { int opaque = 255 << 24; int[] pixels = new int[256*256]; for (int i=0; i < 256; i++) { int red = i << 16; for (int j = 0; j < 256; j++) { int green = j << 8; pixels[i*256 + j] = opaque | red | green; } } MemoryImageSource RGBlendMIS = new MemoryImageSource (256, 256, pixels, 0, 256); this.picture = this.createImage(RGBlendMIS); } public void paint(Graphics g) { // picture is created internally so we know it won't be null g.drawImage(this.picture, 0, 0, this); } } <APPLET CODE="RGBlend.class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=256 HEIGHT=256></APPLET>

Filtriranje slika

Page 208: Java Predavanje I

Java podržavafiltriranjeslika, skup postupaka kojimse slikatransformairana nekipredvidljivnacin. Na primjer, filtarmožeuklonitizelenuiliplavukomponentuslike,ostavljajucisamo crvenu. Ilimožeizoštriti, odnosnozamutitilinijeslike. Izucavanjefiltarajoš je otvorenopodrucje. Ovdje cemo demonstriratinekolikojednostavnihfiltara.Kompliciranijise rade na istinacin, samo što koristekompliciranijealgoritmeza filtriranjepodataka.

U Javinamje, da bismoradilis filtrima, potrebna podklasa odjava.awt.image.ImageFilter i podklasa odjava.awt.image.FilteredImageSource . Ova drugaimplementirasuceljejava.awt.image.ImageProducer . Pocinjeraditisa postojecomslikom, alije provlacikroz odgovarajuciImageFilter prijenegopošaljepixelenekomImageObserver u iliImageConsumer u.

Klasa RGBImageFilter

Klasa java.awt.image.RGBImageFilter je apstraktnapodklasa odjava.awt.image.ImageFilter . Omogucujepisanjefiltarakoji modificirajupixele,jedan po jedan. Koristise kad je filtriranjesvakogpixelanezavisnood ostalihpixela. Nijepogodnaza filteru kojimafiltriranjeovisio susjednimpixelimakao što je npr. filtarkojiuprosjecujeokolnepixele.

Jedinametoda izte klase koju trebate prekritije filterRGB()

public abstract int filterRGB(int x, int y, int rgb)

Zbog performansidobro je prekritii metodufilterRGBPixels () i postavitiatributcanFilterIndexColorModel na true. Taj atributodreduje da lifiltarovisiiline ovisiopozicijipixela. Ako je true, onda se umjestofiltriranjasvakogpixelaslikafiltrirasamoogranicenbroj stavaka u mapiboja, što je mnogobrže. Po pretpostavcifiltarovisiopozicijipa je taj atributinicijalnofalse. public void filterRGBPixels (int x, int y, int w, int h, int pixels[], int offset, int scan)

Metoda filterRGBPixels () prosljedujesvakipixelizpolja pixelametodifilterRGB() jedan po jedan. Medutim, ponekad možetepoboljšatiperformanseizbjegavanjemnepotrebnihpozivametoda i filtriranjapixelajedan po jedan, posebno ako jecanFilterIndexColorModel postavljenna false.

Primjer plavog filtra

Evo jednogjednostavnogfiltrakoji propušta samo plavekomponenteslike. import java.awt.image.*;

Page 209: Java Predavanje I

public class BlueFilter extends RGBImageFilter { protected boolean canFilterIndexColorModel = true; public int filterRGB(int x, int y, int rgb) { return rgb & 0xFF0000FF; } }

AtributcanFilterIndexColorModel je postavljenna true jer je filtriranjeneovisnoopoziciji. Bitovskioperator, &, koristise za selektiranjesamo prvihosam i zadnjihosambitovavrijednostibroja rgb. Stupanjtransparentnostije spremljenu prvih8 bitova. Plavakomponentase nalaziu zadnjih8 bitova. FF je 11111111 pa su svibitoviplaveboje iprozirnostizadržani. Ostalice nestati.Da bismokoristilitaj plavifiltar, kreiratcemo objekt tipajava.awt.image.FilteredImageSource . Na primjer, Image src = getImage(getDocumentBase (), filename);picture = createImage(new FilteredImageSource (src.getSource(), new BlueFilter()));

Metoda getSource() vraca referencuna objekt tipaImageProducer koji je proizveosliku(objekt tipaImage).

Evo sada appletakoji ucitavaslikunavedenuu oznaci<PARAM> i zatimna njuprimjenjujeplavifiltar.

import java.awt.*;import java.awt.image.*;import java.applet.*; public class BlueImage extends Applet { private Image picture; public void init() { String filename = this.getParameter ("imagefile"); if (filename != null) { Image src = this.getImage(getCodeBase(), filename); this.picture = this.createImage( new FilteredImageSource (src.getSource(), new BlueFilter())); } } public void paint (Graphics g) { if (this.picture != null) { g.drawImage(this.picture, 0, 0, this); } else {

Page 210: Java Predavanje I

g.drawString("Nema slike", 20, 20); } } } <APPLET CODE="BlueImage.class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Primjer filtra sivih tonova

Sljedecifiltarprevodiboje slikeu skalusivihtonova. Crvena, zelenai plavaboja suujednacene. Rezultirajucaboja je sivasa istimprosjecnimintenzitetom. import java.awt.image.*; public class GreyFilter extends RGBImageFilter { protected boolean canFilterIndexColorModel = true; public int filterRGB(int x, int y, int rgb) { int red = rgb & 0x00FF0000; red >>>= 16; int green = rgb & 0x0000FF00; green >>>= 8; int blue = rgb & 0x0000FF; int grey = (red + green + blue)/3; return (0x000000FF << 24) | (grey << 16) | (grey << 8) | grey; } }

Primijetiteda su prijeracunanjaprosjeka crvenai zelenakomponentapomaknutedesnoza 16, odnosno8 bitovarespektivno. To ihbaca u raspon od 0 do 255 i omogucujedasa svakomod njihradimopojedinacno. Operator >>> pomicebitoveudesnobezpredznaka. import java.awt.*;import java.awt.image.*;import java.applet.*; public class GreyImage extends Applet { private Image picture;

Page 211: Java Predavanje I

public void init() { String filename = this.getParameter ("imagefile"); if (filename != null) { Image source = this.getImage(getCodeBase(), filename); this.picture = this.createImage( new FilteredImageSource (source.getSource(), new GreyFilter())); } } public void paint (Graphics g) { if (this.picture != null) { g.drawImage(this.picture, 0, 0, this); } else { g.drawString("Nema slike", 20, 20); } } } <APPLET CODE="GreyImage.class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Filtri koji ovise o položaju

Moguse pisatifiltrikoji oviseo položajupixela. Na primjer, sljedecifiltarzatamnjujeslikutako da je zatamnjenjeto vece što se višeudaljujemood gornjeglijevogugla. import java.awt.image.*; public class ShadowFilter extends RGBImageFilter { private double edge; public ShadowFilter (int width, int height) { edge = Math.sqrt(width*width + height*height); } public int filterRGB(int x, int y, int rgb) { double fraction = 1.0 - Math.sqrt(x*x + y*y)/edge; if (fraction <= 0) return 0xFF000000; int red = rgb & 0x00FF0000; red >>>= 16;

Page 212: Java Predavanje I

int green = rgb & 0x0000FF00; green >>>= 8; int blue = rgb & 0x0000FF; int r = (int) (red * fraction); int g = (int) (green * fraction); int b = (int) (blue * fraction); return (0x000000FF << 24) | (r << 16) | (g << 8) | b; } } import java.awt.*;import java.awt.image.*;import java.applet.*; public class ShadowImage extends Applet { private Image picture; public void init() { String filename = this.getParameter ("imagefile"); Image src = this.getImage(getCodeBase(), filename); this.picture = this.createImage(new FilteredImageSource(src.getSource(), new ShadowFilter (this.getSize().width, this.getSize().height))); } public void paint (Graphics g) { g.drawImage(this.picture, 0, 0, this); } }

Primijetiteda ovdje canFilterIndexColorModel višenijepostavljenna true. Svakipixelmora se tretiratiindividualno. Takoder primijetiteda ovaj filtarimakonstruktor. Iakonijenužan, pokazujese korisnim. <APPLET CODE="ShadowImage.class"CODEBASE="http://student.math.hr/~vedris/java/classes/ImageProcessing "WIDTH=435 HEIGHT=300><PARAM NAME="imagefile" VALUE="sun.jpg"></APPLET>

Filtri koji ovise o adjungiranimpixelima

Page 213: Java Predavanje I

Do sad smo pretpostavljalida se svakipixelmožefiltriratineovisnoo susjednimpixelima.To nijeuvijektako. Na primjer, filtriza izoštravanje, zamagljivanjei slicno, tražeznacajnukolicinupodataka o drugimdijelovimaslike.

Kad filtarmora uzimatiu obzirvrijednostine samo filtriranihpixelanego i drugih, nijevišemogucekoristitijednostavnuklasujava.awt.image.RGBImageFilter . Umjestotogatreba raditidirektnosa java.awt.image.ImageFilter . Da biste implementiralisvojfiltar, potrebno je prekritidvijemetodesetPixels().

public void setPixels(int x, int y, int w, int h, ColorModel model, byte pixels[], int offset, int scan) public void setPixels(int x, int y, int w, int h, ColorModel model, int pixels[], int offset, int scan)

Audio

Java omogucujeizvodenjeaudiodatoteka kodiranihu odredenimformatima. To mogubitiAIFF, AU, WAV, MIDI, and RMF datoteke. Klasa java.applet.Applet sadržidvijemetodepomocukojihmožeteskinutizvucnudatotekusa nekogURL-a i izvestije. public void play(URL soundfile) public void play(URL directory, String filename)

Uobicajenoje da se te adrese zadajuu odnosuna codeBase ilidocumentBase , iliURLmožebitizadanpomocuoznake<PARAM>. Audioprimjerza sljedeceappletemožeteskinetesa adrese http://student.math.hr/~vedris/java/sounds/spacemusic.au). import java.applet.*; public class SoundApplet extends Applet { public void init() { String soundfile = this.getParameter ("soundfile"); if (soundfile != null) this.play(this.getCodeBase(), soundfile); } } <APPLET CODE="SoundApplet.class"CODEBASE="http://student.math.hr/~vedris/java/classes/SoundProcessing "WIDTH=200 HEIGHT=100><PARAM NAME="soundfile" VALUE="spacemusic.au">

Page 214: Java Predavanje I

</APPLET>

Kontinuirana izvedba

Umjestopojedinacneizvedbeod pocetka do kraja, appletmožeizvoditizvucniprimjerkontinuirano, tako da ga ucitau objekt "tipa" java.applet.AudioClip (primijetitedaje to sucelje, ne klasa!) i nakon toga izvvodipomocumetodeloop(). Prvo treba snimitizvuku AudioClip na primjerovako: AudioClip ac = this.getAudioClip (new URL( "http://student.math.hr/~vedris/java/sounds/spacemusic.au"));

Tada, kad imateobjekt koji je AudioClip , pozovetenjegovumetoduloop(): ac.loop();

Kad želitezaustavitiizvedbu, pozvatcete metodustop(): ac.stop();

Evo appletakoji omogucujekontinuiranuizvedbuzvucnogprimjera: import java.applet.*; // java.applet.Applet isn't enough public class SoundLoopApplet extends Applet { AudioClip theSound; public void init() { String soundfile = this.getParameter ("soundfile"); if (soundfile != null) { theSound = this.getAudioClip (this.getCodeBase(), soundfile); } } public void start() { if (theSound != null) theSound.loop(); } public void stop() { if (theSound != null) theSound.stop(); } } <APPLET CODE="SoundLoopApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes/SoundProcessing "WIDTH=200 HEIGHT=100><PARAM NAME="soundfile" VALUE="spacemusic.au"></APPLET>

Page 215: Java Predavanje I

Primijetiteda sam appletvodiracunao tomeda izvedbaprestanekad korisniknapustistranicupa se pozovemetodastop(). U protivnombi se izvedbanastavilabeskonacno,sve dok korisnikne ugasibrowser.

Page 216: Java Predavanje I

Deseto predavanje ulaz i izlazOperacije ulaza i izlaza - što je stream? klase streamova odakle streamovidolaze? klasa InputStream citanje byteova citanje više byteova odjednomprebrojavanje dostupnih byteova preskakanje byteova markiranje i resetiranjezatvaranje streamova izlazni streamovi primjer izlaznog streama citanje izdatoteke primjer citanja iz datoteke pisanje u datoteku primjer pisanja udatoteku dodavanje na kraj datoteke filtriranje streamova filtrirani streamovibufferirani streamovi klase podatkovnih streamova klasa PrintStream klasaPushBackInputStream klasa File konstruktori klase File metode klase Fileprimjeri metoda iz klase File klasa FileDialog klasa RandomAccessFile suceljeFilenameFilter klase Reader i Writer klasa Reader klasa Writer klasaInputStreamReader klasa OutputStreamWriter dostupne kodne stranice klasaFileWriter klasa FileReader klasa BufferedReader klasa LineNumberReaderklasa BufferedWriter

Operacije ulaza i izlaza

Podaci se ponekad umjestona zaslonracunalaispisujuu datoteku. Unixi DOS za tusvrhuimajuredirekcijskeoperatore < i >. Ponekad je potreban i finijipristup, na primjerako želiteneke podatke uputitiu datoteku, a drugeostavitina zaslonu. Ilimoždaželiteistovremenoimatipristupu višedatoteka. Takoder, moždaželitetražitiod korisnikadaunesepodatke ne samo preko komandnelinijenego i na nekidruginacin. Iliželiteprocitatidatotekukoja je napisanau odredenomformatu, poslatipodatke preko mrežeiliihs nje ucitati. U Javise sve ove operacijeobavljajuuzpomoc streamova. Streamje naprimjeri System.out koji ste susrelivec u prvompredavanju.

Što je Stream?

Stream je nizpodataka koji imaneodredenuduljinu. Nazivstream(struja, tok) jeodabran jer ta strukturanalikujestrujivode koja neprekidnotece i nemadefiniranogkraja. Još bolja analogijaje rep (red cekanja). Za vrijemedok se uslužujuljudinapocetku repa, novidolazena njegovkraj. Rep je diskretnastruktura, alito ne znacidanjegoviclanovinisumedusobnopovezaniraznimrelacijama.

U Javise streamsastojiod nizadiskretnihbyteova. Onimogupredstavljatiznakoveilineke drugevrstepodataka. Mogudolazitibrže negošto ihje moguceobraditiilipakprocess možecekatidok ne dode sljedeciza obradu.

Kljucobrade streamaje while petljakoja obraduje svakipojedinielementstreamadokne ucitaznakza kraj streamailidok se ne pojavinekidrugiiznimniuvjet. Na Unixuje<Ctrl-D> znakza završetakstreama. Windowsza tu svrhukoristi<Ctrl-Z>.

Page 217: Java Predavanje I

Klase streamova

Gotovesve klase koje izravnorade sa streamovimadijelovisu paketa java.io. (Postojitakoder nekolikododatnihu paketimasun.io i sun.net, alite su namjernoskrivene.Ima i nekolikoklasa u paketu java.util.zip.) Dvijeglavneklase sujava.io.InputStream i java.io.OutputStream . To su apstraktneklase i one cinetemeljmnogihpotklasasa specijaliziranimmogucnostima. Medu njimase najcešcekoriste:

BufferedInputStream

BufferedOutputStream

ByteArrayInputStream

ByteArrayOutputStream

DataInputStream

DataOutputStream

FileInputStream

FileOutputStream

FilterInputStream

FilterOutputStream

LineNumberInputStream

ObjectInputStream

ObjectOutputStream

PipedInputStream

PipedOutputStream

PrintStream

PushbackInputStream

SequenceInputStream

StringBufferInputStream

Odakle streamovi dolaze?

StreamSystem.out je, recimo, OutputStream ; i to posebno, PrintStream . PostojiodgovarajuciSystem.in koji je InputStream namijenjencitanjupodataka s konzole.

Podaci za streamovedolazetakoder i izdatoteka. Kasnijecete vidjetikako koristitiklasuFile te klaseFileInputStream i FileOutputStream za citanjepodataka izdatotekai pisanjeu njih.

Mrežnekonekcijeobicnodaju streamove. O tomece bitirijeciu zasebnompredavanju.Kad se povežetena nekiweb iliftp ilinekidrugiposlužitelj, citatepodatke koje on šaljetako da s njimpovežetejedan InputStream i jedan OutputStream .

Java programii samiproizvodestreamove. Na primjer, ByteArrayInputStream ,ByteArrayOutputStream , StringBufferInputStream , PipedInputStream , iPipedOutputStrea m se koristeza prijenospodataka izjednogdijelaJava programaudrugi.

Page 218: Java Predavanje I

Ponešto neocekivano, komponentekao što je TextArea ne proizvodestreamove.Medutim, stringovekoje onistvarajuuvijekmožetekoristitida bistekreiraliByteArrayInputStream iliStringBufferInputStream .

Klasa InputStream

Klasa java.io.InputStream je apstraktnaklasa koja sadržiosnovnemetodezacitanjecistihbyteovapodataka izstreama. Iako je to apstraktnaklasa, mnogemetodeubibliotecivracajuobjekt tipaInputStream , tako da cete cesto trebatiraditidirektnosnekomod metodadeklariranihu toj klasi. public abstract int read() throws IOExceptionpublic int read(byte[] data) throws IOExceptionpublic int read(byte[] data, int offset, int length) throws IOExceptionpublic long skip(long n) throws IOExceptionpublic int available() throws IOExceptionpublic void close() throws IOExceptionpublic synchronized void mark(int readlimit)public synchronized void reset() throws IOExceptionpublic boolean markSupported ()

Primijetiteda gotovosve ove metodemoguizbacitiIOException . To vrijedizauglavnomsve što se odnosina ulazi izlaz. Jedinaiznimkaod tog pravilaje klasaPrintStream koja ce progutatisve iznimke.

Citanje byteova

Osnovnaread() metoda izklasejava.io.InputStream citapojedinacnineoznacenibyte podataka i vraca njegovuint vrijednost. To je broj izmedu0 i 255. Kad se naidena kraj streama, vraca se -1, i to možetekoristitikao flagpomocukojeg cete ustanovitida ste došlido kraja streama. public abstract int read() throws IOException

Evo jednogjednostavnogprogramakoji vraca kao echo korisnikovunosna komandnojliniji. Bytese prije ispisapretvarau ekvialentniISO Latin-1 znak. Ovaj programnecepravilnoraditisa Unicodeznakovima. Možete ga dakle koristitisamo za cistepodatke, aza tekstovei osobitone-ASCII podatke koristitiklasejava.io.Reader ijava.io.Writer. /* Note that as a general rule on most platforms charactersare only sent to System.in a line at a time, not as each characteris typed. This allows the user to backspace over mistakes and correct them. Java does not allow you to put the console into"raw" mode. */ import java.io.*;

Page 219: Java Predavanje I

public class Echo { public static void main(String[] args) { echo(System.in); } public static void echo(InputStream in) { try { while (true) { // Notice that although a byte is read, an int // with value between 0 and 255 is returned. // Then this is converted to an ISO Latin-1 char // in the same range before being printed. int i = in.read(); // -1 is returned to indicate the end of stream if (i == -1) break; // without the cast a numeric string like "65" // would be printed instead of the character "A" char c = (char) i; System.out.print(c); } } catch (IOException e) { System.err.println(e); } System.out.println(); } } % javac Echo.java% java Echoabcdefgabcdefg<Ctrl-C>%

Citanje više byteova odjednom

Dok osnovnaread() metodacitabyte po byte, sljedecedvijeoverloadedvarijantecitajupoljabyteova. public int read(byte[] data) throws IOExceptionpublic int read(byte[] data, int offset, int length) throws IOException

Page 220: Java Predavanje I

Prva metodacitaonolikobyteovakolikojoj treba da napunipoljedata. Drugacitaonolikobyteovaizulaznogstreamakolikojoj je zadanou argumentulength i spremaihu poljedata pocevšiod pozicijeoffset .

Te su metodeblokoranedok ne stignuraspoloživipodaci. Tada ucitajuonolikopodatakakolikostane u polje ilikolikoje navedenou length .

Nakon toga vracajubroj byteovakoje su ucitale. Ne smijetepretpostavitida ce polje bitiuvijeknapunjenoilida ce zaistabitiucitanolength byteova. Ako naidekraj streama,vraca se -1.

Prebrojavanje dostupnih byteova

Metoda available() ispitujukolikobyteovasa uzlaznogstreamaje spremnozaucitavanjebez blokiranja.

public int available() throws IOException

Na primjer, sljedeciprogramje efikasnijaverzijaprethodnogprogramaEcho jer koristimetoduavailable() za ispitivanjekolikobyteovaje spremnoza ucitavanje, a zatimkreirapolje tocno te velicine, ucitavabyteoveu polje i konvertiraga u String koji zatimispisuje.

import java.io.*; public class EfficientEcho { public static void main(String[] args) { echo(System.in); } public static void echo(InputStream in) { try { while (true) { int n = in.available(); if (n > 0) { byte[] b = new byte[n]; int result = in.read(b); if (result == -1) break; String s = new String(b); System.out.print(s); } // end if } // end while } // end try catch (IOException e) { System.err.println(e); }

Page 221: Java Predavanje I

} } % javac Echo.java% java Echoabcdefgabcdefg<Ctrl-C>%

Preskakanje byteova

Metoda skip() cita i odbacuje specificiranibroj byteova.

public int skip(long n) throws IOException

Možete je koristiti, na primjer, ako želitebrzo prodi standardniheader iliprefiksnekihpodataka. U sljedecemfragmentukoda koristise skip() za preskakanjeprazninaukljucenihu DataInputStream dis.

case 171: // lookupswitch pad = 3 - (position % 4); dis.skip(pad); defaultByte = dis.readInt(); int npairs = dis.readInt(); result = position + " lookupswitch " + defaultByte + " " + npairs; for (int i = 0; i < npairs; i++) { int newPosition = position + pad + 12 + i*8; result += "\n" + newPosition + " " + dis.readInt() + " " + dis.readInt(); }

Markiranje i resetiranje

Cesto je korisnoako možeteucitatinekolikobyteova, a zatimse vratitinatragi ucitatiihponovo. Na primjer, pri oblikovanjunekogkompajlerane možeteznatida litrebateucitatiznak<, <<, ili<<= sve dok ne ucitatedva ilivišebyteova. Bilobi korisnoakobistese moblivratitinatragi ponovoucitatitoken nakonšto ste okrilio kojem se radi.Dizajniranjekompajlerai problemiparsiranjauvijekosiguravajumnoštvoprimjera, noslicnepotrebe se pojavljujui drugdje.

Neki, aline svistreamovidopuštajuvamda markirateodredenupozicijuu streamui ondase vratitena nju. To se radi pomocusljedecihmetoda:

public synchronized void mark(int readlimit)public synchronized void reset() throws IOExceptionpublic boolean markSupported ()

Page 222: Java Predavanje I

Metoda markSupported () vraca true ako taj streampodržavamarkiranje, a false

inace.

Pod pretpostavkomda je markiranjepodržano, metodamark() stavljabookmark namjestogdje se kasniježelitevratitipomocumetodereset(). Istodobno u jednomstreamumožepostojatisamo jedan takav bookmark. Sljedecemarkiranjeizbrisatceprethodno. Ako markiranjenijepodržano, ove ce metode izbacitiIOException .

Zatvaranje streamova

Kad ste završilis nekimstreamom, trebalibistega zatvoritikako bi se otpustiliresursikojisu s njimpovezani. Jednomkad je streamzatvoren, svakipokušaj citanjaiznjegaizbacitce IOException .

Stream(u ovomslucajuulazni) zatvaratepomocumetodeclose():

public void close() throws IOException

Ako se streamne možezatvoriti, izbacitce se IOException .

Izlazni streamovi

Klasa java.io.OutputStream šaljecistebyteovepodataka na neko odredište, npr.konzoluilimrežniposlužitelj. Ova je klasa apstraktna, istokao i InputStream . Medutim,mnogemetodeu biblioteciklasa napravljenesu tako da vracajuobjekte tipaOutputStream umjestoobjekte iznjenihspecificnihpodklasa. Takoder, mnogemetodeklaseOutputStream su opcenitokorisne. To su: public abstract void write(int b) throws IOExceptionpublic void write(byte[] data) throws IOExceptionpublic void write(byte[] data, int offset, int length) throws IOExceptionpublic void flush() throws IOExceptionpublic void close() throws IOException

Nekolikorazlicitihwrite() metodašaljucistebyteovepodataka svakomprocesu kojiosluškujedanistream.

Ponekad operacijskisustavbufferiraizlaznestreamovezbogboljihperformansi. To znacida se byteoviprije ispisaakumulirajuu spremnikcijavelicinamožebitiod nekolikobyteovado nekolikotisucabyteova. Kad se on napuni, svipodaci se ispisujuodjednom.Metoda flush() pokrenutce, medutim, ispisbez obzirada lije spremnikpun ilinije.

Primijetiteda to nije istošto i bufferiranjekoje provodiklasaBufferedOutputStreamkoje izvodiJava runtime. Ovdje se radi o native bufferiranju, dakle procesu na razini

Page 223: Java Predavanje I

operacijskogsustava. Medutim, pozivmetodeflush() trebao bi ispraznitiobaspremnika.

Metoda close() zatvarastreami otpušta resursekoji su s njimpovezani. Jednomkad jestreamzatvoren, pokušaj pisanjau njegaizbacitce IOException .

Primjer izlaznog streama

Jediniizlaznistreamovikoje ste do sad upoznalisu System.out i System.err. Sljedeciprimjerkoristimetodewrite() and flush() izklaseOutputStream da bi naSystem.out ispisaostring HelloWorld import java.io.*; public class HelloOutputStream { public static void main(String[] args) { String s = "Hello World\r\n"; // Convert s to a byte array byte[] b = new byte[s.length()]; s.getBytes(0, s.length()-1, b, 0); try { System.out.write(b); System.out.flush(); } catch (IOException e) { System.err.println(e); } } } % javac HelloOutputStream .java% java HelloOutputStream ello World%

Primijetiteda programne radi baš onako kako bi se ocekivalonegoprogutaprviznak.

Citanje iz datoteke

Klasa java.io.FileInputStream predstavljaInputStream koji citabyteoveizdatoteke. Ima sljedecepublickonstruktorei metode: public FileInputStream (String name) throws FileNotFoundExceptionpublic FileInputStream (File file) throws FileNotFoundException

Page 224: Java Predavanje I

public FileInputStream (FileDescriptor fdObj) public native int read() throws IOExceptionpublic int read(byte[] data) throws IOExceptionpublic int read(byte[] data, int offset, int length) throws IOExceptionpublic native long skip(long n) throws IOExceptionpublic native int available() throws IOExceptionpublic native void close() throws IOExceptionpublic final FileDescriptor getFD() throws IOException

S iznimkomkonstruktorate metodegetFD(), ove metodesamo prekrivajuistoimenemetodeklasejava.io.InputStream . Jedinaje razlikašto citajupodatke izdatoteke.

Primjer citanja iz datoteke

Noviobjekt tipaFileInputStream konstruiratetako da konstruktoruproslijediteimedatoteke, na primjer:

FileInputStream fis = new FileInputStream ("ulaz.txt");

Ako datoteka ne postoji, izbacitce se iznimkaFileNotFoundException , podklasa odIOException . Opcenito, Java ce tražitidatoteke u aktivnomdirektoriju, no one se nemorajunužnonalazitiu direktorijuu kojem se nalazi.classdatoteka.

Sljedecaaplikacijacitadatoteke koje su navedenena komandnojlinijii ispisujenjihovsadržajna System.out.

import java.io.*; public class Type { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { try { FileInputStream fis = new FileInputStream (args[i]); int n; while ((n = fis.available()) > 0) { byte[] b = new byte[n]; int result = fis.read(b); if (result == -1) break; String s = new String(b); System.out.print(s); } // end while fis.close(); } // end try // Is this catch strictly necessary? catch (FileNotFoundException e) { System.err.println("Could not find file " + args[i]); } catch (IOException e) {

Page 225: Java Predavanje I

System.err.println(e); } System.out.println(); } // end for } // end main } % javac Type.java% java Type "../html/TricksterApplet .html"<APPLET CODE="TricksterApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" ARCHIVE="Trickster.jar"WIDTH=1 HEIGHT=1></APPLET>%

Pisanje u datoteku

Klasa java.io.FileOutputStream predstavljaOutputStream koji upisujebyteoveudatoteku. Ima sljedecepublickonstruktorei metode: public FileOutputStream (String name) throws IOExceptionpublic FileOutputStream (String name, boolean append) throws IOExceptionpublic FileOutputStream (File file) throws IOExceptionpublic FileOutputStream (FileDescriptor fdObj) public native void write(int b) throws IOExceptionpublic void write(byte[] data) throws IOExceptionpublic void write(byte[] data, int offset, int length) throws IOExceptionpublic native void close() throws IOExceptionpublic final FileDescriptor getFD() throws IOException

S iznimkomkonstruktorate metodegetFD(),ove metodesamo prekrivajuistoimenemetodeklasejava.io.OutputStream . Jedinaje razlikašto pišupodatke u datoteku.

Primjer pisanja u datoteku

Noviobjekt tipaFileOutputStream konstruiratetako da konstruktoruproslijediteimedatoteke, na primjer:

FileOutputStream fos = new FileOutputStream ("izlaz.txt");

Ako datoteka postojiu aktivnomdirektoriju, bit ce prebrisanai u njuupisaninovipodaci.Ako ne postoji, kreiratce se.

Page 226: Java Predavanje I

U sljedecemprimjerucita se korisnikovinputsa System.in i ispisujese u datotekespecificiranena komandnojliniji.

import java.io.*; public class MultiType { public static void main(String[] args) { FileOutputStream [] fos = new FileOutputStream [args.length]; for (int i = 0; i < args.length; i++) { try { fos[i] = new FileOutputStream (args[i]); } catch (IOException e) { System.err.println(e); } } // end for try { while (true) { int n = System.in.available(); if (n > 0) { byte[] b = new byte[n]; int result = System.in.read(b); if (result == -1) break; for (int i = 0; i < args.length; i++) { try { fos[i].write(b, 0, result); } catch (IOException e) { System.err.println(e); } } // end for } // end if } // end while } // end try catch (IOException e) { System.err.println(e); } for (int i = 0; i < args.length; i++) { try { fos[i].close(); } catch (IOException e) { System.err.println(e); } } } // end main }

Page 227: Java Predavanje I

% javac MultiType.java% java MultiType izlaz1.txt izlaz2.txtnebo je plavo <Ctrl-C>%% ls izlaz*.txtizlaz1.txtizlaz2.txt % more izlaz1.txtnebo je plavo% more izlaz2.txtnebo je plavo%

Dodavanje na kraj datoteke

Ako želiteda se novisadržajdoda na kraj datoteke umjestoda prebrišeprethodnisadržaj, proslijeditcete vrijednosttrue kao drugiargumentkonstruktoruFileOutputStream (). Na primjer:

FileOutputStream fos = new FileOutputStream ("izlaz.txt", true);

U sljedecemprimjerucita se korisnikovinputsa System.in i dodaje na kraj datotekaspecificiranihna komandnojliniji.

import java.io.*; public class Append { public static void main(String[] args) { FileOutputStream [] fos = new FileOutputStream [args.length]; for (int i = 0; i < args.length; i++) { try { fos[i] = new FileOutputStream (args[i], true); } catch (IOException e) { System.err.println(e); } } // end for try { while (true) { int n = System.in.available(); if (n > 0) { byte[] b = new byte[n]; int result = System.in.read(b); if (result == -1) break; for (int i = 0; i < args.length; i++) { try { fos[i].write(b, 0, result);

Page 228: Java Predavanje I

} catch (IOException e) { System.err.println(e); } } // end for } // end if } // end while } // end try catch (IOException e) { System.err.println(e); } for (int i = 0; i < args.length; i++) { try { fos[i].close(); } catch (IOException e) { System.err.println(e); } } // end for } // end main } % javac Append.java% java Append izlaz1.txt izlaz2.txta trava je zelena. <Ctrl-C>% more izlaz1.txtnebo je plavoa trava je zelena. % more izlaz2.txtnebo je plavo a trava je zelena.%

Filtriranje streamova

Klase java.io.FilterInputStream i java.io.FilterOutputStream sukonkretnepodklase od InputStream i OutputStream koje na nekinacinmodificirajupodatke osnovnihstreamova. Rijetkocete ihkoristitiizravno, alinjihovesu podklaseiznimnovažne, posebno DataInputStream i DataOutputStream .

Filtar-streampovezujetes osnovnimtako da da osnovniproslijeditekonstruktorufiltar-streama. Na primjer, da bistekreiralinoviobjekt tipaDataOutputStream izobjektaFileOutputStream moglibistepostupitiovako:

FileOutputStream fos = new FileOutputStream ("ln.txt");DataOutputStream dos = new DataOutputStream (fos);

To se možekombiniratii u jednoj liniji:

Page 229: Java Predavanje I

DataOutputStream dos = new DataOutputStream (new FileOutputStream("ln.txt"));

Filtrirani streamovi

BufferedInputStream i BufferedOutputStreamOve klase bufferirajucitanjei pisanjetako da podatke najprijeucitavajuuspremnik(buffer, interrnopoljebyteova). Tako neka aplikacijamožecitatibyteoveizstreamabez pozivanjanative metodakoje izatoga stoje. Podaci seucitavajuizbufferailiu njegaupisujuu blokovima, a naknadnipristupiusmjeravajuse direktnoprema spremniku.

DataInputStream i DataOutputStreamOve klase citajui pišupodatke koji pripadajuprimitivnimJava tipovima, kao ipodatke tipaStringna nacinkoji ne ovisio mašini(Big-endianza integer,IEEE-754 za floati double, UTF-8 za Unicode)

PrintStream

Ova ste klasuvec susretalipreko njenihimplementacijaSystem.out iSystem.err. Omogucujevrlojednostavnoispisivanjeprimitivnihvrijednosti,objekata i stringliterala. Klasa hvatasve iznimketipaIOException inamijenjenaje ponajprijeza debugging.

PushbackInputStream

Ova klasa osiguravapushback spremnikpomocukojeg je moguce"poništiti"citanjebyteovasa streama. Kod sljedecegcitanjasa streamabit ce ucitanitiponišteni byteovi.

GZIPInputStream i GZIPOutputStream

Ovo su klase izpaketa java.util.zip i obavljajukompresijui dekompresijupodataka.

DigestInputStream i DigestOutputStreamOvo su klase izpaketa java.security i izracunavajutzv. MessageDigest zastreamovekoristecineku jaku hashfunkciju, npr SHA.

CipherInputStream i CipherOutputStreamKlase su izpaketa javax.crypto koji je dio Java CryptographyExtension(JCE), standardnogproširenjaJave, a ukljucenje u JavaTM 2 Platform Std.Ed. v1.4.0. i izracunavajuenkripcijei dekripcijestreamovakoristeciraznealgoritmekao DES, RSA, Blowfishi druge.

ObjectInputStream i ObjectOutputStreamPodklase od of DataInputStream i DataOutputStream koje moguserijaliziratii deserijaliziratiJava objekte u cistebyteove(i obratno). Koristisekod udaljenogpozivanjametoda(RMI) i za JavaBeans.

Page 230: Java Predavanje I

Možete kreiratii svoje vlastitepodklase od java.io.FilterInputStream ijava.io.FilterOutputStream koje ce izvoditifiltriranjaprema vašimpotrebama.

Bufferirani streamovi

Klase java.io.BufferedInputStream i java.io.BufferedOutputStreamomogucujucitanjei pisanjena nacinda se podaci prvo spremajuu spremnik(buffer) kojije zapravointernopoljebyteova. Programtada citabyteoveizstreamabez prethodnogpozivanjanative metodedok god imapodataka u spremniku. Podaci se citajuizspremnikailipišuu njegau blokovima, a nakon toga su dostupniizravnoizspremnika.

Sa stanovištaprogramera, jedinarazlikaizmeduobicnogi bufferiranogstreamaje ukonstruktorima:

public BufferedInputStream (InputStream in)public BufferedInputStream (InputStream in, int size)public BufferedOutputStream (OutputStream out)public BufferedOutputStream (OutputStream out, int size)

Argumentsize je broj byteovau spremniku. Ako nijenaveden, podrazumijevase 512.

Optimalnavelicinaspremnikajako ovisio platformii opcenitoje povezanasa velicinombloka na disku, barem za datotecnestreamove. Manje od 512 ce vjerojatnobitipremalo,a višeod 4096 previše. Idealnobi biloda velicinaspremnikabude cjelobrojnivišekratnikvelicinebloka diska. Za nepouzdanemrežnekonekcijebolje je odabratimanjuvelicinuspremnika. Na primjer,

URL u = new URL("http://java.developer.com");BufferedInputStream bis = new BufferedInputStream (u.openStream(), 256);

Klase podatkovnih streamova

Klase java.io.DataInputStream i java.io.DataOutputStream citajui pišuprimitivneJava tipovepodataka i stringovena nacinkoji ne ovisio mašini. OpcenitoceteDataInputStream koristitiza citanjepodataka koji su napisanipomocuDataOutputStream . Taj formatkorististandardIEEE754 za floatingpoint, big-endianza integer, i modificiraniUTF-8 za Unicode.

DataOutputStream deklarirasljedecekonstruktorei metode:

public DataOutputStream (OutputStream out) public synchronized void write(int b) throws IOExceptionpublic synchronized void write(byte[] data, int offset, int length) throws IOExceptionpublic final void writeBoolean (boolean b) throws IOExceptionpublic final void writeByte(int b) throws IOExceptionpublic final void writeShort(int s) throws IOException

Page 231: Java Predavanje I

public final void writeChar(int c) throws IOExceptionpublic final void writeInt(int i) throws IOExceptionpublic final void writeFloat(float f) throws IOExceptionpublic final void writeDouble(double d) throws IOExceptionpublic final void writeBytes(String s) throws IOExceptionpublic final void writeChars(String s) throws IOExceptionpublic final void writeUTF(String s) throws IOExceptionpublic final int size()public void flush() throws IOException

Metoda size() vraca broj byteovakoji su ispisanina izlaznistream.

Klasa PrintStream

Klasa java.io.PrintStream je podklasa od FilterOutputStream . Implementiranaje u System.out i System.err. Omogucujejednostavanispisprimitivnihvrijednosti,objekata i stringliterala. Za konvertiranjeznakovau byteovekoristikodiranjekoje je nadanoj platformidefault.

Ta klasa ce uhvatitisve iznimketipaIOException , Statuspogreške možeteuvijekdoznatipomocumetodecheckError(). Ona ce vratititrue ako se greška pojavila,false inace.

public boolean checkError()

Ono što se najvišekoristiu ovoj klasisu (overlodaded) metodeprint() i println().Metode println() dodaju znakza završetaklinijesvemušto ispisuju, za razlikuodmetodaprint() koje to ne cine.

public void print(boolean b)public void print(int i)public void print(long l)public void print(float f)public void print(double d)public void print(char s[])public void print(String s)public void print(Object obj)public void println()public void println(boolean x)public void println(char x)public void println(int x)public void println(long x)public void println(float x)public void println(double x)public void println(char x[])public void println(String x)public void println(Object x)

Klasa PrintStream je uglavnomnamijenjenadebagiranjuprograma. Inace jeneslužbenodeprecated u Javi1.1. i dalje. Umjestonje cete višekoristitiklasuPrintWriter .

Page 232: Java Predavanje I

Klasa PushbackInputStream

Klasa PushbackInputStream osiguravapushback spremnikpomocukojeg je moguce"poništiti" citanjebyteovasa streama. Kod sljedecegcitanjasa streamabit ce ucitanitiponišteni byteovi. public void unread(int b) throws IOExceptionpublic void unread(byte[] data, int offset, int length) throws IOExceptionpublic void unread(byte[] data) throws IOException

Po pretpostavci, spremnikimavelicinuod jednogbytea pa ce pokušaj poništavanjavišebyteovaizbacitiIOException . No velicinuspremnikamožetezadatiako uporabitedrugiod sljedecadva konstruktora. public PushbackInputStream (InputStream in)public PushbackInputStream (InputStream in, int size)

Iako i PushbackInputStream i BufferedInputStream koristespremnike, jedinoPushbackInputStream dopušta poništavanje, a jedinoBufferedInputStreamdopušta markiranjei resetiranje. Za streamovetipaPushbackInputStream metodamarkSupported () vraca false. public boolean markSupported ()

Metode read() i available() rade jednako kao s obicnimulaznimstreamovima,jedinošto najprijepokušavajucitatiizpushback spremnika. public int read() throws IOExceptionpublic int read(byte[] data, int offset, int length) throws IOExceptionpublic int available() throws IOException

Klasa File

Klasa java.io.File predstavljaeksterno imedatoteke na racunalu. Njome sepokušavajuapstrahiratidijeloviimenakoji su zavisnio racunalu, na primjerput, separatori slicno.

Dva su nacinareferenciranjadatoteka, relativnii apsolutni. Apsolutnoimenovanjedajepotpuniput do datoteke, pocevšiod imenadiska pa dalje. Detaljioviseo operacijskomsustavu. Na primjer:

Unix: "/math/vedris/file1"DOS: "C:\math\vedrisfile1"MacOS: "Macintosh HD:math:vedris:file1"

Page 233: Java Predavanje I

Sva ova tri stringareferencirajudatotekufile1 na glavnomdiskuu direktoriju/math/vedris/. Razlikujuse na primjerpo separatoru. Unixkoristi/, Dos i Windows\,MacOS :. Drugisustavimogukoristitinešto posve drugo.

Takoder, nemagarancijeda se glavnidisk na Macu zovebaš Macintosh HD ilidauopce postojidisk s timimenom. Na Unixu / i /math moggubitina razlicitimdiskovima, pa cak i na razlicitimmašinama. Zbog takvihrazlogaapsolutnaimenatrebauglavnomizbjegavati.

Relativnoimenovanjekoje treba koristitikad god je moguce, ne daje potpuniput dodatoteke. Umjestotoga daje put koji je relativanprema nekoj poznatojdatoteci. Relativniput možepokazivatidatotekuu istomdirektorijuu kojem se nalazipoznatadatotekajednostavnonavodenjemnjenogimena. Ilimožepokazivatina datotekuu poddirektorijupoznatogdirektorija.

Opcenitose jedan direktorijuzimaza radni i metodekoje tražedatoteke cinitce to uodnosuna taj direktorij. Uobicajenoje da to bude direktorijizkojeg zapocinjeteizvršavatiaplikaciju.

Objekt tipajava.io.File možebitiimedirektorijaistokao i imedatoteke.

Napomena za C programere

Primijetiteda objekt tipaFile nijeistošto i file handle. Postojanjetakvogobjekta nijeekvivalentnopostojanjustvarnedatoteke na disku. Postoje metodekojimamožeteutvrditida lidaniFile objekt zaistareferencirastvarnudatoteku iline (metodaexists()).

Konstruktori klase File

Trisu konstruktoraza klasuFile. Svakiuzimanekuvarijacijuimenadatoteke kaoargument. Najjednostavnijije public File(String path)

Ovdje je path naprostoString koji sadržipotpuniilirelativniput do datoteke, napisanna istinacinkao za operacijskisustavracunala. Na primjer: File f1 = new File("ulaz.txt");File f2 = new File("/etc/passwd");

Ako želite, možeteput do datoteke odvojitiod njenogimenakoristecisljedecikonstruktor: public File(String path, String name)

Ovdje je name imedatoteke, a path imedirektorijau kojem se ona nalazi. Na primjer: File f2 = new File("/etc", "passwd");

Page 234: Java Predavanje I

Na kraju, imamoi konstruktor public File(File dir, String name)

koji se ponaša kao i prethodni, alije dir ovdje objekt tipaFile, a ne naprostoString .

Neke metodeu drugimklasamatakoder vracajuobjekt tipaFile, na primjermetode izklasejava.awt.FileDialog . Takvice objektipoštovatisve konvencijeoperacijskogsustavana kojemse aplikacijaizvršava.

Metode klase File

Kad jednomimateobjekt tipaFile, postojimnogostvarikoje o njemumožetepitatiikoje s njimmožeteuciniti.

public String getName()

Elementarnopitanjeo datotecije ono o njenomimenu. Ime cete doznatipomocumetodegetName() koja ne uzimanikakveargumente, a vraca String koji sadržieksterno imedatoteke (bez puta). Na primjer, dobit cete "file1" umjesto"/math/vedris/file1".

public String getPath()

Metoda getPath() vraca a String koji sadržiput do datoteke. Bitce relativaniliapsolutan, ovisnoo nacinuna koji je daniobjekt bio kreiran.

public String getAbsolutePath ()

Metoda getAbsolutePath () vraca puni, apsolutniput do datoteke.

public String getCanonicalPath () throws IOException

Metoda getCanonicalPath () vraca kanonskuformuputa do datoteke. Ta je formazavisnao operacijskomsustavui mašini.

public String getParent()

Metoda getParent() vraca String koji sadržiimejedinstvenognadredenogdirektorijau odnosuna onaj u kojemse datoteka nalazi, ilinull ako je vec dosegnutvrhhijerarhije.

public boolean exists() throws SecurityException

Metoda exists() naznacujeda liodredena datoteka postojina mjestugdje jeocekujete.

public boolean canWrite() throws SecurityException

Page 235: Java Predavanje I

Metoda canWrite() daje odgovorda liimatepravo pisanjau datoteku. To nijelošeprovjeritiprijenegostvarnopokušatinešto upisati.

public boolean canRead() throws SecurityException

Metoda canRead() daje odgovorda liimatepravo citanjaizdatoteke. Dobro ju jekoristitiprijestvarnogpokušaja citanja.

public boolean isFile() throws SecurityException

Metoda isFile() odgovarana pitanjeda lise radi o datoteci(za razlikuod direktorija).

public boolean isDirectory() throws SecurityException

Metoda isDirectory() vraca true ako se radi o (postojecem) direktoriju.

public boolean isAbsolute()

Metoda isAbsolute() vraca true ako je dano imeapslolutniput, a false ako nije.

public long lastModified () throws SecurityException

Metoda lastModified () vraca vrijemezadnjepromjene. Kako je konverzijau pravidatumdugacka, a procedura ovisnao platformi, to treba koristitiuglavnomza usporedbuvremenazadnjepromjenedvajurazlicitihdatoteka.

public long length() throws SecurityException

Metoda length() daje velicinudatoteke u byteovima.

public boolean mkdir()

Metoda mkdir() pokušavakreiratidirektorijsa zadanimimenom. Ako uspije, vratitcetrue, inacefalse.

public boolean mkdirs() throws SecurityException

Metoda mkdirs() za dano imekreirane samo jedan, negosve potrebne nadredenedirektorijekoji cineput do datoteke. Ako sva kreiranjauspiju, vratitce se true, inacefalse (cak ako su neka kreiranjai uspjela).

public boolean renameTo(File destination) throws SecurityException

Metoda renameTo() pokušavapreimenovatidatoteku. Na primjer, f1.renameTo(f2)pokušavapreimenovatif1 u f2. To možeznacitii premiještanjeu drugidirektorijakoimenatako naznacuju. Ako f2 vec postoji, bit ce prebrisanasa f1 (pod uvjetomda imateodgovarajucedozvole). Ako preimenovanjeuspije, vraca se true, inacefalse.

public String[] list() throws SecurityException

Metoda list() vraca polje stringovakoji sadrže imenadatoteka u navedenomdirektoriju. Korisnaje za procesiranjesvihdatoteka unutardirektorijaodjednom.

Page 236: Java Predavanje I

public String[] list(FilenameFilter filter) throwsSecurityException

Ova varijantametodelist() ciniistošto i prethodna, alimožetekoristitiobjekt klasekoja implementirasuceljeFilenameFilter (pogledajtepoglavljeo tome) za filtriranjeimenadatoteka.

public boolean delete() throws SecurityException

Metoda delete() pokušavaizbrisatidatotekuna koju se odnosi. Vraca true ako jedatoteka postojalai sad je izbrisana, inacefalse.

Klasa File sadržii uobicajenemetodeequals(), hashCode() i toString() koje seponašajutocno onako kao što bisteocekivali. Ne sadržiposebnumetoduclone().

Primjeri metoda iz klase File

Sljedeciprogramcita imenadatoteka s komandnelinijei vraca razneinformacijeo njima,koristecimetode izklaseFile. import java.io.*; public class FileInfo { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { File f = new File(args[i]); if (f.exists()) { System.out.println("getName: " + f.getName()); System.out.println("getPath: " + f.getPath()); System.out.println("getAbsolutePath : " + f.getAbsolutePath()); try { System.out.println("getCanonicalPath : " + f.getCanonicalPath ()); } catch (IOException e) { } System.out.println("getParent: " + f.getParent()); if (f.canWrite()) System.out.println(f.getName() + " is writable."); if (f.canRead()) System.out.println(f.getName() + " is readable."); if (f.isFile()) { System.out.println(f.getName() + " is a file."); } else if (f.isDirectory()) { System.out.println(f.getName() + " is a directory."); } else {

Page 237: Java Predavanje I

System.out.println("What is this?"); } if (f.isAbsolute()) { System.out.println(f.getName() + " is an absolute path."); } else { System.out.println(f.getName() + " is not an absolute path."); } System.out.println("Last Modified" + f.lastModified ()); System.out.println(f.getName() + " is " + f.length() + " bytes."); } else { System.out.println("I'm sorry. I can't find the file " + args[i]); } } } } % javac FileInfo.java% java FileInfo "../html/TricksterApplet .html"getName: TricksterApplet .htmlgetPath: ../html/TricksterApplet .htmlgetAbsolutePath : /math/vedris/public_html/java/classes/../html/TricksterApplet .htmlgetCanonicalPath : /math/vedris/public_html/java/html/TricksterApplet .htmlgetParent: ../htmlTricksterApplet .html is writable.TricksterApplet .html is readable.TricksterApplet .html is a file.TricksterApplet .html is not an absolute path.Last Modified1005656988000TricksterApplet .html is 151 bytes.%

Klasa FileDialog

Klasa java.awt.FileDialog je podklasa od java.awt.Dialog koja se koristizaotvaranjeilispremanjedatoteka. Ona korististandardnedijalogeza open i save koji vecpostoje na racunalu. Ne dodajete joj komponentei ne brinetese o tomekako jeimplementiranainterakcijas korisnikom. Jednostavnodobijeterezultatkoji ce bitiimeidirektorijdatoteke. Buducida se appletine moguoslonitina to da imajudostup u filesystem, ova je klasa korisnauglavnomu aplikacijama.

Trisu koraka potrebna da bistekoristiliFileDialog :

Page 238: Java Predavanje I

1. KreiratinoviFileDialog2. UcinitiFileDialog vidljivim.3. Odabrati imedirektorijai imedatoteke.

Noviobjekt tipaFileDialog kreiratepomocukonstruktora: public FileDialog(Frame parent, String title, int mode)

OkvirFrame je roditeljdijaloga. To ce obicnobitiglavniprozor aplikacije, appletovokvirilinajistaknutijiprozor aplikacije. Takoder možetenaprostokreriratii noviFrame.Argumenttitle je naslovza naš FileDialog , obicnonešto kao "Please choose the fileto open:" Nadaljue, mode je jedna od dvijemnemonickihkonstanti, FileDialog.LOADiliFileDialog.SAVE. Prvucete koristitiako želiteda korisnikodabere datotekukoju ceotvoriti, a druguako želiteda odabere datotekuu koju ce spremitipodatke. Tipicanprimjerizgledaobi ovako: FileDialog fd = new FileDialog(new Frame(), "Please choose a file:", FileDialog.LOAD);

Konacno, ucinitcete FileDialog vidljivimna istinacinkao i drugekomponente.Proslijeditcete true njegovojmetodisetVisible() koju je naslijedioizklasejava.awt.Component .

fd.setVisible(true);

Odavde na daljeoperacijskisustavpreuzimakontrolunad interakcijoms korisnikomsvedok on ne odabere datoteku iliizadeizdijaloga. Vaš programce ovdje statii cekatidakorisnikodabere datoteku. Kad on to ucini, dijalogce nestatis ekrana i vaš programcese nastaviti. Tada cete ustanovitišto je korisnikodabrao, tako da pozovetemetodegetDirectory () i getFile(). Iskoristiteova dva stringada bistekreiralinoviobjekttipaFile. Ukratko,

FileDialog fd = new FileDialog(new Frame(), "Please choose a file:", FileDialog.LOAD);fd.show();if (fd.getFile() != null) { File f = new File(fd.getDirectory (), fd.getFile());}

Ako korisnikotkaže spremanje, obje metode, getDirectory () i getFile() vracajunull. Buditesigurnida ste provjerilitu mogucnost.

Klasa RandomAccessFile

Pomocuklasejava.io.RandomAccessFile pristupase datotekamakoje podržavajuslucajnipristup. One se mogucitatiilise u njihmožepisatipocevšiod odredene pozicijebytea u datoteci. Tu pozicijuspecificirapokazivacdatoteke (file pointer).

Dva su konstruktorau ovoj klasi:

Page 239: Java Predavanje I

public RandomAccessFile (String name, String mode) throws IOExceptionpublic RandomAccessFile (File file, String mode) throws IOException

Prviargumentje datoteka kojoj želitepristupiti. Drugije nacinpristupa. To možebitistring"r" za read-only ili"rw" za pristupkoji omogucujecitanjei pisanje. Java nepodržavawrite only pristup. Na primjer, RandomAccessFile raf = new RandomAccessFile ("ulaz.txt", "r");

Metode getFilePointer (), length(), i seek() omogucujuvamda utvrditeimodificiratepozicijuu datotecina kojoj se citanjei pisanjedogada. Pokušaj traženjapozicijeizakraja datoteke pomaknutce pointerna kraj. Pokušaj pisanjana kraj datotekeproširitce datoteku, a pokušaj citanjas kraja datoteke izbacitce EOFException . public native long getFilePointer () throws IOExceptionpublic native void seek(long pos) throws IOExceptionpublic native long length() throws IOException

Za citanjei pisanjekoristese metodekoje rade identicnokao i metode izDataInputStream i DataOutputStream , osimšto izmedupozivametodaza citanjeipisanjemožetezadatipozicijuod koje citateilipišete. public native int read() throws IOExceptionpublic int read(byte[] input, int offset, int length) throws IOExceptionpublic int read(byte[] input) throws IOExceptionpublic final void readFully(byte[] input) throws IOExceptionpublic final void readFully(byte[] input, int offset, int length) throws IOExceptionpublic native void write(int b) throws IOExceptionpublic void write(byte[] data) throws IOExceptionpublic void write(byte[] data, int offset, int length) throws IOExceptionpublic final boolean readBoolean() throws IOExceptionpublic final byte readByte() throws IOExceptionpublic final int readUnsignedByte () throws IOExceptionpublic final short readShort() throws IOExceptionpublic final int readUnsignedShort () throws IOExceptionpublic final char readChar() throws IOExceptionpublic final int readInt() throws IOExceptionpublic final long readLong() throws IOExceptionpublic final float readFloat() throws IOExceptionpublic final double readDouble() throws IOExceptionpublic final String readLine() throws IOExceptionpublic final String readUTF() throws IOException public final void writeBoolean (boolean b) throws IOExceptionpublic final void writeByte(int b) throws IOExceptionpublic final void writeShort(int s) throws IOExceptionpublic final void writeChar(int c) throws IOExceptionpublic final void writeInt(int i) throws IOExceptionpublic final void writeLong(long l) throws IOExceptionpublic final void writeFloat(float f) throws IOExceptionpublic final void writeDouble(double d) throws IOExceptionpublic final void writeBytes(String s) throws IOException

Page 240: Java Predavanje I

public final void writeChars(String s) throws IOExceptionpublic final void writeUTF(String s) throws IOException

Konacno, imajoš nekolikoraznihmetoda: public final FileDescriptor getFD() throws IOExceptionpublic int skipBytes(int n) throws IOExceptionpublic native void close() throws IOException

Sucelje FilenameFilter

Suceljejava.io.FilenameFilter deklarirasljedecumetodu:

public boolean accept(File directory, String filename)

Ona treba vracatitrue ako datoteka prolazikroz filtar, false inace.

Buducida je FilenameFilter sucelje, moratega implementiratiu nekoj klasi. Ovdje jeprimjerklase koja filtrirasve što nijejava source datoteka. import java.io.*; public class JavaFilter implements FilenameFilter { public boolean accept(File directory, String filename) { if (filename.endsWith(".java")) return true; return false; } } import java.io.*;public class JavaFilterTest { public static void main (String args[]) { JavaFilter jf = new JavaFilter(); File dir = new File("args[0]"); String file = args[1]; if (jf.accept(dir, file)) System.out.println("OK - Java source datoteka"); else System.out.println("Nije Java source datoteka"); } } % javac JavaFilter.java% javac JavaFilterTest .java% java JavaFilterTest "." "JavaFilter.java"

Page 241: Java Predavanje I

OK Java source datoteka% java JavaFilterTest "." "JavaFilter.class"Nije Java source datoteka%

Ime ne mora bitijedinikriterijfiltriranja. Možete testiratidatumzadnjepromjene, dozvole,velicinui drugo. Na primjer, sljedecaaccept() metoda testirada lidatoteka završavaekstenzijom.java i da lije u direktorijuza koji imatedozvolupisanja. public boolean accept(File directory, String filename) { if (filename.endsWith(".java") && directory.canWrite()) return true; return false; }

Klase Reader i Writer

Klase java.io.Reader i java.io.Writer su apstraktnenadklaseklasamakojeobavljajucitanjei pisanjepodataka zasnovanihna znakovima(characters). Znacajnesuza konvertiranjeznakovaizmedurazlicitihznakovnihsustava(character sets).

Ulaznii izlaznistreamovisu opcenitozasnovanina byteovima, no klaseReader i Writersu zasnovanina znakovimakoji moguimatirazlicitevelicine, ovisnoo sustavuznakova.Na primjerASCII i ISO Latin-1 koristeznakovevelicinejedan byte. Unicodekoristiznakoveod dva bytea. UTF-8 koristiznakovevarijabilneduljine, od jednogdo tribytea.Reader i Writer znajukako rukovatitimznakovnimsustavimakao i mnogimdrugim.

Klasa Reader

Metode izklasejava.io.Reader namjernosu napravljenetako da buduslicnemetodamaizklasejava.io.InputStream . Medutim, umjestoda rade s byteovima,one rade sa znakovima(char).

Osnovnaread() metodacitapojedinacniznak(koji možezauzimatiod jednogdo cetiribytea, ovisnoo znakovnomsustavu) i vraca ga kao intizmedu0 i 65535. Ako naidenakraj strama, vraca -1.

public int read() throws IOException

Možete ucitatii višeznakovaodjednomu polje znakova. Metode koje to rade vracajubroj uspješnoucitanihznakovaili-1 ako naiduna kraj streama. public int read(char[] text) throws IOExceptionpublic abstract int read(char[] text, int offset, int length) throws IOException

Page 242: Java Predavanje I

Sve read() metodeblokirajuse ako nijedostupannekiinput, ako se pojaviI/O error iliako naiduna kraj streama.

Možete preskocitiodredenibroj znakovapomocumetodeskip(). Ona ce se takoderblokiratiako nemadostupnoginputa. Vraca broj preskocenihznakovaili-1 ako je naišlana kraj streama.

public long skip(long n) throws IOException

Metoda ready() vraca true ako je Reader spremanza citanje, false inace. Opcenitoce to bitiako pripadnistreamimadostupnihpodataka. public boolean ready() throws IOException

Reader možeiline mora podržavatimarkiranjei resetiranje. Metoda markSupported ()vraca true ako pripadnistreampodržavamarkiranjei resetiranje, false inace. public boolean markSupported ()public void mark(int readAheadLimit ) throws IOExceptionpublic void reset() throws IOException

Konacno, metodaclose() zatvarastreami otpušta resursekoji su s njimpovezani. public abstract void close() throws IOException

Klasa Writer

Metode izklasejava.io.Writer namjernosu napravljenetako da buduslicnemetodamaizjava.io.OutputStream . Medutim, umjestoda rade s byteovima, onerade sa znakovima(char).

Osnovnawrite() metoda ispisujepojedinacniznakod dva bytea s vrijednošcuizmedu0 i 65535. Vrijednostse uzimaizdva nižabytea argumentac (preostaladva višabytea seignoriraju). Podklase koje želeefikasnopisatiznakovemoratce prekritiovumetodu.

public void write(int c) throws IOException

Možete takoder ispisatipolje znakova, podpolje znakova, stringilisubstring. public void write(char[] text) throws IOExceptionpublic abstract void write(char[] text, int offset, int length) throws IOExceptionpublic void write(String s) throws IOExceptionpublic void write(String s, int offset, int length) throws IOException

Kao sviizlaznistreamovi, i ovice moždabitibufferiranina razinioperacijskogsustava.Ako želitesamiodreditikad ce se ispisizvršiti, pozovitemetoduflush(). public abstract void flush() throws IOException

Page 243: Java Predavanje I

Konacno, metodaclose() zatvarastreami otpušta resursekoji su s njimpovezani. public abstract void close() throws IOException

Klasa InputStreamReader

Klasa java.io.InputStreamReader služikao most izmedustreamovabyteovaistreamovaznakova. Cita byteoves ulaznogstreamai prevodiihu znakoveu skladusazadanimznakovnimsustavom.

Znakovnisustav(encoding) možese zadatiu konstruktoruilise možeprihvatitidefaultsustavs racunala.

public InputStreamReader (InputStream in)public InputStreamReader (InputStream in, String encoding) throws UnsupportedEncodingException

Na primjer, da bisteprikljuciliInputStreamReader na System.in sa pretpostavljenimznakovnimsustavom(najcešceISO Latin-1), stavilibiste: InputStreamReader isr = new InputStreamReader (System.in);

S drugestrane, ako želitecitatidatotekukoja je bilanapisanau fontuMacintoshSymbol,možeteto ucinitiovako: FileInputStream fis = new FileInputStream ("symbol.txt");InputStreamReader isr = new InputStreamReader (fis, "MacSymbol");

Metoda getEncoding() vraca stringkoji sadržiimeznakovnogsustavakoji se trenutnokoristi. public String getEncoding()

Ostale metodeprekrivajumetode izjava.io.Reader , alise, izprogrameroveperspektive, ponašajuna istinacinkao i one.

public int read() throws IOExceptionpublic int read(char c[], int off, int length) throws IOExceptionpublic boolean ready() throws IOExceptionpublic void close() throws IOException

Klasa OutputStreamWriter

Klasa java.io.OutputStreamWriter povezujeizlaznebyte streamovei znakovnestreamove. Ispisujebyteovena pripadniizlaznistreamnakonprevodenjaznakovauskladusa zadanimznakovnimsustavom.

Page 244: Java Predavanje I

Znakovnisustavmožese zadatiu konstruktoruilise možeprihvatitidefault sustavsaplatforme.

public OutputStreamWriter (OutputStream out, String enc) throws UnsupportedEncodingExceptionpublic OutputStreamWriter (OutputStream out)

Na primjer, da bisteprikljuciliOutputStreamWriter na System.out sapretpostavljenimznakovnimsustavom(najcešceISO Latin-1), stavilibiste: OutputStreamWriter osw = new OutputStreamWriter (System.out);

S drugestrane, ako želitepisatiu datotekuu MacintoshSymbolfontu, možeteto ucinitiovako: FileOutputStream fos = new FileOutputStream ("symbol.txt");OutputStreamWriter osw = new OutputStreamWriter (fos, "MacSymbol");

Metoda getEncoding()vraca stringkoji sadržiimeznakovnogsustavakoji se trenutnokoristi. public String getEncoding()

Ostale metodeprekrivajumetode izjava.io.Writer , alise, izprogrameroveperspektive, ponašajuna istinacinkao i one.

public void write(int c) throws IOExceptionpublic void write(char c[], int offset, int length) throws IOExceptionpublic void write(String s, int offset, int length) throws IOExceptionpublic void flush() throws IOExceptionpublic void close() throws IOException

Dostupne kodne stranice

Page 245: Java Predavanje I
Page 246: Java Predavanje I

Ime Znakovnisustav

8859_3ISO 8859-3 (LatinExtended-B) Pinyin, Sami, Croatian, and a fewothers

8859_4 ISO 8859-4 (LatinExtended-C)

8859_5 ISO 8859-5 Latin/Cyrillic

8859_6 ISO 8859-6 Latin/Arabic

8859_7 ISO 8859-7 Latin/Greek

8859_8 ISO 8859-8 Latin/Hebrew

8859_9 ISO 8859-9 Latin/Turkish

Big5 The Big5 encodingfor Chinese

CNS11643 Chinese

Cp037 EBCDIC AmericanEnglish

Cp273 IBM273

Cp277 EBCDIC Danish/Norwegian

Cp278 EBCDIC Finnish/Swedish

Cp280 EBCDIC Italian

Cp284 EBCDIC Spanish

Cp285 EBCDIC UK English

Cp297 EBCDIC French

Cp420 EBCDIC Arabic1

Cp424 EBCDIC Hebrew

Cp437the originalDOS IBM PC characterset, essentiallyASCII withafew extra charactersfor drawinglinesand boxes

Cp500 EBCDIC Flemish/Romulsch

Cp737 DOS Greek

Cp775 DOS Baltic

Cp850 DOS Latin-1

Cp852 DOS Latin-2

Cp855 DOS Cyrillic

Cp856 IBM856

Cp857 DOS Turkish

Cp860 DOS Portuguese

Cp861 DOS Icelandic

Cp862 DOS Hebrew

Cp863 DOS CanadianFrench

Cp864 DOS Arabic

Cp865 IBM865

Cp866 IBM866

Cp868 EBCDIC Arabic

Cp869 DOS modernGreek

Page 247: Java Predavanje I

Cp870 EBCDIC Serbian

Cp871 EBCDIC Icelandic

Cp874 WindowsThai

Cp875 IBM875

Cp918 EBCDIC Arabic2

Cp921 IBM921

Cp922 IBM922

Cp1006 IBM1006

Cp1025 IBM1025

Cp1026 IBM1026

Cp1046 IBM1046

Cp1097 IBM1097

Cp1098 IBM1098

Cp1112 IBM1112

Cp1122 IBM1122

Cp1123 IBM1123

Cp1124 IBM1124

Cp1250 WindowsEasternEuropean(essentiallyISO Latin-2)

Cp1251 WindowsCyrillic

Cp1252 WindowsWesternEuropean(essentiallyISO-Latin-1)

Cp1253 WindowsGreek

Cp1254 WindowsTurkish

Cp1255 WindowsHebrew

Cp1256 WindowsArabic

Cp1257 WindowsBaltic

Cp1258 WindowsVietnamese

EUCJIS Japanese EUC

GB2312 Chinese

JIS Japanese Hiragana

JIS0208 Japanese

KSC5601 Korean

MacArabic The MacintoshArabiccharacterset

MacCentralEuropeThe MacintoshCentralEuropeancharacterset

MacCroatian The MacintoshCroatiancharacterset

MacCyrillic The MacintoshCyrilliccharacterset

MacDingbat ZapfDingbats

MacGreek The MacintoshmodernGreek characterset

MacHebrew The MacintoshHebrew characterset

MacIceland The MacintoshIcelandiccharacterset

MacRoman The MacintoshRomancharacterset

Page 248: Java Predavanje I

MacRomania The MacintoshRomaniancharacterset

MacSymbolThe Symbolfont(includesa completeGreek alphabetinplace of theusualRomanletters)

MacThai The MacintoshThaicharacterset

MacTurkish The MacintoshTurkishcharacterset

MacUkraine The MacintoshUkrainiancharacterset

SJIS WindowsJapanese

UTF8 UCS TransformationFormat, 8-bit form

Unicode NormalUnicode

UnicodeBig Unicodewithbig-endianbyte order

Primijetiteda to što Java znaraditis odredenimznakovnimsustavomjoš ne znacida naracunaluautomatskipostoje fontovikoji su potrebnida bi se znakoviiztog sustavaprikazali.

Klasa FileWriter

Klasa java.io.FileWriter služiza pisanjetekstualnihdatoteka koristecipretpostavljeniznakovnisustavi velicinuspremnikas platforme. Ako želitepromijenititevrijednosti, konstruirajteOutputStreamWriter i prikljucitega na FileOutputStream .Ova klasa nemavlastitihmetoda(samo naslijedene), a deklariranisu samo konstruktori. public FileWriter(String fileName) throws IOExceptionpublic FileWriter(String fileName, boolean append) throws IOExceptionpublic FileWriter(File file) throws IOExceptionpublic FileWriter(FileDescriptor fd)

Pogledajmoprimjer: FileWriter fw = new FileWriter("izlaz.txt");

Klasa FileReader

Thejava.io.FileReader služiza citanjetekstualnihkoristecipretpostavljeniznakovnisustavi velicinuspremnikas platforme. Ako želitepromijenitite vrijednosti, konstruirajteInputStreamReader i prikljucitega na FileInputStream . Ova klasa nemavlastitihmetoda(samo naslijedene), a deklariranisu samo konstruktori. public FileReader(String fileName) throws FileNotFoundExceptionpublic FileReader(File file) throws FileNotFoundExceptionpublic FileReader(FileDescriptor fd)

Pogledajmoprimjer:

Page 249: Java Predavanje I

FileReader fr = new FileReader("36.html");

Klasa BufferedReader

Klasa java.io.BufferedReader je podklasa od java.io.Reader koju možeteulancitis drugomReader klasomzbogbufferiranjaznakova. To omoucujeefikasnijecitanjeznakovai linija.

Klasa BufferedReader takoder je znacajnai zbogsvojereadLine() metodekojaomogucujecitanjeteksta linijupo liniju.

Kod svakogcitanjas nebufferiranogReadera, obavljase i odgovarajucecitanjespridruženogulaznogstreama. Zato nijeloša idejaprikljucitiBufferedReader na svakiReader cije su operacijecitanjaskupe, kao npr. za FileReader . Na primjer,

BufferedReader br = new BufferedReader (new FileReader("ulaz.txt"));

Dva su konstruktora, jedan sa pretpostavljenomvelicinomspremnikaod 8192 znaka,dok drugidozvoljavaspecificiranjevelicinespremnika:

public BufferedReader (Reader in, int sz)public BufferedReader (Reader in)

Jedinanovametodau toj klasije readLine():

public String readLine() throws IOException

Ona vraca String koji sadržilinijuteksta iztekstualnedatoteke. Nizovi\r, \n, i \r\nsu pretpostaljeniznakoviza prijelazu noviredak i nisuukljuceniu vraceniString . Usljedecemprimjerucita se tekstualnadatoteka, redak po redak i ispisujese naSystem.out:

// Implement the Unix cat utility in Java import java.io.*; class cat { public static void main (String args[]) { String thisLine; //Loop across the arguments for (int i=0; i < args.length; i++) { //Open the file for reading try { BufferedReader br = new BufferedReader (new FileReader(args[i])); while ((thisLine = br.readLine()) != null) { // while loop begins here System.out.println(thisLine);

Page 250: Java Predavanje I

} // end while } // end try catch (IOException e) { System.err.println("Error: " + e); } } // end for } // end main } % javac cat.java% java cat "../html/TricksterApplet .html" "../html/GridBagCalculator .html"<APPLET CODE="TricksterApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" ARCHIVE="Trickster.jar"WIDTH=1 HEIGHT=1></APPLET><APPLET CODE="GridBagCalculatorApplet .class" CODEBASE="http://student.math.hr/~vedris/java/classes" ARCHIVE="GridBagCalculator .jar" WIDTH=1 HEIGHT=1></APPLET>%

Klasa BufferedReader dopušta markiranjei resetiranje, barem do duljinespremnika.

public boolean markSupported ()public void mark(int readAheadLimit ) throws IOExceptionpublic void reset() throws IOException

Konacno, BufferedReader prekrivanekolikometoda izsvoje nadklaseReader , alisenacinnjihoveuporabe uopce ne mijenja.

public int read() throws IOExceptionpublic int read(char c[], int off, int length) throws IOExceptionpublic long skip(long n) throws IOExceptionpublic boolean ready() throws IOExceptionpublic void close() throws IOException

Klasa LineNumberReader

Klasa java.io.LineNumberReader je podklasa od java.io.BufferedReader kojavodiracunao tomes koje linijetrenutacnocitate. Ima sve metodekao iBufferedReader ukljucjujcii readLine(). Ima dva konstruktorai dvijenovemetode,getLineNumber () i setLineNumber ():

public LineNumberReader (Reader in)public LineNumberReader (Reader in, int size) public void setLineNumber (int lineNumber)public int getLineNumber ()

Page 251: Java Predavanje I

Metoda setLineNumber () ne mijenjafilepointer. Ona samo mijenjavrijednostkojuvraca getLineNumber (). To vam, na primjer, omogucujeda pocnete brojitiod -5 akoznateda imašest linijaheadera za koje ne želiteda udu u numeraciju.

U sljedecemprimjerucita se tekstualnadatoteka, redak po redak i ispisujese naSystem.out no ispredsvake linijeispisujese njenbroj:

import java.io.*; class linecat { public static void main (String args[]) { String thisLine; //Loop across the arguments for (int i=0; i < args.length; i++) { //Open the file for reading try { LineNumberReader br = new LineNumberReader (new FileReader(args[i])); while ((thisLine = br.readLine()) != null) { // while loop begins here System.out.println(br.getLineNumber () + ": " + thisLine); } // end while } // end try catch (IOException e) { System.err.println("Error: " + e); } } // end for } // end main } % javac linecat.java% java linecat "../html/TricksterApplet .html" "../html/GridBagCalculator .html"1: <APPLET CODE="TricksterApplet .class" 2: CODEBASE="http://student.math.hr/~vedris/java/classes" 3: ARCHIVE="Trickster.jar"4: WIDTH=1 HEIGHT=1>5: </APPLET>1: <APPLET CODE="GridBagCalculatorApplet .class" 2: CODEBASE="http://student.math.hr/~vedris/java/classes" 3: ARCHIVE="GridBagCalculator .jar" 4: WIDTH=1 HEIGHT=1>5: </APPLET>%

Klasa BufferedWriter

Page 252: Java Predavanje I

Klasa java.io.BufferedWriter je podklasa od java.io.Writer koju možeteulancitis drugomWriter klasomzbogbufferiranjaznakova. To omogucujeefikasnijeispisivanjeteksta.

Svakiput kad pišetena nebufferiraniWriter , obavljase i pisanjena pridruženiizlaznistream. Zato nijeloša idejaprikljucitiBufferedWriter na svakiWriter cijeoperacijepisanjasu skupe, a ne traže trenutacniodziv. Pogledajmotaj postupak npr. zaFileWriter :

BufferedWriter bw = new BufferedWriter (new FileWriter("izlaz.txt"));

Thereare two constructors, one witha defaultbuffersizeof 8192 characters, and onethat letsyouspecifythe buffersize: public BufferedWriter (Writer out)public BufferedWriter (Writer out, int size)

U ovoj klasinova je metodanewLine() koja ispisujestringza završetaklinije. On jeovisano platformipa tako imamo\n za Unix, \r za Mac, \r\n za Windows. public String newLine() throws IOException

Konacno, BufferedWriter prekrivanekolikometoda izsvoje nadklaseWriter; alinacinnjihoveuporabe ostaje isti: public void write(int c) throws IOExceptionpublic void write(char c[], int off, int length) throws IOExceptionpublic void write(String s, int offset, int length) throws IOExceptionpublic void flush() throws IOExceptionpublic void close() throws IOException

Klasa PrintWriter

Klasa java.io.PrintWriter je podklasa od java.io.Writer koja omogucujekorištenjepoznatihmetodaprint() i println(). Vrloje slicnaklasijava.io.PrintStream . Glavnarazlikaje u pravilnomrukovanjuvišestrukimbyteovimai znakovnimsustavimakoji nisuISO Latin-1. Drugarazlikaje u tome što se automatskiispis(flushing) obavljatek kad se pozoveneka od println() metoda, a ne svakiputkad se pojaviznakza noviredak.

Tendencijaproizvodacaje izbacitiizuporabe PrintStream i umjestonjegakoristitiPrintWriter , no to bi dovelodo pucanjavelikekolicinevec postojecegkoda.

public PrintWriter(Writer out)public PrintWriter(Writer out, boolean autoFlush)public PrintWriter(OutputStream out)public PrintWriter(OutputStream out, boolean autoFlush) public void flush()

Page 253: Java Predavanje I

public void close()public boolean checkError()protected void setError() public void write(int c)public void write(char buf[], int offset, int length)public void write(char buf[])public void write(String s,public void write(String s) public void print(boolean b)public void print(char c)public void print(int i)public void print(long l)public void print(float f)public void print(double d)public void print(char s[])public void print(String s)public void print(Object obj) public void println()public void println(boolean x)public void println(char x)public void println(int x)public void println(long x)public void println(float x)public void println(double x)public void println(char x[])public void println(String x)public void println(Object x)

Page 254: Java Predavanje I

Jedanaesto predavanje -threadoviMultitasking i multithreading što je thread? - kako Java koristi threadove ? klasethreadova jednostavni thread višestruki threadovi imenovanje threadovaprioriteti threadova metoda sleep() sinkronizacija : problem sinkronizacija :nekoliko pokušaja rješenja - kljucna rijec synchronized sinkroziniranje naobjektima primarni thread grupe threadova threadovi demoni ustupanjekontrole spajanje threadova sucelje Runnable animacija pravovremenosttitranje slike pokretanje i zaustavljanje animacije višestruke nezavisne animacije

Multitasking i multithreading

Prvikompjuterimoglisu obavljatizadace samo jednupo jednu. Svisu se programiizvršavalisekvencijalno, jedan po jedan i svakije zauzimaosve resurseracunala. Takavse nacinrada nazivabatch obrada. To je efikasannacinza postizanjemaksimalneiskoristivostiskupihracunalajer se gotovosve CPU vrijemetrošina stvarnuobradu.Medutim, batch obrada je nepovoljnaako programikoji trajunekolikosekundimorajucekatina završetakprogramaod nekolikodana.

Time sharing operacijskisustavisu izmišljenikako bi se omoguciloda višeljudiistodobnokoristijedno racunalo. Operacijskisustavovdje upravljaraspodjelomvremenaizmedurazlicitihprogramakoji se istodobnoizvršavaju.

Jednomkad su sustaviomogucavalirazlicitimkorisnicimaistodobnoizvršavanjeprograma, preostao je još samo malikorak do toga da istikorisnikizvršavaistodobnovišeprograma(multitasking). Svakiaktivniprogram, uobicajenoje reci proces, imaojesvoj vlastitimemorijskiprostor, svoj skup varijabli, svoj stack i heap i tako dalje. Jedanprocess je mogaolansiratidrugiprocess, alinakon toga svakiod njihse ponašao manjeilivišenezavisno. Mehanizmikao što je pozivudaljenihprocedura (remote procedure call,RPC) razvijenisu kako bi omoguciliprocesimamedusobnuinterakciju, alitakva jeinterakcijabilaskupa i komplicirana. Takvo stanjepotrajaloje nekihdvadesetakgodina.

Medutim, nisusamo korisniciti koji imajupotrebu obavljativišeposlovaistodobno.Mnogiprogramipo svojoj su priroditakoder takvi. Web browser na primjer, možeispisivatidatotekuu pozadinidok istodobnoskida stranicuu jednomprozorui formatiraje kako sadržajpristiže. Sposobnost individualnogprogramada radi višeod jedne stvariistodobnonajefikasnijese implementirakroz koncept threadova(multithreading).

Što je thread?

Page 255: Java Predavanje I

Thread (u prijevodu: nit, konac, trag, staza) možemodefiniratikao tok izvodenjaoperacijakoji se dogada nezavisnood procesa ilidogadaja u okolini. Threadje poputklasicnogprogramakoji zapocinjeu tockiA i završavau tockiB. On nemau sebi petljukoja ocekuje dogadaje vec se izvršavane gledajucišto se dogada oko njega. Bezthreadovacijelibi programpovremenomorao stajatizbognekogprocesa koji intenzivnokoristiCPU ilizbogneke beskonacnepetlje, stavljeneu njeganamjernoilipogreškom.Koncept threadovaomogucujeda zahtjevniprocesine ometajuostaleprocese unjihovomizvršavanju.

Pokazujese da je implementiranjethreadovasloženijeod implementiranjamultitaskingauoperacijskomsustavu. Razlogrelativnojednostavnomimplementiranjumultitaskingaje štosu programiu praviluizoliranijedniod drugih. Threadoviu jednomprogramu, medutim,nisumedusobnoizoliranii morajuvoditiracunajedan o drugome. Na primjer, ako zavrijemedok se u jednomthreaduispisujenekitekst, orisniku drugomthreaduobrišediotog istogteksta, nastajeproblem: što u tom slucajutreba bitiispisano?

Okruženjakoja, poput Jave, podržavajuthreadoveimajumehanizamsinkronizacije.Threadovimaje, naime, omogucenoprivremenozakljucavanjeresursakoje dijelesdrugimthreadovima, cimese osiguravaintegritetpodataka. Sinkronizaciju, medutim, valjakoristitis mjeromjer ce prednostikoje donose threadovibitiponišteneako cijelisustavbude cesto morao cekatidok se pojediniresursne otkljuca. Pravilniodabir objekata imetodakoje treba sinkroniziratipripada vještiniprogramiranjai osjecaj za njegastjece sevježbom.

Kako Java koristi threadove?

Java aplikacijei appletisu po prirodithreadovski. Runtime okolinazapocinjeizvršavanjeprogramasa main() metodomunutarjednogthreada. Garbage collection se obavljaudrugomthreadu. Screen updating se pojavljujeu trecemthreadu. Moguse takoderpojavljivatii drugithreadovi, uglavnomvezaniuzzadace koje obavljaappletvieweriliweb browser. Sve se to dogada bez eksplicitnogznanjaprogramera. Diovremenazanimatce vas samo ono što se dogada u primarnomthreadukoji sadržimain() metoduprograma. Tada se ne moratenioptrerecivatikonceptomthreadova.

Ponekad, medutim, želitedodati svoje vlastitethreadovenekomappletuiliaplikaciji.Najjednostavnijirazlogza to bio bi, na primjer, izdvojitidugaracunanjaod ostatkaprograma. Ako želitepronacidesetmilijuntiprimbroj, ne želiteprisiljavatikorisnikadaceka besposlendok racunaloobavljato traženje. Isto vrijedii za cekanje da nekiresurspostane dostupan, recimovelikagrafickadatoteka koju skidates mreže. Svakavremenskizahtjevnaoperacijatrebalabi bitismještenau zasebnithread.

Drugirazlogza korištenjethreadovaje ravnomjernaraspodjelamogucnostiracunalaizmedurazlicitihzadaca. Ako želiteiscrtavatislucajnepravokutnikena ekranu, svejednoželiteostavitikorisnikumogucnostda komuniciras appletom. Ako se sav CPU trošinacrtanje, to nece bitimoguce. Na natjecateljskim(preemptive) operacijskimsustavimakao što je SolarisiliWindowsNT, korisnikmožeu slucajupotrebe, ako ništadrugo,prekinutiaplikaciju. Na kooperativnim(cooperative) sustavimakao što je MacOs ili

Page 256: Java Predavanje I

Windows, to nece bitimoguceako se ne ucinireboot mašine, a to je, naravno, loše.Uporabomthreadovaomogucitcete da korisnickiunosdobije visokprioritet, a crtanjeslicicanizak. Tada ce korisnikmocizaustavitiapplet i bez gašenjaracunalana glavnomprekidacu.

Klase threadova

U Javipostoje dva nacinada klasupretvorimou thread. Jedan je da je ucinimopodklasomklasejava.lang.Thread . Ako je naša klasa vec podklasa neke drugeklase, onda to, naravno, nece bitimoguce, pa cemo koristitidruginacin, a to jeimplementiranjesuceljajava.lang.Runnable .

Klasa Thread imatriglavnemetodekoje se koristeza upravljanjethreadovima:

public native synchronized void start()public void run()public final void stop()

Metoda start() pripremathread za izvršavanje. Metoda run() je ta koja obavljazadacunamijenjenuthreadu. Threadse normalnozavršavakad ona završi. Threadsemožezaustavitii pomocumetodestop(), alise taj nacinpokazao nesigurnimi zbog togaje ova metodadeprecated (v. objašnjenjau bibliotecipotprograma). Zbog istograzlogadeprecated su i metodesuspend() i resume().

Metoda run() se ne pozivaeksplicitno. Ona ce, nakonšto ste pozvalimetodustart()bitiautomatskipozvanakad za to dode vrijeme.

SuceljeRunnable omogucujeuporabukoncepta threadovau klasamakoje ne mogubitipodklase klaseThread . Ono deklarirasamo jednumetodu, run():

public abstract void run()

Ako za argumentkonstruktoraThread() supstituirateobjekt izklase koja implementiraRunnable , mocicete njegovurun() metodukoristitiumjestorun() metode izklaseThread.

Jednostavni thread

Kad pišeteprogramkoji sadržithreadove, možetezamišljatida pišetevišerazlicitihprogramaod kojihsvakiimasvojurun() metodu. Pogledajmoslucajkad je svakitakavthread podklasa od java.lang.Thread . Sljedeciprogramje thread koji ispisujebrojeve iod-10 do 9.

public class BytePrinter extends Thread { public void run() { System.out.println("pocinjem!");

Page 257: Java Predavanje I

for (int b = -10; b < 10; b++) { System.out.println(b); } System.out.println("gotovo!"); } }

Threadcete lansiratitako da ga proizvedeteinstanciranjemodgovarajuceklase, a zatimpozovetenjegovustart() metodu. Na primjer, da bismoinstanciraliklasuBytePrinter , postupitcemo ovako: BytePrinter bp = new BytePrinter();

Ova klasa imasamo pretpostavljenikonstruktorbez argumenata, alinemanikakvograzlogada klase threadovanemajui drugacijekonstruktore, baš kao i bilokoje drugeklase.

Sad možetepozvatinjegovu start() metodu:

bp.start();

Jednomkad je start() metodapozvana, izvršavanjeprogeramase dijelina dva dijela.Jedan dio CPU vremenakoristise za naredbe koje dolazeizabp.start(), a drugidioza izvršavanjethreadabp. Ne možese unaprijedpredvidjetikoje ce naredbe bitiizvršeneprve. Najvjerojatnijeje da ce bitipomiješane. Threadbp ce se nastavitiizvršavatisvedok ne nastupijedan od sljedecihsedam uvjeta:

bp-ova run() metoda je završila.bp-ova stop() metoda je pozvana.bp-ova suspend() metoda je pozvana.bp-ova sleep() metoda je pozvana.bp-ova yield() metoda je pozvana.bp je blokiranjer ceka nedostupniresursbp je istisnut(preempted) od nekogdrugogthreada.

Jednomkad programskakontroladosegnekraj bp-ove run() metode, thread se gasi.Ne možetega ponovopokrenuti, alimožetekreiratinovuinstancuodgovarajuceklase injupokrenuti.

Višestruki threadovi

Sljedeciprogramlansiratri threada tipaBytePrinter : public class ThreadsTest { public static void main(String args[]) { BytePrinter bp1 = new BytePrinter(); BytePrinter bp2 = new BytePrinter(); BytePrinter bp3 = new BytePrinter(); bp1.start();

Page 258: Java Predavanje I

bp2.start(); bp3.start(); } }

Redosljedispisakoje proizvodiovaj programovisio implementacijii uglavnomjenepredvidljiv. Može izgledatiotprilikeovako: % javac BytePrinter.java% javac ThreadsTest.java% java ThreadsTestpocinjem!-10. . . -4pocinjem!pocinjem!-10-10-9. . . 9gotovo!3. . . 9gotovo!-3-2. . . 9gotovo!%

Imenovanje threadova

Cesto je korisnodati razlicitimthreadovimaisteklase imenapo kojimaihmožeterazlikovati. SljedecikonstruktorklaseThread vamto omogucuje: public Thread(String name)

Uobicajenoga je pozvatiizkonstruktorapodklase s kojom radimo, kao što je ucinjenousljedecemprimjeru: public class NamedBytePrinter extends Thread { public NamedBytePrinter (String name) { super(name); } public void run() { System.out.println(this.getName() + ": pocinjem!");

Page 259: Java Predavanje I

for (int b = -10; b < 10; b++) { System.out.println(this.getName() + ": " + b); } System.out.println(this.getName() + ": gotovo!"); } }

Metoda getName() izklaseThread vratitce imethreada. Sljedeciprogramomogucujerazlikovanjeispisanihredaka prema threadovimakoji su ihproizveli. public class NamedThreadsTest { public static void main(String[] args) { NamedBytePrinter frank = new NamedBytePrinter ("Frank"); NamedBytePrinter mary = new NamedBytePrinter ("Mary"); NamedBytePrinter chris = new NamedBytePrinter ("Chris"); frank.start(); mary.start(); chris.start(); } } % javac NamedBytePrinter .java% javac NamedThreadsTest .java% java NamedThreadsTestFrank: pocinjem!Frank: -10. . . Frank: -4Mary: pocinjem!Chris: pocinjem!Mary: -10. . . Mary: 9Mary: gotovo!Chris: 3. . . Chris: gotovo!Frank: -3. . . Frank: 9Frank: gotovo!%

Prioriteti threadova

Nisusvithreadovijednako važni. Ponekad je potrebno nekomthreadudodijelitiviševremenanegodrugom. Threadovikoji komunicirajus korisnikomtrebajuimativrlovisok

Page 260: Java Predavanje I

prioritet. S drugestrane, threadovimakoji obavljajuracunanjau pozadinitreba dodijelitinizakprioritet.

Prioritetthreadazadaje se cijelimbrojemizmedu1 i 10. Deset je najvišiprioritet, jedan jenajniži. Normalniprioritetje pet. Threadovis višimprioritetomdobit ce višeCPUvremena.

Napomena: primijetiteda je ovo izravnosuprotnonacinuna koji se prioritetidefinirajuuUNIXu, gdje vecibroj oznacavamanjiprioritet.

Zbog udobnosti, klasaThread definiratrimnemonickekonstante, Thread.MAX_PRIORITY , Thread.MIN_PRIORITY i Thread.NORM_PRIORITY koje možetekoristitiumjestonumerickihvrijednosti.

PrioritetthreadazadajetepomocumetodesetPriority():

setPriority(int newPriority)

Sljedeciprogramdodjeljujethreadovimafrank, mary i chris razliciteprioritete. Iako jechris pokrenutzadnji, vjerojatnoce bitigotovprvi, buducida muje dodijeljennajvišiprioritet.

public class MixedPriorityTest { public static void main(String args[]) { NamedBytePrinter frank = new NamedBytePrinter ("Frank"); NamedBytePrinter mary = new NamedBytePrinter ("Mary"); NamedBytePrinter chris = new NamedBytePrinter ("Chris"); frank.setPriority(Thread.MIN_PRIORITY); mary.setPriority(Thread.NORM_PRIORITY); chris.setPriority(Thread.MAX_PRIORITY); frank.start(); mary.start(); chris.start(); } } % javac MixedPriorityTest .java% java MixedPriorityTestChris: pocinjem!Chris: -10. . . Chris: 9Chris: gotovo!Mary: pocinjem!Mary: -10. . . Mary: 9Mary: gotovo!Frank: pocinjem!Frank: -10. . .

Page 261: Java Predavanje I

Frank: 9Frank: gotovo!%

Metoda sleep()

Ponekad je brzinaizvršvanjaveca negošto želite. U tom slucajubit ce potrebno usporitiizvršavanjepojedinihthreadova. To se radi pomocumetodesleep():

public static void sleep(long millis) throws InterruptedException

Ovdje je millis broj milisekundikoji treba proci prijenego thread nastavisizvršavanjem. Metoda sleep() možeodbacitijava.lang.InterruptedExceptionkoju je potrebno uhvatitipa pozivove metodemora bitiunutartry-catch bloka. Naprimjer, ako želimoodgoditiizvršavanjeza jednusekundu, stavilibismo:

try { Thread.sleep(1000); } catch (InterruptedException e) { }

Sinkronizacija: problem

Do sad smo promatralithreadovekoji se izvršavajunezavisnojedan od drugoga. Nijedan thread nijemorao znatišto rade ostali. Ponekad, medutim, threadovimorajudijelitipodatke. U tom slucajuvažnje osiguratida jedan thread ne promijenipodatke u vrijemedok ihdrugithread koristi. Klasicniprimjerje pristupdatoteci. Ako jedan thread piše udatotekuu vrijemedok je drugithread cita, vjerojatnoje da ce ovaj drugithread dobitinekonzistentnepodatke. Promotrimo, na primjer, sljedeciproblem: public class Counter { int i = 0; public void count() { int limit = i + 100; while (i++ != limit) System.out.println(i); } } public class CounterThread extends Thread { Counter c; public CounterThread (Counter c) { this.c = c; }

Page 262: Java Predavanje I

public void run() { c.count(); } public static void main(String[] args) { Counter c = new Counter(); CounterThread ct1 = new CounterThread (c); CounterThread ct2 = new CounterThread (c); ct1.start(); ct2.start(); } }

Programce se ponašatiposve nedeterministicki. Nema pravilapo kojemubismomoglipredvidjetikakav ce bitiizlaz.

% javac Counter.java% javac CounterThread .java% java CounterThread. . . ? ? ? . . .%

Sinkronizacija: nekoliko pokušajarješenja

Kljucnije problemu prethodnomprogramušto dva threadamodificirajuattributeistogobjekta. Pri tome, redosljedmodificiranjaje neodreden.

Postojivišemogucihrješenjaovogproblema. Nisu, medutim, sva rješenjadobra u svimsituacijama. Na primjer, jedno od najjednostavnijihi najizravnijihje ucinitiobjektnepromjenjivim(immutable), dakle ne dozvolitida se mijenjanakonšto je jednomkonstruiran. Nepromjenjivostmožeteposticitako da sve attributeproglasiteza private ,klasune snabdijetenikakvomsetter metodomi ne dozvoliteni jednojmetodiizklase(osimkonstruktorima) da mijenjajuvrijednostiatributa. Medutim, takvo rješenjejeneprikladnoza naš problemjer metodacount() mora mijenjatiatributi.

Slicnustvarmožeteucinititako da attributedeklariratekao final. Na taj nacinonise nemogumijenjatinakonšto je objekt konstruiran. No to je takoder neprikladno.

U našemprimjerubilobi jednostavnoucinitivarijablui lokalnomumjestoda bude atribut:

public class Counter { public void count() { int i = 0; int limit = 100; while (i++ != limit) System.out.println(i); }

Page 263: Java Predavanje I

}

Timešto smoi ucinililokalnomvarijablom, svakithread koji pozivametoducount() natom objektudobit ce svojuvlastituvarijablui. Svakiput kad se metodapozove, zasebnistack se konstruiraza njenevarijablei argumente. Razlicitipozivimetodene dijelevarijable.

Medutim, semantikaprogramavišenijeista. Sada svakithread brojiod 0 do 100. Ako jeto bilanamjera, rješenjeje dobro, aliako smo htjelida prvithread brojiod 0 do 100, adrugiod 101 do 200, rješenjene valja.

Ponešto opcenitijerješenjekoje kombiniraprethodnadva bilobi kopirativrijednostatributau lokalnuvarijablu, a zatimmijenjatisamo nju, ostavljajuciatributnepromijenjenunutarmetode. Na primjer: public class Counter { int i = 0; public void count() { int i = this.i; int limit = i + 100; while (i++ != limit) System.out.println(i); } }

Primijetitekako sada lokalnavarijablai prekrivaatributi, na koji se referiramopomocukljucnerijecithis.

Ovaj trik je uglavnomkoristankad ne trebate vratitipromijenjenuvrijednostvarijablenatragu atributnakonšto je metodazavršila. Sljedecavarijantasacuvatce stanje, alijejoš uvijekpodložnanekim, manjeociglednim, sinkronizacijskimproblemima:

public class Counter { int i = 0; public void count() { int i = this.i; int limit = i + 100; while (i++ != limit) System.out.println(i); this.i = i; } }

Ovo je, u stvari, još gore negooriginalniprimjerjer ce u 99% slucajevaraditidobro iproblemce bitigotovonemoguceuocitiako ga se ne primijetiu izvornomkodu.

Page 264: Java Predavanje I

Kljucna rijec synchronized

Java vamomogucujeda pod odredenimuvjetimamožetegarantiratida neka metodaneceistodobnobitipozvanaod višethreadova. Ostalithreadovimoratce cekatidok prvithread ne završi. U meduvremenuonistoje blokirani.

Ovo se postižeprimjenomkljucnerijecisynchronized na promatranumetodu:

public class SychronizedCounter extends Counter { public synchronized void count() { int limit = i + 100; while (i++ != limit) System.out.println(i); } }

Medutim, sinkronizacijaimasvoje nedostatke. Ona bitnosmanjujepreformanse.Opcenito, sinkroniziranemetodesu trido deset puta sporijeod ekvivalentnihnesinkroniziranih. Sinkronizacijatakoder ne otklanjaautomatskisve pogreške kojeproizlazeizthreadovskognacinaizvršavanja.

Sinkroniziranje na objektima

Svakomobjektudodijeljenje tzv. monitor. Kad kljucnurijecsynchronized primjenitena nekumetodu, dobijetemonitorodredenogobjekta, odnosnozakljucavatega. Dokgod jedan thread posjedujemonitor, odnosnolokot nekogobjekta, ni jedan drugithreadne možedobititaj lokot. (Drugithreadovice, eventualnomocidobitilokotedrugihobjekata izisteklase).

Kad koristitekljucnurijecsynchronized kako bistespecificiralida je neka metodasinkronizirana, zakljucavateodredeniobjekt kojemuta metodapripada. (Statickemetodemogutakoder bitisinkronizirane. U tom slucajulokot se stavljana objekt izklasejava.lang.Class koji je pridruženklasivašegobjekta.) Kako postojisamo jedanlokot za svakiobjekt, nijesamo sinkroniziranametoda ta koju ne mogupozvatiostalithreadoviistodobno. Takoder se to odnosina ostale inkroniziranemetode iliblokovekoda u tom objektu.

Sinkroniziratimožetei na nižimrazinamanegošto je razinametode. Na primjer, sljedeciprogramiamobi problemaako bi drugithread promijeniovrijednostod i ilithis.i uvrijemedok se obavljapridruživanje.

public class Counter { int i = 0; public void count() { int i = this.i; int limit = i + 100;

Page 265: Java Predavanje I

while (i++ != limit) System.out.println(i); this.i = i; } }

To se možeispravititako da sinkroniziratelinijekoda koje referencirajutaj atribut: public void count() { synchronized (this) { int i = this.i; } int limit = i + 100; while (i++ != limit) System.out.println(i); synchronized (this) { this.i = i; } }

U ovomprimjerusinkroniziralismo sam objekt, tj. this. Možete takoder sinkroniziratiidrugeobjekte. Na primjer, sljedecastatickametodakoristijednostavnibubblesort zasortiranjepolja cijelihbrojeva. Sinkroniziratcemo to polje da bismobilisigurnida gadrugithreadovinece diratidok ga sortiramo. public static void bubbleSort(int[] n) { boolean sorted = false; synchronized (n) { while (!sorted) { sorted = true; for (int i=0; i < n.length - 1; i++) { if (n[i] > n[i+1]) { int temp = n[i]; n[i] = n[i+1]; n[i+1] = temp; sorted = false; } // end if } // end for } // end while } // end synchronized } // end sort

Ovdje se ne brineteo tomeda se this objekt moždane promijeniod stranedrugogthreada. Na kraju, metoda je staticka. Brinetese o tomeda drugithreadovine promijenepoljedok ga sortirate.

Takoder primijetiteda u pravilune znateništao tome što se dogada u programuizvanvaše metode. Možda ce bitisamo jedan thread koji želipristuppolju, a moždace ihbitimnogo. Da litreba iline treba sinkroniziratimetodukao što je ova, ovisio tomegdje cese ona koristiti. Ako pišetemetode i klase opce namjenekoje ce se koristitiu mnogimrazlicitimprogramima, moratepretpostavitida ce razlicitithreadovipozivatimetoduistodobno.

Page 266: Java Predavanje I

Polja možetesinkroniziratijer su to objekti. Ne možetesinkroniziratiprimitivnetipovepodataka kao što su int, float, ilichar.

Stringovemožetesinkroniziratijer su objekti, alije to nepotrebnojer su onii takonepromjenjivi. (Stringne možetepromijeniti, možetesamo napravitinovi.)

Primarni thread

U pravilu, prilikomizvršavanjaJava programaaktivnasu bar tri threada. Najprije, tu jeglavnithread unutarkojeg se vaš programizvršava. To je thread koji ukljucujemain()metodukoja je pokrenulavašuaplikaciju. U appletu, to ce bitithread unutarkojeg sulansiraniappletvieweriliweb browser.

Zatim, tu je garbage collector, thread koji za programomcistimemorijui obavljaraznefinalizacije. Taj thread u praviluimaniskiprioritet.

U programimakoji koristeAWT aktivanje još jedan thread koji se brineo ažuriranjuekrana i otprilike100 puta u sekundiprovjeravatreba linešto bitiobnovljeno(repainted).

Konacno, tu su svithreadovikoje eksplicitnopokrene vaš program. U svako dobaprogramradi u nekomthreadui nikadne izlaziizsustavathreadova. Možete ustanovitikoji thread se trenutnoizvršavapomocustatickemetodecurrentThread ():

public static Thread currentThread ()

Na primjer, sljedeciprogramispisujeimeprimarnogthreada izvršavanja: public class PrimaryThread { public static void main(String[] args) { System.out.println(Thread.currentThread ()); } } % javac PrimaryThread .java% java PrimaryThreadThread[main,5,main]%

MetoducurrentThread () koristiteda bistedobilireferencuna trenutacnoaktivnithread i njimemanipulirali.

Grupe threadova

Page 267: Java Predavanje I

Threadovisu organiziraniu grupe. Grupa threadovaje jednostavnokolekcijapovezanihthreadova. Na primjer, izsigurnosnihrazlogasvithreadovikoje lansiranekiappletsmještajuse u jednugrupu. Appletuje dozvoljenomanipuliratithreadovimaizsvojegrupe, aline i onimaizdrugihgrupa. Na taj nacinappletmože, na primjer, iskljucitisistemskigarbage collector, a da pri tomene smetaostalimprogramima.

Grupe threadovaorganiziranesu u hijerarhijuroditelj-djeca.

Sljedeciprogramispisujesve aktivnethreadove. Uz pomoc metodagetThreadGroup ()izklasejava.lang.Thread i getParent() izjava.lang.ThreadGroup popet ce sedo najvišegrupethreadova, a zatimpomocuactiveCount() ustanovitikolikothreadovaimau grupite pomocumetodeenumerate() ispisatisve threadoveizglavnegrupei njenedjece (što ovdje pokrivasve grupethreadova, inacepostoji i rekurzivnavarijantametodeenumerate()).

public class AllThreads { public static void main(String[] args) { ThreadGroup top = Thread.currentThread ().getThreadGroup (); while(true) { if (top.getParent() != null) top = top.getParent(); else break; } Thread[] theThreads = new Thread[top.activeCount()]; top.enumerate(theThreads); for (int i = 0; i < theThreads.length; i++) { System.out.println(theThreads[i]); } } }

Popis threadovase mijenjai ovisanje o sustavu, no možeizgledatina primjerovako: % javac AllThreads.java% java AllThreadsThread[Reference Handler,10,system]Thread[Finalizer,8,system]Thread[Signal Dispatcher,10,system]Thread[main,5,main]%

Threadovi demoni

Threadovikoji rade u pozadinikao podrška runtime okruženjunazivajuse demoni(daemon threads). Na primjer, clock handler, idle, garbage collector, screen updatersu demoni. thatwork inthe backgroundto support the runtimeenvironmentare calleddaemon threads. Virtualnamašinase zaustavljakad su svinon-demonthreadovizavršili.

Page 268: Java Predavanje I

Po pretpostavci, threadovikoje kreiratenisudemoni. Ako želiteda onito postanu,poslužitcete se metodomsetDaemon(true). Da bisteustanovilije linekithread demonilinije, pozovitemetoduisDaemon(). public final void setDaemon(boolean isDaemon) public final boolean isDaemon()

Ustupanje kontrole

Buducida u pravilune možetepredvidjetida lice vaš programraditiu kooperativnomilinatjecateljskom(preemptive) okruženju, treba omogucitida threadovikoji intenzivnokoristeCPU s vremenana vrijemeprepustekontroluostalimthreadovima. Cetirisusituacijeu kojimace thread prepustitikontrolu:

ako je blokiran.Ako je ustupiokontrolupomocumetodeyield().Ako je uspavanpomocumetodesleep().Ako je suspendiran(to izbjegavajte: metodesuspend() i resume() sudepricated).

Blokiranjenastajeako thread mora cekatida se neka operacijazavrši. Obicnosu to I/Ooperacije, posebno one koje ukljucujupristuppreko mreže. Moguceje blokiranjei zbogcekanja na korisnikovunos. Obicno je dobro stavitiI/O operacijeu odvojenethreadovevisokogprioritetajer ce racunalona taj nacinbitiefikasnijeiskorišteno. Ostalithreadovikoji intenzivnokoristeCPU obavitce mnogoposla dok cekaju na podatke koji trebajudoci preko mrežeiliod korisnikakoji treba nešto utipkati.

Kad aktivnithread pozovemetoduyield(), on ce se privremenozaustavitii ustupitikontroludrugimthreadovima. Virtualnamašinace potražitiimalithreadovaistogilivišegprioritetakoji cekaju i ako ima, dodijelitce kontrolusljedecemu redu. Ako nema,kontrolace se vratitithreadukoji ju je prepustio. Znacida yield() samo signaliziraspremnostza prepuštanjekontrolei ne garantirada ce thread zaistabitizaustavljen. Toovisiu potpunostio drugimthreadovima.

Ako thread bezuvjetnoželipredatikontroluna neko vrijeme, bez obzirada lidrugithreadovicekaju iline, on možepozvatimetodusleep(). Ona ce ga uspavatinaodredeno vrijemetijekomkojega drugithreadoviimajuprilikuza izvršavanje.

public static void sleep(long milliseconds ) throws InterruptedExceptionpublic static void sleep(long milliseconds , int nanoseconds) throws InterruptedException

Konacno, thread možebitisuspendiranna neodredenovrijeme. On sam, a još cešce nekidrugithread, možepozvatimetodususpend() koja ce izazvatizaustavljanjethreadasvedok ga nekidrugithread ne aktivirapozivanjemmetoderesume(). Medutim, kao štosmo vec rekli, ove dvijemetodesu se pokazalenesigurminai zato su sada deprecatedkao i metodastop() pa ih, dakle, nemojtenikoristiti.

Page 269: Java Predavanje I

Spajanje threadova

Spajanje threadovaznacida jedan thread ceka dok drugine završi. Za to postoje trioverloaded join() metodekoje blokirajuthread koji ihje pozvao, tako dugodok sethread cijajoin() metoda je pozvanane ugasi. public final void join() throws InterruptedException public final void join(long milliseconds ) throws InterruptedException public final void join(long milliseconds , int nanoseconds) throws InterruptedException

Na primjerthread koji pozovet.join() cekat ce da se threadt završipa tek ondanastaviti. Ako pozovet.join(1000) cekat ce bar jednusekundudok se threadt nezavršii tada ce nastaviti.

Spajanje threadovakorisnoje u situacijamakad threadoviovisejedan o drugom. Naprimjer, možese cekatina ucitavanjepodataka izdatoteke ilina ucitavanjeslikes mreže.

Sucelje Runnable

Do sada su svithreadovis kojimasmo radilibilipodklase od java.lang.Thread .Ponekad, medutim, želiteda se kao threadoviponašajui klase koje su vec podklasedrugihklasa. Tipicanprimjerje kad želiteda se appletponaša kao thread. U takvimslucajevimaimplementiratcete u vašoj klasisuceljejava.lang.Runnable . Onodeklarirajednujedinumetodu, run().

public void run()

Tu cete metoduimplementiratiistokao što biste to ucinilida je vaša klasa podklasa odThread, samo cete još deklariratida implementiratesuceljeRunnable . public class MyThreadedClass extends SomeClass implements Runnable { . . . public void run() { . . . } }

Sad cete prvo kreirativaš Runnable objekt, a zatimnoviobjekt tipaThread tako dakao argumentkonstruktorudate vaš objekt. Nakon toga možetepozvatistart()metoduizklaseThread: MyThreadedClass mtc = new MyThreadedClass ();

Page 270: Java Predavanje I

Thread t = new Thread(mtc);t.start();

Animacija

Animacijaje jedna od glavnihprimjenasuceljaRunnable . Da bistepokrenuliobjekte uJavi, kreiratethread koji racunasukcesivneframeove na ekranui pozivametodurepaint() za obnovuslike. Možete takoder postavitii beskonacnupetljuu vašupaint() metodu, alito nijedobro, osobitona non-preemptivesustavimakao što je Mac. Totakoder ne osiguravadobru pravovremenost(timing).

Pocnimosa jednostavnomanimacijomodbijanjacrveneloptice(prikazanekao krug) odunutrašnjihrubovakutije(prikazanekao pravokutnik). Njene koordinatebit cespremljeneu atributur koji je tipajava.awt.Rectangle . Metoda paint() gledatcetaj pravokutniki iscrtatimuupisanikrug.

Appletovarun() metodamjestoje gdje se akcijazapravodogada. Ovdje ce sepovecavatikoordinatelopticei provjeravatida lise ona primaklarubuvidljivogpodrucja.Ako jest, odgovarajucakoordinatace se smanjivati.

import java.awt.*;import java.applet.*; public class Bounce extends Applet implements Runnable { Rectangle r; int deltaX = 1; int deltaY = 1; public void init () { r = new Rectangle( 37, 17, 20, 20); Thread t = new Thread(this); t.start(); } public void paint (Graphics g) { g.setColor(Color.red); g.fillOval(r.x, r.y, r.width, r.height); } public void run() { while (true) { // infinite loop r.x += deltaX; r.y += deltaY; if (r.x >= getSize().width - 20 || r.x < 0) deltaX *= -1; if (r.y >= getSize().height 20 || r.y < 0) deltaY *= -1; this.repaint(); } }

Page 271: Java Predavanje I

} <APPLET CODE="Bounce.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Pravovremenost

Prava animacijamora osiguratimehanizampravovremenosti. Animacijakoju smo upravonapravilibit ce na nekimsustavimaprebrza, a nanekimamoždai prespora. Potrebno je na nekinacinreguliratitu brzinu.

Filmskistandard je 24 framea u sekundi. Filmovisetom brzinomi snimaju, a kod projekcijene želimodabrzinaprojektora utjecena brzinuizmjeneframeova,

pogotovoako razlicitiprojektoriimajurazlicitebrzine. To je, inace, razlog, zašto starinijemifilmoviizgledajuneprirodnobrzo. Oni su snimanibrzinomod 15 frameovausekundi, dok današnjiprojektorirade sa 24 frameau sekundi. Televizijskaslikaseobnavljabrzinomod 30 frameovau sekundina više.

Iako ne možeteubrzatianimacijuiznadmogucnostivirtualnemašine, možeteje usporitikoristecimetodusleep(). Sljedeciappletogranicavabrzinukretanjalopticena 50pixela(vertikalnoi horizontalno) u sekundi.

import java.awt.*;import java.applet.*;import java.util.*; public class SleepyBounce extends Applet implements Runnable { Rectangle r; int deltaX = 1; int deltaY = 1; int speed = 50; public void init () { r = new Rectangle(37, 17, 20, 20); Thread t = new Thread(this); t.start(); } public void paint (Graphics g) { g.setColor(Color.red); g.fillOval(r.x, r.y, r.width, r.height); }

Page 272: Java Predavanje I

public void run() { while (true) { // infinite loop long t1 = (new Date()).getTime(); r.x += deltaX; r.y += deltaY; if (r.x >= getSize().width - 20 || r.x < 0) deltaX *= -1; if (r.y >= getSize().height - 20 || r.y < 0) deltaY *= -1; this.repaint(); long t2 = (new Date()).getTime(); long sleepTime = speed - (t2 - t1); if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (InterruptedException ie) { } } } } } <APPLET CODE="SleepyBounce .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Titranje slike

Možda ste primijetilititranjeslikekod izvršavanjaovog appleta. To je uobicajeniproblemanimacijskihappleta. Nastaje zbognesinkroniziranostiobnavljanjaslikena fizickomekranui obnavljanjaslikekoje diktiraapplet. Kad to dvoje nijeu skladu, nastajetitranje.

Dva su nacinana koje možeteriješititaj problem. Najjednostavnijerješenjeje definiranjetzv. clipping podrucja. To je pravokutnikunutarkojeg možetecrtati, a izvannjeganemožete. Definiranjemclipping podrucja omedujeteprostor u koji možetecrtati. To znacida ništaizvantog podrucja nece titrati. Titranjeje ogranicenosamo na to podrucje.Nadalje, malapovršinase možebrzo iscrtatipa je i vjerojatnosttitranjamanja.

Da bistedefiniraliclipping pravokutnik, pozvatcete metodug.clipRect(Rect r)

unutarvaše paint(). Ovaj applet je upravoi pogodanza to jer vec imagotovpravokutnikkoji treba biticlipping. Pogledajmosada revidiraniapplet:

import java.awt.*;import java.applet.*;import java.util.*; public class ClipBounce extends Applet implements Runnable {

Page 273: Java Predavanje I

Rectangle r; int deltaX = 1; int deltaY = 1; int speed = 50; public void init () { r = new Rectangle(37, 17, 20, 20); Thread t = new Thread(this); t.start(); } public void paint (Graphics g) { g.setColor(Color.red); g.clipRect(r.x, r.y, r.width, r.height); g.fillOval(r.x, r.y, r.width, r.height); } public void run() { while (true) { // infinite loop long t1 = (new Date()).getTime(); r.x += deltaX; r.y += deltaY; if (r.x >= getSize().width - 20 || r.x < 0) deltaX *= -1; if (r.y >= getSize().height - 20 || r.y < 0) deltaY *= -1; this.repaint(); long t2 = (new Date()).getTime(); long sleepTime = speed - (t2 - t1); if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (InterruptedException ie) { } } } } } <APPLET CODE="ClipBounce.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Drugii obicnoefikasnijinacinizbjegavanjatitranjasastojise u korištenjutehniketzv.offscreen slikai update() metode. Pregazitelitu metodu, možeteobavitisve crtanjenaoffscreen sliku, tj. objekt tipaImage, a zatimkopiratigotoviobjekt na ekran. Kopiranjeslikeodvijase punobrže i glatkijenego iscrtavanjepojedinihelemenatana ekran pa utom slucajunemavidljivogtitranja.

Page 274: Java Predavanje I

Recept je jednostavan. Kopirajtesljedeciblok koda u svoj programi titranjece nestati.Dodaliste triprivate atributai publicmetoduupdate().

private Image offScreenImage ; private Dimension offScreenSize ; private Graphics offScreenGraphics ; public final synchronized void update (Graphics g) { Dimension d = this.getSize(); if((this.offScreenImage == null) || (d.width != this.offScreenSize .width) || (d.height != this.offScreenSize .height)) { this.offScreenImage = this.createImage(d.width, d.height); this.offScreenSize = d; this.offScreenGraphics = this.offScreenImage .getGraphics(); } this.offScreenGraphics .clearRect(0, 0, d.width, d.height); this.paint(this.offScreenGraphics ); g.drawImage(this.offScreenImage , 0, 0, null); }

Imatcemo, dakle:

import java.awt.*;import java.applet.*;import java.util.*; public class FlickBounce extends Applet implements Runnable { Rectangle r; int deltaX = 1; int deltaY = 1; int speed = 50; private Image offScreenImage ; private Dimension offScreenSize ; private Graphics offScreenGraphics ; public final synchronized void update (Graphics g) { Dimension d = this.getSize(); if((this.offScreenImage == null) || (d.width != this.offScreenSize .width) || (d.height != this.offScreenSize .height)) { this.offScreenImage = this.createImage(d.width, d.height); this.offScreenSize = d; this.offScreenGraphics = this.offScreenImage .getGraphics(); } this.offScreenGraphics .clearRect(0, 0, d.width, d.height); this.paint(this.offScreenGraphics ); g.drawImage(this.offScreenImage , 0, 0, null); }

Page 275: Java Predavanje I

public void init () { r = new Rectangle(37, 17, 20, 20); Thread t = new Thread(this); t.start(); } public void paint (Graphics g) { g.setColor(Color.red); g.fillOval(r.x, r.y, r.width, r.height); } public void run() { while (true) { // infinite loop long t1 = (new Date()).getTime(); r.x += deltaX; r.y += deltaY; if (r.x >= getSize().width - 20 || r.x < 0) deltaX *= -1; if (r.y >= getSize().height - 20 || r.y < 0) deltaY *= -1; this.repaint(); long t2 = (new Date()).getTime(); long sleepTime = speed - (t2 - t1); if (sleepTime > 0) { try { Thread.sleep(sleepTime); } catch (InterruptedException ie) { } } } } } <APPLET CODE="FlickBounce.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Pokretanje i zaustavljanje animacije

Ponekad je dobro je dati korisnikumogucnostda zaustavithread koji se izvršava. Sajednostavnimanimacijamakao što je ova iznašegprimjera, uobicajenoje da se animacijazaustavljai pokrece klikanjemmiša.

Da bismoto implementirali, dodat cemo booleovskiatributbouncing koji ce bititrueako i samo ako se thread izvršava. Zatimcemo dodatiMouseListener metodukojazaustavljathread ako je pokrenuti pokrece ga ako je zaustavljen. Primijetiteda smo se

Page 276: Java Predavanje I

ovdje ipak koristilideprecated metodamasuspend() i resume(). Pokušajtepreraditiovaj applet tako da ihizbjegnete!

import java.awt.*;import java.awt.event.*;import java.applet.*;import java.util.*; public class StartStopBounce extends Applet implements Runnable,MouseListener { Rectangle r; int deltaX = 1; int deltaY = 1; int speed = 50; boolean bouncing = false; Thread bounce; public void init () { r = new Rectangle(37, 17, 20, 20); addMouseListener (this); bounce = new Thread(this); } public void start() { bounce.start(); bouncing = true; } //kod za reduciranje titranja private Image offScreenImage ; private Dimension offScreenSize ; private Graphics offScreenGraphics ; public final synchronized void update (Graphics g) { Dimension d = this.getSize(); if((this.offScreenImage == null) || (d.width !=this.offScreenSize .width) || (d.height != this.offScreenSize .height)) { this.offScreenImage = this.createImage(d.width, d.height); this.offScreenSize = d; this.offScreenGraphics = this.offScreenImage .getGraphics(); } offScreenGraphics .clearRect(0, 0, d.width, d.height); this.paint(this.offScreenGraphics ); g.drawImage(this.offScreenImage , 0, 0, null);//kraj koda za reduciranje titranja } public void paint (Graphics g) { g.setColor(Color.red); g.fillOval(r.x, r.y, r.width, r.height); }

Page 277: Java Predavanje I

public void run() { while (true) { // infinite loop long t1 = (new Date()).getTime(); r.x += deltaX; r.y += deltaY; if (r.x >= getSize().width - 20 || r.x < 0) deltaX *= -1; if (r.y >= getSize().height - 20 || r.y < 0) deltaY *= -1; this.repaint(); long t2 = (new Date()).getTime(); try { Thread.sleep(speed - (t2 - t1)); } catch (InterruptedException ie) { } } } public void mouseClicked (MouseEvent e) { if (bouncing) { bounce.suspend(); bouncing = false; } else { bounce.resume(); bouncing = true; } } public void mousePressed (MouseEvent e) {} public void mouseReleased (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited(MouseEvent e) {} } <APPLET CODE="StartStopBounce .class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Višestruke nezavisne animacije

Ponekad imasmislapokrenutivišeanimacijaistodobno.U tom slucaju, applet ce implementiratisuceljeRunnable , a klase animiranihobjekata bit ce podklaseod Thread . Sljedeciprogramdemonstrirato pomocuappletau kojemse dvijelopticenezavisnoodbijajuodrubova.

Page 278: Java Predavanje I

import java.awt.*;import java.applet.*; public class TwoBall extends Applet implements Runnable { Ball b1, b2; Thread t; //kod za reduciranje titranja private Image offScreenImage ; private Dimension offScreenSize ; private Graphics offScreenGraphics ; public final synchronized void update (Graphics g) { Dimension d = this.getSize(); if((this.offScreenImage == null) || (d.width != this.offScreenSize .width) || (d.height != this.offScreenSize .height)) { this.offScreenImage = this.createImage(d.width, d.height); this.offScreenSize = d; this.offScreenGraphics = this.offScreenImage .getGraphics(); } this.offScreenGraphics .clearRect(0, 0, d.width, d.height); this.paint(this.offScreenGraphics ); g.drawImage(this.offScreenImage , 0, 0, null); }//kraj koda za reduciranje titranja public void init () { b1 = new Ball(10, 32, getSize()); b1.start(); b2 = new Ball(155, 75, getSize()); b2.start(); t = new Thread(this); t.start(); } public void paint (Graphics g) { g.setColor(Color.red); g.fillOval(b1.getX(), b1.getY(), b1.getWidth(), b1.getHeight()); g.fillOval(b2.getX(), b2.getY(), b2.getWidth(), b2.getHeight()); } public void run() { Thread.currentThread ().setPriority(Thread.MIN_PRIORITY); while (true) { // infinite loop this.repaint();

Page 279: Java Predavanje I

try { Thread.sleep(10); } catch (InterruptedException e) { } } } } class Ball extends Thread { private Rectangle r; private int deltaX = 1; private int deltaY = 1; private Dimension bounds; public Ball(int x, int y, Dimension d) { r = new Rectangle(x, y, 20, 20); bounds = d; } public int getX() { return r.x; } public int getY() { return r.y; } public int getHeight() { return r.height; } public int getWidth() { return r.width; } public void run() { Thread.currentThread ().setPriority(Thread.MIN_PRIORITY); while (true) { // infinite loop r.x += deltaX; r.y += deltaY; if (r.x + r.width >= bounds.width || r.x < 0) { deltaX *= -1; } if (r.y + r.height >= bounds.height || r.y < 0) { deltaY *= -1; } try { Thread.sleep(30); } catch (InterruptedException e) { }

Page 280: Java Predavanje I

} } } <APPLET CODE="TwoBall.class"CODEBASE="http://student.math.hr/~vedris/java/classes"WIDTH=200 HEIGHT=100></APPLET>

Page 281: Java Predavanje I

u pripremi

Dvanaesto predavanje mrežnoprogramiranjePortovi protokoli internet adrese kreiranje InetAddress objekata parsiranjeInetAddress objekata URL -

Portovi

U pravilu(koje imamnogoiznimaka) svako racunaloimasamo jednuInternetadresu.Medutim, svako racunalocesto treba komuniciratis višeod jednogracunalaistodobno.Na primjer, u istovrijememožese odvijatinekolikoftp sesija, nekolikoweb konekcija,chat i tako dalje.

Da bi se to omogucilo, mrežnosuceljeracunalapodijeljenoje na 65536 ulaza, takozvanihportova. Port je apstrakcija. To nijenikakvifizickiulazkao što su serijskiiliparalelniportovina osobnimracunalima. No podaci putujuInternetomu paketima, pri cemusvakipaket nosine samo adresu hosta nego i broj porta na koji treba stici. Host ce na osnovispecificiranogporta odreditikojemprogramuje namijenjendoticnipaket podataka.

Ako želite, IP adresu možetezamišljatikao ulicnuadresu, a portove kao brojeve stanovau kucama. Routerikoji transportirajupakete brinuse samo o ulicnojadresi , dakle necitajubroj porta. To je prepuštenolokalnomracunalu.

Na Unixupotrebne su vamroot privilegijeza osluškivanjekonekcijana portovimaod 0do 1023. Konekcijena portovimaod 1024 do 65535 možeosluškivatisvatko, dok gododredeniport nijezauzet(na istomportu ne moževišeod jednogprogramaistodobnoosluškivatikonekcije). Na operacijskimsustavimaWindowsNT, Windows95 i Mac bilokoji korisnikmožebez posebnihprivilegijaosluškivatibilokoji port.

Bilokoji udaljenihost možeostvaritikonekcijuna poslužiteljkoji osluškujenekiportispod 1024. Nadalje, višestrukesimultanekonekcijemoguse ostvaritina udaljenihost iudaljeniport. Na primjer, web poslužiteljkoji osluškuje(u pravilu) na portu 80 možeistovremenoobradivatidesetke konekcijaistodobno, sve usmjerenena port 80.

Ukratko, samo jedan process na lokalnomhostumožekoristitinekiport. Naprotiv,mnogoudaljenihhostovamožeostvarivatikonekcijena jedan te isti(udaljeni) port.

Mnogiservisirade na tzv. opcepoznatim(well-known), portovima. To znacida protokolispecificirajuda nekiservismožeilimora koristitiodredeniport. Na primjer, httpposlužiteljiobicnoosluškujuna portu 80, SMTP poslužiteljina portu 25, Echo poslužitelji

Page 282: Java Predavanje I

na portu 7, a Discardposlužiteljina portu 9. Nemajusviservisiopcepoznateportove. NaprimjerNFS dozvoljavada se portoviotkrivajuu vrijemeizvršavanja.

Protokoli

Neformalnogovoreci, protocoldefinirakakodva hosta medusobnokomuniciraju. U radiokomunikaciji, na primjer, protokolispecificirajuda po završetkuporuke treba reci overili kraj . Kod racunalnihmrežaprotokoldefinirašto jest, a što nijeprihvatljivoza jednogilidrugogsudionikakomunikacijeu odredenomvremenskomtrenutku.

Na primjer, daytime protokol, specificiranu RFC 867, kaže da se klijentpovezujesposlužiteljemna portu 13. Poslužiteljtada kaže klijentutocno vrijemeu formatukoji je zacovjeka citljiv, a nakon toga prekida konekciju.

S drugestrane, time protokol, specificiranu RFC 868, propisujebinarnureprezentacijuvremenakoja je citljivaza racunala.

Daytime i time šaljuistuinformaciju. Medutim, onikoristerazliciteformatei razliciteprotokoleda bi je poslali.

Postojionolikorazlicitihvrstaprotokolakolikoimaservisakoji se njimakoriste.Lockstep protokolitraže jedan odgovorza svakiupit. Neki protokolikao što je FTPkoristevišestrukekonekcija. Vecinakoristisamo jednu. Neki protokoli, kao HTTPdozvoljavajusamo jedan upiti jedan odgovorpo konekciji. Drugi, kao FTP,dozvoljavajuvišestrukekonekcijei višeodgovoraunutarsvake konekcije.

Internet adrese

Svako racunalona Internetuidentificirase pomocujedinstvene, cetverobajtneIP adrese.Ona se obicnozapisujeu tzv. dotted quad formatukao npr. 161.53.8.14 gdje je svakibyte neoznacenavrijednostizmedu0 i 255.

Buducida je ovakvebrojeve teško zapamtiti, adrese se mapirajuu imenakaostudent.math.hr , jagor.srce.hr i tako dalje. Medutim, bitnaje numerickaadresa, ne

ime.

Klasa java.net.InetAddress predstavljatakve adrese. Izmeduostalog, ona sadržiimetodeza konvertiranjenumerickihadresa u imenahostovai obrunuto.

public static InetAddress getByName(String host) throws UnknownHostExceptionpublic static InetAddress[] getAllByName (String host) throws UnknownHostExceptionpublic static InetAddress getLocalHost () throws UnknownHostExceptionpublic boolean isMulticastAddress ()public String getHostName()

Page 283: Java Predavanje I

public byte[] getAddress()public String getHostAddress ()public int hashCode()public boolean equals(Object obj)public String toString()

Kreiranje InetAddress objekata

Klasa InetAddress je maloneobicnajer nemanijedan public konstruktor. Umjestotoga imehosta ilidotted quad adresu u stringformatuprosljedujetestatickojmetodiInetAddress.getByName() kao u sljedecemprimjeru: try { InetAddress public = InetAddress.getByName("public.srce.hr"); InetAddress jagor = InetAddress.getByName("161.53.2.130");}catch (UnknownHostException e) { System.err.println(e);}

Neki hostoviimajuvišeadresa. Ako pretpostavljateda je to slucajsa hostomkojegispitujete, možetedobitipoljeobjekata tipaInetAddress pomocustatickemetodeInetAddress.getAllByName (), na primjerovako: import java.net.*; public class HostAddresses { public static void main (String args[]) { try { InetAddress[] addresses = InetAddress.getAllByName (args[0]); for (int i = 0; i < addresses.length; i++) { System.out.println(addresses[i]); } } catch (UnknownHostException e) { System.out.println("Ne mogu naci trazeni host"); } catch (ArrayIndexOutOfBoundsException e) { System.out.println("Upisite ime trazenog hosta"); } } }

Imatcemo: % javac HostAddresses .java% java HostAddresses student.math.hrstudent.math.hr/161.53.8.14student.math.hr/161.53.29.70%

Page 284: Java Predavanje I

Konacno, statickametodaInetAddress.getLocalHost () vraca objekt tipaInetAddress koji sadržiadresu racunalana kojemse programizvršava: try { InetAddress me = InetAddress.getLocalHost ();}catch (UnknownHostException e) { System.err.println(e);}

Parsiranje InetAddress objekata

Za objekt tipaInetAddress možetedobitiimehosta kao string, IP adresu kao stringilikao poljebyteova, a takoder možeteispitatije lito tzv. multicast adresa (adresa klaseD, cija su prva cetiribita1110). To se rješavasljedecimmetodama: public String getHostName()public String getHostAddress ()public byte[] getAddress()public boolean isMulticastAddress ()

Sljedeciprogramispisujepodatke o lokalnomhostu. import java.net.*; public class LocalHost { public static void main(String[] args) { try { InetAddress me = InetAddress.getLocalHost (); System.out.println("Ime lokalnog hosta -----> " +me.getHostName()); System.out.println("Adresa lokalnog hosta ---> " +me.getHostAddress ()); byte[] address = me.getAddress(); System.out.print("Adresa po byteovima -----> "); for (int i = 0; i < address.length; i++) { System.out.print(address[i] + " "); } System.out.println(); if (me.isMulticastAddress ()) System.out.println("multicast"); else System.out.println("nije multicast"); } catch (UnknownHostException e) { System.err.println("Ne mogu naci trazeni host"); } } }

Page 285: Java Predavanje I

% javac LocalHost.java% java LocalHostIme lokalnog hosta -----> student.math.hrAdresa lokalnog hosta ---> 161.53.8.14Adresa po byteovima -----> -95 53 8 14nije multicast%

Primijetiteda su byteovikoje vraca metodagetAddress() oznaceniiako se, premakonvenciji, za dotted quad adrese koristeneoznacenibyteovi.

URL

URL, kraticaza "UniformResourceLocator", je nacinza jednoznacnoidentificiranjelokacijenekogresursana internetu. TipicniURL-oviizgledajuovako: http://public.srce.hr/file:///Macintosh%20HD/Java/Docs/JDK%201.1.1%20docs/api/java.net.InetAddress.html#_top_http://www.macintouch.com:80/newsrecent.shtmlftp://ftp.carnet.hr/pub/mailto:[email protected]://student.math.hr

VecinaURL-ova možese rastavitina sljedecekomponente(koje ne morajusve bitiprisutneu svakomURL-u):

protokolhostportdatotekareferenca, sekcijailisidro (anchor)

Klasa URL

URL-ovisu u Javipredstavljeniklasomjava.net.URL. Postoje konstruktorizakreiranjenovogURL-a i metodeza parsiranjerazlicitihdijelovaURL-a. Ipak, bitnidioove klase su metodekoje vamomogucujuda sa nekogURL-a dobijeteInputStream ina taj nacincitatepodatke s poslužitelja.

Klasa URL usko je povezanas handlerima protokola i sadržaja. Ciljje odvojitisnimljene(downloaded) podatke od protokolakoji je korištenza njihovosnimanje. Handlerprotokola je odgovoranza komuniciranjesa poslužiteljem, tj. prenošenjebyteovaodposlužiteljado klijenta. On obavljapotrebne pregovore (negotiations) oko poslužiteljaisvihpotrebnihheadera. Njegov je posao dobavitibyteovetraženihpodataka. Handlersadržajapreuzimate byteovei prevodiihu nekuvrstuJava objekta kao što jeInputStream iliImageProducer .

Page 286: Java Predavanje I

Kad konstruirateobjekt tipaURL, Java ce potražitihandlerprotokolakoji razumijeprotokolski dio URL-a, kao što je npr. "http" ili"mailto". Ako ne pronade takav

handler, izbacitce MalformedURLException . Koji su protokolipodržani, ovisioimplementaciji, no http i filesu podržaniuglavnomsvagdje. Sun-ov JDK 1.1. razumijesljedecihdeset:

fileftpgopherhttpmailtoappletresourcedocnetdocsystemresourceverbatim

Posljednjihpet su specificniSun-oviprotokolii koristeihinternoJDK i HotJava.

Konstruiranje URL objekata

Pogledajmoneke od konstruktoraklaseURL. SvioniizbacujuMalformedURLException . public URL(String u) throws MalformedURLExceptionpublic URL(String protocol, String host, String file) throws MalformedURLExceptionpublic URL(String protocol, String host, int port, String file) throws MalformedURLExceptionpublic URL(URL context, String u) throws MalformedURLException

Za potpuni, apsolutniURLkao što jehttp://student.math.hr/~vedris/java/java-predavanja/java-predavanje-01.htm

konstruirateodgovarajuciURL objekt ovako: URL u = null; try { u = new URL("http://student.math.hr/~vedris/java/java-predavanja/java-predavanje-01.htm "); } catch (MalformedURLException e) { }

You can also constructthe URLby passingitspieces to the constructor, likethis: URL u = null; try { u = new URL("http", "student.math.hr", "~vedris/java/java-predavanja/java-predavanje-01.htm");

Page 287: Java Predavanje I

} catch (MalformedURLException e) { }

U pravilune moratespecificiratiport za URL. Vecinaprotokola imapretpostavljeni(default) URL, pa tako za http pretpostavljamo80. Medutim, ako tražimonešto što nijena defaultportu, poslužitcemo se trecimkonstruktorom: URL u = null; try { u = new URL("http", "student.math.hr", 80, "~vedris/java/java-predavanja/java-predavanje-01.htm"); } catch (MalformedURLException e) { }

Konacno, mnogeHTMLdatoteke sadrže relativneURL-ove. Na primjer, URL ovestranicejehttp://student.math.hr/~vedris/java/java-predavanja/java-predavanje-12.htm

Ako bismohtjelimiroriratiove stranicena nekomdrugomracunalu, moglibismoumjestoapsolutnihkoristitirelativneURL-ove koji nasljedujuimehosta itd.. Na primjer, ako naovoj straniciimamolinkjava-predavanje-02, onda on zapravopokazujena http://student.math.hr/~vedris/java/java-predavanja/java-

predavanje-02.htm, medutim, na racunaluregoc.srce.hr pokazivaobi nahttp://regoc.srce.hr/~vedris/java/java-predavanja/java-predavanje-12.htm

i tako dalje. Cetvrtiod gore navedenihkonstruktorakreiraURLkoji je relativanuodnosuna zadaniURL. Na primjer: URL u1, u2; try { u1 = new URL("http://student.math.hr/~vedris/java/java-predavanja/java-predavanje-01.htm"); u2 = new URL(u1, "java-predavanje-02.htm"); } catch (MalformedURLException e) { }

To je posebno korisnikod parsiranjaHTML-a.

Parsiranje URL objekata

Klasa java.net.URL koristisljedecemetodeza rastavljanjeURLana njegovekomponente: public String getProtocol()public String getHost()

Page 288: Java Predavanje I

public int getPort() public String getFile()public String getRef()

Na primjer, try { URL u = new URL("http://student.math.hr/~vedris/java/html/TricksterApplet .html#top"); System.out.println("Protokol: " + u.getProtocol()); System.out.println("Host : " + u.getHost()); System.out.println("Port : " + u.getPort()); System.out.println("File : " + u.getFile()); System.out.println("Anchor : " + u.getRef()); } catch (MalformedURLException e) { }

Ako port u URLunijeeksplicitnospecificiran, vraca se -1. To ne znacida se pokušavanapravitikonekcijana (nepostojeci) port 1, nego jednostavnoda se koristidefault port.

Ako ne postojireferenca(anchor), onda je ona naprostonull, pa treba uhvatitiNullPointerException ili, još bolje, ispitatida je non-nullprijenego lije koristimo.

Konacno, ako je izostavljenfile, kao na primjeru http://student.math.hr,odgovarajucase vrijednostpostavljana "/".

Citanje podataka sa URLa

Metoda openStream() otvara konekcijuna poslužiteljkojeg URLspecificirate vracaInputStream s podacimaizte konekcije. To omogucujesnimanjepodataka saposlužitelja. Sviheaderi koji dolazeprijestvarnihpodataka ilitraženedatoteke bit ceobrisaniprijenegostreambude otvoren. Dobitcete samo cistepodatke. public final InputStream openStream() throws IOException

Streamcete procitatikoristecise metodamaizpaketa java.io o kojem smo govoriliudesetompredavanju. Primijetiteda vecinamrežnihkonekcijapredstavljamanjepouzdanisporijiizvorpodataka negošto su to datoteke. Bitce dakle potrebno izvršitibufferiranje,koristecise pri tom klasamaBufferedInputStream iliBufferedReader .

ProgramizsljedecegprimjeracitanizURLasa komandnelinije. Iz svakogargumentapokušavaformiratiURL, povezatise na specificiraniposlužitelji snimitipodatke koje ceonda ispisatina System.out.

import java.net.*;import java.io.*; public class Webcat {

Page 289: Java Predavanje I

public static void main(String[] args) { for (int i = 0; i < args.length; i++) { try { URL u = new URL(args[i]); InputStream is = u.openStream(); InputStreamReader isr = new InputStreamReader (is); BufferedReader br = new BufferedReader (isr); String theLine; while ((theLine = br.readLine()) != null) { System.out.println(theLine); } } catch (MalformedURLException e) { System.err.println(e); } catch (IOException e) { System.err.println(e); } } } } % javac Webcat.java% java Webcat "http://student.math.hr/~vedris/java/html/TricksterApplet .html"<APPLET CODE="TricksterApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Trickster.jar"WIDTH=1 HEIGHT=1></APPLET>%

Uticnice (sockets)

Prijenegose podaci šaljupreko Internetas jednoghosta na drugiuzpomoc TCP/IP, onise pakirajuu pakete razlicitih, alikonacnihvelicinakoji se nazivajudatagrami. Velicinadatagramavariraod nekolikodesetaka byteovapa do oko 60,000 byteova. Sve što jevece od toga, a cesto i ono što je manjeod toga, treba podijelitiu manjedijeloveprijeodašiljanja. Prednost takvogslanjapodataka je u tome što ako se jedan paket putemizgubi, on se možeposlatiponovobez da se opet šaljusviostalipaketi. Takoder, akopaketi stignuizvanporetka, onise mogupravilnoporedati i kod primatelja.

Ipak, sve je ovo transparentnoza Java programera. Hostovugradenimrežnisoftvercetransparentnoobavitirazdiobupodataka u pakete na stranipošiljateljate ihponovospojitina straniprimatelja. Umjestotoga, Java programerse susreces vrlovisokomapstrakcijomkoju nazivamouticnica(socket). Uticnicapredstavljapouzdanukonekcijuza prijenospodataka izmedudva hosta. Ona vas izoliraod detaljakodiranjapaketa,gubitkai ponovnogslanjapošiljki, te uspostavljanjaporetka medupristiglimpaketima.

Page 290: Java Predavanje I

Uticnicaobavljasljedececetirifundamentalneoperacije:

1. uspostavljanjevezes udaljenimracunalom2. slanjepodataka3. primanjepodataka4. prekidanjeveze

Uticnicane možebitiprikljucenana višehostovaistodobno.

Klasa Socket

Klasa java.net.Socket omogucujeizvodenjesvihcetirijufundamentalnihoperacijanauticnicama. Možete ostvaritikonekcijuna udaljenoracunalo, slatii primatipodatke teprekinutikonekciju.

Konekcijase obavljauzpomoc konstruktora. Svakomobjektu tipaSocket pridruženjetocno jedan udaljenihost. Da bisteostvarilikonekcijuna drugihost, moratekreiratinoviobjekti tipaSocket.

public Socket(String host, int port) throws UnknownHostException , IOExceptionpublic Socket(InetAddress address, int port) throws IOExceptionpublic Socket(String host, int port, InetAddress localAddress , int localPort) throws IOExceptionpublic Socket(InetAddress address, int port, InetAddress localAddress , int localPort) throws IOException

Slanjei primanjepodataka obavljase pomocuizlaznihi ulaznihstreamova. Sljedecemetodedaju odgovarajucestreamoveza danuuticnicu. public InputStream getInputStream () throws IOExceptionpublic OutputStream getOutputStream () throws IOException

Sljedecametodazatvarauticnicu: public synchronized void close() throws IOException

Postoji i nekolikometodakoje postavljanjurazliciteopcijevezaneuzuticnicu, nouglavnomcete otkritida su default vrijednostisasvimzadovoljavajuce. public void setTcpNoDelay (boolean on) throws SocketExceptionpublic boolean getTcpNoDelay () throws SocketExceptionpublic void setSoLinger(boolean on, int val) throws SocketExceptionpublic int getSoLinger() throws SocketExceptionpublic synchronized void setSoTimeout (int timeout) throws SocketExceptionpublic synchronized int getSoTimeout () throws SocketExceptionpublic static synchronized void setSocketImplFactory(SocketImplFactory fac) throws IOException

Sljedecemetodadaju razliciteinformacijeo uticnici: public InetAddress getInetAddress ()

Page 291: Java Predavanje I

public InetAddress getLocalAddress ()public int getPort()public int getLocalPort ()

Na kraju, tu je i uobicajenatoString() metoda: public String toString()

Konstruiranje Socket objekata

Pogledajmopublic, non-deprecated konstruktoreklaseSocket . public Socket(String host, int port) throws UnknownHostException , IOExceptionpublic Socket(InetAddress address, int port) throws IOExceptionpublic Socket(String host, int port, InetAddress localAddr, int localPort) throws IOExceptionpublic Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOException

Potrebno je, dakle, specificiratiu najmanjurukuhost i port na koji se želitekonektirati.Host možebitispecificiranbilokao string, npr "student.math.hr" ilikao objekt tipaInetAddress . Port mora biticijelibroj izmedu1 i 65535. Ne možebitibilokoji, vec gatrebate znatiistokao i imehosta. Na primjer, Socket webStudent = new Socket("student.math.hr", 80);

Posljednjadva konstruktoratakoder specificirajuhost i port sa kojega ostvarujetekonekciju. Na sistemusa višeIP adresa, kao što su mnogiweb poslužitelji, to vamomogucujeda odaberete svoje mrežnosuceljei IP adresu. Možete specificiratii brojporta, alikako svakipojediniport možebitizauzet, najboljeje stavitiport 0. To ce recisistemuda izaberebilokoji slobodniport. Ako želiteznatis kojeg porta ste napravilikonekciju, pozvatcete metodugetLocalPort (). Socket webStudent = new Socket("student.math.hr", 80, "pc-mladen.srce.hr", 0);

Ovi konstruktorinece samo kreiratinoviobjekt tipaSocket . Oni ce takoder pokušatiostvaritikonekcijuna specificiraniudaljeniposlužitelj. Svionizato odbacujuIOException u slucajuda se konekcijaizbilokojeg razlogane možeuspostaviti.

Port Scanner

Ne možetese naprostokonektiratina bilokoji port na bilokojemhostu. Konekcijajemogucasamo na one portove na kojimaudaljenoracunaloosluškuje dolaznekonekcije.Konstruktoreuticnicamožetekoristitida bisteustanovilina kojimportovimaracunaloosluškuje. Pogledajteprimjer: import java.net.*;

Page 292: Java Predavanje I

import java.io.IOException; public class PortScanner { public static void main(String[] args) { for (int i = 0; i < args.length; i++) { try { InetAddress ia = InetAddress.getByName(args[i]); scan(ia); } catch (UnknownHostException e) { System.err.println(args[i] + " is not a valid host name."); } } } public static void scan(InetAddress remote) { // Do I need to synchronize remote? // What happens if someone changes it while this method // is running? String hostname = remote.getHostName(); // Skanirat cemo samo portove od 78 do 81. // Potpuno skaniranje islo bi od 0 do 65535. Ne cinite to bez dozvole vlasnika hosta! for (int port = 78; port < 82; port++) { try { Socket s = new Socket(remote, port); System.out.println("Server slusa na portu " + port + " racunala " + hostname); s.close(); } catch (IOException e) { System.out.println("Racunalo ne slusa na portu " + port); } } } public static void scan(String remote) throws UnknownHostException { // Why throw the UnknownHostException ? Why not catch it like I did // in the main() method? InetAddress ia = InetAddress.getByName(remote); scan(ia); } }

Izvršitcemo ovuogranicenuverzijuPortScannerakoja ispitujesamo portove od 78 do81. Primijetitcete da racunaloslušana portu 80. To je standardniport za web poslužitelj.

Page 293: Java Predavanje I

% javac PortScanner.java% java PortScanner localhostRacunalo ne slusa na portu 78Racunalo ne slusa na portu 79Server slusa na portu 80 racunala localhostRacunalo ne slusa na portu 81%

Upozorenje: Ne pokušavajte usmjeritikompletniPortScanner prema

mašinikoja nije vaša vlastita bez dozvole vlasnika / sistem inženjera, jer ce se tosmatratihakerskim napadomi ugrožavanjemsigurnostiracunala!!!

Citanje ulaza sa uticnice

Jednomkad je uticnicakonektirana, možeteslatipodatke na poslužiteljputemizlaznogstreamailiihprimatisa poslužiteljapomocuulaznogstreama. Koje tocno podatke šaljeteiliprimateobicnoovisio protokolu.

Metoda getInputStream () vraca objekt tipaInputStream koji citapodatke izuticnice. Možete koristitiuobicajenemetodeklaseInputStream o kojimaste uciliudesetompredavnju. Uglavnomce bitipotrebno povezatiInputStream sa nekimdrugimulaznimstreamomilireaderomkako bi se lakše moglorukovatipodacima.

Na primjer, sljedecifragmentkoda radi konekcijuna daytime poslužiteljna portu 13racunalastudent.math.hr i ispisujepodatke koje od njegadobije.

try { Socket s = new Socket("student.math.hr", 13); InputStream is = s.getInputStream (); InputStreamReader isr = new InputStreamReader (is); BufferedReader br = new BufferedReader (isr); String theTime = br.readLine(); System.out.println(theTime); } catch (IOException e) { return (new Date()).toString(); }

Klijent Daytime

Pogledajmosada kompletanprogram, Daytime klijent, koji se konektirana daytimeposlužiteljracunalastudent.math.hr na portu 13 i ispisujepodatke koje od njegadobije. import java.net.*;import java.io.*;import java.util.Date;

Page 294: Java Predavanje I

public class Daytime { InetAddress server; int port = 13; public static void main(String[] args) { try { Daytime d = new Daytime("student.math.hr"); System.out.println(d.getTime()); } catch (IOException e) { System.err.println(e); } } public Daytime() throws UnknownHostException { this (InetAddress.getLocalHost ()); } public Daytime(String name) throws UnknownHostException { this(InetAddress.getByName(name)); } public Daytime(InetAddress server) { this.server = server; } public String getTime() { if (server == null) return (new Date()).toString(); try { Socket s = new Socket(server, port); InputStream is = s.getInputStream (); InputStreamReader isr = new InputStreamReader (is); BufferedReader br = new BufferedReader (isr); StringBuffer sb = new StringBuffer (); String theLine; while ((theLine = br.readLine()) != null) { sb.append(theLine + "\r\n"); } return sb.toString(); } catch (IOException e) { return (new Date()).toString(); } } } % javac Daytime.java% java DaytimeTue Jan 22 16:16:31 MET 2002

Page 295: Java Predavanje I

%

Pisanje izlaza preko uticnice

Metoda getOutputStream () vraca objekt tipaOutputStream pomocukojeg seispisujupodaci na uticnicu. Možete koristitisve uobicajenemetoedklaseOutputStreamo kojimaste uciliu desetompredavanju. Uglavnomce bitipotrebno povezatiOutputStream sa nekimdrugimizlaznimstreamomilireaderomkako bi se lakše moglorukovatipodacima.

Na primjer, sljedeciprogramse konektirana discard poslužiteljna portu 9 racunalastudent.math.hr i šaljemupodatke koje cita sa standardnogulazaSystem.in.

byte[] b = new byte[128]; try { Socket s = new Socket("student.math.hr", 9); OutputStream out = s.getOutputStream (); while (true) { int n = System.in.available(); if (n > b.length) n = b.length; int m = System.in.read(b, 0, n); if (m == -1) break; out.write(b, 0, n); } s.close(); } catch (IOException e) { }

Klijent Discard

Pogledajmosada kompletanprogram, Discard klijent, koji se konektirana Discardposlužiteljracunalastudent.math.hr na portu 9 i šaljemupodatke koje cita sastandardnogulazaSystem.in. import java.net.*;import java.io.*; public class Discard extends Thread { InetAddress server; int port = 9; InputStream theInput; public static void main(String[] args) { try { Discard d = new Discard("student.math.hr"); d.start(); }

Page 296: Java Predavanje I

catch (IOException e) { System.err.println(e); } } public Discard() throws UnknownHostException { this (InetAddress.getLocalHost (), System.in); } public Discard(String name) throws UnknownHostException { this(InetAddress.getByName(name), System.in); } public Discard(InetAddress server) { this(server, System.in); } public Discard(InetAddress server, InputStream is) { this.server = server; theInput = System.in; } public void run() { byte[] b = new byte[128]; try { Socket s = new Socket(server, port); OutputStream out = s.getOutputStream (); while (true) { int n = theInput.available(); if (n > b.length) n = b.length; int m = theInput.read(b, 0, n); if (m == -1) break; out.write(b, 0, m); } s.close(); } catch (IOException e) { } } } % javac Discard.java% java Discardasdf<Ctrl-C>%

Citanje i pisanje kroz uticnicu

Nije uobicajenoda se s uticnicesamo cita ilida se na njusamo piše. Vecinaprotokolatražida klijenti cita i piše. Neki protokolitražeda citanjei pisanjebude naizmjenicno,npr.

Page 297: Java Predavanje I

writereadwritereadwriteread

Drugiprotokoli, npr. HTTP1.0, traževišestrukeispisenakonkojihslijedevišestrukacitanja, npr.: writewritewritereadreadreadread

Neki protokolidozvoljavajuda klijentoviupitii poslužiteljeviodgovoribudu slobodnoizmiješani.

Java ne stavljanikakverestrikcijena citanjei pisanjepo uticnicama. Jedan thread možecitatis uticnice, a drugimožepo njoj istodobnopisati. (Primijetiteda to nijeistokao kadjedan thread citadatoteku, a drugipiše u nju.)

Citanje i pisanje uticnice za HTTP

Programu sljedecemprimjerušaljeupitHTTPposlužiteljukoristeciizlaznistreamuticnice, a zatimcitaodgovorkoristeciulaznistreamuticnice. HTTPposlužiteljisamizatvarajukonekcijukad pošaljuodgovor. import java.net.*;import java.io.*; public class Grabber { public static void main(String[] args) { int port = 80; for (int i = 0; i < args.length; i++) { try { URL u = new URL(args[i]); if (u.getPort() != -1) port = u.getPort(); if (!(u.getProtocol().equalsIgnoreCase ("http"))) { System.err.println("Sorry. I only understand http."); continue; } Socket s = new Socket(u.getHost(), port); OutputStream theOutput = s.getOutputStream (); // no auto-flushing PrintWriter pw = new PrintWriter(theOutput, false);

Page 298: Java Predavanje I

// native line endings are uncertain so add them manually pw.print("GET " + u.getFile() + " HTTP/1.0\r\n"); pw.print("Accept: text/plain, text/html, text/*\r\n"); pw.print("\r\n"); pw.flush(); InputStream in = s.getInputStream (); InputStreamReader isr = new InputStreamReader (in); BufferedReader br = new BufferedReader (isr); int c; while ((c = br.read()) != -1) { System.out.print((char) c); } } catch (MalformedURLException e) { System.err.println(args[i] + " is not a valid URL"); } catch (IOException e) { System.err.println(e); } } } }

Pogledajtepozivprogramai odgovorsa tipicnimpocetkom, karakteristicnimza HTTPposlužitelje: % java Grabber "http://student.math.hr:80/~vedris/java/html/TricksterApplet .html"HTTP/1.1 200 OKDate: Tue, 22 Jan 2002 15:32:38 GMTServer: Apache/1.2.6Last-Modified: Tue, 13 Nov 2001 13:09:48 GMTETag: "213be-97-3bf11b9c"Content-Length: 151Accept-Ranges: bytesConnection: closeContent-Type: text/html <APPLET CODE="TricksterApplet .class"CODEBASE="http://student.math.hr/~vedris/java/classes"ARCHIVE="Trickster.jar"WIDTH=1 HEIGHT=1></APPLET>%

Readingand Writingto a Socket for Echo

Citanje i pisanje po uticnici za Echo

Page 299: Java Predavanje I

The echo protocolsimplyechoes back anythingits sent. The followingecho clientreadsdata froman inputstream, thenpasses it out to an outputstreamconnectedto a socket,connectedto a networkecho server. A second thread reads the inputcomingback fromthe server. Themain() methodreads some filenamesfromthe commandlineand passesthemintothe outputstream. import java.net.*;import java.io.*;import java.util.*; public class Echo { InetAddress server; int port = 7; InputStream theInput; public static void main(String[] args) { if (args.length == 0) { System.err.println("Usage: java Echo file1 file2..."); System.exit(1); } Vector v = new Vector(); for (int i = 0; i < args.length; i++) { try { FileInputStream fis = new FileInputStream (args[i]); v.addElement(fis); } catch (IOException e) { } } InputStream in = new SequenceInputStream (v.elements()); try { Echo d = new Echo("metalab.unc.edu", in); d.start(); } catch (IOException e) { System.err.println(e); } } public Echo() throws UnknownHostException { this (InetAddress.getLocalHost (), System.in); } public Echo(String name) throws UnknownHostException { this(InetAddress.getByName(name), System.in); } public Echo(String name, InputStream is) throws UnknownHostException { this(InetAddress.getByName(name), is);

Page 300: Java Predavanje I

} public Echo(InetAddress server) { this(server, System.in); } public Echo(InetAddress server, InputStream is) { this.server = server; theInput = is; } public void start() { try { Socket s = new Socket(server, port); CopyThread toServer = new CopyThread("toServer", theInput, s.getOutputStream ()); CopyThread fromServer = new CopyThread("fromServer", s.getInputStream (), System.out); toServer.start(); fromServer.start(); } catch (IOException e) { System.err.println(e); } } } class CopyThread extends Thread { InputStream in; OutputStream out; public CopyThread(String name, InputStream in, OutputStream out) { super(name); this.in = in; this.out = out; } public void run() { byte[] b = new byte[128]; try { while (true) { int n = in.available(); if (n == 0) Thread.yield(); else System.err.println(n); if (n > b.length) n = b.length; int m = in.read(b, 0, n); if (m == -1) { System.out.println(getName() + " done!"); break; } out.write(b, 0, n); } } catch (IOException e) { }

Page 301: Java Predavanje I

} }

Server Sockets

Server Sockets

Uticnice poslužitelja (server sockets)

Thereare two ends to each connection: the client, that is the host that initiatestheconnection, and the server, that is the host that responds to the connection. Clientsandserversare connectedby sockets.

On the server side insteadof connectingto a remotehost, a programwaitsfor other hoststo connectto it. A server socket binds to a particularport on the localmachine. Once ithas successfullybound to a port, it listens for incomingconnectionattempts. Whenitdetects a connectionattempt, it accepts the connection. Thiscreates a socket betweenthe clientand the serverover whichthe clientand the servercommunicate.

Multipleclientscan connectto the same port on the serverat the same time. Incomingdata is distinguishedby the port to whichit is addressed and the clienthost and port fromwhichit came. The servercan tellfor whichservice(likehttp or ftp) the data is intendedby inspectingthe port. It can tellwhichopen socket on that servicethe data is intendedby lookingat the clientaddress and port stored withthe data.

No more thanone server socket can listento a particularport at one time. Therefore,sincea servermayneed to handlemanyconnectionsat once, serverprogramstend to beheavilymulti-threaded. Generallythe server socket listeningon the port willonlyacceptthe connections. It thenpasses offthe actualprocessingof connectionsto a separatethread.

Incomingconnectionsare stored ina queueuntilthe servercan accept them. (On mostsystemsthe defaultqueue lengthis between5 and 50. Once the queuefillsup furtherincomingconnectionsare refuseduntilspace inthe queueopens up.)

The java.net.ServerSocketClass

Klasa ServerSocket

Page 302: Java Predavanje I

Thejava.net.ServerSocket class representsa server socket. It is constructedon aparticularport. Thenit callsaccept() to listenfor incomingconnections. accept()blocks untila connectionis detected. Thenaccept() returnsa java.net.Socket

object youuse to performthe actualcommunicationwiththe client.

Thereare three constructorsthat let youspecifythe port to bindto, the queue lengthforincomingconnections, and the IP address to bindto:

public ServerSocket (int port) throws IOExceptionpublic ServerSocket (int port, int backlog) throws IOExceptionpublic ServerSocket (int port, int backlog, InetAddress bindAddr) throws IOException

Theaccept() and close() methodsprovidethe basic functionalityof a server socket. public Socket accept() throws IOExceptionpublic void close() throws IOException

On a serverwithmultipleIP addresses, the getInetAddress () methodtellsyouwhichone thisserver socket is listeningto. The getLocalPort() methodtellsyou whichportyou're listeningto. public InetAddress getInetAddress ()public int getLocalPort ()

Thereare three methodsto set and get variousoptions. The defaultsare generallyfine. public synchronized void setSoTimeout (int timeout) throws SocketExceptionpublic synchronized int getSoTimeout () throws IOExceptionpublic static synchronized void setSocketFactory (SocketImplFactory fac) throws IOException

Finally, there's the usualtoString() method: public String toString()

LocalPortScanner

Lokalni PortScanner

You can attemptto determinewhichports are currentlyoccupiedby tryingto createserver sockets on allof them, and seeingwhere thatoperationfails. import java.net.*;import java.io.IOException;

Page 303: Java Predavanje I

public class LocalPortScanner { public static void main(String[] args) { // first test to see whether or not we can bind to ports // below 1024 boolean rootaccess = false; for (int port = 1; port < 1024; port += 50) { try { ServerSocket ss = new ServerSocket (port); // if successful rootaccess = true; ss.close(); break; } catch (IOException e) { } } int startport = 1; if (!rootaccess) startport = 1024; int stopport = 65535; for (int port = startport; port <= stopport; port++) { try { ServerSocket ss = new ServerSocket (port); ss.close(); } catch (IOException e) { System.out.println("Port " + port + " is occupied."); } } } }

The java.net.ServerSocketConstructors

Konstruktori klase ServerSocket

Thejava.net.ServerSocket classhas three constructorsthat let youspecifythe portto bindto, the queue lengthfor incomingconnections, and the IP address to bindto: public ServerSocket (int port) throws IOExceptionpublic ServerSocket (int port, int backlog) throws IOExceptionpublic ServerSocket (int port, int backlog, InetAddress bindAddr) throws IOException

Normallyyouonlyspecifythe port youwant to listenon, likethis:

Page 304: Java Predavanje I

try { ServerSocket ss = new ServerSocket (80); } catch (IOException e) { System.err.println(e); }

Whenyoucreate a ServerSocket object, it attemptsto bindto the port on the localhost givenby the port argument. If anotherserver socket is alreadylisteningto the port,thena java.net.BindException , a subclassof java.io.IOException , is thrown.No more thanone process or thread can listento a particularport at a time. Thisincludesnon-Java processes or threads. For example, ifthere's alreadyan HTTPserver runningon port 80, youwon't be able to bindto port 80.

On Unixsystems(but not Windowsor the Mac) yourprogrammustbe runningas root tobindto a port between1 and 1023.

0 is a specialport number. It tellsJava to pick an availableport. You can thenfindoutwhatport it's picked withthe getLocalPort () method. Thisis usefulifthe clientandthe serverhavealreadyestablisheda separate channelof communicationover whichthechosenport numbercan be communicated.

For example, the ftp protocoluses two sockets. The initialconnectionis made by theclientto the server to send commands. One of the commandssent tellsthe server thenameof the port on whichthe clientis listening. The server thenconnectsto the clientonthisport to send data.

try { ServerSocket ftpdata = new ServerSocket (0); int port = ftpdata.getLocalPort (); } catch (IOException e) { System.err.println(e); }

Adjustingthe queue length

Podešavanje duljine repa public ServerSocket (int port, int backlog) throws IOException

The operatingsystemstores incomingconnectionsfor each port ina first-in, first-outqueueuntiltheycan be accepted. The defaultqueue lengthvariesfromoperatingsystemto operatingsystem. However, it tends to be between5 and 50. Once the queuefillsupfurtherconnectionsare refuseduntilspace opens up inthe queue. If you thinkyou aren't

Page 305: Java Predavanje I

goingto be processingconnectionsveryquicklyyou maywishto expandthe queuewhenyou constructthe server socket. For example, try { ServerSocket httpd = new ServerSocket (80, 50); } catch (IOException e) { System.err.println(e); }

Each systemhas a maximumqueuelengthbeyondwhichthe queuecannotbe expanded.If you ask for a queue longerthanthe maximumqueuesizeon a particularplatform,(generallyaroundfiftyto a hundred) thenthe queue is merelyexpandedto itsmaximumsize.

Once the server socket has been constructed, you cannotchangethe queue lengthit uses.

Choosinga localaddress

Odabir lokalne adrese

Manyhosts havemore thanone IP address. Thisis especiallycommonat web serverfarmswherea singlemachineis shared by multiplesites. By default, a server socket bindsto allavailableIP addresses. That is it accepts connectionsaddressed to anyof the localIP addresses on a givenport. Howeveryoucan modifythatbehaviorwiththisconstructor: public ServerSocket (int port, int backlog, InetAddress bindAddr) throws IOException

You mustalso specifythe queue lengthinthisconstructor. try { InetAddress ia = InetAddress.getByName("199.1.32.90"); ServerSocket ss = new ServerSocket (80, 50, ia); } catch (IOException e) { System.err.println(e); }

How wouldyoubindto some but not allIP addresses on the server?

WritingData to a Client

Page 306: Java Predavanje I

Ispis podataka na klijent

The followingsimpleprogramrepeatedlyanswersclientrequestsby sendingback theclient's address and port. Thenit closes the connection. import java.net.*;import java.io.*; public class HelloServer { public final static int defaultPort = 2345; public static void main(String[] args) { int port = defaultPort; try { port = Integer.parseInt(args[0]); } catch (Exception e) { } if (port <= 0 || port >= 65536) port = defaultPort; try { ServerSocket ss = new ServerSocket (port); while (true) { try { Socket s = ss.accept(); PrintWriter pw = new PrintWriter(s.getOutputStream ()); pw.println("Hello " + s.getInetAddress () + " on port " + s.getPort()); pw.println("This is " + s.getLocalAddress () + " on port " + s.getLocalPort ()); pw.flush(); s.close(); } catch (IOException e) { } } } catch (IOException e) { System.err.println(e); } } }

Pokrenemliovaj programna lokalnomracunalu, npr. pc-mladen.srce.hr i, dok je onaktivan, napravims racunalastudent.mat.hr telnetna pc-mladen.srce.hr 2345,dobit cu sljedece: % telnet pc-mladen.srce.hr 2345 Trying...Connected to pc-mladen.srce.hr.

Page 307: Java Predavanje I

Escape character is '^]'.Hello student.math.hr/161.53.8.14 on port 51546This is pc-mladen.srce.hr/161.53.2.93 on port 2345Connection closed by foreign host.% telnet pc-mladen.srce.hr 2345Trying...Connected to pc-mladen.srce.hr.Escape character is '^]'.Hello student.math.hr/161.53.8.14 on port 51547This is pc-mladen.srce.hr/161.53.2.93 on port 2345Connection closed by foreign host.

Primijetiteda se dolazniport promijenikod svakognovogtelneta. Kad HelloServer

prestanes radom, port koji je on osluškivaobit ce opet slobodan, što možeteprovjeritipomocuprogramaLocalPortScanner . Takoder, pokušamlisada napravititelnetnaport 2345, dobit cu: % telnet pc-mladen.srce.hr 2345Trying...telnet: Unable to connect to remote host: Connection refused%

Kad HelloServer prestanes radom, port koji je on osluškivaobit ce opet slobodan,što možeteprovjeritipomocuprogramaLocalPortScanner .

ReadingData witha ServerSocket

Citanje podataka pomocu uticniceposlužitelja

The port scannerprettymuchexhaustswhatyoucan do withjust the constructors.AlmostallServerSocket objects youcreate willuse theiraccept() methodto connectto a client. public Socket accept() throws IOException

Thereare no getInputStream () or getOutputStream () methodsfor ServerSocket.Insteadyouuse accept() to returna Socket object, and thencallitsgetInputStream() or getOutputStream () methods.

For example,

try { ServerSocket ss = new ServerSocket (2345); Socket s = ss.accept(); PrintWriter pw = new PrintWriter(s.getOutputStream ()); pw.println("Hello There!"); pw.println("Goodbye now.);

Page 308: Java Predavanje I

s.close(); } catch (IOException e) { System.err.println(e); }

Notice inthisexample, I closed the Socket s, not the ServerSocket ss. ss is stillbound to port 2345. You get a new socket for each connectionbut it's easy to reuse theserver socket. For example, the nextcode fragmentrepeatedlyaccepts connections: try { ServerSocket ss = new ServerSocket (2345); while (true) { Socket s = ss.accept(); PrintWriter pw = new PrintWriter(s.getOutputStream ()); pw.println("Hello There!"); pw.println("Goodbye now.); s.close(); } } catch (IOException e) { System.err.println(e); }

Interactingwitha Client

Interakcija s klijentom

More commonly, a serverneeds to both read a clientrequestand writea response. Thefollowingprogramreads whateverthe clientsends and thensends it back to the client. Inshort thisis an echo server. import java.net.*;import java.io.*; public class EchoServer { public final static int defaultPort = 2346; public static void main(String[] args) { int port = defaultPort; try { port = Integer.parseInt(args[0]); } catch (Exception e) { } if (port <= 0 || port >= 65536) port = defaultPort;

Page 309: Java Predavanje I

try { ServerSocket ss = new ServerSocket (port); while (true) { try { Socket s = ss.accept(); OutputStream os = s.getOutputStream (); InputStream is = s.getInputStream (); while (true) { int n = is.read(); if (n == -1) break; os.write(n); os.flush(); } } catch (IOException e) { } } } catch (IOException e) { System.err.println(e); } } }

Na jednomracunalu, npr pc-mladen.srce.hr pokrenemEchoServer: % javac EchoServer% java EchoServer . . . %

S drugogracunala, npr. student.math.hr napravimtelnetna pc-mladen.srce.hr 2346.Imamo: telnet pc-mladen.srce.hr 2346Trying...Connected to pc-mladen.srce.hr.Escape character is '^]'.jedanjedandvadva^]Connection closed by foreign host.

Ako ne možeteizaciiztelneta, prekiniteEchoServerna lokalnomracunalusa <Ctrl-C>,pa ce se telnetautomatskiotkvaciti.

AddingThreadingto a Server

Page 310: Java Predavanje I

Dodavanje threadova poslužitelju

The last two programscouldonlyhandleone clientat a time. Thatwasn't so muchof aproblemfor HelloServer because it had onlya verybriefinteractionwitheach client.Howeverthe EchoServer mighthangon to a connectionindefinitely. In thiscase, it'sbetter to make yourservermulti-threaded. Thereshouldbe a loop whichcontinuallyaccepts new connections. However, rather thanhandlingthe connectiondirectlytheSocket shouldbe passed to a Thread object thathandlesthe connection.

The followingexampleis a threadedecho program.

import java.net.*;import java.io.*; public class ThreadedEchoServer extends Thread { public final static int defaultPort = 2347; Socket theConnection ; public static void main(String[] args) { int port = defaultPort; try { port = Integer.parseInt(args[0]); } catch (Exception e) { } if (port <= 0 || port >= 65536) port = defaultPort; try { ServerSocket ss = new ServerSocket (port); while (true) { try { Socket s = ss.accept(); ThreadedEchoServer tes = new ThreadedEchoServer (s); tes.start(); } catch (IOException e) { } } } catch (IOException e) { System.err.println(e); } } public ThreadedEchoServer (Socket s) { theConnection = s; } public void run() {

Page 311: Java Predavanje I

try { OutputStream os = theConnection .getOutputStream (); InputStream is = theConnection .getInputStream (); while (true) { int n = is.read(); if (n == -1) break; os.write(n); os.flush(); } } catch (IOException e) { } } }

Na lokalnomracunalu, npr pc-mladen.srce.hr: % javac ThreadedEchoServer .java% java ThreadedEchoServer. . .%

Na racunalustudent.math.hr: % telnet pc-mladen.srce.hr 2347Trying...Connected to pc-mladen.srce.hr.Escape character is '^]'.jedan-studentjedan-studentdva-studentdva-student^]Connection closed by foreign host.%

Istodobno, na racunaluregoc.srce.hr: % telnet pc-mladen.srce.hr 2347Trying 161.53.2.93...Connected to pc-mladen.srce.hr.Escape character is '^]'.jedan-regocjedan-regocdva-regocdva-regoc^]Connection closed by foreign host.%

Ako ne možeteizaciiztelneta, prekiniteEchoServerna lokalnomracunalusa <Ctrl-C>,pa ce se telnetautomatskiotkvaciti.Note that explicityieldsare not requiredbecause allthe differentthreadswilltend toblock on callsto read() and accept().

Page 312: Java Predavanje I

Addinga ThreadPool to a Server

Dodavanje Thread Poola poslužitelju

Multi-threadingis a good thingbut it's stillnot a perfectsolution. For example, let's take alook at the accept loop of the ThreadedEchoServer: while (true) { try { Socket s = ss.accept(); ThreadedEchoServer tes = new ThreadedEchoServer (s); tes.start(); } catch (IOException e) { }

Everytimeyoupass throughthisloop, a new thread gets created. Everytimeaconnectionis finishedthe thread is disposedof. Spawninga new thread for eachconnectiontakes a non-trivialamountof time, especiallyon a heavilyloaded server. Itwouldbe better not to spawn so manythreads.

An alternativeapproach is to create a pool of threadswhenthe server launches, storeincomingconnectionsina queue, and have the threads inthe pool progressivelyremoveconnectionsfromthe queueand process them. Thisis particularlysimplesincetheoperatingsystemdoes infact store the incomingconnectionsina queue. The mainchangeyou need to make to implementthisis to callaccept() inthe run() methodrather thaninthe main() method. The programbelowdemonstrates.

import java.net.*;import java.io.*; public class PoolEchoServer extends Thread { public final static int defaultPort = 2347; ServerSocket theServer; static int numberOfThreads = 10; public static void main(String[] args) { int port = defaultPort; try { port = Integer.parseInt(args[0]); } catch (Exception e) { } if (port <= 0 || port >= 65536) port = defaultPort;

Page 313: Java Predavanje I

try { ServerSocket ss = new ServerSocket (port); for (int i = 0; i < numberOfThreads ; i++) { PoolEchoServer pes = new PoolEchoServer (ss); pes.start(); } } catch (IOException e) { System.err.println(e); } } public PoolEchoServer (ServerSocket ss) { theServer = ss; } public void run() { while (true) { try { Socket s = theServer.accept(); OutputStream out = s.getOutputStream (); InputStream in = s.getInputStream (); while (true) { int n = in.read(); if (n == -1) break; out.write(n); out.flush(); } // end while } // end try catch (IOException e) { } } // end while } // end run }

In the programabove the numberof threads is set to ten. Thiscan be adjustedforperformancereasons. How wouldyou go about testingthe performanceof thisprogramrelativeto the one that spawnsa new thread for each connection? How wouldyoudeterminethe optimumnumberof threads to spawn?

UDP

IntroducingUDP

Što je UDP?

Page 314: Java Predavanje I

The User Datagram Protocol, UDP for short, providesunguaranteed, connectionlesstransmissionof data across an IP network. By contrast, TCP, providesreliable,connection-orientedtransmissionof data.

BothTCP and UDP splitdata intopackets calleddatagrams. HoweverTCP includesextra headers inthe datagramto enableretransmissionof lostpackets and reassemblyofpackets intothe correct order iftheyarriveout of order. UDP does not providethis. If aUDP packet is lost, it's lost. It willnot be retransmitted. Similarly, packets appear inthereceivingprograminthe order theywere received, not necessarilyinthe order theyweresent.

Giventhese disadvantagesyoumaywellwonder whyanyonewouldpreferUDP to TCP.The answer is speed. UDP can be up to three timesfasterthanTCP; and there are manyapplicationsfor whichreliabletransmissionof data is not nearlyas importantas speed.For examplelostor out of order packets mayappear as staticinan audioor videofeed,but the overallpictureor soundcouldstillbe intelligible.

Telephonevs. snailmailanalogy.

Protocolsthatuse UDP includeNFS, FSP, and TFTP.

The UDP Classes

UDP klase

Java's support for UDP is containedintwo classes, java.net.DatagramSocket andjava.net.DatagramPacket . A DatagramSocketis used to send and receiveDatagramPackets. SinceUDP is connectionless, streamsare not used. You mustfityourdata intopackets of no more thanabout 60,000 bytes. You can manuallysplitthe dataacross multiplepackets ifnecessary.

TheDatagramPacket class is a wrapper for an array of bytes fromwhichdata willbesent or intowhichdata willbe received. It also containsthe address and port to whichthepacket willbe sent.

TheDatagramSocket class is a connectionto a port thatdoes the sendingand receiving.UnlikeTCP sockets, there is no distinctionbetweena UDP socket and a UDP serversocket. The sameDatagramSocket can both and receive. AlsounlikeTCP sockets, aDatagramSocket can send to multiple, differentaddresses. The address to whichdatagoes is stored inthe packet, not inthe socket.

UDP ports are separate fromTCP ports. Each computerhas 65,536 UDP ports as wellas its65,536 TCP ports. You can havea ServerSocket bound to TCP port 20 at thesame timeas a DatagramSocket is bound to UDP port 20. Most of the timeit shouldbe obviousfromcontextwhetheror not I'm talkingabout TCP ports or UDP ports.

Page 315: Java Predavanje I

java.net.DatagramPacket

Klasa DatagramPacket

TheDatagramPacket class is a wrapper for an array of bytes fromwhichdata willbesent or intowhichdata willbe received. It also containsthe address and port to whichthepacket willbe sent. public DatagramPacket (byte[] data, int length)public DatagramPacket (byte[] data, int length, InetAddress host, int port)

You constructa DatagramPacket object by passingan array of bytes and the numberof those bytes to send to the DatagramPacket () constructorlikethis: String s = "My first UDP Packet" byte[] b = s.getBytes(); DatagramPacket dp = new DatagramPacket (b, b.length);

Normallyyou'llalso pass inthe host and port to whichyouwant to send the packet: try { InetAddress metalab = new InetAddess("metalab.unc.edu"); int chargen = 19; String s = "My second UDP Packet" byte[] b = s.getBytes(); DatagramPacket dp = new DatagramPacket (b, b.length, ia, chargen);}catch (UnknownHostException e) { System.err.println(e);}

The byte array that's passed to the constructoris stored by reference, not by value. If youcahngeit's contentselsewhere, the contentsof the DatagramPacket changeas well.

DatagramPacket s themselvesare not immutable. You can changethe data, the lengthofthe data, the port, or the address at any timewiththese fourmethods:

public synchronized void setAddress(InetAddress host)public synchronized void setPort(int port)public synchronized void setData(byte buffer[])public synchronized void setLength(int length)

You can retrievethese itemswiththese fourget methods: public synchronized InetAddress getAddress()public synchronized int getPort()public synchronized byte[] getData()public synchronized int getLength()

Page 316: Java Predavanje I

Thesemethodsare primarilyusefulwhenyou're receivingdatagrams.

java.net.DatagramSocket

Klasa DatagramSocket

Thejava.net.DatagramSocket classhas three constructors: public DatagramSocket () throws SocketExceptionpublic DatagramSocket (int port) throws SocketExceptionpublic DatagramSocket (int port, InetAddress laddr) throws SocketException

The firstis used for datagramsockets that are primarilyintendedto act as clients; that issockets thatwillsend datagramsbefore receivingany. The secned two that specifytheport and optionallythe IP address of the socket, are primarilyintendedfor servers thatmustrunon a well-knownport.

The LocalPortScannerdevelopedearlieronlyfoundTCP ports. The followingprogramdetects UDP ports inuse. As withTCP ports, youmustbe root on Unixsystemsto bindto ports below1024.

import java.net.*;import java.io.IOException; public class UDPPortScanner { public static void main(String[] args) { // first test to see whether or not we can bind to ports // below 1024 boolean rootaccess = false; for (int port = 1; port < 1024; port += 50) { try { ServerSocket ss = new ServerSocket (port); // if successful rootaccess = true; ss.close(); break; } catch (IOException e) { } } int startport = 1; if (!rootaccess) startport = 1024; int stopport = 65535; for (int port = startport; port <= stopport; port++) {

Page 317: Java Predavanje I

try { DatagramSocket ds = new DatagramSocket (port); ds.close(); } catch (IOException e) { System.out.println("UDP Port " + port + " is occupied."); } } } }

SinceUDP is connectionlessit is not possibleto writea remoteUDP port scanner. Theonlyway youknow whetheror not a UDP server is listeningon a remoteport is ifitsends somethingback to you.

SendingUDP Datagrams

Slanje UDP Datagrama

To send data to a particularserver, you firstmustconvertthe data intobyte array. Nextyou pass thisbyte array, the lengthof the data inthe array (mostof the timethiswillbethe lengthof the array) and the InetAddress and port to whichyouwishto send it intothe DatagramPacket () constructor. For example, try { InetAddress metalab = new InetAddess("metalab.unc.edu"); int chargen = 19; String s = "My second UDP Packet"; byte[] b = s.getBytes(); DatagramPacket dp = new DatagramPacket (b, b.length, metalab, chargen);}catch (UnknownHostException e) { System.err.println(e);}

Next youcreate a DatagramSocket object and pass the packet to its send() method:For example, try { DatagramSocket sender = new DatagramSocket (); sender.send(dp);}catch (IOException e) { System.err.println(e);}

Page 318: Java Predavanje I

ReceivingUDP Datagrams

Primanje UDP Datagrama

To receivedata sent to you, youconstructa DatagramSocket object on the port onwhichyouwant to listen. Thenyoupass an emptyDatagramPacket object to theDatagramSocket 's receive() method. public synchronized void receive(DatagramPacket dp) throws IOException

The callingthread blocks untilthe a datagramis received. Thendp is filledwiththe datafromthatdatagram. You can thenuse getPort() and and getAddress() to tellwherethe packet came from, getData() to retrievethe data, and getLength() to see howmanybytes were inthe data. If the receivedpacket was too longfor the buffer, thenit'struncatedto the lengthof the buffer. For example, try { byte buffer = new byte[65536]; // maximum size of an IP packet DatagramPacket incoming = new DatagramPacket (buffer, buffer.length); DatagramSocket ds = new DatagramSocket (2134); ds.receive(dp); byte[] data = dp.getData(); String s = new String(data, 0, data.getLength()); System.out.println("Port " + dp.getPort() + " on " + dp.getAddress() + " sent this message:"); System.out.println(s);}catch (IOException e) { System.err.println(e);}

Sendingand ReceivingUDP Datagrams

Slanje i primanje UDP Datagrama

Most of the timea programneeds to both receiveand send UDP datagrams. Forexample, the UDP echo servicelistenson port 7. Whenit receivesa datagramit copiesthe data out of the datagramintoa new datagramand sends it back to the sendinghost.(Whycan't it just resend the same datagram?)

The followingUDPEchoClient reads what the user types on System.in and sends it toan echo server specifiedon the commondline. Note thatpreciselybecause UDP is

Page 319: Java Predavanje I

unreliable, you're not guaranteedthat each lineyou type willinfact be echoed back. Itmaybe lostgoingbetweenclientand serveror returningfromserver to client.

import java.net.*;import java.io.*; public class UDPEchoClient extends Thread { public final static int port = 7; DatagramSocket ds; public static void main(String[] args) { InputStreamReader isr = new InputStreamReader (System.in); BufferedReader br = new BufferedReader (isr); String theLine; DatagramSocket ds = null; InetAddress server = null; try { server = InetAddress.getByName("metalab.unc.edu"); ds = new DatagramSocket (); } catch (IOException e) { System.err.println(e); System.exit(1); } UDPEchoClient uec = new UDPEchoClient (ds); uec.start(); try { while ((theLine = br.readLine()) != null) { byte[] data = theLine.getBytes(); DatagramPacket dp = new DatagramPacket (data, data.length, server, port); ds.send(dp); Thread.yield(); } } catch (IOException e) { System.err.println(e); } uec.stop(); } public UDPEchoClient (DatagramSocket ds) { this.ds = ds; } public void run() { byte[] buffer = new byte[1024]; DatagramPacket incoming = new DatagramPacket (buffer, buffer.length);

Page 320: Java Predavanje I

while (true) { try { incoming.setLength(bufffer.length); ds.receive(incoming); byte[] data = incoming.getData(); System.out.println(new String(data, 0, incoming.getLength())); } catch (IOException e) { System.err.println(e); } } } }

Page 321: Java Predavanje I

u pripremi

Trinaesto predavanje - ispis i prijenospodataka

Printing

Printing

Printing

Java 1.1 implementsprintingthroughthe java.awt.PrintGraphics interfaceand theabstractjava.awt.Printjob class.

To begina printjob youcallthe staticmethodToolkit.getPrintJob(). Thisreturnsaplatformspecificinstanceof the abstractPrintJob class. (Platformspecificdetailsarehiddeninsidethe sunclasses.)

ThePrintJob object givesyou informationabout the page sizeand the printerresolution. It also has a getGraphics() methodthat returnsa Graphics object thatimplementsthe PrintGraphics interface. Oftenyou'lldraw the page by passingthisobject to yourpaint() method. Other timesyou'llwant to specializefor printing. Forexample, youmightwant to draw inblack and whiteinsteadof color. (RegrettablyJavadoes not providea methodto determinethe availablecolorson the printer.)

A page is sent to the printerwhenyou invokeitsGraphics 's object's dispose()method. You can printmultiplepages by repeatedlycallinggetGraphics() and thedisposingeach Graphics object.

SecurityRestrictionson Printing

Security Restrictions on Printing

As a generalruleappletsare not allowedto initiateprintjobs. Onlyapplicationscan dothat. You wouldn't wanta maliciousapplet to churnyourprinterwithmanypages of pureblack, wastingallyour toner, for example.

ThecheckPrintJobAccess () methodof the SecurityManager class is used todeterminewhetheror not printingis allowed.

Page 322: Java Predavanje I

public void checkPrintJobAccess ()

For example, try { SecurityManager sm = System.getSecurityManager (); if (sm != null) sm.checkPrintJobAccess (); // print...}catch (SecurityException e) { System.err.println("Sorry. Printing is not allowed.");}

Creatinga PrintJob

Creating a PrintJob

The abstractjava.awt.PrintJob classhas a singlepublicnoragsconstructor,PrintJob(). Howeverbecause it's an abstract classyoucan't instatiateit. Insteadyoumustcallthe getPrintJob() methodinthe java.awt.Toolkit class. public abstract PrintJob getPrintJob(Frame parent, String title, Properties props)

TheFrame willholdthe platformspecificprintdialog. Thetitle stringidentifiesthisjobinthe printqueueand on the cover page. Theprops argumentsis ajava.awt.Properties object You can use to requestdifferentprintingoptionsonUnix. Howeverthisdoesn't work on Windows, and inanycase printingoptionsareplatformspecific.

PrintJob Dialog

A PrintJob dialog

Page 323: Java Predavanje I

For example:

PrintJob pj = Toolkit.getDefaultToolkit ().getPrintJob(new Frame(), "Hello World", null);

Thisreturnsa platformspecificsubclassof the PrintJob class. If the user cancelsthePrintJobinthe dialogbox, thenthismethodshouldreturnnull. (Thismaybe a littlebuggyunderWindows, though.)

Methodsof java.awt.PrintJob

Methods of the java.awt.PrintJob class

For example: PrintJob pj = Toolkit.getDefaultToolkit ().getPrintJob(new Frame(), "Hello World", null);

Thisreturnsa platformspecificsubclassof the PrintJob class. The firstthingyou'llwantto do withthisobject is determinethe characteristicsof the printer. Thereare threemethodsfor this: public abstract int getPageResolution () public abstract Dimension getPageDimension () public abstract boolean lastPageFirst ()

ThegetPageResolution () methodreturnsthe numberof dots per inchof thee printer,typically300 or 600 for most laserprinters. getPageDimension () returnsajava.awt.Dimension object givingthe sizeof the printablearea of the page inpixels(not inches!). For example, the followingcode fragmentprintsthe totalnumberof pixelson the page: PrintJob pj = Toolkit.getPrintJob(); int resolution = pj.getPageResolution (); Dimension d = pg.getPageDimension (); System.out.println("There are " + (resolution * d.width * d.height) + " pixels on a page.");

FinallylastPageFirst () returnstrue ifthe lastpage willbe printedfirst, falseotherwise.

You use thisinformationto prepare your imageto be drawn on the page. dependingonthe sizeof the page and the type of the image, youmayneed to spiltit across multiplepages. Sometimesit's easier to justdraw the entireimageon each page, but useclipRect() to set the fractionof the imageto actuallybe drawn.

Page 324: Java Predavanje I

The drawingitselfis done witha java.awt.Graphics object likethe one youuse inthepaint() methodof an applet. Thisis returnedby getGraphics(), and has allthe usualmethodof the Graphics class, drawLine(), drawString(), and so on.

public abstract Graphics getGraphics()

There's one importantcaveat: Unilkethe Graphicsobjects passed as argumentsto apaint() method, thisobject does not intiallyhavea fontset. You'llgenerallywant to setits fontbefore usingit likethis: Font courier = new Font("Courier", Font.PLAIN, 12); g.setFont(courier);

Whenyou're done witha PrintJob callitsend() methodto performanynecessaryflushingand cleanup. public abstract void end()

PrintingGraphics: an example

Printing Graphics: An example

The followingsimpleprogramprintssome circles: import java.awt.*; public class PrintableBullseye extends Canvas { public static void main(String[] args) { PrintableFrame pf = new PrintableFrame ("Printable Frame"); pf.add("Center", new PrintableBullseye ()); pf.setVisible(true); } public Dimension getPreferredSize () { return new Dimension(250, 250); } public Dimension getMinimumSize () { return new Dimension(50, 50); } public void paint(Graphics g) { int rectLeft, rectTop, rectHeight, rectWidth; int height = this.getSize().height;

Page 325: Java Predavanje I

int width = this.getSize().width; Color red = Color.red; if (g instanceof PrintGraphics ) { red = Color.black; } for (int i=8; i >= 0; i--) { if ((i % 2) == 0) g.setColor(red); else g.setColor(Color.white); rectHeight = height*i/8; rectWidth = width*i/8; rectLeft = width/2 - i*width/16; rectTop = height/2 - i*height/16; g.fillOval(rectLeft, rectTop, rectWidth, rectHeight); } } }

PrintingText

Printing Text

The trickto printingtext is to measureit and compare it to the page sizeand resolutionina givenfont. You do thiswiththe java.awt.FontMetrics class. // This example is from the book _Java AWT Reference_ by John Zukowski.// Written by John Zukowski. Copyright (c) 1997 O'Reilly & Associates.// You may study, use, modify, and distribute this example for any purpose.// This example is provided WITHOUT WARRANTY either expressed orimport java.awt.*;import java.awt.event.*;import java.io.*;import java.util.Properties; public class TestPrint extends Frame { TextArea textArea; Label statusInfo; Button loadButton, printButton, closeButton; Properties p = new Properties(); public TestPrint() { super ("File Loader"); add (statusInfo = new Label(), "North"); Panel p = new Panel (); p.add (loadButton = new Button ("Load")); loadButton.addActionListener ( new LoadFileCommand () ); p.add (printButton = new Button ("Print")); printButton.addActionListener ( new PrintCommand () ); p.add (closeButton = new Button ("Close")); closeButton.addActionListener ( new CloseCommand () );

Page 326: Java Predavanje I

add (p, "South"); add (textArea = new TextArea (10, 40), "Center"); pack(); } public static void main (String args[]) { TestPrint f = new TestPrint(); f.show(); } // Bail Out class CloseCommand implements ActionListener { public void actionPerformed (ActionEvent e) { System.exit (0); } } // Load a file into the text area. class LoadFileCommand implements ActionListener { public void actionPerformed (ActionEvent e) { int state; String msg; FileDialog file = new FileDialog (TestPrint.this, "Load File", FileDialog.LOAD); file.setFile ("*.java"); // Set initial filename filter file.show(); // Blocks String curFile; if ((curFile = file.getFile()) != null) { String filename = file.getDirectory () + curFile; char[] data; setCursor (Cursor.getPredefinedCursor (Cursor.WAIT_CURSOR)); File f = new File (filename); try { FileReader fin = new FileReader (f); int filesize = (int)f.length(); data = new char[filesize]; fin.read (data, 0, filesize); } catch (FileNotFoundException exc) { String errorString = "File Not Found: " + filename; data = errorString.toCharArray (); } catch (IOException exc) { String errorString = "IOException: " + filename; data = errorString.toCharArray (); } statusInfo.setText ("Load: " + filename); textArea.setText (new String (data)); setCursor (Cursor.getPredefinedCursor (Cursor.DEFAULT_CURSOR)); } } } // Print a file into the text area. class PrintCommand implements ActionListener { public void actionPerformed (ActionEvent e) { PrintJob pjob = getToolkit().getPrintJob(TestPrint.this, "Cool Stuff", p); if (pjob != null) { Graphics pg = pjob.getGraphics();

Page 327: Java Predavanje I

if (pg != null) { String s = textArea.getText(); printLongString (pjob, pg, s); pg.dispose(); } pjob.end(); } } } // Print string to graphics via printjob // Does not deal with word wrap or tabs void printLongString (PrintJob pjob, Graphics pg, String s) { int pageNum = 1; int linesForThisPage = 0; int linesForThisJob = 0; // Note: String is immutable so won't change while printing. if (!(pg instanceof PrintGraphics )) { throw new IllegalArgumentException ("Graphics context not PrintGraphics "); } StringReader sr = new StringReader (s); LineNumberReader lnr = new LineNumberReader (sr); String nextLine; int pageHeight = pjob.getPageDimension ().height; Font helv = new Font("Helvetica", Font.PLAIN, 12); //have to set the font to get any output pg.setFont (helv); FontMetrics fm = pg.getFontMetrics (helv); int fontHeight = fm.getHeight(); int fontDescent = fm.getDescent(); int curHeight = 0; try { do { nextLine = lnr.readLine(); if (nextLine != null) { if ((curHeight + fontHeight) > pageHeight) { // New Page System.out.println ("" + linesForThisPage + " lines printed for page " + pageNum); pageNum++; linesForThisPage = 0; pg.dispose(); pg = pjob.getGraphics(); if (pg != null) { pg.setFont (helv); } curHeight = 0; } curHeight += fontHeight; if (pg != null) { pg.drawString (nextLine, 0, curHeight - fontDescent); linesForThisPage ++; linesForThisJob ++; } else { System.out.println ("pg null"); } }

Page 328: Java Predavanje I

} while (nextLine != null); } catch (EOFException eof) { // Fine, ignore } catch (Throwable t) { // Anything else t.printStackTrace (); } System.out.println ("" + linesForThisPage + " lines printed for page " + pageNum); System.out.println ("pages printed: " + pageNum); System.out.println ("total lines printed: " + linesForThisJob ); }}

PrintingComponents

Printing Components

You don't draw mostbuttons, lists, scrollbars, panels, and so on inyourpaint()method. You don't have to printthemthere either. Thejava.awt.Component classhasprint() and printAll() methods public void print(Graphics g) public void printAll(Graphics g)

java.awt.Container adds a printComponents () methodthatprintsallcomponentsinthe container: public void printComponents (Graphics g)

For example, to printa Frame f, youmightdo this:

Toolkit tk = f.getToolkit(); Printjob pj = tk.getPrintJob(this, getTitle(), null); if (pj != null) { Graphics pg = pj.getGraphics(); f.printComponents (pg); pg.dispose(); pj.end(); }

Howeverthisisn't alwayswhatyouwant sinceprintComponents () onlyprintsthevisiblearea. for example, inthe text editingapplicationthe TextArea mayonlyshow partof the text at one time, but you reallywant to printallthe text.

Page 329: Java Predavanje I

PrintingComponents: an example

Printing Components

The followingsimpleprogramprintsitselfwhenyou press the printbutton: import java.awt.*; public class PrintableFrame extends Frame implements ActionListener { Button printButton; public static void main(String[] args) { PrintableFrame pf = new PrintableFrame ("Printable Frame"); Label quote = new Label( "Now is the time for all good men to come to the aid of their country."); pf.add("North", quote); } public PrintableFrame (String s) { super(s); setSize(350, 200); setLocation(100, 100); printButton = new Button("Print Me!"); printButton.addActionListener (this); Panel p = new Panel(); p.add(printButton); add("South", p); } public void actionPerformed (ActionEvent e) { PrintJob pj = getToolkit().getPrintJob(this, getTitle(), null); if (pj != null) { Graphics pg = pj.getGraphics(); printComponents (pg); pg.dispose(); pj.end(); } } }

Cut, Copy, and Paste: java.awt.datatransfer

Page 330: Java Predavanje I

The Clipboard

The Clipboard

Modern, multitaskingoperatingsystemsand graphicaluser interfacesallowyou totransferdata betweenprogramsat the requestof the user througha systemfacilitycalleda clipboard. In general, clipboardscan containtext, pictures, sound, formattedtext, datainparticularformatsand more. However, not allprogramsknow how to interpretalldataformats.

Most of the timethe user somehowselectsthe data to be placed on the clipboard. Thedata maythenbe copied to the clipboard, generallyby selecting"Copy" fromthe Editmenuor by usingthe C shortcutkey. Alternatelydata can be cut out of the runningprogramand placed on the clipboard. Copied data remainsinthe originaldocumentwhilecut data is deletedfromthe originaldocument. The data is thenplaced back intothe samedocumentor intoa differentdocumnentby pastingit fromthe clipboard. On mostoperatingsystems(thoughOpenWindowsis a notableexception) pastingdoes notremovethe data fromthe clipboard.

As wellas the systemclipboardmanyapplicationshaveprivateclipboardsthat are usedfor intra-applicationdata transfer. The systemclipboardis used for inter-applicationdatatransfer.

The java.awt.datatransferPackage

The java.awt.datatransfer Package

Thejava.awt.datatransfer package providesclassesto support transferof data toand fromthe systemclipboard. Support for the clipboardis stillinits infancyinJava 1.1.Onlystringdata is supported, and onlycut, copy, and paste. Other data types and dragand drop willbe added inthe future.

Thejava.awt.datatransfer .Transferable interfaceis implementodby classesthat representdata to be transferred. It includesmethodsto determinethe possibledataflavorsof the object and to retrievethe data itself.

Thejava.awt.datatransfer .DataFlavor classprovidesa MIME type basedsystemfor determiningthe type of data on the clipboard. For example, flavorsinclude"text/plain; charset=unicode" and "application/x-java-serialized-object"

A java.awt.datatransfer .UnsupportedFlavorException is thrownwhenyouask a Transferable object to returnitscontentsinan incompatibleflavor.

Page 331: Java Predavanje I

Thejava.awt.datatransfer .Clipboard classallowsthe transferof data throughcut, copy, and paste operations. Althoughthere's onlyone systemclipboard, yourprogrammaycreate manydifferentClipboard objects for internaluse.

For synchronizationpurposes each clipboardmustbe the exclusivepropertyof oneobject. Thisobject mustimplementthe java.awt.datatransfer .ClipboardOwnerinterface. Thisinterfacedeclaesa singlemethod, lostOwnership (), whichis whichisused to warn an object that it no longerowns the clipboard.

Thejava.awt.datatransfer .StringSelection class is the one concreteimplementationof Transferable and ClipboardOwner includedinJava 1.1. It allowsyou to transferplaintext to and fromthe systemclipboard.

Other classesand methodsfor Copy and Paste

Other classes and methods for Copyand Paste

Thereare a few methodsand classesoutsidethe java.awt.datatransfer packagethat are relevantto copy and paste.

ThegetSystemClipboard () methodof the java.awt.Toolkit class returnsaClipboard object whichrepresentsthe systemclipboard:

public abstract Clipboard getSystemClipboard ()

Thejava.lang.SecurityManager class includesa checkSystemClipboardAccess

() methodthatdetermineswhetheror not thisprogramis allowedto access the systemclipboard. The methodis voidbut throwsa SecurityException ifaccess is notallowed. public void checkSystemClipboardAccess ()

The concernis that the clipboardmaycontainprivatedata whichthe user wouldnot wantrevealedto the server. As a generalrule, applets loaded fromweb serverswillnot beallowedto access the systemclipboard. Thisdoes not, however, applyto privateclipboardsyoucreate. For example, try { SecurityManager sm = SecurityManager .getSecurityManager (); if (sm != null) sm.checkSystemClipboardAccess (); Clipboard cb = Toolkit.getDefaultToolkit ().getSystemClipboard (); //... handle clipboard } catch (SecurityException e) {

Page 332: Java Predavanje I

System.err.println("Cannot access the system clipboard"); }

Thejava.awt.TextComponent class, whichboth TextArea and TextField extend,has a getSelectedText () methodthat returnsthe currentvalueof the selectionas aString: public synchronized String getSelectedText ()

You'lloftenuse thismethodto decide what to copy or cut. SeveralotherTextComponent methodsare also usefulfor manipulatingthe selection: public synchronized int getSelectionStart () public synchronized void setSelectionStart (int selectionStart ) public synchronized void setSelectionEnd (int selectionEnd ) public synchronized void select(int selectionStart , int selectionEnd ) public synchronized void selectAll() public void setCaretPosition (int position) public int getCaretPosition ()

TheTextArea class (but not the TextField class) also has insert() andreplaceRange () methodsyoucan use for pasting: public synchronized void insert(String s, int pos) public synchronized void replaceRange (String s, int start, int end)

What's the differencebetweenthese two methods? Whenwouldyou use insert() andwhenwouldyouuse replaceRange ()?

ImplementingCopy and Paste

Implementing Copy and Paste

Implementing Copying

1. Get the systemclipboardusingthe getSystemClipboard () methodof thejava.awt.Toolkit class.

2. Create a new object, suchas a StringSelection , whichimplementsthetransferableinterfaceand containsthe data youwant to copy.

3. Put thatobject on the clipboardusingthe setContents() methodof theClipboardclass.

For example,

public void copy(TextField tf) {

Page 333: Java Predavanje I

StringSelection data = new StringSelection (tf.getText()); Clipboard clipboard = Toolkit().getDefaultToolkit ().getSystemClipboard (); clipboard.setContents(data, data); }

Implementing Pasting

1. Get the systemclipboardusingthe getSystemClipboard () methodof thejava.awt.Toolkit class.

2. Get the clipboard's contentsusingusingthe getContents() methodof theClipboardclass.

3. Get the data ina particularflavorusinggetTransferData ().4. Cast the object returnedto the approriatetype.

For example,

public void paste(TextField tf) { Clipboard clipboard = Toolkit().getDefaultToolkit ().getSystemClipboard (); Transferable data = clipboard.getContents(this); String s; try { s = (String) (data.getTransferData (DataFlavor.stringFlavor )); } catch (Exception e) { s = data.toString(); } tf.setText(s); }

A SimpleExampleof Copy and Paste

A Simple Example of Copy and Paste // This example is based on one from // the book _Java AWT Reference_ by John Zukowski.// You may study, use, modify, and distribute this example for any purpose. import java.io.*;import java.awt.*;import java.awt.datatransfer .*;import java.awt.event.*;

Page 334: Java Predavanje I

public class ClipMe extends Frame implements ActionListener { TextField tf; TextArea ta; public static void main (String args[]) { new ClipMe().show(); } public ClipMe() { super("Clipping Example"); add(tf = new TextField("Welcome"), "North"); add(ta = new TextArea(), "Center"); MenuBar mb = new MenuBar(); mb.add(makeEditMenu ()); setMenuBar(mb); setSize(250, 250); } Menu makeEditMenu () { Menu editMenu = new Menu("Edit"); MenuItem mi = new MenuItem("Cut"); mi.addActionListener (this); editMenu.add(mi); mi = new MenuItem("Copy"); mi.addActionListener (this); editMenu.add(mi); mi = new MenuItem("Paste"); mi.addActionListener (this); editMenu.add(mi); mi = new MenuItem("Clear"); mi.addActionListener (this); editMenu.add(mi); return editMenu; } public void actionPerformed (ActionEvent evt) { Clipboard clipboard = getToolkit().getSystemClipboard (); String cmd = evt.getActionCommand (); if (cmd.equalsIgnoreCase ("copy")) { StringSelection data = new StringSelection (tf.getText()); clipboard.setContents(data, data); } else if (cmd.equalsIgnoreCase ("clear")) { tf.setText(""); } else if (cmd.equalsIgnoreCase ("paste")) {

Page 335: Java Predavanje I

Transferable clipData = clipboard.getContents(this); String s; try { s = (String)(clipData.getTransferData(DataFlavor.stringFlavor )); } catch (Exception e) { s = e.toString(); } ta.setText(s); } else if (cmd.equalsIgnoreCase ("cut")) { StringSelection data = new StringSelection (tf.getText()); clipboard.setContents(data, data); tf.setText(""); } } }

Data Flavors

Data Flavors

Differentapplicationsunderstanddata differently, eventhe same kindof data. Forexamplemostword processors support some formof formattedtextwithdifferentfonts,styles, sizesand so on. HoweverMicrosoftWord 6.0 for the Mac is not able to readformattedtextproduced by ClarisWorksand viceversa. PicturesfromPhotoshopcan becopied and pasted intomanyprograms, but the layerstend to get flattenedwhenyou dothat.

The clipboardonlyreallyunderstandsraw bytes. It does not inherentlyknow howwhetherthose bytes are textor a pictureor a tableor somethingelse. Thejava.awt.datatransfer .DataFlavor classuses MIME types and subtypestoidentifythe kindof data stored inthe clipboard.

MIME, the MultipurposeInternetMailExtensions, is an InternetstandarddefinedinRFCs 2045 through2049 for transferringmultimedia, binarydata through7-bit ASCIIemail. RFC 2046 inparticularspecifiesthe MIME type systemand definesthe base setof mediatypes. New MIME types are registoeredwithand approved by the InternetAssignedNumbersAuthority(IANA). The currentlistof standardizedtypes is availablefromftp://ftp.isi.edu/in-notes/iana/assignments/media-types/media-types.

A MIME type has a type and a subtype. For example, text/plain, application/x-java-serialized-object, or image/gif. Thereare fivedefinedtypes: text, image, audio, video,multipart, message, model, and application. The firstsevenare self-explanatory. The lastis used for arbitrarybinarydata. Subtypesthat beginwithan x suchas "x-java-serialized-

Page 336: Java Predavanje I

object" are unofficial, applicationspecificextensions. Two differentprogramsare notguaranteedto interpretthe same x type as representingthe same kindof data.

The java.awt.datatransfer.DataFlavorclass

The java.awt.datatransfer .DataFlavor class

Thejava.awt.datatransfer .DataFlavor classencapsulatesa MIME type torepresentthe data formatof an object stored on the clipboardas raw bytes. Each dataflavorhas a representation class, a MIME type, and a humanpresentablename.The representationclass is the Java classwhichapproximatesthe data. For example, theplaintext flavoruses the representationclassjava.io.InputStream and the MIMEtype "text/plain; charset=unicode". The humanpresentablenameis justa slightlymorereader-friendlyvariantof the MIME type like"JPEG picture" insteadof "image/jpeg".

Currentlytwo specificdata flavorsare defined, DataFlavor.plainTextFlavor andDataFlavor.stringFlavor .

Thereare two constructorsthat allowyou to create new data flavors:

public DataFlavor(Class representationClass , String humanPresentableName ) public DataFlavor(String mimeType, String humanPresentableName )

The firstconstructorspecifiesthe representationclassand the humanpresentablename.Howeverthe MIME type is normallyset to "application/x-java-serialized-object". Thesecond constructorletsyouset the MIME type but uses the representationclassInputStream .

Givena data flavor, the followingmethodsretreiveand set informationabout the flavor:

public String getMimeType() public Class getRepresentationClass () public String getHumanPresentableName () public void setHumanPresentableName (String humanPresentableName ) public boolean equals(DataFlavor dataFlavor) public boolean isMimeTypeEqual (String mimeType) public final boolean isMimeTypeEqual (DataFlavor dataFlavor)

The java.awt.datatransfer.Clipboardclass

Page 337: Java Predavanje I

The java.awt.datatransfer .Clipboard class

Thejava.awt.datatransfer .Clipboard class representsan object onto whichyoucan put transferableobjects and fromwhichyou can get transferableobjects.

There's one constructoryoucan use to create privateclipboards. Howevermostof thhetimeyou'lljustget the systemclipboardinstead:

public Clipboard(String name)

Thereare also three methodsthat allowyou to get the nameof the object currentlyon theclipboard(onlyone object can be on a clipboardat a time), to get the contentsof theclipboard(paste), or to set the contentsof the clipboard(cut or copy): public String getName() public synchronized void setContents(Transferable contents, ClipboardOwner owner) public synchronized Transferable getContents(Object requestor)

The java.awt.datatransfer.ClipboardOwnerinterface

The java.awt.datatransfer .ClipboardOwner interface

For synchronizationpurposes each clipboardmustbe the exclusivepropertyof oneobject. Thisobject mustimplementthe java.awt.datatransfer .ClipboardOwnerinterface. Thisinterfacedeclaesa singlemethod, lostOwnership (), whichis whichisused to warn an object that it no longerowns the clipboard. public abstract void lostOwnership (Clipboard clipboard, Transferable contents)

The java.awt.datatransfer.Transferableinterface

The java.awt.datatransfer .Transferable interface

Thejava.awt.datatransfer .Transferable interfacemustbe implementedby anyclass thatwillrepresentthe data to be cut or pasted. It definesthree methods: public abstract boolean isDataFlavorSupported (DataFlavor flavor) public abstract DataFlavor[] getTransferDataFlavors () public abstract Object getTransferData (DataFlavor flavor)

Page 338: Java Predavanje I

throws UnsupportedFlavorException , IOException

You can ask a Transferable object whetherit supportsa particulardata flavoryouwantwithisDataFlavorSupported () or you can ask it to listallthe data flavorsitsupportswithgetTransferDataFlavors ().

Note especiallythatone object maysupport multipledata flavors. For example, mostobjects shouldprovidea plaintext flavoras a lowestcommondenominatorallapplicationscan handle. However, the same data mayalso be availableinan HTMLflavorfor applicationsthat can handlethe additonalformatting.

Finallyyou requestan object of a particularflavorwithgetTransferData (). If theflavoryou request is not availablean UnsupportedFlavorException is thrown.

The java.awt.datatransfer.StringSelectionclass

The java.awt.datatransfer .StringSelection class

Thejava.awt.datatransfer .StringSelection class is the onlyconcreteimplementationof the java.awt.datatransfer .Transferable interfaceand thejava.awt.datatransfer .ClipboardOwner interfaceinJava 1.1. It letsyou transfera stringinplaintext format.

It has the fourmethodsit mustimplementto support its interfaces:

public abstract boolean isDataFlavorSupported (DataFlavor flavor) public abstract DataFlavor[] getTransferDataFlavors () public abstract Object getTransferData (DataFlavor flavor) throws UnsupportedFlavorException , IOException public void lostOwnership (Clipboard clipboard, Transferable contents)

It also has a constructoryouuse to create a new StringSelection object: public StringSelection (String data)

Continuing Onward

FutureDirectionsObject OrientedAnalysisand DesignJava 2D APIJava 3D APIThe VirtualMachineand ByteCode

Page 339: Java Predavanje I

Java's SecurityModelCode signingand encryptionwiththe java.securitypackageNativeMethodsJDBCRemoteMethod Invocation(RMI)Java Web ServerJavaBeansThe Java Media APIJava TelephonyServicesAPIJavaOSJava ElectronicCommerceFrameworkJavaSpacesProtocoland ContentHandlersThe Java Namingand DirectoryInterface(JNDI)CORBA and IDLJavaScript