You are on page 1of 339

Prvo predavanje

Javom

upoznavanje s

Aplikacija Hello World kompiliranje i izvravanje 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 viestruko
referenciranje objekta staticke varijable metode prenoenje 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 izvravanje programa


Trisu koraka u stvaranjuprograma:
1. pisanjekoda
2. kompilacijaizvornogkoda
3. izvravanjekompilirnogkoda
Pod UNIXomkompilacijai izvravanjeizgledaovako:
% javac HelloWorld .java
% java HelloWorld
Hello World
%

Na racunalustudent .math.hr se Java kompajler(javac ), Java interpreter(java ) i


ostalialatinalazeu direktoriju/opt/java/bin , dakle dodajte taj direktoriju vau $
PATH varijablu:
% export PATH=$PATH:/opt/java/bin

Pod Windowsimaslicno; mora se koristitiDOS-shell:


C:> javac HelloWorld .java
C:> java HelloWorld
Hello World
C:>

Pri tom opet varijablaPATH koja se definirau odgovarajucemretku datoteke


autoexec .bat ilipomocu
Start

Settints

System

Environment Variables

PATH

mora sadravatiodgovarajucidirektorij, npr ;c:\jdk1.3.0_02\bin\;


Primijetiteuporabu .java ekstenzijekod kompiliranja,aline i .class ekstenzijekod
izvravanja.

for-petlje
class 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.

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!
Hello
there!
%

Za ispisretka koristese metode println (...) izklase PrintStream . U naem


programu System.out.println () ispisujesadraj standardnogoutput streama
System.out klase System , u ovomslucajuargumenteizakojihslijediline-separator
ovisano platformi([carriage return] (ASCII 13, \r) i [linefeed ] (ASCII 10, \n)
na Windowsima, [linefeed ] na UNIXu, [carriage return] na Mac-u)

System.err.println ()
System.err .

ispisujesadraj sa standardnogerror output streama

Moete konkateniratiargumenteza println () pomocuznaka +, npr.


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

Ako koristiteprint() umjestoprintln () onda nakon ispisanemaznaka za novi


redak. Npr,
System.out.print("Ucitano je ");
System.out.print(args.length);
System.out.print(" argumenata s komandne linije");
System.out.println ();

prekida linijui pokrece ispis. U praviluse nitanece ispisatina


ekranudok god se ne pojaviznak za prijelomlinije.
System.out.println ()

Fibonaccijevi brojevi
class 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 pridruivanje


varijabli.

Variable i tipovi podataka


U javipostoji8 primitivnihtipovapodataka:
boolean
byte
short

int
long
float
double
char

Medutimpostojisamo 7 vrsta literala, a jedan medunjima(String ) nijeprimitivnitip


podataka:

Ne

boolean : true ilifalse


int : 89, -945, 37865
long : 89L, -945L, 5123567876L
float : 89.5f, -32.5f,
double : 89.5, -32.5, 87.6E45
char : 'c', '9', 't'
String : "Ovo je string literal "
postoje literalitipa short ilibyte .

je referentni iliobjektni tip, ne primitivni


. Medutim, java kompajlerima
posebnu podrku za String ove, pa moeizgledatikao da je to primitivnitip.
String

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

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

System.out.println ("Hello World!");


} // main metoda ovdje zavrsava
} // HelloWorld program ovdje zavrsava

Komentarise evaluirajuu znak space (praznina), a ne u nita. Zato bi sljedeciprimjer


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

Java ovo pretvarau pogrenunaredbu


int i = 78 76;

a ne u
int i = 7876;

Argumenti na komandnoj liniji


class 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 u


programkao polje stringova. Pocetna komponentasvakog polja uvijekje nulta. Npr,
% java printArgs Hello There
args[0] je string"Hello".
args[1] je string"There".
args.length je 2.

Svi argumentis komandnelinijeprenose se kao stringovi, nikadkao brojevi. Kasnijecete


naucitipretvaratistringoveu brojeve.

Klase, atributi i metode


Klasa je obrazac iliprototipkoji definiravarijablei metode zajednickesvimobjektima
neke vrste

Atribuitikau to nekiobjekt jest.


Metode kau to nekiobjekt radi.
class TwoDPoint {
double x;
double y;
}

Da biste kompiliralitu klasu, spremiteje u datoteku TwoDPoint .java i otipkajte:


% javac TwoDPoint .java

Primijetiteda ovo nije kompletanprogram. Ne moetega, naime, izvritijer mu


nedostaje main() metoda.

Objekti
Objekt je primjerak(instanca) klase.
Objekte moetekreiratipomocukljucnerijecinew izakoje slijeditzv. konstruktor
klase. Sljedeciprogramkreira objekt tipa TwoDPoint 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;
origin.y = 0.0;

// Inicijaliziramo njegove atribute

// 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. Pozivkonstruktorauz kljucnurijec new


potreban je za alociranjeobjekta.
Staviteovu klasuu datoteku OriginPrinter .java u istomdirektorijukao
TwoDPoint .java , kompajlirajteje i izvrite(to je sada kompletanprogram):
% javac OriginPrinter .java
% java OriginPrinter

Ishodiste ima koordinate 0.0, 0.0


%

Razlikovanje objekata iste klase


Opcenito, klase ce imativieod jednogobjekta. Za razlikovanjeobjekata unutariste
klase koristese referentnevarijable. Sljedeciprogramkreira dva razlicitaobjekta tipa
TwoDPoint 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 TwoPointPrinter
Ishodiste ima koordinate 0.0, 0.0
Tocka one ima koordinate 1.0, 0.0
%

Variableone i origin su dvijerazlicitereferentnevarijablekoje pokazujuna dva


razlicitaobjekta. Nije dovoljnosamo identificirativarijablukao clanaklase, vec treba
specificiratina koji objekt u toj klasise ona referira.

Viestruko referenciranje objekta

Moguceje da dvijereferentnevarijablepokazujuna istiobjekt. Kad na nekiobjekt ne


pokazujenijedna referentnavarijabla, on ce bitioznacenza uklanjanje(garbage
collection). Sljedeciprogramdeklariradvijereferentnevarijabletipa TwoDPoint, kreira
jedan objekt tipa TwoDPointi pridruujetaj objekt objema varijablama. Te se dvije
varijablesmatrajujednakima.
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 EqualPointPrinter
Tocka origin1 ima koordinate 0.0, 0.0
Tocka origin2 ima koordinate 0.0, 0.0
%
Primijetiteda su origin1 i origin2 dvijerazlicitereferentnevarijablekoje referenciraju
istiobjekt tipa point .

Staticke varijable
Statickavarijablaje varijablaklase, ona pripada klasi(samoj klasi), a ne nekom
objektu (instanciklase).
class Point {
double x;
double y;
static double xorigin = 0.0;

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 PointPrinter
Ishodiste je u tocki (0.0, 0.0)
%

Primijetiteda za ispisstatickihvarijablinijebilopotrebno kreiratikonkretniobjekt.


Varijablamaklase pristupase pomocuimenaklase, a ne pomocuimenareferentne
varijable.

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

Primijetiteda se kljucnarijec this koristikako bi se iznutrareferenciralavarijablakoja


pripada istojklasi. Sada moemopreraditiprogramOriginPrinterovako:
class OriginPrinter {
public static void main(String[] args) {
TwoDPoint origin;
origin = new TwoDPoint ();
origin.x = 0.0;
origin.y = 0.0;

origin.print();
}
}

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

Prenoenje argumenata u metodu


Dodat cemo klasi TwoDPoint 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 listaargumenatarazrjeujeovu dvosmislenost.To se naziva
overloading. Metoda System.out.println () takoder primjeroverloaded metode.
Metoda main(String[] args) je non-overloaded metoda koja imapolje
String ova 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);
}
}

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 klasi TwoDPoint dodati novumetoduza ispis, getAsString () koja
za razlikuod prethodnedvijeimapovratnitip (return type) i vraca vrijednosttipa
String .
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 ovu metodumoemokoristitina svimmjestimagdje bi inacedola vrijednost


tipa String , npr,
String s = origin.getAsString ();
System.out.println (s);

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

Sada moemojo jednompreraditiklasu OriginPrinter :

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 metode samo postavljajuvrijednosti
varijabli(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;
}
}

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 metode samo vracajuvrijednostivarijebli
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;
}

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 dugo dok se razlikujupo
listiargumenatai povratnomtipu. Npr. klasi TwoDPoint koja sadriattributex i y
moemododati i istoimeneaccessor metode bez 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 + ")");
}
}

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 moemoumjestosetX(value) koristitix(value), a umjestogetX() stavitix() i


analognoza y. tako da OriginPrintermoeizgledatii 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:

% javac TwoDPoint .java


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

Konstruktori
Konstruktorislueza instanciranjeklasa, dakle kreiranjeobjekata koji su instanceneke
klase. To su posebne metode koje imajuisto imekao njihovaklasa i ne vracajunikakvu
vrijednost. 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() {

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

U jednoj klasimoebitii viekonstruktora. Svakikonstruktorzadaje po jedan nacin


kreiranjaobjekata 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 kljucna


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

this.x = x;

Klasu TwoDPointmoemo, 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;

}
}

Kaemo da unutarmetode, deklaracijalokalnevarijableiliargumentasa istimimenom


kao neka (member) varijablaskriva ilizasjenjuje(hides)tu varijablu. Ona se moe
referenciratidodavanjemprefiksathis .

Polja
Polje je kolekcijavarijabliistogtipa. Npr. args[] u main() metodije polje objekata
tipa String .
Zamislimoklasukoja broji pojavljivanjaznamenaka0-9. Pretpostavimoda elimo
testiratida lije raspodjelabrojeva koje generirageneratorslucajnihbrojeva doista
uniformna.Ako jest, sve znamenkabi trebaleimatipriblinoistufrekvencijunakon duljeg
vremena.
Napravitcemo polje ndigits od 10 elemenata. Nultielementce pratitibroj
pojavljivanjanula, prvielementbroj pojavljivanjajedinicaitd. Koristitcemo klasu
java.util.Random . Za generiranjeslucajnihbrojeva koristitcemo metodu
nextDouble () 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++) {
ndigits [i] = 0;
}

for (long i=0; i < 100000; i++) {


slucajnih brojeva
x = myRandom .nextDouble () * 10.0;
izmedju 0 i 9
n = (int) x;
broj
ndigits [n]++;
dobivenog slucajnog broja
}

// inicijaliziranje polja

// testiranje generatora
// novi slucajni broj
// pretvaranje u cijeli
// biljezimo pojavu

for (int i = 0; i < 10; i++) {


// ispis rezultata
System.out.println (i+": " + ndigits [i]);

}
}
}

Ispis moeizgledatiotprilikeovako:
% javac RandomTest .java
% java RandomTest
0: 9967
1: 9808
2: 10069
3: 10057
4: 9984
5: 9932
6: 10004
7: 10128
8: 9952
9: 10099
%

U programusu tri for -petlje: jedna za inicijaliziranje


polja, drugaza izvodenje
odgovarajucihracunai treca za ispisrezultata. To je uobicajenou programimakoji
koristepolja.

Drugo predavanje
proceduralna sintaksa
Primitivni tipovi podataka operatori razmak literali identifikatori kljucne
rijeci separatori zbrajanje cijelih brojeva zbrajanje brojeva tipa double
mnoenje i dijeljenje neocekivani kvocijenti racunanje ostatka , modulo
prioritet izvravanja operatora zagrade mijeanje tipova podataka automatsko
dodjeljivanje tipova podataka (casting ) pretvaranje stringova u brojeve podaci
tipa char Unicode naredbe za kontrolu toka naredba if ispitivanje jednakosti
klauzula else klauzula else if while petlja for petlja do while petlja
booleovski podaci relacijski operatori prioritet izvravanja relacijskih operatora
ispitivanje jednakosti objekata naredba break naredba continue labelirane
petlje naredba switch-case kondicionalni operator (? :) logicki operatori
prioritet izvravanja logickih operatora deklariranje polja kreiranje polja
inicijaliziranje polja metoda System.arraycopy () deklariranje , alociranje i
inicijaliziranje dvodimenzionalnih polja viedimenzionalna i neuravnoteena polja

Primitivni tipovi podataka


Primitivnitipovipodataka u Javivrlosu slicnionimau C i C++. To su boolean , byte ,
short , int , long , float , double i char . Tip boolean je dodan u Javi.
Implementacijaje medutimbitnoprocicenana nekolikonacina.
1. Dok C i C++ ostavljajumnogestvariovisnimao mainii kompajleru(npr. duljinu
za int ), Java specificirasve.
2. Java ne doputa pretvaranjetipovaizmeduproizvoljnihvarijabli. Doputenoje
pretvaranjejedinomedunumerickimvarijablamate izmedupodklasa i nadklasa
istogobjekta.
3. Sve numerickevarijableu Javisu oznacene.
boolean

1-bit. Moe poprimitivrijednostitrue ilifalse .


true i false su definiranekonstantejezikai nisuisto to i True i False , TRUE i
FALSE , nulai ne-nula, 1 i 0 ilibilokoja druganumerickavrijednost. Ne moese

pretvoritiniu jedan drugitip varijablenitise drugitipovimogupretvoritiu


boolean .
byte

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


short

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


int

4 bytea, oznacena(komplementod 2), od -2,147,483,648 do 2,147,483,647.


Kao kod svihnumerickihtipova, moguceje pretvaranje(casting) u ostale
numericketipove(byte , short , long , float , doubl e). Kod pretvaranjas

gubitkominformacija(lossy casts), npr int u byte , konverzijase obavlja


moduloduljina 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 do


3.40282346638528860e+38 (positivniilinegativni).
Kao kod svihnumerickihtipova, moguceje pretvaranje(casting) u ostale
numericketipove(byte , short , long , int , double ). Kod pretvaranjas
gubitkominformacija(lossy casts), npr float u short , decimalnidio se
odbacuje, i konverzijase obavljamoduloduljina kraceg tipa.
double

8 bytea IEEE754, od 4.94065645841246544e-324d do


1.79769313486231570e+308d (positivnior negativni).
char

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


Vrijednostitipa char nisuisto to i vrijednostitipa byte , int , short ili
Strings .

Operatori

Operator

Akcija
+
Zbrajanjebrojeva, konkatenacijastringova
+=
Zbrajanjei pridruivanjebrojeva, konkatenacijai pridruivanjestringova
Oduzimanje
-=
Oduzimanjei pridruivanje
*
Mnoenje
*=
Mnoenjei pridruivanje
/
Dijeljenje
/=
Dijeljenjei pridruivanje
|
BitovskiOR
|=
BitovskiOR i pridruivanje
^
BitovskiXOR
^=
BitovskiXOR i pridruivanje
&
BitovskiAND
&=
BitovskiAND i pridruivanje
%
Modulo(racunanjeostatka)
%=
Moduloi pridruivanje
>
Vece
>=
Vece ilijednako
<
manje
<=
Manje ilijednako
!
booleovskiNOT
!=
razlicito
++
Povecavanjeza jedan
-Smanjivanjeza jedan
>>
Shift pomak bitovau desno, zajednosa znakom
>>=
Shift pomak bitovau desno, zajednosa znakomi pridruivanje
<<
Shift pomak bitovau lijevo
<<=
Shift pomak bitovau lijevoi pridruivanje
>>>
Neoznacenibitovskishiftu desno
>>>=
Neoznacenibitovskishiftu desno i pridruivanje
&&
BooleovskiAND
||
BooleovskiOR
==
Booleovskajednakost
=
Pridruivanje
~
BitovskiNOT
?:
Uvjet
instanceof Provjera tipa

Razmak (white space)


Razmakje u praviluznak [space], koji dobijetekad pritisnete<spacebar> no u Javi
postoje jo 4 znaka za 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 proizvestitvrdi
prijelomlinijeu tekstu izvornogprograma.
Osimu literalimatipa String , jedan razmakje ekvivalentannizuuzastopnihrazmakabilo
koje vrste.
Unutarliteralatipa String i char jedinidozvoljenirazmakje znak [space]. Umjesto
znakova[horizontaltab], [formfeed], [carriagereturn] i [linefeed] morajuse stavljati
odgovarajuceescape-sekvence, npr. \t, \r, \f i \n. Ne moeterazlomitistringovako:
String poem = "Mary had a little lamb
whose fleece was white as snow
and everywhere that Mary went
the 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 moeterazlomitikroz nekolikoredaka, jedinone moeteto uciniti


sa literalimatipa String . Takoder primijetiteda \n funkcionirasamo na UNIX-u. Ako
elitesvoj kod ucinitineovisnimo platformi, umjesto\n upotrijebitcete metodu
System.getProperty ("line.separator ") koja ce vratitiodgovarajuciznak za danu
platformu. Pogledajtetakoder i metodu System.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 dozvoljavaju
umetanjebilokojeg Unicodeznaka.

Literali
Literalitipa String oznacavajuse dvostrukimnavodnicima,npr HelloWorld!.
Takoder, dva + dva je isto to i dvadva . Navodnici, medutimnisu dio literala.
Vrijednostliterala HelloWorld! je HelloWorld!, a ne HelloWorld!. Takoder
formatiranjeznakovanemautjecajana vrijednoststringa, dakle Hello World! je isto
to i HelloWorld!.
Literalitipa char oznacavajuse jednostrukimnavodnicimai smijusadravatitocno jedno
slovo, npr. c je literaltipa char cija vrijednostje slovoc.

Booleovskiliteralisu true i false , a znaceistinui la.


Brojevimogutakoder bitiliterali. Npr. 34 je literaltipa int i njegovaje vrijednostbroj
34, dok je 1.5 literaltipa double , a to su i 45.6, 76.4E8 (76.4 puta 10 na osmu) i
-32.0.
Nadalje, 34L je literaltipa long i oznacavabroj 34, dok su 1.5F, 45.6f i 76.4E8F
literalitipa float.

Identifikatori
Identifikatori su imenavariabli, metoda, klasa, paketa i sucelja. Za razlikuod literalato
nisusame stvarinego nacinnjihovogreferenciranja. U programuHelloWorldidentifikatori
su HelloWorld , String , args , main i System.out.println .
Identifikatorimorajubitisastavljeniod slova, brojeva i znakova_ (underscore) i $
(dollarsign). Pocetno slovoidentifikatorasmijebitisamo slovo, _ ili$. Mala i velikaslova
se razlikuju. Ime ne moesadravatirazmak.
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
testing 1-2-3 // - nije alfanumericki znak
O'Reilly // ' nije alfanumericki znak
OReilly _&_Associates // & nije alfanumericki znak

Kljucne rijeci

Postoji50 rezerviranihkljucnihrijecikoje u Javi1.1 (51 u Javi1.2). U tablicije navedeno


njih48 koje se stvarnokoriste.

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 akcija za switchnaredbu
Do
Pocetak do whilepetlje
double
deklariradouble variabluilipovratnitip
Else
Oznacavadio koda koji se izvravaako uvjetu if naredbinijeistinit
extends
Oznacavada je promatranaklasa potklasa neke drugeklase
Deklarirada klasa ne moeimatipodklasuilida varijablailimetoda ne
Final
moebit pregaena
finally
Deklarirablok koda koji ce garantiranobitiizveden
Float
deklarirafloat variabluilipovratnitip
For
Pocetak for petlje
If
Izvravakod ako je uvjetistinit
implements
Deklarirada promatranaklasa implementiradano sucelje
import
Doputa pristupklasiiligrupiklasa 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
Definirapaket kojemupripada datoteka sa promatranimizvornim
package
kodom
private
Deklarirametoduilimembervarijablukao privatnu
protected
Deklariraklasu, metoduilimembervarijablukao zaticenu
public
Deklariraklasu, metoduilimembervarijablukao javnu
return
Vraca vrijednostizmetode
Short
deklarirashort (short integer) variabluilipovratnitip
static
Deklarirada varijablailimetoda pripada klasi, a ne objektu
Super
Referencana roditeljapromatranogobjekta
switch
Ispitujeistinitostnekolikomogucihuvjeta
synchronized Oznacavada je promatranidio koda osjetljivna threadove
this

throw
throws
transient
try
void
volatile
while

Referencana sam promatraniobjekt


Odbacivanjeiznimke
Deklariraiznimkekoje metoda odbacuje
Varijablane smijebitiserijalizirana
Pokuava izvritioperacijukoja moeeventualnoodbacitiiznimku
Deklarirada metoda ne vraca nikakvuvrijednost
Upozoravakompajlerda se varijablamijenjaasinhrono
Pocetak whilepetlje

Jo dvije, const i goto , rezerviranesu, alinisuimplementirane


. To omogucuje
kompajlerubolje kreiranjeporuka o pogrekamau slucajukriveupotrebe ovih
uobicajenihkljucnihrijecijezikaC++ u Java programima.
Java 1.2 dodaje kljucnurijec strictfp kojom se deklarirada metoda iliklasa mora biti
izvrenasa egzaktnomIEEE754 semantikom.
Primijetiteda true and false nisukljucnerijecinego booleovskiliterali. Svejedno, ni
njihne moetekoristitikao imenavarijabli.

Separatori
Separatoripomauu definiranjustructureprograma. U programuHelloWorldkoristese
zagrade, ( ), viticastezagrade, { }, tocka, ., tocka-zarez, ;.
Separator
()
{}
[]
;
,
.
:

Svrha
Zatvaraargumenteu definicijamai pozivimametoda; podeava prioritete
izvravanjau aritmetickimizrazima; okruujeumjetnopretvorenetipove
podataka (cast types); izdvajauvjetneizrazeu naredbamaza kontrolutoka
Definirablokovekoda; automatskiinicijalizirapolja
Deklarirapolje tipova; izdvajavrijednostielemenatapolja
Zavravanaredbu
Razdvajananizaneidentifikatoreu deklaracijamavarijabli; ulancavanaredbe
u uvjetnomdijelufor petlje
Selektiravarijabluilimetodunekog objekta; separiraimenapaketa od imena
podpakete i imenaklasa
Koristise nakon labelau petljama

Zbrajanje cijelih brojeva


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

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 izvriteAddInts :


%
%
i
j
i
i
%

javac AddInts .java


java AddInts
je 1
je 2
+ j je 3
- j je -1

Zbrajanje brojeva tipa double


Brojevitipa double sadre 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:

%
%
x
y
x
x

javac AddDoubles .java


java AddDoubles
je 7.5
je 5.4
+ y je 12.9
- y je 2.0999999999999996

Mnoenje i dijeljenje
Operatori mnoenjai dijeljenjasu * (mnoenje) 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 MultiplyDivide
i je 10
j je 2
i/j je 5
i * j je 20
%

Realnibrojevitipa floati doublemnoese i dijelena istinacin. U slucajucjelobrojnog


dijeljenja, rezultatse zaokruujeprema dolje. Npr. cjelobrojnodijeljenje10 sa 3 daje 3.

Neocekivani kvocijenti
2/3 = 0
3/2 = 1
1/0 = ArithmeticException
0/0 = ArithmeticException
1.0/0.0 = Inf
1.0/0 = Inf

0.0/0.0 = NaN (not a number )


-1.0/0.0 = -Inf
Inf + 1 = Inf
Inf + Inf = Inf
Inf - Inf = NaN
Inf/Inf = NaN
NaN + anything = NaN
NaN - anything = NaN
NaN * anything = NaN
NaN - anything = NaN
NaN < NaN je false
NaN > NaN je false
NaN <= NaN je false
NaN >= NaN je false
NaN == NaN je false
NaN != 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 Remainder
i je 10
j je 3
i%j je 1
%

Primijetiteda se operacijamodulomoeu Javiprimijenitii na realnebrojeve. Npr. 5.5 %


1.5 je 1.

Prioritet izvravanja operatora

Vie operatora moebitiu istomizrazu:


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

Sljedeciprogramracunaenergijuekvivalentnumasijednogelektronauz pomoc
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 mc2
8.18771e-08
%

U slucajurazlicitihoperatora, prioritetje uobicajen: Sljedece tri naredbe su ekvivalentne


int n = 1 - 2 * 3 - 4 + 5;
int n = 1 - (2 * 3) - 4 + 5;
int n= -4;

Unutardo sada spomenutihoperatora, operacijese izvravajusljedecimprioritetom:


1. *, /, % Sva mnoenja, dijeljenjai modulood lijevana desno.
2. +, - Sva zbrajanjai oduzimanjaod lijevana desno.
3. = Pridruivanjedesne strane lijevoj

Zagrade
Zagradese koristeza mijenjanjeuobicajenogredosljedaoperacija. Sljedeciprimjer
pokazujepretvaranjeFahrenheitovihstupnjevau Celsiusovepo formuliC = (5/9) (F 32) gdje su C stupnjeviCelsiusaa F stupnjeviFahrenheita. Programispisujetablicu
konverzijaizmedu0 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;

// 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 FahrToCelsius
0.0 F = -17.77777777777778 C
20.0 F = -6.666666666666667 C
40.0 F = 4.444444444444445 C
60.0 F = 15.555555555555557 C
80.0 F = 26.666666666666668 C
100.0 F = 37.77777777777778 C
120.0 F = 48.88888888888889 C
140.0 F = 60.0 C
160.0 F = 71.11111111111111 C
180.0 F = 82.22222222222223 C
200.0 F = 93.33333333333334 C
220.0 F = 104.44444444444444 C
240.0 F = 115.55555555555556 C
260.0 F = 126.66666666666667 C
280.0 F = 137.77777777777777 C
300.0 F = 148.88888888888889 C
%

U ovomprogramunemamnogonovogu odnosu na prethodneprimjere, no panju


obratimona sljedeculiniju:
celsius = (5.0 / 9.0) * (fahr-32.0);

To je prijevodformuleC = (5/9)(F - 32) gdje je dodana * za mnoenjejer Java ne


podravaimplicitnomnoenjefaktora u zagradama. Zagradese koristekao i u obicnoj
algebri, za prilagodbupravilaprioriteta. Za operacijekoje koristeuobicajenearitmeticke
operatore (+, -, *, /), pravilaprioritetasu ista kao i u obicnojalgebri.

Mijeanje tipova podataka


Razlicititipovipodataka moguse pojavitiu istojnaredbi. Primjerpokazujeistovremenu
upotrebu int 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
k = i * x;
System.out.println ("i
k = i - x;
System.out.println ("i
k = x - i;
System.out.println ("x
k = i / x;
System.out.println ("i
k = x / i;
System.out.println ("x

+ x je " + k);
* x je " + k);
- x je " + k);
- i je " + k);
/ x je " + k);
/ i je " + k);

}
}

Izlaz:
%
%
i
x
i
i
i
x
i
x

javac IntAndDouble .java


java IntAndDouble
je 10
je 2.5
+ x je 12.5
* x je 25.0
- x je 7.5
- i je -7.5
/ x je 4.0
/ i je 0.25%

Redoslijedmoeimatiutjecajana rezultatkad se tipovipodataka mijeaju. Na primjer,


1 / 2 * 3.5 = 0.0
3.5 * 1 / 2 = 1.75
3.5 / 2 = 1.75

Kod mijeanjatipovapodataka, uobicajenimatematickizakonikomutacijeopcenitone


vrijede, posebno ne kad se mijeajucjelobrojne(integer) i realne(floating point)
vrijednosti.
1.0 / 2 * 3.5 = 1.75
3.5 * 1.0 / 2 = 1.75
1 / 2.0 * 3.5 = 1.75
3.5 * 1.0 / 2.0 = 1.75

Automatsko dodjeljivanje tipova


podataka (casting)
Ako int podijelimosa int dobijemo int .
Ako double podijelimosa double dobijemo double .
Ako int podijelimosa double ilidouble sa double , dobijemo double jer u slucaju
nejednakostitipovaJava teidodjeljivanjuto iregtipa kako se sprijecilogubljenje
informacija.
Pravilo:
Ako je bilokoja varijablau aritmetickojbinarnojoperaciji(zbrajanje,
oduzimanjemnoenje, dijeljenje, modulo) tipa double onda Java tretira
obje vrijednostikao double .
Ako nijedna nije double , alije jedna float , Java tretiraobje vrijednosti
kao float .
Ako nijedna nijeni float ni double , alije jedna long , Java tretiraobje
vrijednostikao long .
Konacno, ako nijedna nije double , float ni long , Java tretiraobje
vrijednostikao int , cak ako u jednadbiuopce nemacijelihbrojeva.
Dakle, rezultatce biti double , float , long iliint , ovisnoo tipovimaargumenata.
U naredbipridruivanja
, dakle ako postojiznak jednakosti, Java usporedujetip na lijevoj
stranisa konacnimtipomna desnoj strani. Tip na lijevojstraninece se promijeniti
, alice
se provjeritida livrijednostsa desne strane (double , float , int or long ) odgovara
tipuna lijevojstrani. Sve se moesmjestitiu double. Sve osim double moese
smjestitiu float. Svakicjelobrojnitip moese smjestitiu long , ali float i double ne
mogu, dok se sve tipa int , short i byte moesmjestitiu int . Ako se desna strana
moesmjestitiu lijevu, pridruivanjese normalnoobavlja.
Pridruivanjevrijednostitipa long varijablamatipa int ilipak vrijednostitipa double
varijablamatipa float moeuzrokovatiproblemei kompajlervamtakva pridruivanja
nece dopustitiosimako eksplicitnonavedeteda elitepretvaranje(casting). Prisilno

pretvaranjetipovaoznacavase navodenjemodgovarajucegtipa u okruglimzagradama


neposrednoprije izrazakoji treba pretvoriti. Na primjer,
int i = (int) 9.0/4.0;

Kad se vrijednostpretvarau drugitip prije pridruivanja


, nizoperacijase poduzimada bi
se desna strana skratila na pravuvelicinu.Za konverzijuizmedurealnih(floating point)
i cijelihbrojeva (npr. int ililong ), razlomljenidio se odbacuje (zaokruujena nulu). To
ce proizvesticijelibroj. Ako je on dovoljnomalida stane u lijevustranu, pridruivanjeje
zavreno. U suprotnom, ako je prevelik, bit ce mupridruenanajveca, a ako je premali,
najmanjamogucavrijednostza odgovarajucitip.
Valjavoditiracunao tome da prisilnopretvaranjemoeuzrokovatipogreke kojimace
bitivrloteko uciu trag i zato ovu mogucnosttreba koristitis oprezom.

Pretvaranje stringova u brojeve


Prilikomobrade korisnickoginputacesto je potrebno neki String pretvoritiu int . To
se radi uz pomoc staticke metode Integer .valueOf (String s) u kombinacijis
(nestatickom) metodom intValue () koje pripadajuklasi java.lang.Integer . Npr.
String "22" pretvorilibismou int 22 na sljedecinacin:
int i = Integer .valueOf ("22").intValue ();

S tipovimadouble , float i long postupamoslicno, koristecistatickemetode


Double.valueOf (String s), Float.valueOf (String s) i Long.valueOf
(String s) u kombinacijis odgovarajucimmetodamadoubleValue () , floatValue
() i longValue () koje pripadaju, respektivno, klasama java.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 () metode relativnosu inteligentnei moguprepoznatiznakoveplusi


minus, eksponentei ostale uobicajenebrojcane formate. Medutim, ako kao argument
dobijuneto potpunone-numericko, npr. "Hello World", vjerojatnoce izbaciti
NumberFormatException . Za sad jo nisteucilikako baratatis iznimakamapa u svojim
programimaizbjegavajtetakve situacije.
Preraditcemo sada programE = mc2 tako da o masiu kilogramimabude prihvacenkao
korisnickiinputsa komandnelinije. Ovaj postupak tipicanje za mnogeprograme.
class mc2 {
public static void main (String args[]) {

double mass;
double c = 2.998E8;
double E;

// meters/second

mass = Double.valueOf (args[0]).doubleValue ();


E = mass * c * c;
System.out.println (E + " Joules");
}
}

Obrada i rezultati:
% javac mc2.java
% java mc2 0.0456
4.098529824 E15 Joules
%

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

Statickametoda Double.valueOf (args[0]) vratitce vrijednosttipa Double , a tek ce


metoda doubleValue () pretvorititu vrijednostu vrijednosttipa double . Zato bi
navedenalinijaizazvalagrekuu kompajliranju:
% javac mc2.java
mc2.java:8: incompatible types
found
: java.lang.Double
required : double
mass = Double.valueOf (args[0]);
^
1 error
%

Podaci tipa char


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

Za znakovekoji se ne moguutipkatiJava osiguravaescape sekvence. To je backslashiz


kojeg slijedialfanumerickikod. Npr. '\n' je znak za novireda, '\t' je znak za tab, '\
\' je sam backslash. Definiranesu sljedeceescape sekvence:

\b backspace
\t tab
\n linefeed
\f formfeed
\r carriagereturn
\" Dvostrukinavodnici, "
\' Jednostrukinavodnici, '
\\ backslash, \
Escape sekvencaza dvostrukenavodnikekoristise uglavnomu stringovimagdje bi
pojava 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 reprezentira
gotovosve znakoveu gotovosvimalfabetimai pismovnimsustavimasvijeta, ukljucujuci
engleski, arapski, kineskii druge. Problemje, medutim, to mnogioperacijskisustavii
web preglednicine podravajuUnicode. Java ce uglavnompravilnotretiratiinputneUnicodeznakova. Prvih128 znakovau Unicodetabliciidenticnisu sa uobicajenim
ASCII znakovima. Drugih128 znakovapodudara se sa gornjih128 znakovau ISO
Latin1 proirenomASCII skupu. Ostalih65,280 predstavljaproblem.
PojedinacneUnicodeznakovemoetereferenciratikoristeciescape sekvancu\u izkoje
slijedicetverocifreniheksadecimalnibroj. Npr.
\u00A9
\u0022
\u00BD
\u0394
\u00F8

"
1/2

Znak za copyright
Dvostrukinavodnici
Razlomak
Velikogrcko delta
Malo o prekrienoznakomslash

Moete cak koristitipotpuneUnicodeznakovnenizoveza imenovanjevarijabli. Npr.


String Mj\u00F8lner = "Hammer of Thor";

Naredbe za kontrolu toka

if
else
else if
while
for
do while
switch case
break
continue
Primijetiteda je goto

je rezerviranarijecalinijeimplementirana
. O obradi iznimakabit

ce rijecikasnije.

Naredba if
Primijetimoda smo se u klasi emc2 koristiliargumentoms komandnelinije, alinismo
provjeravalije lion uopce uneen. Sljedeciprogramispisujeprviargumentsa komandne
linije, aliprvo uz pomoc 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) { }. Blok koda unutarviticastihzagrada, System.out.println (args[0]), bit

ce izvrenako i samo ako je duljinapolja args veca od nule.


Argumentiza kondicionalnenaredbe kao to je if morajubitibooleovski, dakle izrazikoji
se evaluirajuna true ilifalse. Cjelobrojniargumentinisudoputeni.
%
%
%
%
%
%

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

Ispitivanje jednakosti
Testiranjejednakostije neto sloenije. Ocekivalibiste da se za ispitivanjejesu lidva
broja jednakikoristiznak jednakosti=. Medutim, on je rezerviranza operator

pridruivanjapa je za ispitivanjejednakostiuvedennoviznak, dvostrukajednakost, ==.


Taj je znak posuden izC-a.
Ta se dva znaka grekomlako moguzamijeniti
, no kako u Javinisudozvoljenina istim
mjestima, kompajlerce to otkriti. Ipak, sljedecasituacijamoebitiproblematicna:
boolean b = true;
if (b = false) {
System.out.println ("b is false");
}

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

Kako literalune moetepridruitinikakvuvrijednost, kompajlerce u tom slucajuotkriti


da 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 se
else if kako bi se mogleispitatisve mogucnosti
. Preradimosada Helloprogramtako
da barata sa 4 imenas komandnelinije.

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 rjeenja, kao to


pokazujusljedeciprimjeri.

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

// Ispis Hello

i = 0;
prolaza kroz petlju
while (i < args.length) {
System.out.print(args[i]);
System.out.print(" ");
i = i + 1;
}
System.out.println ();
}

// Inicijaliziramo brojac
// Testiramo i iteriramo

// Povecamo brojac prolaza za 1


// 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 inicijalizirati


i inkrementirativievarijabliodjednom. U
tom slucajuse inicijalizatori
i inkrementoriodvajajuzarezimakao u sljedecemprimjeru:
for (int i = 1, j = 100; i < 100;
System.out.println (i + j);
}

i = i+1, j = j-1)

Ipak, viestrukoispitivanjeuvjetana ovaj nacinnijedoputeno. Sljedeca naredba


rezultiralabi porukomo grekiu kompilaciji:
for (int i = 1, j = 100;
{ // pogresno !!!

i <= 100, j > 0;

i = i-1, j = j-1)

Za vi estruko ispitivanjeuvjetakoristebooleovskilogi ki operatori && i || o kojima e


bitirije 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 booleovskavarijablamoepoprimitijednuod dvijevrijednostitrue ilifalse .
Primijetiteda te vrijednostinisuisto to i String ovi"true" i "false", a nisuninumericke
vrijednostikao 1 i 0. Takoder primijetiteda su rijecitrue i falserezerviranerijeciu Javi,
nazivajuse booleovskiliteralii osjetljivesu na velikai malaslova.
boolean test1 = true;
boolean test2 = false;

Relacijski operatori
Java ima6 relacijskihoperatora koji usporedujudva broja i vracajubooleovsku
vrijednost. To su <, >, <=, >=, ==, i !=.
Manje
True ako je x manjeod y, inacefalse.
> y Vece
True ako je x iveceod y, inacefalse.
<= y Manje ilijednako True ako je x manjeilijednako y, inacefalse.
>= y Vece ilijednako True ako je x vece ilijednako + y, inacefalse.
== y Jednako
True ako je x jednako y, inacefalse.
!= y Nejednako
True ako je x razlicitood y, inacefalse.

x < y
x
x
x
x
x

Sljedeciprimjerikoda pokazjuuporaburelacijskihoperatora:
boolean
boolean
boolean
boolean
boolean
boolean
boolean
boolean

test1
test2
test3
test4
test5
test6
test7
test8

=
=
=
=
=
=
=
=

1 < 2;
// True
1 > 2;
// False
3.5 != 1;
// True
17*3.5 >= 67.0 - 42; // True
9.8*54 <= 654;
// True
6*4 == 3*8;
// True
6*4 <= 3*8;
// True
6*4 < 3*8;
// False

To, medutimne ilustriratipicnuuporabubooleovskihvarijabli. U praksi se one gotovo


jedinokoristeu kondicionalnimnaredbamai ispitivanjimauvjetau petljama. Vec smo
vidjeliprimjer:
if (args.length > 0) {
System.out.println ("Hello " + args[0]);
}

gdje je args.length > 0 booleovskavrijednost, dakle true ilifalse . Zato moemo


takoder pisati:
boolean test = args.length > 0;
if (test) {
System.out.println ("Hello " + args[0]);
}

Prioritet izvr avanja relacijskih


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

izazvalogrekuu kompiliranjujer 4 < 3 vraca false , a to se ne moemnoitisa 6 ili8.


Relacijskioperatoriizvravajuse nakon aritmetickih, a prijeoperatorapridruivanja
.
Operator == imaneto manjiprioritetnego <, >, <= i >=. Pogledajterevidiranutablicu
prioriteta:
1. *, /, % Sva mnoenja, dijeljenjai modulood lijevana desno
2. +, - Sva zbrajanjai oduzimanjaod lijevana desno
3. <, >, >=, <= Sva usporedivanjamedusobnihvelicina
4. ==, != Sva usporedivanjajednakostii nejednakosti
5. = Pridruivanjedesne 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 moguse
koristitisa String ovima, booleovskimvarijablamapoljima(arrays) kao nis drugim
neprimitivnim
tipovimaza koje nijedefiniranlinearniuredaj. Za jednakost == vrijedi
praviloda je true jednako true i razlicitood false . Isto tako je Jack went up the hill
razlicitood Jillwent up the hill. Medutim, pokuajte izvritesljedeciprogram:
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 druge


vrste, koristimose metodom equals(Object o) izpaketa java.lang.String .
Pogledajmoispravnuverzijuprogramakoja ce raditionako kako ocekujemo. Razloziza
ovo seuprilicnoduboko u filozofijuJave i priroduobjekata kakvisu npr. stringovi.
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.equals(s2) ) {
System.out.println ("Stringovi su jednaki .");
}
else {
System.out.println ("Stringovi nisu jednaki .");
}
}
}
% javac JackAndJill .java
% java JackAndJill
Stringovi su jednaki .
%

Naredba break
Naredba break uzrokujeizlazakizpetljeprije nego to uvjetza ulazaku sljede u iteraciju
postane la an. Na primjer, u sljedecojvarijantiprograma CountWheat koji racuna
parcijalnesumereda Si=1, ,64(2i) pri cemuse ispisujeporuka o pogrekii 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

% java CountWheat
2
6
62
126
1022
2046
16382
32766
262142
524286
4194302
8388606
67108862
134217726
1073741822
2147483646
Gotovo!
%

14
30
254
510
4094
8190
65534
131070
1048574
2097150
16777214
33554430
268435454
536870910
Overflow : grains = -2147483648

Naredba break najcece se koristiunutarnaredbe switch .

Naredba continue
Naredba continue vraca kontroluna pocetak najblieunutarnjepetljekojom je
obuhvacena, ne izvravajucipri tom ostatak naredbiu tijelupetlje. Ako je to for petlja,
brojac se inkrementira.Sljedeciprimjerpokazujekako se moepreskocitiobrada parnih
elemenatau 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 vecinislucajevaproblemmoe


rijeitii 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 tanje
najunutarnjijepetljekoja ihobuhva a. Pogledajtesljedeciprimjerdvijeugnijedene
petlje:
for (int i=1; i < 10; i++) {
for (int j=1; j < 4; j++) {
if (j == 2) break;
System.out.println (i + ", " + j);
}

Rezultatizvravanjabio bi
1,
2,
3,
4,
5,
6,
7,
8,
9,

1
1
1
1
1
1
1
1
1

jer se unutarnjapetljaprekinesvakiput kad j postane 2, alise vanjskapetljaizvrido


kraja. Ako elimoprekinutiobje petlje, labelirajmovanjskupetljui navedimotu labeluu
break 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 rezultatizvravanjabio
1, 1

jer je j postao 2, a vanjskapetljaje prekinuta.

Naredba switch-case
Switch-case naredba je zapravokraticaza odredene vrste ifnaredbi.
sljedecinizif naredbikoje se sve odnose na istuvelicinu:

Pogledajmo

if (x == 0) doSomething 0();
else if (x == 1) doSomething 1();
else if (x == 2) doSomething 2();
else if (x == 3) doSomething 3();
else if (x == 4) doSomething 4();
else doSomethingElse ();

Ovaj bi se kod uz pomoc switch-case naredbe mogaozapisatiovako:


switch (x) {
case 0:
doSomething 0();
break;
case 1:
doSomething 1();
break;
case 2:

doSomething 2();
break;
case 3:
doSomething 3();
break;
case 4:
doSomething 4();
break;
default :
doSomethingElse ();
}

U ovomprimjerux mora bitivarijablailiizrazkoji se izracunavailipretvarau int bez


gubitkainformacijaTo znacida varijablamora biti, odnosno da izrazmora vracatirezultat
tipa int , byte , short ilichar . Izraz x usporedujese redom s vrijednostimanavedenim
u svakoj case naredbidok se ne naidena podudarnost. U naemprimjeruse x
usporedujes literalima
, alito takoder mogubitivarijableiliizrazikoji vracajurezultattipa
int , byte , short ilichar . Ako se niu jednomslucajune pronade podudarnostizvrava
se akcija naznacenasa default .
Kad je podudarnostpronadena, izvravase sve to slijedido kraja switch bloka ili
naredbe break . Uobicajenoje stavljatibreak naredbuna kraj svakog case bloka kako
bi se izbjegliraznineocekivaniefekti.

Kondicionalni operator (? :)
Vrijednostneke varijablecesto ovisisamo o tome je lineka booleovskavarijablaistinita
iline. Npr. jedna od uobicajenihoperacijaje traenjemaksimumaizmedudvije
vrijednostii pridruivanjete velicinenekoj varijabli:
if (a > b) {
max = a;
}
else {
max = b;
}

Kako je ovo cesta situacija, uvedenje kondicionalnioperator ? : kao kraticaza ovakvu


if-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) istinitililaan. Ako je istinit, vraca se a, u suprotnomb.
Uvjetmoebitibilokoji izrazkoji vraca booleovskuvrijednost.
Kondicionalnioperator funkcionirajedinokod pridruivanjavrijednostinekoj varijabli,
koritenjavrijednostiza pozivanjemetode iliu nekimdrugimsituacijamakad je tip
njegovogdrugogi treceg argumentadefiniran. Pogledajmosljedeciprimjer:
if (name.equals("Rumplestiltskin ")) {

System.out.println ("Give back child");


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

Ovo se ne moe zapisatiovako:


name.equals("Rumplestiltskin ")
// ovo je primjer
pogresne upotrebe operatora ?:
? System.out.println ("Give back child")
: System.out.println ("Laugh");

Prije svega, drugii treciargumentsu void (ne vracajuvrijednost). Takoder, nikakvo


pridruivanjene naznacujetip koji bi trebaloocekivatiza drugii trecioperator (iako se
zna da to ne moebiti void ).
Prviargumentmora vracatiregularnibooleovskitip, a drugii treciargumentmoraju
vracativrijednostikoje su kompatibilnesa cijelimocekivanimpovratnimizrazom. Nikad
ne moetekoristitivoid metode kao argumentekondicionalnogoperatora.

Logicki operatori
Do sada uvedenirelacijskioperatori(<, <=, >, >=, !=) dovoljnisu za testiranje
pojedinacnoguvjeta.Za ispitivanjeviestrukihuvjeta, moralibismokoristitivie if
naredbi:
if (x == 2) {
if (y != 2) {
System.out.println ("Oba uvjeta su true.");
}
}

To, medutim, moebitinepregledno, a taj nedostatakrjeava se uporabomlogickih


operatora &&, || i !.
Operator && je logickiand koji za dvijebooleovskevrijednostii vraca true ako i samo
ako su oba operanda true . Npr.
boolean b;
b = 3 > 2 && 5 < 7; // b je true
b = 2 > 3 && 5 < 7; // b je sada false

Operator || je logickior koji za dvijebooleovskevrijednostivraca true ako je bar


jedan operand true . Npr.
boolean
b = 3 >
b = 2 >
b = 2 >

b;
2 || 5 < 7; // b je true
3 || 5 < 7; // b je i dalje true
3 || 5 > 7; // now b je false

Operator ! je logickanegacijakoja za booleovskuvrijednostvraca true ako je operand


false i obrunuto. Npr.
boolean b;
b = !(3 > 2); // b je false
b = !(2 > 3); // b je true

Ovi operatoriomogucujujednostavnjeispitivanjeviestrukihuvjeta. Na prviprimjer


moese sada zapisatimnogopreglednije:
if (x == 2 && y != 2) {
System.out.println ("Oba uvjeta su true.");
}

Prioritet izvravanja logickih


operatora
Prilikomizvravanjaoperatora && ili||, prvo se izracunavaizrazna lijevojstrani
operatora. Pogledajmosljedeciprimjer:
boolean b, c,
b = !(3 > 2);
c = !(2 > 3);
d = b && c;

d;
// b je false
// c je true
// d je false

Kad se izracunavaizrazd = b && c;, prvo se provjeravada lije b true . Ovjdjeje b


false , pa onda takoder b && c mora biti false bez obziraje li c true ilinije. Zato se
vrijednostvarijablec u ovomizrazuuopce ne provjerava.
Na istinacin, kad Java naidena operator ||, pokuat ce skratitiizracunavanjecim
ustanovida je lijevioperand true , jer onda i cijelirezultatmora biti true .
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 lijevastrana prva


izraunava, a ako je istinita, onda se desna nece niracunati. Ova skracivanjanisuza Javu
tolikoznacajnakao za C jer u Javioba operanda za && i || morajubitibooleovskapa to
reducirasporedne efekte koji oviseo tome jesu liilioperandistvarnoizracunati. No
svejedno, moguceje eksplicitnospecificiratiracunanjeoba operanda, tj. izbjeci
skracivanje.
Ako eliteizracunavativrijednostibooleovskihizrazabez obzirana istinosnuvrijednost
moetese koristitioperatorima& i | (bitovskiand i bitovskior) umjesto&& i ||.
Medutim, paziteda operandibudu zaistabooleovskijer ovioperatoriimajusvoj smisaoi
za numericketipove, a znacenjeimje ondje posve drugacije.

Dodajmokonacno operatore &&, ||, &, | i ? u tablicuprioriteta:


1.
2.
3.
4.
5.
6.
7.
8.
9.
10.

*, /, % Multiplikativni
operatori
+, - Aditivnioperatori
<, >, >=, <= Relacijskioperatori
==, != Usporedbe jednakostii nejednakosti
& Bitovskiand
| Bitovskior
&& Logickiand
|| Logickior
? : Kondicionalnioperator
= Operator pridruivanja

Deklariranje polja
Polja morajuimatiodredenitip, npr. byte , int , String ilidouble . Samo varijable
odgovarajucegtipa mogubitispremljeneu isto polje. Jedno polje ne moeistodobno
sadravatirecimobrojeve i stringove. Polja morajukao i ostale varijablebitideklarirana.
Deklarirajuse dodavanjemuglatihzagrada [] kao sufikstipuvarijable. Na primjer:
int[] k;
float[] yt;
String[] names;

Ovo znacida je k polje int -ova, yt polje float -a, a names polje String -ova. Uglate
zagrademoetepo vlastitomizborudodati i varijabliumjestotipuilicak jednomi drugom.
int k[];
float yt[];
String names[];
int[] k[];
float[] yt[];
String[] names[];

Kreiranje polja
Deklarirajucipolje samo smo reklikoje vrste vrijednostice polje sadravati. Timega jo
nismokreirali. Polja se kao i ostaliobjektiu Javikreirajupomocukljucnerijecinew.
Varijablekoje smo maloprijedeklariralimoemokreiratiovako:
k = new int[3];
yt = new float[7];
names = new String[50];

Brojeviu uglatimzagradamaspecificirajuduljinupolja, tj. Kolikoimakomponenatakoje


ce sadrativrijednosti. Polje k moeimati3 broja tipa int , polje yt moesadrati7

brojeva tipa float , a polje names moesadrati50 String -ova. Ovaj se korak
ponekad nazivaalociranjempolja jer se njimeizdvajapotrebna memorijaza polje.

Inicijaliziranje polja
Pojedinacnekomponentepolja referencirajuse imenompolja i cijelimbrojem koji
predstavljapozicijukomponenteunutarpolja. Ovi se brojevinazivajusubskriptimaili
indeksima komponentiu polju. Indeksisu cijelibrojevipoceviod 0 (nula). Dakle gore
deklariranopolje k imakomponentek[0], k[1] i k[2]. Buducida se pocinjeod nule,
ne postoji k[3]. Pokuaj referenciranjanepostojecekomponenterezultiratce
odbacivanjemiznimkeArrayIndexOutOfBoundsException . Komponentepolja mogu
se upotrebljavatikao i drugevarijablekoje nisukomponentepolja.
k[0] = 2;
k[1] = 5;
k[2] = -2;
yt[17] = 7.5f;
names[4] = "Fred";

Ovaj se korak nazivainicijaliziranjempolja, preciznijeinicijaliziranjemkomponenata


polja. Pod inicijaliziranjem
polja obicnose podrazumijevainicijaliziranje
svih
komponenatapolja. Naravno da za ioleveca polja necemoinicijalizirati
jednupo jednu
komponentu, nego cemo se posluitipetljomkao u sljedecemprimjeru:
float[] squares ;
squares = new float[101];
for (int i=0; i <= 100; i++) {
squares [i] = i*i;
}

Primijetimoda ce brojevitipa int kad budu spremljeniu ovo polje postati float jer je
polje tako deklarirano.

Metoda System.arraycopy()
Kopiranjepolja nijenekiteak zadatak, alije efikasnijeako je implementiranou samom
sustavu. Zato java.lang.System sadristatickumetodu System.arraycopy () koju
moetekoristitiza kopiranjejednogpolja u drugo. Definiranaje ovako:
public static void arraycopy (Object source, int sourcePosition ,
Object destination , int destinationPosition , int numberOfElements )

Metoda System.arraycopy () kopira numberOfElements elemenataizpolaznogpoja


source , pocevis elementomna pozicijisourcePosition , na polje destination
poceviod pozicijedestinationPosition . Polje destination mora vec postojatiu
trenutkupozivanjametode System.arraycopy () jer ga ona sama nece kreirati.. Polja
source i destination morajubitiistogtipa. Na primjer,

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 i
inicijaliziranje dvodimenzionalnih
polja
Dvodimenzionalnapolja se deklariraju, alocirajui inicijaliziraju
slicnokao
jednodimenzionalna
. Specificiratcete dvijedimenzijeumjestojedne i vjerojatnokoristiti
dvijeugnijedenepetlje. U sljedecemprimjeruse svakomelementudvodimenzionalnog
polja dodjeljujesumanjegovihindeksa.
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 punjenjepolja ovisiiskljucivoo namjenipojedinogpolja. U


sljedecemprimjeruracunamojedinicnumatricuzadanevelicine(kvadratnumatricukoja
po 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 {

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

U dvodimenzionalnom
poljuiznimkaArrayIndexOutOfBoundsException pojavljuje
se kad god prekoracitemaksimalniindeksbilopo recimabilopo stupcija.
Dvodimenzionalnopolje moetetakoder deklarirati, alociratii inicijalizirati
u jednom
koraku, zadajucilistuinicijalnihvrijednostiunutarugnijedenihviticastihzagrada. Npr.
jedinicna3x3 matricamoese zadatiovako:
double[][] ID3 = {
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
};

Razmacii prijelomiredaka su iskljucivozbog programera. Sljedecizapisbio bi posve


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

Viedimenzionalna polja i
neuravnoteena polja
Ne moratese ogranicavatina dvodimenzionalnapolja. Java dopzta polja od 3, 4 ilivie
dimenzija. Ipak, ako trebate vieod 3 dimenzijeza polje, vjerojatnokoristitepogrenu
strukturupodataka. Cak su i trodimenzionalnapolja rijetkaosimu programimaza
znanstvenei inenjerskeaplikacije.
Sintaksaza trodimenzionalnapolja je direktnaekstenzijasintakseza dvodimenzionalna
.
Sljedeciprogramdeklarira, alocirai inicijalizirajedno trodimenzionalnopolje. U svaki
elementspremljenaje 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;
}

}
}
}
}

Potrebna je dakle dodatna ugnijedenafor petljaza baratanjedodatnomdimenzijom


.
Sintaksaza jo viedimenzijeje slicna.
Java kao niC nemapravihviedimenzionalnih
polja. Java simuliraviedimenzionalna
polja
koristecipolja cijisu elementidrugapolja. To znacida je moguceimatii neuravnoteena
polja, dakle polja u kojimadimenzijanijejednaka za sve retke. U praksi, medutim, takve
strukturevaljaizbjegavati.

Trece predavanje

objekti i klase

Objektno orijentirano programiranje primjer: klasa Car kreiranje objekata uz


pomoc operatora new separator pristupa clanovima . uporaba objekata unutar
razlicitih klasa inicijaliziranje atributa metode pozivanje metoda implicirani
this member varijable nasuprot lokalnim varijablama prenoenje argumenata u
metodu prenoenje argumenata u metodu, primjer setter metode uporaba setter
metoda, primjer vracanje vrijednosti iz metode vracanje nekoliko vrijednosti iz
metoda uporaba getter metoda, primjer konstruktori uporaba konstruktora
ogranicenja zatita pristupa (access protection ) cetiri razine zatite pristupa to
treba biti public, a to private ? tri koristi od zatite pristupa primjer zatite
pristupa promjena implementacije

Objektno orijentirano programiranje


U klasicnomproceduralnomprogramiranjupokuavase problemizrealnogsvijeta
prikazatipomocumalogbroja unaprijeddefiniranihtipovapodataka: cijelihbrojeva,
realnihbrojeva, stringovai eventualnopolja. U objektno orijentiranomprogramiranju
kreiratemodelpromatranogsustavarealnogsvijeta. Klase su tipovikoje programer
definirakako bi modeliraodijelovesustava.
Klasa je zamiljenakao prototip, nacrt iliideja za svoje primjerke(instance). Moete
imaticijelei realnebrojeve i stringove, alitakoder imatei automobile, motocikle, ljude,
zgrade, oblake, pse, andele, studente, tecajeve, bankovneracunei bilokakve tipovekoji
su bitniza rjeavanjezadanogproblema.
Klase specificirajupodatke i ponaanje, kako vlastito, tako i objekata koji se iznjih
kreiraju. Klasa imadva dijela: atributei metode. Atributiopisujuto klasa jest. Metode
opisujuto klasa cini.
Koristeciprototipkoji klasa predstavlja, moetekreiratiproizvoljanbroj objekata, a
svakiod njihje primjerak(instanca) klase. Razlicitiobjektiiste klase imajuiste atributei
metode, alivrijednostiatributabit ce opcenitorazlicite. Npr. Svi ljudiimajuneku boju
ociju, alise ona razlikujeod covjeka do covjeka.
S drugestrane, objekt neke klase imaiste metode kao i ostaliobjektite klase, osimto
metode oviseo vrijednostimasvojihargumenatai objektovihatributa.
To se reflektirau runtime oblikuobjekta. Svakiobjekt imaodvojenblok memorijeza
svoje atribute, alimemorijau kojoj su zabiljeenemetode zajednickaje za sve objekte
dane klase.

Primjer: klasa Car


Pretpostavimoda elimonapisatiprogramza simulacijuprometakoji biljeiprolazak
vozila. Na svakomvozilumoemopromatratisvojstvakao to je brzina, maksimalna
brzinai registarskaoznaka koja ga jednoznacnoidentificira
. U tradicionalnim
programskimjezicimaimalibismoopisalibismoto pomocudvijefloating point varijable
i jednimstringom. U objektno orijentiranomjezikukoristimokoncept klase da bismo
podatke 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. Atributinamkau to neka klasa jest i koja su
njenasvojstva.
Objekt je specificnainstanca, primjerakneke klase, sa konkretnim(eventualno
promjenljivim
) vrijednostimaatributa. Dok je klasa opcenitazamisao(blueprint) nekih
objekata, instancaje konkretniobjekt.

Kreiranje objekata uz pomoc


operatora new
Da bismokreiralikonkretniobject neke klase, odnosno instanciraliklasu, koristimo
kljucnurijecnew izakoje slijedipozivtzv. konstruktoraklase. Pogledajmokako bismo
deklariralii kreiralinovuvarijablutipa Car koju cemo nazvatic.
Car c;
c = new Car();

Prva rijec, Car , deklariratip varijable c. Klase su tipovipa kad varijablama


dodjeljujemotipove, dodjeljujemoimzapravoklase te ihdeklariramona istinacinkao
varijablecijisu tipoviint , char , double itd.
Znak jednakostije operatorpridruivanja
, a rijec new je operatorkreiranja
(instanciranja).
Na kraju, primijetimometodu Car(). Zagradenaznacujuda je to metoda, a ne tip
podataka kao npr. rijec Car u prvomretku. To je konstruktor, metoda koja kreira novu
instancuklase. O konstruktorimacet ucitiuskoro. Ako svojuklasui ne snabdijete
konstruktorima, kompajlerce umetnutisvoj default konstruktorbez argumenata.

Deklaracijutipa i kreiranjeinstanceobicnopiemou jednoj naredbi, npr.


Car c = new Car();

Separator pristupa clanovima .


Jednomkad ste kreiralinekiobjekt, potrebna vamje mogucnostpristupanjegovim
clanovima(varijablamai metodama). Za to cete upotrijebitiseparator pristupa, tocku (.).
Klasa Car imatri atributa:
licensePlate
speed
maxSpeed
Dakle, ako je c objekt tipa Car , c

takoder imatri odgovarajucevarijable:

c.licensePlate
c.speed
c.maxSpeed

Koristiteihkao to biste koristilibilokoju 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 i


metodu) nekog objekta po njegovomimenu.

Uporaba objekata unutar razlicitih


klasa
Sljedeciprogramkreira noviprimjerakautomobila(objekta klase Car ), dodjeljuje
vrijednostinjegovimvarijablamai 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;

System.out.println (c.licensePlate + " se krece brzinom od " +


c.speed +
"kilometara na sat.");
}
}

Ovaj programne zahtijevasamo klasu CarTest nego takoder i klasu Car . Da biste ga
mogliizvriti, staviteklasu Car u datoteku Car.java ., a klasu CarTest u datoteku
CarTest .java . Obje datoteke neka budu u istomdirektoriju. Kompilirajteobje
datoteke na uobicajeninacini na kraju izvriteCarTest .
% javac Car.java
% javac CarTest .java
% java CarTest
New York A45 636 se krece brzinom od 70.0 kilometara na sat.
%

Primijetiteda klasa Car nema main() metodu, dakle ne moeteje izvriti. Ona postoji
jedinotako da je pozivajudrugiprogramikoji imajuvlastitemain() metode.
Mnoge aplikacijekoje cete pisatikoristitce vieklasa. Uobicajenoje da se svaka klasa
staviu svojuvlastitudatoteku. Uskoro cete naucitikoristitii pakete (packages) kako
biste mogliorganiziratisvoje cesto koriteneklase unutarrazlicitihdirektorija. Za sada
dritesve datoteke sa izvornimprogramima(*.java) kao i one sa kompiliranim
programima(*.class) unutarjednogdirektorija. Iako smo kompiliraliobje klase
odvojeno, dovoljnobi bilokompiliratisamo klasu CarTest jer ce kompajlervec sam
pronaciklasu Car .

Inicijaliziranje atributa
Atributise mogu(i najcece trebaju) inicijalizirati
odmahcimsu deklarirani, isto kao i
lokalnevarijable. Klasu Car moemopreradititako da inicijaliziramo
njeneattribute
ovako:
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
}

Sljedeciprogramkreira noviautomobil(object tipa Car ) i ispisujeodgovarajuce


podatke.
class CarTest 2 {
public static void main(String args[]) {
Car c = new Car();

System.out.println (c.licensePlate + " se krece brzinom od " +


c.speed +
"kilometara na sat.");
}
}

Rezultatizvravanjabi bio
% javac Car.java
% javac CarTest .java
% java CarTest
se krece brzinom od 0.0 kilometara na sat.
%

Metode
Tipovipodataka ne znacemnogoako ne moetes njimanitanapraviti. Zbog toga
postoje metode. Dok atributikazjujuto klasa jest, metode kazujuto ona cini. Atribute
i metode nazivamozajednicimimenomclanovimaklase. Klase koje ste do sada
upoznaliimajuuglavnomsamo jednumetodu, main(). Medutim, opcenitoklase mogu
imatimnogorazlicitihmetoda. Na primjer, klasuCar moemosnabdjetimetodomkoja ce
simulirativonjumaksimalnombrzinom:
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 metoda koju smo nazvalifloorIt ().
Pocinjekljucnomrijecivoid to je povratnitip (return type) te metode. Svaka metoda
mora imatipovratnitip koji moebitiilivoid ilinekitip podataka kao int , byte , float ,
String , iliklasa koju ste samidefinirali
. Povratnitip pokazujevrstuvrijednostikoja ce
bitivracenapozivnojmetodinakon to se pozvanametoda izvri. Ako je povratnitip na
primjerint , onda tu metodumoetekoristitisvagdjegdje biste inacekoristililiteralili
varijablutipa int .Ako je povratnitip void , metoda ne vraca nikakvuvrijednost.
Ime ove metode je floorIt , a izanjegaslijedepraznezagrade. Kad bi ova metoda
imalaargumente, onibi se naveliunutartihzagrada. Tijelometode nalazise unutar
viticastihzagrada.
this.speed = this.maxSpeed ;

Primijetiteda smo unutarklase Car koristiliispred imenamembervarijablikljucnurijec


this to kako bismonaznacilida su to varijabletrenutnoaktivnogobjekta.

Pozivanje metoda
Izvanklase Car , metodu floorIt () pozvatcete na istinacinkao to ste referencirali
attribute, dakle navodeciimeobjekta kojeg elite ubrzati i separator ., kao to
pokazujesljedeciprimjer
class CarTest 3 {
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 CarTest 3.java
% java CarTest 3
New 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 klasu Car . Svaka metoda u Java programumora, za


razlikuod C++ programa, pripadatinekoj klasi.

Implicirani this
Unutarklase Car nijenunododavatiimenimaatributaprefiks this. jer se on
podrazumijeva. To je zato jer metoda floorIt () mora bitipozvanaod specificne
instanceklase Car , a ta instancazna gdje su njenipodaci. Ilidrugimrijecima, svakiobject
izklase Car imasvojuvlastitufloorIt () metodu.

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 uvijekeksplicitnokoristitiprefiks this , ali


kasnijese od toga moei odustati.

Member varijable nasuprot lokalnim


varijablama
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;
}
}

Svi dosadanjiprogramibilisu vrlojednostavni. Svakije imaotocno jednuklasukoja je


imalapo jednumetodu, main(), i u njoj je bilasadranasva programskalogikai njene
vlastite, lokalne varijablekoje nisumoglebitireferenciraneizvanmetode.
S drugestrane, varijablelicensePlate , speed i maxSpeed klase Car class, pripadaju
objektu tipa Car , a ne pojedinojmetodi. Definiranesu izvanbilokoje metode, aliunutar
klase i nazivajuse membervarijableiliatributi(fields).
Member nijeisto to i membervarijablailiatribut. Memberiukljucujui attributei metode.

Prenoenje argumenata u metodu

Direktnopristupanjeatributimasmatrase loomprogramerskomnavikom. Dobro


objektno orijentiranoprogramiranjeprakticirapristuppoljimaiskljucivoputemmetoda.
To vamomogucujeda promijeniteimplementacijuneke klase bez da ita mijenjateu
njenomsucelju. To vamtakoder omogucujeugradivanjeraznihogranicenjana vrijednosti
atributa.
Za to je potrebno imatimehanizamprenoenjainformacijau klasu, a to se radi pomocu
argumenata. Na primjer, da bismodozvoliliostalimobjektimada mijenjajuvrijednost
atributaspeed na nekomobjektu tipa Car , klasu Car moemosnabdijetimetodomkoju
cemo nazvatiaccelerate (). Ta metoda ne dozvoljavapojedinacnomautomobilu
ubrzavanjeiznadmaksimalnebrzineiliispod 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 linijametode nazivase njenomsignaturom. Signaturavoid accelerate


(double deltaV) oznacavada metoda accelerate () ne vraca nikakvuvrijednost, a
uzimajedan argumenttipa double koji ce unutarte metode bitioznacenimenom
deltaV . Java prenosiargumentemetodamapo vrijednosti, ne po referenci.

Prenoenje argumenata u metodu,


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
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;
}

}
}
class CarTest 4 {
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 CarTest 4.java
% java CarTest 4
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
%

Setter metode

brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom

od
od
od
od
od
od
od
od
od
od
od
od
od
od
od
od

0.0 kilometara na sat.


10.0 kilometara na sat.
20.0 kilometara na sat.
30.0 kilometara na sat.
40.0 kilometara na sat.
50.0 kilometara na sat.
60.0 kilometara na sat.
70.0 kilometara na sat.
80.0 kilometara na sat.
90.0 kilometara na sat.
100.0 kilometara na sat.
110.0 kilometara na sat.
120.0 kilometara na sat.
123.45 kilometara na sat.
123.45 kilometara na sat.
123.45 kilometara na sat.

Setter metode, zvanetakoder i mutator metode, imajuzadatak dodjeljivatiatributima


vrijednostikoje se zadajuputemargumenata. Ove metode u praviluvracaju void .
Uobicajenoje koristitithis.name za referenciranjeatributai dodjeljivanjevrijednostiiz
istoimenogargumenta. 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, primjer


class CarTest 5 {
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 +

" 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 CarTest 5.java
% java CarTest 5
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
%

brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom

od
od
od
od
od
od
od
od
od
od
od
od
od
od
od
od

0.0 kilometara na sat.


10.0 kilometara na sat.
20.0 kilometara na sat.
30.0 kilometara na sat.
40.0 kilometara na sat.
50.0 kilometara na sat.
60.0 kilometara na sat.
70.0 kilometara na sat.
80.0 kilometara na sat.
90.0 kilometara na sat.
100.0 kilometara na sat.
110.0 kilometara na sat.
120.0 kilometara na sat.
123.45 kilometara na sat.
123.45 kilometara na sat.
123.45 kilometara na sat.

Getter metode
Cesto je korisnoda metoda vraca neku vrijednostonoj klasikoja ju je pozvala. To se
radi pomocukljucnerijecireturn na zavretkutijelametode te naznakompovratnog
tipa na njenompocetku. Na primjersljedecametoda getLicensePlate () vraca
trenutacnuvrijednostatributalicensePlate u klasi Car .
String getLicensePlate () {
return this.licensePlate ;
}

Ovakve metode koje samo vracajuvrijednostnekog atributanazivajuse getter ili


accessor metode. SignaturaString getLicensePlate () namkae da metoda
getLicensePlate () vraca vrijednosttipa String i ne trainikakveargumente. Unutar
metode imamolinijureturn this.licensePlate ; koja vraca String sadranu

atributulicensePlate onometko je metodupozvao. Povratnitip u return naredbi


mora odgovaratideklariranompovratnomtipuu signaturi.

Vracanje nekoliko vrijednosti iz


metoda
Metoda ne moevratitivieod jedne vrijednosti. Ne moetena primjervratiti
licensePlate , speed i maxSpeed iziste metode. Moglibiste ih, naravno, sloitiu
objekt neke vrste i njegavratiti, no to nijepravinacin. Pravilnobi bilodefiniratiodvojene
metode, getSpeed (), getMaxSpeed (), i getLicensePlate (), od kojihsvaka vraca
po 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 ;

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

Uporaba getter metoda, primjer


class CarTest 6 {
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 vie nema direktnogpristupaatributima!


Izlaz:
% javac Car.java
% javac CarTest 5.java
% java CarTest 5
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece
New York A45 636 se krece

brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom
brzinom

od
od
od
od
od
od
od
od
od
od
od
od
od

0.0 kilometara na sat.


10.0 kilometara na sat.
20.0 kilometara na sat.
30.0 kilometara na sat.
40.0 kilometara na sat.
50.0 kilometara na sat.
60.0 kilometara na sat.
70.0 kilometara na sat.
80.0 kilometara na sat.
90.0 kilometara na sat.
100.0 kilometara na sat.
110.0 kilometara na sat.
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.
%

Konstruktori
Konstruktorkreira novuinstancuklase. On inicijalizirapotrebne varijablei obavljasve
poslovekoji su potrebnida bi se klasa pripremilaza uporabu. Pogledajmoprimjer:
Car c = new Car();

Ovdje je Car() konstruktorklase Car . Konstruktorimauvijekisto imekao i


pripadnaklasa.
Ako klasune snabdijemonikakvimkonstruktorom, Java osiguravajedan genericki, bez
argumenata, tzv. noargs constructor, medutim, bolje je imativlastite
konstruktore. .Konstruktorse radi tako da se napiemetoda koja imaisto imekao i
klasa. Zato se konstruktorklase Car zove Car().
Konstruktorinemajupovratnogtipa. Oni zapravovracajuinstancusvoje klase, alito cine
implicitno
, ne eksplicitno.
Sljedeca metoda je konstruktorkoji inicijaliziravarijablukoja predstavljaregistarsku
plocicu(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, moetenapisatikonstruktorkoji primatri argumentai koristiihza inicijaliziranje


odgovarajucihvarijabli:
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;
}

Ilimodaeliteda inicijalnabrzinauvijekbude jedanaka nuli, a maksimalnabrzinai


registarskaplocicaspecificiraneargumentima
:

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;
}

// 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, CarTest 7, koristitreciod navedenihkonstruktoraza inicijaliziranje
objekata tipa Car umjestoda direktnopostavljavrijednosti.
class CarTest 7 {
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.");
}
}
}

Primijetiteda viene moratevoditiracunao atributimalicensePlate , speed i


maxSpeed . Sve to trebate znatije kako konstruiratinoviprimjerakklase Car i kako
ispisatinjegovepodatke.
Postavljase pitanjejesu limetode setLicensePlate () i setMaximumSpeed () zaista
jo potrebne kad se atributilicensePlate i maxSpeed postavljajuu konstruktorima.
Odgovor ovisio tome elimolidopustitinjihovomijenjanjejednomnakon to je objekt
vec kreiran. Klase koje ne doputajupromjenuatributasvojihobjekata nakon to su
kreirani, nazivajuse nepromjenjivima(immutable). String je primjertakve klase. Ne
moetepromijenitinjegovepodatke, moetesamo kreiratinoviobjekt tipa String .

Ogranicenja
Mogucnostimplementiranjaogranicenjajedan je od razlogaza davanjeprednosti
koritenjukonstruktorai setter metoda pred direktnimdohvacanjemvarijabli. Na primjer,
u klasi Car vanoje osiguratida brzinanikadne bude veca od propisanemaksimalne
brzinei da nijedna ne bude manjaod nule.
Vec smo to vidjeliu primjerumetode accelerate () koja, na nacinkako je napravljena,
nece pridijelitiautomobilubrzinuvecu od 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) klase Car 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;
}
}

Zatita pristupa (access protection)


Globalnevarijablesu klasicniizvorpogreaka u veciniprogramskihjezika. Neka
nepoznatafunkcijaobicnopromijenivrijednostvarijabletamo gdje programerto ne
ocekuje.
Vecinaobjektno orijentiranihjezika, Java takoder, omogucujezatituvarijabliod
modifikacijeizvana. To vamdaje garancijuda ce vaa klasa ostatikonzistentnatako dugo
dok su njenevlastitemetode u redu. Na primjer, u klasiCar eljelibismobitisigurnida ni
jedan blok programskogkoda izneke drugeklase nece mocipromijenitivarijabluspeed
tako da bude veca od maxSpeed. elimopronacinacinda sljedeciprimjerkoda ucinimo
nelegalnim
:
Car c = new Car("New York A234 567", 100.0);
c.speed = 150.0;

Ovaj kod naruavauvjetkoji smo postavilina nau klasu. elimoomogucitikompajleru


da provede potivanjetakvihuvjeta.
Klasa prezentiraprema vanjskomsvijetuodredenuslikusebe, tzv. sucelje. Ta slikakae
da klasa imaodredene metode i odredene atribute. Sve ostalo, ukljucjucidetaljniizgledi
funkcioniranjemetoda je skriveno. Tako dugo dok se ta slikane mijenja, programer
moeslobodnomijenjatinacinna koji je ona implementirana
. To izmeduostaloga
dozvoljavaprogrameruda mijenjai poboljavaalgoritmekoje klasa koristibez bojazni
da ce to na nekinepredvidljivnacinnaruitifunkcioniranjeklase. To se naziva
enkapsulacijom
Druginacinrazmiljanjao enkapsulacijije sljedeci. Zamislimoda klasa potpisuje
ugovor sa ostalimklasamau programu. Taj ugovorkae da klasa imaodredene
jednoznacnoimenovanemetode sa zadanimtipovimaargumenatai povratnimtipovima.
Ugovormoetakoder reci da klasa imaatributezadanogimenai zadanogtipa. Medutim,
on ne kae kako su te metode implementiranenitizabranjujepostojanjedrugihmetoda i
atributakoje klasa modakoristi. On samo garantiraprisutnostodredenihmetoda i
atributapri cemune iskljucujeostale metode niatribute. Takav je ugovorimplementiran
kroz koncept zatitepristupa.

Cetiri razine zatite pristupa


Bilokoja dva razlicitaJava objekta mogujedan prema drugombitiu jednoj od sljedecih
relacija:
Oba objekta su u istojklasi
Jedan objekt je u podklasiklase kojoj pripada drugiobjekt
Oba objekta su u istompaketu
Nita od navedenog(oba objekta su u nepovezanimklasamai razlicitimpaketima)

Ove relacijenisumedusobnoisklucive. Jedan objekt moe, na primjer, bitiu podklasi


klase drugogobjekta unutaristogpaketa.
Moete definiratikoji ce memberivae klase, dakle atributii metode, bitidostupnidrugim
objektimaizsvake od ove cetirigrupeu odnosu na promatranuklasu.
elitelida bilokoji objekt moepozvatiodredenumetoduilipromijenitiodredeni
atribut, oznacitcete taj memberkao public .
elitelida samo objektiiziste klase mogupozvatiodredenumetoduilipromijeniti
odredeniatribut, oznacitcete taj memberkao private .
elitelipristupdozvolitisamo objektimakoji pripadajupodklasiilise nalaze
unutaristogpaketa, oznacitcete ihkao protected .
Konacno, elitelipristupdo odredenogmemberaomogucitisamo objektimaiz
istogpaketa, izostavitcete specifikacijupristupa. Taj default pristupnazivase
package , alinemasvojukljucnurijec.
Po pretpostavci, sve klase koje piete pripadajuistompaketu. Medutim, one nisuu istim
paketimasa Java klasamakao to je System iliApplet .
Atributimai metodamaoznacenimkao public moese pristupitis bilokojeg mjesta
odakle je sam objekt vidljiv. Njihovbroj treba dratina minimumui onitrebajubitiusko
povezanisa kljucnomfunkcionalnocuklase. Ne trebajuprikazivatidetalje
implementacije
. Osimrijetkihizuzetaka, atributtine bi trebalibiti public .
Atributimai metodamaoznacenimkao private moepristupitijedinoobjekt sam ili
drugiobjekt iste klase (tzv. sibling).

to treba biti public, a to private?


Klase su u pravilupublic .
Varijablesu u praviluprivate .
Konstruktorisu u pravilupublic .
Getter i setter metode su u pravilupublic .
O ostalimmetodamatreba odlucivatiod slucajado slucaja.
Ova se pravilamogupo voljimijenjatiako za to postojirazlog. Medutim, dobro ihje
imatina umujer pokrivajuvelikuvecinuprakticnihpotreba.

Tri koristi od zatite pristupa


Koritenjemogucnostizatitepodataka osiguravatri bitnekoristi:
1. Omogucujeuvodenjeogranicenjana stanje objekta

2. Osiguravajednostavnijekorisnickosucelje. Programerikorisnicine morajuznati


sve to se nalaziunutarklase, dovoljnoimje da poznajujavne(public) segmente.
3. Odvaja suceljeod implementacije
, cimese omogucujeda se jedno mijenja
nezavisnood drugoga(zamislimonpr. da smo odlucilida registarskaplocica,
licensePlate viene bude String nego instancanove klase LicensePlate ).

Primjer zatite pristupa


Evo kako bi klasa Car u praksi zaistaizgledala. Primijetiteda su sviatributisada
private , a moeimse pristupitijedinokroz metode koje 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 ;
}

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;
}
}
}

Pokuajmosada izneke drugeklase direktnopristupitiatributimaklase Car da vidimo


to ce se dogoditi:
class CarTest 8 {
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.");

}
}

Evo to bi se dogodiloako pokuate kompiliratiCarTest 8 uz revidiranuklasu Car :


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

U mnogimslucajevimabit ce takoder metoda koje su private , protected iliimaju


default pristup. Zajednickise one nazivajunon-public metode.
U mnogimslucajevimaatributi(varijable) bit ce protected ilice imatidefault pristup, dok
su, medutim, public varijablerijetke. Takva koncepcijaomogucujeprogramerima
promjenuimplementacijeklase i istovremenozadravanjenepromijenjenogsuceljaprema
vanjskomsvijetu.

Promjena implementacije
Pretpostavimoda elimoprilagoditiklasu Car za uporabuu simulacijiprometavelikog
grada kao to je New York, gdje ce svakirealniautomobilna cesti bitireprezentiranpo
jednimobjektomtipa Car . To je velikakolicinaobjekata i poeljnoje smanjitikolicinu
zauzetememorije. Svakiobjekt tipa Car zauzimaoko 60 byteova, to najvieovisio
duljiniStringaza registarskuplocicu. Na numerickimvarijablamamoemoutedjeti8
byteovapo objektu ako 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;
}

// 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, nijedna drugaklasa koja ovisio ovoj klasine mora se
mijenjatipa cak niponovnokompilirati
. Ovdje bismomogliicidalje pa napravitivlastitu
klasu LicensePlate koja bi doz voljavaASCII znakoveod jednogbytea umjesto
Unicodeznakovaod dva bytea i tako dalje.

Peto predavanje

appleti

HTML, jezik za oblikovanje web stranica - URL, jedinstvena adresa dokumenta


dijelovi URLa linkovi relativni URLovi applet Hello World to je applet?
HTML oznaka <applet> - odabir pozicije na stranici alternativni tekst
imenovanje appleta JAR arhive HTML oznaka <object > - velicina appleta
HTML oznaka <param> - obrada nepoznatog broja parametara sigurnost appleta
to applet moe ciniti? s kim applet moe komunicirati ? koliko CPU vremena
applet dobija ? sigurnost i social engineering sprecavnje hakerskih napada kroz
applete ivotni ciklus appleta metode init(), start(), stop() i destroy ()
koordinatni sustav objekti klase Graphics crtanje linija crtanje pravokutnika
punjenje pravokutnika brisanje pravokutnika elipse i krunice primjer,
bullseye poligoni viestruke linije (polylines ) ucitavanje slika metode
getCodeBase () i getDocumentBase () prikaz slike u pravoj velicini skaliranje slika
boje sistemske boje fontovi odabir oblika i velicine fonta klasa FontMetrics

HTML - jezik za oblikovanje web


stranica
HTML znaciHyperTextMarkup Language. HTML datoteke su tekstualnedatoteke u
kojimasu dijeloviteksta oznacenipomocutagova (oznaika). Ekstenzijatakve datltekeje
.htm ili.html . Evo primjerajedne jednostavneHTML datoteke:
<html>
<head>
<title>Moj prvi HTML Document </title>
</head>
<body>
<h1>Zaglavlje velicine 1</h1>
Ovdje se pie vidljivi dio dokumenta .
Ovako se <STRONG>naglaava </STRONG> sadraj .
</body>
</html>

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


>zovuse oznake (tags). Oznake se mogupisativelikimilimalimslovima(nisucase
sensitive).
Vecinaoznaka imazatvarackoji definiradoseg oznake. Zatvaracimaisto imekao i
oznaka, alimuje dodan slash (/) nakon otvorenezagrade. Na primjer, </html>, </
head>, i </title> su zatvaraci. Tekst izmedu<title> i </title>, Moj prvi HTML
dokument izgornjegprimjera, predstavljanaslovstranice.
Oznake se u pravilumogupisatiunutardrugihoznaka, alise ne mogupreklapati.

Neke oznake imajudodatne atribute(to nijeisto to i atributiu Javi). Atributje imeiza


kojeg slijediznak jednakostii vrijednost, a zajednos oznakompoblieodreduje nacin
interpretacijeteksta. Na primjer, da bismozaglavljeH1 centrirali, moemokoristitiatribut
ALIGN i dati muvrijednostcenter ; tj.
<h1 align="center">Zaglavlje velicine 1</h1>

Atributisu takoder case-insensitive. Dvostrukinavodnicioko vrijednostisu opcionalni


osimako vrijednostsadribjeline.Za potpunuinformacijuo HTML-u pogledajte
HyperTextMarkup Languagena W3C - World Wide Web Consortium.

URL jedinstvena adresa dokumenta


URL je kraticaza uniformresource locator. To je pointerna odredeniresurs na nekoj
lokacijina Internetu. Na primjer, http://student .math.hr/~vedris/ ilihttp://
student .math.hr/~vedris/java/java-predavanje -05.htm su URLovi.
URL specificiraprotokol za pristupposluitelju
, npr. ftp, http, imeposluitelja,lokaciju
datoteke na posluiteljui eventualnolokacijunekog mjesta(sidro, anchor) unutar
datoteke. Opci oblikURLa je
protocol ://hostname [:port]/path/filename #section

Dijelovi URL-a
Protokolje uglavnomjedan od sljedecih:
file datoteka na lokalnomdisku
ftp ftp posluitelj
http World Wide Web posluitelj
https secure http, Web posluiteljsa zatitompodataka
gopher gopherposluitelj
mailto emailadresa
news Usenetnewsgroup
telnet veza na serviszasnovanna Telnet- u
WAIS WAIS posluitelj
rmi remotemethodinvocation

Hostname (imeposluitelja) mora bitivaljanomrenoimehosta na Internetu, a moebiti


i IP adresa, npr student .math.hr, www.ora.com or shock.njit .edu alii
204.29.207.217 ili128.235.252.184 .
Port (broj porta) je opcionalanZa http je default port 80.
Path (put do datoteke) pokazujeodredenidirektorijna posluitelju
. Formirase u odnosu
na pocetnidirektorijservisa(server root, document root) koji ne mora biti(i obicno

nije) nunopocetnidirektorij(root) sustavadatoteka (file system). Cijelisustavdatoteka


obicnose ne otkrivajavnosti.
Filename (imedatoteke) pokazujena odredenudatoteku unutarnavedenogdirektorija.
Na mnogimposluiteljimauobicajenoje da se, ako je imedatoteke izostavljeno,
podrazumijevadatoteka index.html . Na drugimace se dobitiispisdirektorija, a neki
ce poslatiporuku o pogreki.
Section (mjestounutardatoteke) referenciraimenovanosidro (anchor) unutarHTML
dokumenta. Ono se oznacavaovako:
<A NAME="xtocid1902914 ">Comments </A>

URL koji pokazujena to sidro sadrinakon imenadatoteke jo i imesidra ispred kojeg


je znak #, na primjerovako:
http://metalab .unc.edu/javafaq /javafaq .html#xtocid1902914

Linkovi
Da biste u HTML datotecinapravililinkod dijelateksta, zatvoritcete ga unutaroznaka
<A> i </A>. Oznaci <A> dodat cete atributHREF i u njemunavestiurlna koji elite
usmjeritiva link. Na primjer,
Ovaj link pokazuje na
<A HREF="http://student .math.hr/~vedris/java/java-predavanja /javapredavanje -05.htm">
peto predavanje iz Jave
</A>
na PMF-u.

Vecinabrowsera ce tako oznacenitekst prikazatipodvuceno, u plavojililjubicastojboji,


no to ovisio podeenostibrowsera. Klikanjemna taj dio teksta prikazatce se resurs koji
je navedenu pripadnomURLu.

Relativni URL-ovi
When a web browser reads an HTML document, it has a great deal of informationabout
the document. Thisincludesthe protocol used to retrievethe document, the nameof the
host where the documentlives, and the path to that documenton the host. Most of thisis
likelyto be the same for manyof the URLs inthat document. RelativeURLs inheritthe
protocol, hostname, and path of theirparent documentrather thanrespecifyingit ineach
<A HREF> tag. Thusifany piece of the URL is missing
, it is assumedto be the same as
that of the documentinwhichthe URL is found. Such a URL is calleda relative URL. In
contrast, a completelyspecifiedURL is calledan absoluteURL. Na primjer, ako
pregledavajucidokumenthttp://metalab .unc.edu/javafaq /books.html kliknete
na sljedecihiperlink:

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

Browser ce odrezatibooks.html sa zavretkaizrazahttp://metalab .unc.edu/


javafaq /books.html i ostavitihttp://metalab .unc.edu/javafaq /, a zatim
pripojitijavafaq .html na zavretakizrazahttp://metalab .unc.edu/javafaq / da
bi dobio http://metalab .unc.edu/javafaq /javafaq .html.
Ako relativnilinkpocinjesa /, onda je on relativanu odnosu na document root umjesto
na 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 zavretakizrazahttp://metalab .unc.edu/ da bi dobio http://
metalab .unc.edu/boutell /faq/www_faq.html .
RelativniURLoviimajuraznihprednosti. Smanjujukolicinupotrebnogtipkanja, alito je
jo vanije, omogucujupremijetanjecijelihstabalaHTML dokumenatabez naruavanja
njihovihinternihlinkova

Applet Hello World


Jedan od razlogapopularnostiJave je mogucnostpisanjainteraktivnihappleta na 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 applet HelloWorld neto sloenijinego aplikacija, a imai neto


dodatnogposla da bi ga se pokrenulo.
Najprijespremiteizvornikod u datoteku HelloWorldApplet .java . Kompilirajteje na
uobicajeninacin. Dobitcete klasu HelloWorldApplet .class . Da biste je pokrenuli,
potrebno je napravitiHTML dokumentkoji ce sadratina applet. Evo jednogtakvog
dokumenta:
<HTML>
<HEAD>
<TITLE> HelloWorldApplet </TITLE>
</HEAD>
<BODY>

Ovo je applet HelloWorld :<P>


<applet code="HelloWorldApplet .class" width="150" height="50">
</applet>
</BODY>
</HTML>

Spremitetu datoteku pod imenomHelloWorldApplet .html u istidirektorijgdje se


nalazidatoteka HelloWorldApplet .class . Pogledajtetu HTML datoteku pomocu
nekog standardnog(Java enabled) browsera kao to je Internet Explorer, Netscape ili
Applet viewer koji se nalaziu JDK paketu. Vidjetcete stringHelloWorld unutar
pravokutnikavelicine150x50 tocaka.

Ako je kompilacijaprola bez pogreke, a ne viditestringHelloWorld, provjeriteda lije


klasa u istomdirektorijukao i HTML datoteka. Takoder buditesigurnida koristite
dovoljnonovuverzijubrowsera, koja podravaJavu. Ako niApplet Viewer ne vidiva
applet, pogreka je vjerojatnou appletu, a ne u browseru.

to je Applet?
Appletje malaaplikacijakoja je zamiljenada se ne izvravasamostalno, nego unutar
drugeaplikacije, tipicnounutarweb browsera. Klasa java.applet.Applet osigurava
standardnosuceljeizmeduappleta i njihoveokoline. Evo to se sve nazivaappletom:
malaaplikacija
sigurniprogramkoji se izvravaunutarweb browsera
podklasa klase java.applet.Applet
instancapodklase 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 HTML stranicuugradujupomocuoznaka <APPLET> i </APPLET>. Oznaka
<APPLET> se ponaa licnokao <IMG>. Kompiliranaklasa koja sadriappletovkod
referencirase pomocuatributaCODE . Njezinaje lokacijarelativnau odnosu na izvorni

HTML dokument. Na primjer, ako pregledavatestranicuhttp://metalab .unc.edu/


javafaq /index.html , a ta stranicareferenciraapplet pomocu
CODE="Animation .class", onda bi datoteka Animation .class trebalabitina adresi
http://metalab .unc.edu/javafaq /animation .class .
Medutim, suprotnood uobicajeneprakse, ako se applet nalazinegdjedrugdje, a ne u
istomdirektorijukao i HTML dokument, ne moeteu atributu<CODE> jednostavno
navestinjegovURL, nego umjestotoga moratekoristitijo i atributCODEBASE u kojem
cete navestidio URLa koji pokazujeput do appleta. Na primjer, da je HTML stranicas
naimappletomHelloWorldApplet bilanapisanakao
<APPLET CODE="HelloWorldApplet .class" CODEBASE ="classes "
WIDTH=200 HEIGHT=200>
</APPLET>

onda bi browser pokuao traitiklasu HelloWorldApplet .class u poddirektoriju


classesonog direktorijau kojem se nalaziHTML dokument. Takoder, ako napiemo
<APPLET CODE="HelloWorldApplet .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes " WIDTH=200
HEIGHT=200>
</APPLET>

onda ce browser pokuatinacinau klasuna adresi http://student .math.hr/


~vedris/java/classes /HelloWorldApplet .class neovisnoo tome gdje se
HTML dokumentnalazi.
Ukratko, browser pokuavarekonstruiratiURL po formuli(CODEBASE + "/" + CODE ).
Jednomkad je URL formiran, vrijedesva pravilao relativnimi apsolutnimURLovima.
Ekstenziju.class moeteu atributuCODE izostavitii pisatisamo imeklase. Na primjer
<APPLET CODE="HelloWorldApplet "
CODEBASE ="http://student .math.hr/~vedris/java/classes " WIDTH=200
HEIGHT=200>
</APPLET>

Ako applet nijeu 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 traitiklasuna adresi http://student.math.hr/~vedris/java/


classes/hr/math/student/vedris/myApplets/HelloWorldApplet.class, pa struktura
direktorijana serverumora bitinapravljenau skladus hijerarhijompaketa.
AtributiHEIGHT i WIDTH rade na istinacinkao i kod oznake IMG , odredujucivelicinu
pravokutnikakoji ce browser rezerviratiza prikazappleta. Velicinesu specificiraneu
pikselimai obaveznesu.

Odabir pozicije na stranici


Oznaka <APPLET> imanekolikoatributaza definiranjepozicijeappleta na stranici.
AtributALIGN odreduje kako je appletovpravokutnikpozicioniranna straniceu odnosu
na drugeelemente. Dozvoljenevrijednostiovog atributasu LEFT , RIGHT , TOP , TEXTTOP ,
MIDDLE , ABSMIDDLE , BASELINE , BOTTOM i ABSBOTTOM . Atributje opcionalan.
U atributimaHSPACE i VSPACE moguceje odreditikolicinupraznogprostora (u
pikselima) izmeduappleta i okolnogteksta. I ovisu atributiopcionalni.
<applet code="HelloWorldApplet .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes " width=200
height=200
ALIGN=RIGHT HSPACE=5 VSPACE=10>
</APPLET>

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

Alternativni tekst
Oznaka <APPLET> imai atributALT . Browser ga koristiu slucajuako iznekog razlogane
moeizvestiapplet. Na primjer, ako je u browseruiskljucenaopcija za dozvoluizvodenja
Java appleta, trebao bi se prikazatitekst navedenu atributuALT . AtributALT je
opcionalan.
<applet code="HelloWorldApplet .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes " width=200
height=200
ALIGN=RIGHT HSPACE=5 VSPACE=10
ALT="Hello World!">
</APPLET>

Ovimse atributomne koristestarijibrowserikoji uopce ne razumijuoznaku <APPLET>.


Oni umjestotoga prikazujucistitekst koji se nalaziizmeduoznake <APPLET> i njenog
zatvaraca, </APPLET>. S drugestrane, browserikoji su Java enabled ignoriratce taj
tekst. Na primjer, sljedeciHTML fragmentispisujestringHello World! svima, dakle i
Java enabled i non-Java enabled browserima.
<applet code="HelloWorldApplet .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes " width=200
height=200
ALIGN=RIGHT HSPACE=5 VSPACE=10
ALT="Hello World!">
Hello World!<P>
</APPLET>

Imenovanje appleta
Appletuse unutarweb stranicemoedati imekako bi mogaokomuniciratis drugim
appletima. To se radi pomocuatributaNAME . Na primjer,
<applet code="HelloWorldApplet .class" Name=Applet_01
CODEBASE ="http://student .math.hr/~vedris/java/classes " width=200
height=200
ALIGN=RIGHT HSPACE=5 VSPACE=10
ALT="Hello World!">
Hello World!<P>
</APPLET>

JAR arhive
Sve slike, zvukovei klase koje su potrebne za izvravanjevaegappleta moetespakirati
u JAR arhivui tako ihucitatiodjednom, a ne svaku posebno. Timesmanjujetebroj
konekcijakoje browser mora ostvaritida bi dobio sve to mutreba. Ako se appletova
klasa 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 dalje HelloWorldApplet . Medutim, browser ce


odgovarajucudatoteku potraitiu arhiviHelloWorld .jar a ne u zasebnojdatoteci
HelloWorldApplet .class .
Arhivaje spakiranana nekiod uobicajenihnacina, na primjer:
% jar cf HelloWorld .jar HelloWorldApplet .class
added manifest
adding: HelloWorldApplet .class(in = 384) (out= 271)(deflated 29%)
%

elimolipogledatito imau arhivi, moemoto ucinitiovako:


% jar tf HelloWorld .jar
META-INF/
META-INF/MANIFEST .MF
HelloWorldApplet .class
%

HTML oznaka <OBJECT>


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

Atribut<OBJECT> omogucujei ukljucivanjeActiveXkontrolai drugihaktivnihelemenata,


no za Javu namto ne treba. Podravajuje samo najnovijeverzijebrowsera i smatrase da
ce oznaka <APPLET> bitijo dosta vremenaaktualna.
Moete imatii obje oznake, jednuunutardruge, ovako:
<OBJECT CLASSID ="HelloWorldApplet .class" WIDTH=200 HEIGHT=200
CODEBASE ="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 sadraj izmedunje i njenog


zatvaraca, dok ce ga ostaliprikazati. ElementiPARAM su istiza obje oznake.

Velicina appleta
Velicinaprostora koju zauzimaapplet dok se izvravaunutarweb browsera zadanaje
atributimaHEIGHTi WIDTH i sam applet je ne moepromijeniti
. Medutim, moe
doznatikolikaje ta velicina, to muje potrebno npr. da ne bi crtao izvanzadanog
prostora.
Velicinaappleta doznajese pomocumetode getSize () koju klasa
java.applet.Applet nasljedujeod svoje nadklase java.awt.Component . Ova
metoda vraca objekt tipa java.awt.Dimension . Takav objekt imadva atributatipa
int , to su height i width . Pogledajmosljedeciprimjerappleta koji ispisujesvoje
dimenzije.
import java.applet.*;
import java.awt.*;

public class SizeApplet extends Applet {


public void paint(Graphics g) {
Dimension appletSize = this.getSize ();

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 visinaappleta uzetau obzirkod odlucivanjagdje smjestititekst.


Koritenjeappletovedimenzijeza odredivanjemjestaobjekata na stranicicesto je
koritenatehnika.

HTML oznaka <param>


Parametrise izHTML dokumentaprenose appletimapomocupara NAME=VALUE i oznaci
<PARAM> koja se smjetaizmeduoznake <APPLET > i njenogzatvaraca. Unutarsamog
appleta vrijednostiproslijedeneputemoznake <PARAM> citajuse pomocumetode
getParameter () izklase java.applet.Applet .
Sljedeciprogramdemonstriraispisstringovadobivenihsa HTML stranice. Stringkoji se
ispisujeje 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 HTML straniciimatcemo parametar"Message" cija ce vrijednostbitistring"Kako


ste?".
<HTML>
<HEAD>
<TITLE>DrawStringApplet </TITLE>

</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 potrebe


da ga iznovakompiliramo.

Ovaj je applet vrloslicanappletu HelloWorldApplet . Medutim, umjestoda fiksno


kodiramoporuku koju on ispisuje, ona ce bitiucitanau varijabluinputFromPage
izravnoizklauzulePARAM u HTMLu.
Metodi getParameter () daje se kao argumentimeparametrasa HTML stranice, a ona
ce vratitinjegovuvrijednost. I argumenti povratnavrijednostsu stringovi. Ako je
potreban drugacijitip, morat cete osiguratipotrebne konverzije.
Oznaka <PARAM> stavljase izmedu<APPLET> i </APPLET>. Ona imasvoje atribute,
NAME i VALUE koji identificiraju
njegovoimei vrijednost. Oba se stavljajuu dvostruke
navodnikeako sadre praznine.
Broj parametaranijeogranicen. Moete imatipo voljimnogooznaka <PARAM> koje
applet i ne mora sve iskoristiti. Viak ce bitina sigurannacinignoriran.

Obrada nepoznatog broja parametara


Ponekad je potrebno obraditinepoznatibroj parametara. U tom slucaju, parametri
trebajubitiimenovanina 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 ).

Metoda paint() ispisujesvakistringna ekran, povecavajuciy pozicijuza 15 piksela


svakiput.
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 izgledaoHTML dokument


<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 syllables
into the last line as I can.">
Ova stranica ce biti vrlo dosadna ako vas browser ne razumije Javu.

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

Procesiranjeproizvoljnelisteparametarabez znanjao nacinuformiranjanjihovihimenaza


sad nijemoguce.

Sigurnost appleta
Suprotnorairenommiljenju,Java appletisu sigurniza korisnikekoji surfajupo
internetu. Nece vamse dogoditida vamapplet formatiradisk iliunesevirusu sustav.
Zbog mehanizamavirtualnemaine, hvatanjaiznimakai tako dalje, Java appletii
aplikacijesu u praksi sigurnijiod tradicionalnihprogramskihjezika.
Appletiimajuugradenadodatna sigurnosnaogranicenjakako bi zatitilikorisnikeod
programerskihpogreaka, alii od virusa. To je implementiranopomocuklase
java.lang.SecurityManager . Razlicitepodklase ove klase osiguravajurazlicita
sigurnosnaokruenjana razlicitimvirtualnimmainama. Loa strana toga je uvodenje
raznihrestrikcijana akcije koje aplet moeciniti.

to applet moe ciniti?


Appletmoe:
crtatislikena web stranici
kreiratinoviprostor i crtatiu njega
reproduciratizvuk
primatiinputod korisnikapreko tastatureilimia
Povezivatise na server s kojeg je doao te slatii primatipodatke s tog servera.
Sve to s timogranicenjimamoeteucinitimoguceje ucinitiizappleta. S drugestrane,
applet ne moe:
pisatipodatke na bilokoji disk na hostu
citatipodatke s hostovogdiska bez korisnikovedozvole. U nekimokruenjima,
npr Netscape, applet ne moecitatipodatke s korisnikovogdiska cak niuz
dozvolu
brisatidatoteke
citatiilipisatipo bilokojem blokumemorije, cak i u nezaticenimoperacijskim
sustavimakao to je MacOS. Sav pristupmemorijistrogo je kontroliran.

povezivatise s hostovimana Internetu, osimsa hostoms kojeg dolazi


pozivatidirektnonative API
unositivirusena host
sruitihostovsistem(smatrase da je tako, no tu tvrdnjutreba uzetis rezervom).

S kim applet moe komunicirati?


Po pretpostavciapplet moeostvaritimrenukonekcijusamo na stroj (file system) s
kojeg je ucitan. Taj sistemse zove codebase. Appletne moekomuniciratis bilokojim
strojemna internetu. Sva komunikacijate vrste mora bitiposredovanapreko posluitelja.
Razlogje taj to bi inaceapplet mogaolansiratis neke mainenapade na internumreu
organizacije. To bi pogotovobio problemza maineunutarfirewallakoje su obicno
konfiguriranetako da jedne drugimavjeruju. Takoder, to bi omogucilohakerimada lake
sakrijusvojupravulokaciju.
HotJava, Sunovapplet vieweri InternetExplorer(aline i Netscape) dozvoljavajuvamda
appletudopustiteostvarivanjekonekcijana proizvoljnistroj, alito nijedefault opcija.

Koliko CPU vremena applet dobija?


Jedan od razlogaza briguoko zlonamjernihappleta je mogucnostpretjeraneuporabe
CPU vremena, to je problemna, recimoMac-u, a neto manjena WindowsNT ili
Solaris. U svakomslucaju, applet moenatjeratikorisnikada npr. prisilnougasibrowser
to moeuzrokovatiodredenigubitakpodataka.
Moguceje takoder da applet koristiCPU vrijemeza svrhekoje nisuodmahvidljive. Na
primjer, nekipopularniapplet moelansirtinapad na password datoteku pomocutzv.
kineskelutrije. Ili, applet koji simuliraneku igrumoeu backgroundulansiratithread koji
pokuavaslucajnimpristupomrazbitienkripcijuneke datoteke. U tom slucajumogaobi
ostvaritikonekcijuprema svomserverui poslatikljucnatrag. to je applet popularniji, to
je vjerojatnostpronalaenjakljucaveca. Ipak, Java kod se lako dekompilira, pa se takvi
appletimoguotkriti.

Sigurnost i social engineering


Suprotnopopularnomvjerovanju, vecinaprovalana kompjutorenijerezultatbriljantnih
ideja i velikogznanjanego razlicitihoblikakrade passworda, od pretraivanjasmeca do
prijevareputemlansiranjaprozora na kojem pie da je veza prekinutapa se traiupis
passworda (pogledajteza primjerovaj TricksterApplet ). Takve aktivnostipoznatesu
pod nazivomsocial engineering., u slobodnomprijevodu"lovu mutnom".

Sprecavanje hakerskih napada kroz


applete
Da bi se sprijeciletakve zabune, prozoriappleta su uvijeksnabdjeveninekomuocljivom
porukomkao: "Warning: AppletWindow" ili"UnsignedJava AppletWindow." To,
naravno, jo uvijekne garantirada netko nece upisatisvoj password ne citajucito pie
na prozoru. Obrazovanjekorisnikana prvomje mjestuu racunalnojsigurnosti.

ivotni ciklus appleta


1.
2.
3.
4.
5.
6.
7.
8.

9.
10.

broser ucitavaHTML stranicui pronalazioznaku <APPLET>


browser analiziraoznaku <APPLET> traeciatributCODE i eventualnoCODEBASE .
browser ucitava.class datoteku appleta sa prethodnopronadenogURLa
browser konvertirabytoveu Java klasu, dakle objekt od java.lang.Class
object.
browser instanciraappletovuklasukako bi formiraoobjekt-applet. To zahtijeva
da applet imakonstruktorbez argumenata.
browser pozivaappletovuinit() metodu.
browser pozivaappletovustart() metodu.
dok se applet izvrava, browser mualje informacijeo dogadajimakoji su mu
namijenjeni
, npr. klikmiem, pritisakna tipkuitd. preko appletove handleEvent
() metode. Dogadajikoji rade update kau appletuda se iznovaprikae(repaint)
browser pozivaappletovustop() metodu.
browser pozivaappletovudestroy () metodu.

Metode init(), start(), stop() i


destroy()
Svi appletiimajusljedececetirimetode:
public void init();
public void start();

public void stop();


public void destroy ();

Imajuihjer ihimanjihovanadklasa, java.applet.Applet (pored ostalih, naravno). U


nadklasisu one samo deklariranei ne cinenita, npr.
public void init() {}

Podklase mogu(alii ne moraju) prekritiove metode kako bi ispunileodredene zadace u


odredeno vrijeme. Na primjer, metoda init() je dobro mjestoza ucitavanjeparametara
izoznake <PARAM> jer ona ce bitipozvanaupravou trenutkukad se applet pocne
izvravati. because it's calledexactlyonce whenthe applet starts up. Buducida su
deklariraneu nadklasi, Web browser ce pozvatite metode kad mutrebaju, cak nine
znajucijesu liimplementiraneu appletuiliu nadklasi. To je dobar primjerpolimorfizma
.
Metoda start() se pozivabar jednomu appletovomivotnomciklusu, onda kad se
applet starta ilirestarta. Ponekad to moebitii vienego jednom. Mnogiappletinemaju
eksplicitnustart()metodunego je nasljedujuiznadklase. Najcece se koristiza
startanjethreadova koje ce applet trebatidok se izvrava.
Metoda stop() se pozivabar jednom, kad browser napustistranicukoja sadriapplet.
Kad se na njuopet vrati, pozvatce se metoda start(). Koristise za zaustavljanje
zaustavljanjethreadovakoje applet koristi. Kad je applet zaustavljen, ne bi trebao troiti
CPU cikluse.
Metoda destroy () se pozivatocno jednomu ivotnomciklusuappleta, upravoprije
nego browser otpustiapplet. Koristise uglavnomza zavrnocicenje. is calledexactly
once inan applet's life, just before the browser unloadsthe applet. Thismethodis
generallyused to performany finalclean-up.
U JDK appletvieweru, izboropcije Restart pozivastop() i onda start(). Opcija
Reload pozivaredom stop(), destroy () i init(). (Normalnobi byte kodovitrebali
bitiponovnoucitanizajednos HTML dokumentom, no u Netscapeu postojiproblems
tim.)
Appletovemetode start() i stop() nemajuveze sa istoimenimmetodamaizklase
java.lang.Thread .
Va vlastitikod pozivatce povremenometode start() i stop(). S drugestrane,
pozivanjemetoda init() i destroy () nijedobra ideja. Browser (ilidrugaokolina) je
taj koji ce pozvatiove metode.

Koordinatni sustav
Java korististandardni, dvodimenzionalni
sustavza racunalnugrafiku. Prvividljivipikselu
gornjemlijevomkutuappletovepodlogeje tocka (0, 0). Koordinatese povecavaju
prema desno i prema dolje.

Objekti klase Graphics


Crtanje se u Javiobavljapomocuobjekata klase java.awt.Graphics .
U pocetku cete koristitigrafickiobjekt koji se daje kao argumentmetodi paint
(Graphics g)koju klasa java.applet.Applet nasljedujeod klase
java.awt.Container . Kasnijecete upoznatii ostale objekte klase Graphics . Sve to
sada budete naucilio crtanjuu appletimavrijedii za objekte kao to su paneli, okviri,
gumbi, podlogeitd.
Svakiobjekt tipa Graphics imasvoj vlastitikoordinatnisustavi metode za crtanje
stringova, linija, pravokutnika, krugova, poligonai tako dalje. Crtanje u Javipocinjeod
pojedinacnogobjekta tipa Graphics . Pristuptom objektu ostvarujetepreko metode
paint(Graphics g) u svomappletu.. Svakipozivmetode za crtanjeizgledatce
otprilikeovako:
g.drawString ("Hello World", 0, 50)

gdje je g specificniobjekt tipa Graphics pomocukojeg crtate.


Zbog razumljivosti
, g ce namuvijekznacitivec postojeciobjekt klase Graphics .
Naravno da, kao i kod svake drugemetode, moetekoristitii drugaimenaza odredeni
kontekst, npr myGraphics iliappletGraphics i slicno.

Crtanje linija

Za crtanjeravnelinijepozovitemetodu drawline () cija je signatura:


public abstract void drawLine (int
int
int
int

x1,
y1,
x2,
y2)

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

Pri tome su (x1, y1) i (x2, y2) krajnjetocke linije, a g je objekt tipa Graphics
pomocukojeg crtate. Pogledajmoprogramkoji ce nacrtatilinijudijagonalnopreko
appleta.
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 izklase Graphics i metode drawRect () cija je
signatura:
public void drawRect (int
int
int
int

x,
y,
width,
height)

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

Prva dva argumentasu koordinategornjeglijevoguglapravokutnika, dok su ostala dva


njegovairinai visina. Sljedeciprogramcrta pravokutnikoko appleta.

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.
Zato crtamopravokutniksamo do getSize ().height-1 i getSize ().width-1?
Zato jer se lijevigornjiugao nalaziu tocki (0, 0), a ne u (1, 1). To znacida aplet velicine
100 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 crtanjekvadrata ne postojiposebma drawSquare () metoda. Kvadrat je naprosto
pravokutnikkojemusu duljinai irinaiste.

Punjenje pravokutnika
Metoda drawRect () crta prazanpravokutnik. Ako ga eliteispuniti, koristitemetodu
fillRect () cija je signatura:
public abstract void fillRect (int
int
int
int

x,
y,
width,
height)

Sljedeciprogramcrta ispunjenipravokutniku centruappleta. Morat cemo razlikovati


velicinupravokutnikaod velicineappleta.
import java.applet.*;
import java.awt.*;
public class FillAndCenter extends Applet {

public void paint(Graphics g) {


int
int
int
int
int
int

appletHeight
appletWidth
rectHeight
rectWidth
rectTop
rectLeft

=
=
=
=
=
=

this.getSize ().height;
this.getSize ().width;
appletHeight /3;
appletWidth /3;
(appletHeight - rectHeight )/2;
(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
Nacrtanipravokutnikmoese izbrisatimetodom clearRect () cija je signatura:
public abstract void clearRect (int
int
int
int

x,
y,
width,
height)

Pogledajmoprogramkoji koristiovu metoduda bi prikazaobljeskanjepravokutnikana


ekranu.
import java.applet.*;
import java.awt.*;
public class Blink extends Applet {
public void paint(Graphics g) {
int
int
int
int
int
int

appletHeight
appletWidth
rectHeight
rectWidth
rectTop
rectLeft

=
=
=
=
=
=

this.getSize ().height;
this.getSize ().width;
appletHeight /3;
appletWidth /3;
(appletHeight - rectHeight )/2;
(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);

}
}
}
<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 najboljeto moemoucinitidok


ne naucimoraditis threadovima.

Elipse i krunice
Elipsei krunicecrtajuse pomocumetode drawOval (), a pune pomocumetode
fillOval () cije su signature:
public abstract void drawOval (int
int
int
int

x,
y,
width,
height)

public abstract void fillOval (int


int
int
int

x,
y,
width,
height)

Argumentiovihmetoda predstavljajukoordinategornjeglijevoguglate irinui visinu


pravokutnikakojemuje elipsaupisana(pogledajtesliku)

Nema posebne metode za crtanjekrunice. Krunicaje naprosto elipsaupisanau


kvadrat.
Java takoder sadrimetode za crtanjepraznihi ispunjenihlukova. To su metode
drawArc () i fillArc () . Ponaajuse slicnokao drawOval () i fillOval () .
Signaturesu im:
public abstract void drawArc (int x,
int y,
int width,

int height,
int startAngle ,
int arcAngle )
public abstract void fillArc (int
int
int
int
int
int

x,
y,
width,
height,
startAngle ,
arcAngle )

U pravokutnikse upisujenajvecimoguciluk. Lokacijalukaod 0 stupnjeva, kao i to da li


je luknacrtanu smijerukazaljkena satu iliprotivnomje neovisnoo platformi.

Primjer

bullseye

Ovo je jednostavniapplet koji crta nizispunjenih,koncentricnihkrugova, naizmjenicno


crvenihi 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>

Klasa koja crta ovu slikuvelikaje 684 bytea. EkvivalentnaGIF slikaimalabi 1,850
bytea, dakle gotovotri puta vie.

Poligoni
U Javisu pravokutnicidefiniranipomocupozicijesvojeggornjeglijevogugla, visinei
irine. Implicitnose podrazumijevada pravokutniknijerotiran. Ako jest, moramoga
smatratispecijalnimslucajempoligona, tj. objekta izklase java.awt.Polygon .
Poligonisu definiranisvojimvrhovimabez dodatnihpretpostavkiosimda leeu
dvodimenzionalnojravnini.Osnovnikonstruktorklase Polygon je
public Polygon (int[] xpoints ,
int[] ypoints ,
int npoints )

je polje koje sadrix koordinatevrhovapoligona, a ypoints polje koje sadri


y koordinatenjegovihvrhova. Oba polja trebajuimatiduljinunpoints . Pogledajmo
primjerkonstrukcijetrokuta s pravimkutemu ishoditu:
xpoints

int[] xpoints = {0, 3, 0};


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

Da biste taj trokut i nacrtali, moeteunutarsvoje paint() metode pozvatiizklase


java.awt.Graphics metodu drawPoligon () sa signaturom
public void drawPolygon (Polygon p)

ovako :
g.drawPolygon (myTriangle );

Na raspolaganjuvamje i drugaverzijametode drawPolygon () koja imasignaturu:


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

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

Postojitakoder i polimorfnametoda fillPolygon (). Sintaksaje ocekivana:


g.fillPolygon (myTriangle );
g.fillPolygon (xpoints , ypoints , xpoints .length());

Viestruke linije (polylines)


Java automatskizatvarapoligonekoje nacrta (desna slika).

Ako elitecrtatiotvorenepoligone(lijevaslika), koristitcete metodu drawPolyline ().


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 appleta ucitavajuse s mreepreko URLa koji
pokazujena datoteku sa slikom. Mogu bitispremljenena web posluitelju
, lokalnom
diskuilibilogdje kamo applet moedoci preko URLa. Treba pazitida budu spremljene
tamo gdje ce ihkorisnikkoji gledaapplet mocidohvatiti. URL koji pokazujena va
lokalnidisk modaradi dok testirateapplet, alimodanece bitiod koristiza nekoga tko
dolazis mree.
U praviluse, iako to nijenuno, slikestavljajuu istidirektorijgdje je applet iliu onaj gdje
je HTML datoteka. Staviteslikuu appletovdirektorijako ce se ona koristitiu svim
instancamaapleta, a u HTML direktorijako ce razliciteinstanceappleta koristitirazlicite
slike. Treca mogucnostje stavitisve slikeu nekiposebnidirektoriji onda preko <PARAM>
oznake reci appletugdje su.
Ako znatetocan URL slike, moeteje ucitatipomocumetode getImage ():
URL imageURL = new URL("http://www.prenhall .com/logo.gif");
java.awt.Image img = this.getImage (imageURL );

Iliu jednoj naredbi:


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

Metoda getImage () pripada klasi java.applet.Applet . Za URL objekte koristimo


klasu java.net.URL . Provjeravajteu svojimprogramimada su te klase importiraneako
ihkoristite.

Metode getCodeBase() i
getDocumentBase()
Ako ne znatetocan URL slike, aliznatenjenoimei da se ona nalaziu istomdirektoriju
kao i applet, moetekoristitidruguvarijantumetode getImage () koja uzimaURL i ime
datoteke. Koristiteappletovumetodu getCodeBase () da dobijeteURL appletovog
direktorija:
Image img = this.getImage (this.getCodeBase (), "test.gif");

Metoda getCodeBase () vraca objekt tipa URL koji pokazujena direktorijizkojeg je


applet doao.
Konacno, ako je slikaspremljenau istomdirektorijukao i HTML datoteka, moete
uporabitiistumetodu getImage (), alijoj dajte getDocumentBase (). To ce vratiti
URL koji pokazujena direktoriju kojem se nalaziHTML stranicakoja je pozvalaapplet.
Image img = this.getImage (this.getDocumentBase (), "test.gif");

Ako se slikaucitavas Interneta, moepotrajatidok se sva ne ucita. U praviluvas to ne


mora brinutii moeteje crtatiodmahnakon spajanjana nekiod spomenutihURLova.
Java ce se sama pobrinutiza update kako podaci budu stizali, bez vae intervencije.
Sve slikekoje va applet koristiucitajteu metodi init(). Nemjte ihucitavatiunutar
metode paint() jer ce se inacesvakiput kad se applet obnovislikeucitavatiizpocetka.

Prikaz slike u pravoj velicini


Jednomkad je slikaucitana, nacrtajteje u metodi paint() pomocumetode drawImage
() ovako:
g.drawImage (img, x, y, io)

Pri tome je img objekt klase Image koji ste vec ucitaliunutarmetode init(). Nadalje,
x je apscisa, a y ordinatalijevoggornjeguglaslike. Argumentio je objekt klase koja
implementirainterfaceImageObserver . Taj interfacepropisujekako Java rukuje
asinhronimobnavljanjemslikekad se ona ucitavasa udaljenogracunala. Buducida klasa
java.applet.Applet implementiraImageObserver za sad samo stavitekljucnurijec
this za odgovarajuciargumentmetode drawImage () cimenaznacujeteda elitekoristiti
ImageObserver trenutnoaktivnogappleta.
Metoda paint() koja ne radi nitaosimcrtanjaslikeu pravoj velicini,poceviod
gornjeglijevoguglaizgledalabi ovako:
public void paint(Graphics g) {
g.drawImage (img, 0, 0, this);
}

Skaliranje slika
Slikumoetei skaliratiunutarzadanogpravokutnikakoristecisljedecuverzijumetode
drawImage () :
public boolean drawImage (Image img, int x, int y,
int width, int height, ImageObserver io)

pri cemusu width i height dimenzijepravokutnikau koji elitesmjestitisliku. Ostali


argumentisu istikao i prije. Ako skaliranjenijeu skladus proporcijamaslike, on moe
izgledatiizobliceno.
Da biste izbjegliizoblicenja, koristitemetode getHeight () i getWidth () koje vam
daju pravuvelicinuslike. Tada je moeteskaliratina odgovarajucinacin. Na primjer, ako
je elitesmanjitina cetvrtinu, postupilibiste ovako:
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.image
this.scaleFactor
("scalefactor "));
}

{
= this.getParameter ("imagefile ");
= this.getImage (this.getCodeBase (), filename );
= Integer .parseInt (this.getParameter

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>

Metoda init() cita dva parametraod kojihjedan daje imeslike, a drugifaktor


povecanja. Metoda paint() racunaomjerei zatimcrta sliku.
Moda se pitatezato se skaliranjeobavljau metodi paint() a ne vec u metodi init()
kad se velicinaslikeu pravilui onako ne mijenjadinamicki.
Razlogje taj to za vrijemeizvravanjametode init() slikavjerojatnonece bitido kraja
ucitana, a u tom slucajumetode getWidth () i getHeight () ce vratiti 1 i skaliranjese
uopce nece obaviti. Pokuajte to vidjetito se dogada ako racunanjepremjestimou
metodu init():
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 Javiinstanceklase java.awt.Color . Uvjeritese da ste importiralitu klasu
prije nego koristiteboje koje nisudefault. Nove boje moetekreiratikoristeciRGB
trojke 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);

Nekolikonajcece koritenihboja 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 tipa


Graphics koji obavljaodredena crtanja. Za promjenuboje potrebno je promijenitiboju
vaegobjekta iz Graphics . Tada ce sve to crtate poprimititu boju, do sljedece
promjene.
Kad se applet pocne izvravati, njegovaboja je crna. Moete je promijenitistavljajuci
npr. g.setColor (Color.red). Vratitcete je na pocetnuako pozovete g.setColor
(Color.black). Sljedecikod bi proizveoruicastistring, 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 nakon ove zadnjelinijebitizeleno. Da biste se vratilina pocetnu


boju, moetekoristitiki metodu getColor () 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, postojiklasa java.awt.SystemColor koja je podklasa od
java.awt.Color i omogucujekoritenjeboja native komponenata. Na primjer, ako
elitepozadinuvaet appleta ucinitiistomkao i pozadinuprozora, moeteu init()
metodipostupitiovako:
public void paint (Graphics g) {
g.setColor (SystemColor .control );
g.fillRect (0, 0, this.getSize ().width, this.getSize ().height);
}

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 caption
text
SystemColor .inactiveCaption // Background color for inactive
captions
SystemColor .inactiveCaptionText // Text color for inactive
captions
SystemColor .inactiveCaptionBorder // Border color for inactive
captions
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 highlighted
text
SystemColor .textHighlightText // text color for highlighted
text
SystemColor .control // Background color for controls
SystemColor .controlText // Text color for controls
SystemColor .controlLtHighlight // Light highlight color for
controls
SystemColor .controlHighlight // Highlight color for controls
SystemColor .controlShadow // Shadow color for controls
SystemColor .controlDkShadow // Dark shadow color for controls
SystemColor .inactiveControlText // Text color for inactive
controls
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 appletu HelloWorldApplet . Pozivatemetodu
drawString () za objekt tipa Graphics . Toj metodidajete argumenttipa String kao i
koordinatex i y. Ako je g objekt tipa Graphics onda je sintaksasljedeca:
g.drawString (String s, int x, int y)

Stringje ovdje tekst koji hocete ispisati. Integerix i y su koordinatedonjeglijevogugla


teksta. Tekst ce bitiispisaniznadi desno od te tocke. Izuzetaksu slovasa indeksimakoji
mogubitiispisanii ispod crte.
Do sad smo koristilidefaultfont, no Java dozvoljavai izborfonta. Garantirase postojanje
seriffontakao to je Timeskojemuse pristupapreko imena"Serif", zatim

neproporcionalnogfontakao to je Courier, koji se referencirakao "Mono" i, konacno,


sans seriffontakao Helveticakojem se pristupakao "SansSerif".
Sljedeciapplet ispisujelistudostupnihfontovana racunalugdje se izvrava. Koristise
metodom getFontList () it klase java.awt.Toolkit . Ova metoda vraca polje
stringovakoji sadre imenadostupnihfontova. Svi fontoviimplementiranina vaem
racunalumodai 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

Odabir oblikafontaje jednostavan. Kreiratenoviobjekt tipa Font . Zatimpozovete


g.setFont (Font f). Da biste instanciraliklasu Font 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 mnemonickakonstantaiz java.awt.Font koja kae da lije tekst
bold, 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

Primijetiteda se tekst nece sam prebacivatiu noviredak, cak niako u njegastavite\n.


Za takve tekstove pogodnijeje koristitikomponentekao to je TextAreao kojimacete
ucitiposlije. Ipak, da biste doznalikolikoprostora zauzimava tekst koristitcete objekte
izklase java.awt.FontMetrics .
Sljedeciprimjerproirujena applet DrawString . Ako tekst prelaziirinuappleta, on ce
se prelomitiu noviredak.
Da bismodobilimetrikutrenutacnoggrafickogobjekta, koristitcemo metodu
java.awt.Graphics .getFontMetrics () . Iz klase java.awt.FontMetrics
primijenitcemo na taj objekt metodu stringWidth (String s) koja ce namvratiti
irinustringa, a onda getLeading () da dobijemoodgovarajuciprored. Na raspolaganju
je jo mnogometoda kojimase utvrdujuvelicineteksta, no ove ce bitidovoljne.
Konacno, trebat ce namklasa java.util.StringTokenizer da bismostringrazbilina
pojedinerijeci.
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 + " ");
}
}

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>

esto predavanje - komponente


to su komponente ? labele tri koraka u dodavanju komponente gdje je metoda
paint()? metode klase Label buttoni akcije na buttonima primjer appleta sa
akcijom na buttonu razliciti obrasci za dogadaje viestruki ActionListeneri
metode za buttone Action naredbe vie buttona u istom appletu unutarnje klase
kao EventListeneri tekstualna polja primjer tekstualnih polja u Javi TextArea
klasa TextComponent sucelje TextListener i klasa TextEvent klasa Canvas klasa
Choice metode klase Choice klasa ItemListener klasa Checkbox dogadaji iz
klase Checkbox klasa CheckboxGroup primjer CheckboxGroup klasa List
metode klase List dogadaji klase List klasa Scrollbar

to su komponente?
Komponentesu sastavnicegrafickogkorisnickogsucelja(GUI, graphical user
interface).
U Javi, komponentesu podklase od java.awt.Component , a najcece koritenesu:
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;

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 su


java.applet.Applet i java.awt.Label .
Naa klasa ce imatisamo jednumetodu, init(). Ona ce obavititri stvari. Deklariratce
da je l labela, instanciratije pomocukonstruktoraLabel(String s) i dodati je
razmjetaju(layout). Opcenito, to se ne mora obavitiuvijekunutarmetode init(), ali
najceca praksa je upravotakva.

Tri koraka u dodavanju komponente


public void init() {
Label l;
l = new Label("Hello Container ");
this.add(l);
}

Kljucnastvar koju valjazapamtitio dodavanjukomponentiappletusu sljedecatri koraka:


1. Deklariratikomponentu
2. Inicijalizirati
komponentu
3. Dodatikomponenturazmjetaju(layout)
Prva dva koraka morajuse obavitiprilikomkreiranjainstancebilokoje klase, tako da
namsamo trecikorak predstavljanovost.
Moete to napraviti, naravno, i u jednoj naredbi, na primjerovako:
this.add(new Label("Hello Container "));

Nedostatak ovog kraceg zapisaje taj to se izgubilareferencana labelu(varijablal).


Ipak, labelese u pravilune mijenjaju, tako da uglavnomnijeposebna smetnja.

Gdje je metoda paint()


Primijetiteda u naemappletunema paint(), a tekst se svejednoispisujena ekranu.
Komponentese, naime, same iscrtavaju. Svakiput kad se container kao to je applet
ponovnoiscrta, on pozove ne samo svojuvlastitupaint() metodu, nego i paint()
metode svihsvojihkomponenti. Klasa java.awt.Label imasvojuvlastitupaint()
metodukoja zna kako se treba iscrtati. O iscrtavanjukomponentine moratevoditiracuna
dok god ne kreiratevlastiteklase komponenatailiizmijeniteizgledsistemskih
komponenata.

Metode klase Label


Labelesu jednostavniobjektikoji imajutek nekolikokonstruktorai vlastitih,ako se
izuzmuone koje su naslijedeneod java.awt.Component (kojoj je java.awt.Label
podklasa).
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
public
public
public
public

void addNotify ()
int getAlignment ()
synchronized void setAlignment (int alignment )
String getText ()
synchronized void setText (String text)

Vec smo vidjeliosnovnikonstruktorza labele. Moete takoder kreiratilabelukoristeci


konstruktorLabel() bez argumenata, no to opcenitonemasmisla. Nadalje, moete
odreditida tekst bude poravnatlijevo, desno ilicentrirano, za to vamstojina
raspolaganjuodgovarajucikonstruktor:
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 iz java.awt.Label koje ce povremenobitipotrebne, a to su getText


() i setText (String s). One dozvoljavajuda doznatei promijenitetekst labeledok
se applet izvrava. Na primjer,
String s = l.getText ();
l.setText ("Ovo je nova labela");

Buttoni
Buttonisu instanceklase java.awt.Button koja je podklasa od
java.awt.Component . Buttonise kreirajupomocukonstruktoraButton(String
label). On ce kreiratinovibuttonsa labelomkoja ce na njemubitiispisana. Kad ga
kreirate, moetega dodati razmjetaju. Na primjer,
Button b;
b = new Button("My First Button");
this.add(b);

Sintaksaje gotovoidenticnakao za labelei vidjetcete da je takva i za ostale komponente


grafickogsucelja. Jedinoto se mijenjasu konstruktori.
Kraci oblikje takoder isti:
add(new Button("My First Button"));

Evo jednogappleta koji sadributton:

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, buttonicineneto kad kliknetena njih. Kad mikliknena neki
objekt tipa Button , onda ce on ispalitiobjekt tipa ActionEvent . Da biste bilispremni

odgovoritina taj dogadaj, potrebno je buttonupridruitii 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 tipa ActionListener ucinitce neto s rezultatom, objektomtipa ActionEvent


kojeg je ispaliobuttonnakon to je zabiljeioklikmiem. Na primjer, sljedecaklasa ce,
kad dobije ActionEvent , 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 pie "Beep". Buttonje na uobicajeni
nacindodan razmjetaju, a metoda addActionListener () propisujeda ce na
buttonoveActionEvente reagiratiodgovarajuciActionListener, u ovomslucajuobjekt
klase BeepAction .

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

public class BeepApplet extends Applet {


public void init () {

// 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 moeodvojitiod ostalog
koda. Kako je ActionListener sucelje(interface), a ne klasa, on moebiti
implementirangdje god namodgovara. Na primjer, applet moei sam obradivatisvoje
dogadaje, 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();
}

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

Viestruki ActionListeneri
Primijetiteda nisteogranicenina samo jedan listener po dogadaju. Na primjer, sljedeci
programgenerirapet 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 klase


BeepAction dobit ce kopijutog dogadaja. Redosljedprimanjatihkopija nije
specificiran.
Ako je vae racunaloprebrzo da biste culisvihpet beep-ova, dodajte unutarmetode
ActionPerformed () izklase BeepAction jo i naredbu
System.out.println ("Beep");

Pogledateliapplet pomocuappletviewera, mocicete pratitiispissvakiput kad pritisnete


buttoni vidjetida se akcija zaistadogada pet puta.

Metode za buttone
Buttonisu jednostavniobjekti. Uglavnomsve to trebate napravitis njimaje dodati ihu
razmjetaji pridruitiim ActionListener . Na raspolaganjusu vami sljedecemetode:
public
public
public
public
public
public
public

void addNotify ()
String getLabel ()
synchronized void setLabel (String label)
void setActionCommand (String command )
String getActionCommand ()
void addActionListener (ActionListener l)
void removeActionListener (ActionListener l)

kreira takozvani peer objekt za zadanibutton, tj. native maskukoja


izgledakao WindowsbuttoniliMac buttoniliMotifbutton, no ona se rijetkodirektno
poziva.
addNotify ()

Metode getLabel () i setLabel (String s) omogucujudohvacanjei mijenjanje


teksta koji se pojavljujena buttonuza vrijemeizvravanjaappleta. Na primjer, za neki
Button b, moemoimati:
String s = b.getLabel ();
b.setLabel ("Here's the new label");

Primijetiteda metoda unatocsugestivnomimenugetLabel () vraca objekt tipa String ,


a ne Label .
Metode setActionCommand () i getActionCommand () modificirajukomandnistring
koji sa sobom nosi ActionEvent . Po pretpostavcito je labelabuttona, alito se moe
promijeniti
. Na primjer, moetezadatibroj ponvljanjabeep signalakoji ce applet
proizvestina klikmiem(pogledajteBeepFiveApplet ).
Metoda addActionListener () registriranekiobjekt kao onaj koji bi trebao primiti
ActionEvent koji ce Button ispaliti
. Metoda removeActionListener () ponitavatu
registraciju, tako da objekt tipa ActionListener vienece primatiActionEvente koje
buttonispali.

Action naredbe
Metode setActionCommand () i getActionCommand () modificirajukomandnistring
koji putujeuz ActionEvent . Po pretpostavci, to je labelabuttona, alito se moe
promijeniti
. Na primjer, moetena taj nacinproslijeditibroj ponaljanjabeep signalakoje
applet treba proizvesti.
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 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>

Vie buttona u istom appletu


Naravno, moguceje imativieod jednogbuttonau appletu. Svakibuttonkoji ce izazvati
neku akcijumora registriratibar jedan objekt koji je ActionListener . Razlicitibuttoni
moguregistriratirazliciteActionListener e , aliihmogui dijeliti. ActionListener i za
buttonemogupripadatiistojklasi, aline moraju. Ako dva buttonaregistrirajuisti
ActionListener , uobicajenoje koristitiactionkomanduda bismorazlikovaliakcije.

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>

Unutarnje klase kao Event Listeneri


Uobicajenoje da klasa koja realiziraevent listener bude unutarnjaklasa. To se najcece
primjenjujena prilagodenepodklase komponenatakoje elesame obradivatisvoje
dogadaje.
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"

WIDTH=200 HEIGHT=100>
</APPLET>

Tekstualna polja
Klasa java.awt.TextField omogucujeugradnjumaske za unos i editiranjejedne linije
teksta. Korisnaje za jednostavneoperacijeunosa malihkolicinapodataka. Ima cetiri
konstruktora:
public
public
public
public

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

Zbog nacinana koji Java razmjetatekst, konstruktorbez argumenatabi valjalo


izbjegavati. Koristiteilionaj koji ima String ilizadajte broj znakovakoje ce ta kucica
sadravati. Na primjer,
TextField name = new TextField ("Type your name here");
TextField socialSecurity = new TextField (11);

Kad korisnikpritisnetipkureturnilienter unutarTextField a, ispalise jedan


ActionEvent . Moete ga ulovitipomocu ActionListener a, isto kao u slucaju
buttona. Imajtena umuda vecinakorisnikanijesvjesnada se neto dogada tek onda kad
pritisnureturnunutarTextField a. Zato uvijekosigurajtei alternativninacinispaljivanja
ActionEvent a, na primjerpomocubuttonailiretka na izborniku.
Metoda getText () vraca sadraj TextField a. Metoda setText (String s) ga
mijenja.
Metoda setEditable () omogucujeda korisnikudozvoliteilizabranitemodificiranje
sadraja TextField a.

Primjer tekstualnih polja u Javi


Sljedeciapplet cita tekst izjednog TextField a i ispisujega velikimslovimau drugi
TextField .
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class CapitalizeApplet extends Applet {


private TextField input;
private TextField output;
public void init () {

// 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 ovomprogramukoritenje drugacijiobrazac za obradu dogadaja. Konstruktorklase


CapitalizerAction je iskoritenza prosljedivanjereferencirazlicitimkomponentama
koje metoda actionPerformed () modificira.

TextArea
Klasa java.awt.TextArea je podklasa od java.awt.TextComponent koja
osiguravamaskuza editiranjevielinijateksta. 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, izbjegavajtekoritenjekonstruktora


bez argumenata. Radijepocnitesa onimkoji zadaje String ilibroj redaka i stupaca koje
ce ta povrinazauzeti. Na primjer,
TextArea address = new TextArea ("Upiite svoju adresu", 5, 80);

Po pretpostavci, TextAreas nemascrollbar. Moete ihdodati ako odgovarajucem


konstruktorupreneseteneku od 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 TextField a, TextArea ne generiranikakavactionEvent kad korisnik


pritisnereturnunutarpolja. Umjestotoga, linijase prekida, a kursor prenosiu novired.
No i nadalje, metoda getText () vraca tekst koji sadri TextArea , a setText () ga
mijenja. Metoda setEditable () doputa vamda odrediteda lice korisnikmoci
mijenjatisadraj. Obje klase, TextField i TextArea , nasljedujusve ove metode od
svoje nadklase, TextComponent .

Nadalje, tekst moetedodavatina kraj pomocumetode append(), umetatipomocu


metode insert(), a zamijenitipomocumetode replaceRange ():
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 klasa
sadrimetode koje su zajednickeza obje klase, ukljucujucii nekolikometoda koje smo
vec vidjeli.: getText (), setText (), i setEditable (). Klasa TextComponent ima
takoder i metode za manipuliranjeselekcijomi kursoromte za procesiranjeTextEvent a.
Selekcijase koristiza copy/paste alii za drugesvrhe. Prviznak u TextComponent i je
znak broj 0; drugije znak broj 1 i tako dalje.
public synchronized
public synchronized
public synchronized
public synchronized
public synchronized
selectionEnd )
public synchronized
public synchronized

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

Kursor (caret) je mjestoinsertiranjateksta. Tamo se pojavljujetekst kad ga korisnik


utipka. Dvijesu metode koje to reguliraju:
public void setCaretPosition (int position )
public int getCaretPosition ()

Sucelje TextListener i klasa


TextEvent
Klase TextArea i TextField moguinstaliratisucelje
java.awt.event.TextListener koje hvatadogadaje izklase
java.awt.event.TextEvent . TextComponent e ispaljujuTextEvent e svakiput kad
se njihovtekst promijeni. To se dogada uglavnomsvakiput kad korisnikpritisnetipku
unutarkomponente.
Sucelje TextListener propisujesamo jednumetodu, textValueChanged ():
public abstract void textValueChanged (TextEvent te)

Nekoj TextComponent i pridruujeteTextListener tako da pozovetenjenumetodu


addTextListener () . Na primjer,

TextArea password = new TextArea (24)


password .addTextListener (new PasswordChecker ());

Ipak, u najvecembroju slucajevabit ce posve dovoljnoprocitatii postavititekst (get i


set). Procesiranjeznak po znak je relativnorijetkopotrebno.
Napomenimoda se TextListener uklanja pozivanjemmetode removeTextListener
() .
public void removeTextListener (TextListener tl)

Klasa Canvas
Klasa java.awt.Canvas definirapravokutnupovrinu(podlogu, pozadinu) po kojoj
moetepisatii crtatikoristecimetode izklase java.awt.Graphics . Klasa Canvas ima
samo tri metode:
public Canvas()
public void addNotify ()
public void paint(Graphics g)

Podlogeuglavnomne instanciratedirektno. Umjestotoga piete podklasukoja ce


pregazitipaint() metodukako biste nacrta lislikukoju trebate. Na primjer, sljedeca
podklasa od Canvas crta velikucrvenuelipsukoju moetedodati vaemappletu:
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);
}
}

Appletkoji koristikomponentenikakone bi smiopregazitimetodu paint() jer ce to


zbog nacinana koji Java rasporeduje komponenteizazvatinepredvidljiverezultate.
Umjestotoga treba kreiratiobjekt tipa Canvas i sva crtanjaobavitipomocunjegove
paint() metode.
Podlogese dodaju apletimana istinacinkao i ostale komponente. Na primjer,
public void init() {
this.add(new RedOval ());
}

Podlogeu pravilune ispaljujunikakvedogadaje, no poslijecete naucitikako se to moe


promijeniti
.

Klasa Choice
Klasa java.awt.Choice implementirapopup izborniksa fiksnompozicijom(postoji
takoder i klasa java.awt.PopupMenu kod koje pozicijanijefiksnai pojavljujese kad
korisnikkliknei dridesnu tipkumia).

Kreiranjeizbornikaje neto malokompleksnijeod kreiranjakomponentikoje smo do


sada vidjeli. Imamo, naime, dodatnikorak, dodavanjepojedinacnihopcija u izbornik.
Cijelipostupak izgledaovako:
1. DeklariratiChoice
2. AlociratiChoice
3. Dodatiopcije izborniku(alocirnomobjektu tipa Choice )
4. Dodatiizbornikrazmjetaju(layout)
5. PridruitiItemListener 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);
}

Metode klase Choice


Klasa Choice imaviemetoda za dodavanje, uklanjanjei vracanjerazlicitihopcija sa
popisa. Popis opcija se pocinjebrojitiod 0.
public
public
public
public
public
public
public
public

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

Ipak, uglavnomcete opcije ugraditiizbornikcimse applet pokrene i necete ihkasnije


mijenjati.
Sljedece metode citajuilipostavljajutrenutacnoselektiranuopcijuizizbornika, dakle
opcijukoja je u tom trenutkuvidljiva.
public
public
public
public
public
public

synchronized void removeAll ()


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

Sucelje ItemListener i klasa


ItemEvent
Kad korisnikodabere novuopcijuu izborniku, onda izbornik(objekt tipa Choice )
ispaljujedva dogadaja tipa java.awt.event.ItemEvent , jedan koji indicirada je
pocetna opcija deselektiranai drugi, da je selektirananova opcija. Te dogadaje moete
procesiratitako da instaliratesucelje java.awt.event.ItemListener , a svom
izbornikupridruiteodgovarajuciItemListener objekt koji ce hvatatispomenute
dogadaje.
No imai drugihnacinada se to napravi. Na primjer, odabranuvrijednostizizbornika
moeteprovjeravatikad se dogodinekidrugidogadaj, na primjerpritisakna nekibutton.
Pogledajmo primjersljedecegappleta koji prikazujeizborniks brojevimaod d1 do 5.
Korisnikbiranjembroja odreduje kolikoputa applet alje beep signal.
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

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 implementirasucelje ItemListener . Ona pomocumetode


ItemEvent .getStateChange () filtriradogadaje prouzrokovanedeselektiranjem
opcija i proizvodibeep samo kad se opcija selektira. Konstantekoje namstoje na
raspolaganjusu:
ItemEvent .DESELECTED
ItemEvent .ITEM_FIRST
ItemEvent .ITEM_LAST
ItemEvent .ITEM_STATE_CHANGED
ItemEvent .SELECTED

Metoda ItemEvent .getItem () se koristida se dobije trenutnoselektiranaopcija. Kao


i prije, ako ne moetecutisve beepove, dodajte izanaredbi tk.beep(); u klasi

jo i naredbu System.out.println ("beep"); i pogledajteapplet sa


appletviewerom.
BeepItem

Klasa Checkbox
Klasa java.awt.Checkbox , se koristiza selektiranjeboolean vrijednosti. Svaki
Checkbox imalabelukoja bi trebalareci korisnikuto pojediniCheckbox predstavlja.
Na primjerCheckbox sa labelom"Olives" u appletu Ingredients za narucivanjepizze
(vididolje) bilabi cekiranaako korisnikelimasline, a u protivnomnecekirana.
Dodavanje Checkbox a appletuje jednostavno. Deklarirajte, konstruirajtei dodajte:
Checkbox c;
c = new Checkbox ("Pepperoni "));
add(c);

Kao i obicno, ovo se moenapisatii u jednoj naredbi:


add(new Checkbox ("Pepperoni "));

Po pretpostavci, checkboxovisu necekiranikad se kreiraju. Ako eliteda nekiod njih


bude odmahcekiran, koristitesljedecikonstruktor:
add(new Checkbox ("Pepperoni ", null, true));

Vrijednostnull je ovdje referencana CheckboxGroup i znacida ovaj Checkbox ne


spada u CheckboxGroup (vididalje).
Svaki Checkbox ima boolean vrijednost, bilo true ilifalse . Kad je Checkbox
cekiran, ta vrijednostje true . Kad je necekiran, ona je false . Toj vrijednostipristupate
pomocu Checkbox ovihmetoda getState () 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 normalnimokolnostimarezultatkorisnikove
akcije, ispaljujese dogadaj tipa java.awt.event.ItemEvent . Taj dogadaj uglavnom
ignoriratei ispitujetestanje Checkbox a direktnokad vamtreba. Ipak, ako eliteodmah
znatito stanje, registriratcete uz njega ItemListener i u odgovarajucojklasi
implementiratisucelje java.awt.event.ItemListener .

PripadniItemEvent je potpunoistikao i onaj za Choice . Taj se dogadaj zapravo


koristiza indiciranjeselekcijai deselekcijau svimvrstamapopisa opcija, ukljucujuci
checkboxove, radio buttone, choice, i liste.
Sljedeciprogramje applet koji pita "What do you want on your pizza?" Kad je dodatak
cekiran, cijenase povecavaza 50 centa. Kad se dodatak decekira, cijenase smanjujeza
50 cdnta. Cijenaje pokazanau TextField u.
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);
}

}
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 unutargrupe
ne moebiticekiranovieod jednogcheckboxaistovremeno. Takvicheckboxoviizklase
CheckboxGroup se cesto zovuradio buttons. Checkboxovikoji pripadajuistoj
CheckboxGroup i ne moguse istovremenocekirati. Kad korisnikcekira jednog, sviostali
se automatskidecekiraju.
Konstruktorza CheckboxGroup je trivijalan.Nema argumenatai cak ne morate
dodavatitu komponentuappletujer ona nijedio korisnickogsuceljanego naprosto nacin
uredenjacheckboxova.
CheckboxGroup cbg = new CheckboxGroup ();

Da biste omogucilida se jedna grupacheckboxovaponaa kao radio buttons,


konstruirajtesvakipojedinina ovaj nacin:
public Checkbox (String label, CheckboxGroup cbg, boolean checked )

Labela label pripada odredenomcheckboxu, a cbg je grupau koju stavljatetaj


checkbox. Ona mora u tom trenutkuvec postojati.

Kad god elite, moeteprocitatiiliodreditikoji checkbox je cekiran, koristecise jednom


od sljedecedvijemetode:
public Checkbox getSelectedCheckbox ()
public synchronized void setSelectedCheckbox (Checkbox box)

Primjer CheckboxGroup
Sljedeciprogrampita korisnikakako eliplatitipizzu. Primijetiteda za razlikuod
prethodnogprimjerau kojem je mogaoizabrativiedodataka na pizzu, sada moe
odabratitocno 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, postupitejednako


kao i u slucajubilokojeg drugog Checkbox a.

Klasa List
Listesa scrollbarom, objektiklase java.awt.List , korisnesu za spremanjeduljih
popisa red po red. Elementilistesu stringovi. Na primjer,

Metode klase List


Novi objekt tipa List 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 pravilumanjiod


broja elemenatasame liste, dok je allowMultipleSelections argumentkoji
odreduje moelikorisnikselektirativieod jednogretka istovremeno(npr. pomocu
Shift- click).
Sljedece metode dodaju retke na kraj liste:
public void add(String item)
public void addItem (String item) // deprecated ! Koristite prvu
metodu

Sljedece dvijemetode dodaju retke na zadanupozicijuu listi:


public synchronized void add(String item, int index)

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


deprecated !

Sljedece metode uklanjajuretke izliste:


public
public
public
public

synchronized
synchronized
synchronized
synchronized

void
void
void
void

removeAll ()
remove(String item)
remove(int position )
delItem (int position )

Sljedece metode doputajuvamda procitateodredene retke izliste:


public int getItemCount ()
public String getItem (int index)
public synchronized String[] getItems ()

Moete takoder zamijenitiodredeniredak:


public synchronized void replaceItem (String newValue , int index)

Ove metode omogucujuvamda doznatekoje je retke korisnikselektirao::


public
public
public
public
public

synchronized int getSelectedIndex ()


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

Mnoinskioblikovihmetoda koristitcete ako listadozvoljavaviestrukuselekciju. Da li


je ona dozvoljena, ustanovitcete metodom isMultipleMode (), a to moetepromijeniti
pomocu setMultipleMode ().
public boolean isMultipleMode ()
public synchronized void setMultipleMode (boolean b)

Sljedece metode omogucujuvammanipuliranjeselektiranjem:


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

Sljedece dvijemetode odredujuda lije redak na odredenomindeksuvidljivunutar


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

ListEvents

Dogadaji klase List

Listscan firetwo separate types of events. When a listitemis selectedor deselected, the
List firesan ItemEvent . However, whenthe user doubleclickson a listitem, the List
firesan ActionEvent . Therefore, you can registerboth an ItemListener to process
selectionsand/or an ActionListener to process doubleclicks.
public
public
public
public

void
void
void
void

addItemListener (ItemListener l)
removeItemListener (ItemListener l)
addActionListener (ActionListener l)
removeActionListener (ActionListener l)

The actioncommandinthe ActionEvent is the listitemwhichwas doubleclicked.

Klasa Scrollbar
Klase List , TextArea , i ScrollPane s imajugotovescrollbare. No ako elitescrollati
nekidrugiobjekt, treba vamklasa java.awt.Scrollbar . Scrollbariimajupuno
primjena. Elementarnaje pomicanjevidljivogpodrucja. Takoder se mogukoristitiza
postavljanjevrijednostiizmedudva zadanabroja. Ilimoguprolazitikroz vieekrana, kao
u operacijamana bazamapodataka koje trae sukcesivneslogove.
Imamotri konstruktora:
public Scrollbar ()
public Scrollbar (int orientation )
public Scrollbar (int orientation , int value, int visible , int min,
int max)

Argumentorientation je jedna od mnemonickihkonstanti, Scrollbar .HORIZONTAL


iliScrollbar .VERTICAL . Prema ocekivanju, one odredujuda lije scrollbarrazmjeten
s lijevana desno iliodozgo prema dolje.
Sve vrijemeScrollbar imajednuan int vrijednost. To je pocetna vrijednostkoja
mora bitiizmeduminimalnei maksimalnekoje se zadajusa zadnjadva argumenta. Kad se
Scrollbar kreira, njegovapocetna vrijednostce biti value . Defaultje 0.
Argumentvisible predstavljavelicinuvidljivogdijelaskrolabilnepovrineu pikselima.
To se koristikod pomicanjapo stranici.
Dogadaj koji Scrollbar ispaljujeje tipa java.awt.event.AdjustmentEvent . Klasa
koja ce ga uhvatitimora implementiratisucelje
java.awt.event.AdjustmentListener . Ona mora implementirati
metodu
adjustmentValueChanged () sa sljedecomsignaturom
:
public void adjustmentValueChanged (AdjustmentEvent e)

Sljedeciprogramje applet koji mijenjabroj u TextField u izmedu1 i 100 u ovisnostio


pozicijioznake na scrollbaru. U praksi bi taj broj, naravno, morao neto predstavljati.
import java.applet.*;
import java.awt.*;

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>

Sedmo predavanje - dogadaji


Proceduralni programi rep dogadaja (event queue ) dogadaji niske razine (low
level events ) dogadaji visoke razine (high level events ) hijerarhija klasa
dogadaja obrada dogadaja razliciti EventListeneri primjer uporabe
MouseListenera dogadaji vezani uz tipke (key events ) kodovi tipki razlicite
tipke i njihovi kodovi modifikatori (modifier keys ) modifikatori uz tipke mia
dogadaji 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 izvravanja. Kontrolase
prebacuje linearnood prve naredbe na drugu, od drugena trecu i tako dalje, sa
eventualnimpetljamai grananjima. Korisnikunosipodatke samo u tocno odredenim
trenucima, kad je racunalospremnoprimitite podatke.
Programikoji podravajuGUI (GraphicalUser Interface) ne mogufunkcioniratina takav
nacin. Korisnikumora bitiomogucenoda praktickiu svakomtrenutkukliknemiem,
odabere stavkuizbornika, unesetekst i slicno.

Rep dogadaja (event queue)


Umjestoproceduralnog, GUI modelizahtijevajudogadajnipristup. Svaka korisnikova
akcija, bio to klik, pritisaktipke ilineto drugo, stavljase u tzv. rep dogadaja(event
queue), onako kako se dogadajipojavljuju. Uobicajenoje da se todogada na razini
operacijskogsustava. Programuklanjadogadaje izrepa i obraduje ih, jedan po jedan.
Opcenito, jedna beskonacna while petljacita dogadaje izrepa, a dugacka switch
naredba raspodjeljujeihodgovarajucimdijelovimaprogramakoji ce ihobraditi..
Ovisnoo arhitekturisustava, moemoimatijedan velikisistemskirep dogadaja ilipak
svaka aplikacijamoeimativlastitirep dogadaja. Operacijskisustavmora osiguratida
pravidogadajistignudo pravihprograma.
U aplikacijamakojimase mibavimo, dakle u Java programima, svaka virtualnamaina
imajedan glavniAWT rep dogadaja. Takoder je gotovosigurnoprisutani native rep
dogadaja, no micemo promatratisamo Javinrep. Java programce jedinou tom repu
vidjetidogadaje koje mualje native korisnickosucelje.

Dogadaji niske razine (low level events)


Dogadajiniskerazinepredstavljajudirektnukomunikacijus korisnikom. To moebiti
pritisakna tipku, klikanjemiemi slicno. Ukljucenesu sljedeceklase:
java.awt.event.ComponentEvent

komponentapomaknuta, promijenjenajoj je velicinaitd.


java.awt.event.FocusEvent

komponentadobilailiizgubilafokus
java.awt.event.KeyEvent

tipka pritisnuta, tipka otputenaitd.


java.awt.event.MouseEvent

tipka miapritisnuta, podignuta, kliknuta, mipomaknut, mipovucenitd.


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 level


events)
Dogadajivisokerazineilisemantickidogadajisadre u sebi znacenjekoje je pridijeljeno
komponentikorisnickogsucelja. Klase koje ovdje igrajuulogusu:
java.awt.event.ActionEvent

izvrenaje naredba
java.awt.event.AdjustmentEvent

prilagodenaje vrijednost(npr. scrollbarom)


java.awt.event.ItemEvent

stanje stavke se promijenilo


java.awt.event.TextEvent

vrijednosttekstualnogobjekta se promijenila
Na primjer, kad korisnikkliknemiemna buttoni zatimga otpusti, buttonce dobititri
odvojenadogadaja nierazine, tipa MouseEvent (jedan za pritisaktipke mia, mouse
down, drugiza otputanjetipke, mouse up, trecieventualnoza povlacenjemia, mouse
drag, ako je nastupilo). Buttonce nakon toga ispalitijedan dogadaj vierazine, tipa
ActionEvent .
Ako korisnikkliknemiemna button, povuce miaizvanbuttonai onda ga otpusti, button
ce dobitidva odvojenadogadaja nierazine(jedan za mouse down, drugiza mouse
drag). U tom slucajuignoriratce ihi nece ucinitinita.

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
|

+--java.awt.event.WindowEvent

Obrada dogadaja
Za obradu dogadaja izrepa zaduenaje Java runtime. Posebno, ona osiguravada svaki
dogadaj niskerazinedospije do odgovarajucekomponente. Ne moratese brinutikojoj je
komponentikoji dogadaj namijenjen. To sustavrjeava automatski. Specijalno, runtime
prosljedujedogadaj metodi processEvent () klase java.awt.Component :
protected void processEvent (AWTEvent e)

Metoda processEvent () prepoznajetip dogadaja i prosljedujega jednoj od pet drugih


metoda iziste klase:
protected
protected
protected
protected
protected

void
void
void
void
void

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

Svaka od tihmetoda pokuavavidjetije linekilistener odgovarajucegtipa registriranza


tu komponentu. Ako jest, dogadaj se prosljedujesvakomod registriranihlistenera
nepredvidljivimporetkom.
Interno, ove metode koristeobjekt tipa java.awt.AWTEventMulticaster kako bi
vodilepopis registracijalistenera uz svaku komponentu.

Razliciti EventListeneri
Da biste omoguciliodgovaranjena dogadaje koje komponentadobiva, pridruujete
komponenti(registrirate) event listener odgovarajucegtipa. Eventlistenerje svakiobjekt
koji implementirasucelje java.util.EventListener . AWT definiravienjegovih
podsucelja, 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

java.awt.event.InputMethodListener

Svako od tihsuceljadefiniradogadaje na koje eventlistenertog tipa mora bitispreman


odgovoriti. Na primjer, sucelje MouseListener deklarirasljedecemetode:
public
public
public
public
public

abstract
abstract
abstract
abstract
abstract

void
void
void
void
void

mouseClicked (MouseEvent e)
mousePressed (MouseEvent e)
mouseReleased (MouseEvent e)
mouseEntered (MouseEvent e)
mouseExited (MouseEvent e)

Kada, na primjer, komponentadobije dogadaj tipa MouseEvent , njenametoda


processMouseEvent () provjeravanjegovID da bi ustanovilada lije mikliknut,
pritisnut, otputen, uvedeniliizveden. Tada pozivaodgovarajucumetoduu svakom
registriranomobjektu koji implementiraMouseListener .

Primjer uporabe MouseListenera


Na primjer, pretpostavimoda elimoapplet koji crta crvenikrug oko mjestagdje
korisnikkliknemiem. Prisjetitese da je java.applet.Applet podklasa od
java.awt.Component . Prema tome, da bi applet odgovaraona klikanjemiem, uz
njegamora bitiregistriranodgovarajuciMouseListener . U takvimappletima
najjednostavnijeje da sam applet bude MouseListener . Koordinatnisustavse odnosi
na komponentukojoj je dogadaj namijenjen, ne nunona cijeliapplet (no to je u ovom
slucajuisto).
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) {}

// 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) tipa java.awt.event.KeyEvent alje se komponentiako korisnik
pritisnetipkudok komponentaimafokus. Ti su dogadajipredstavljenipo jednom
cjelobrojnomkonstantom:
Tipka je pritisnuta
KeyEvent .KEY_RELEASED Tipka je otputena
KeyEvent .KEY_TYPED
Tipka je pritisnutai zatimotputena
KeyEvent .KEY_PRESSED

Uglavnomcete imatiposla sa ovimposljednjimdogadajemvezanimuz tipke,


KeyEvent .KEY_TYPED .
Glavnastvar koju obicnotrebate doznatiuz neki KeyEvent je koja je tipka pritisnuta. Tu
informacijudobijetepomocumetode getKeyChar ():
public char getKeyChar ()

Ona ce vamvratitiUnicodeznak koji odgovarapritisnutojtipki.


Dogadajikao KEY_PRESSED iliKEY_RELEASED ne nose samo znak. Oni takoder imajui
kod tipke. (Za razlikuod njih, dogadaji KEY_TYPED nemajukod, odnosno, kod imje
nedefiniran). Ako za neki KeyEvent trebate doznatikoja tipka je pritisnuta, a ne koji je
znak upisan, doznatcete to pomocumetode getKeyCode ():
public int getKeyCode ()

Moete to i konvertiratiu lokaliziranistringkao na primjer"END", "F4" ili"Q" pomocu


statickemetode KeyEvent .getKeyText ():
public static String getKeyText (int keyCode )

U praviluna dogadaje vezaneuz tipke odgovarateu samoj komponenti, tako da uz nju


registrirateneki KeyListener . Sucelje KeyListener deklarirasljedecemetode, po
jednuza svakitip KeyEvent a.
public abstract void keyTyped (KeyEvent e)
public abstract void keyPressed (KeyEvent e)
public abstract void keyReleased (KeyEvent e)

Kodovi tipki
Nisu sve tastaturenapravljenena istinacin. Mac imatipke za naredbe i opcije. PC ima
Alttipke. Neki imajutipkuWindows95, nekinemaju. Neki imajunumerickutastaturu,
nekine. Emacsocekuje Meta tipkukoja rijetkozasebnopostoji, no obicnoje pridruena
Escape tipki(koju takoder neke tastaturenemaju). Nekonzistentnosttastaturaje je jedan
od problemas kojimase cross-platform environment mora na nekinacinpozabaviti.
Klasa Java.awt.event.KeyEvent definiraneto vieod stotinuvirtualnihkodova za
tipke koji se mapirajuna razlicite, uvijekprisutne, tipke. KeyEvent .VK_0 do
KeyEvent .VK_9 su iste kao 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, odnosno njihovikodovi:

KeyEvent .VK_ACCEPT
KeyEvent .VK_ADD
KeyEvent .VK_ALT
KeyEvent .VK_BACK_QUOTE
KeyEvent .VK_BACK_SLASH
KeyEvent .VK_BACK_SPACE
KeyEvent .VK_CANCEL
KeyEvent .VK_CAPS_LOCK
KeyEvent .VK_CLEAR

KeyEvent .VK_F4
KeyEvent .VK_F5
KeyEvent .VK_F6
KeyEvent .VK_F7
KeyEvent .VK_F8
KeyEvent .VK_F9
KeyEvent .VK_F10
KeyEvent .VK_F11
KeyEvent .VK_F12

KeyEvent .VK_NUMPAD4
KeyEvent .VK_NUMPAD5
KeyEvent .VK_NUMPAD6
KeyEvent .VK_NUMPAD7
KeyEvent .VK_NUMPAD8
KeyEvent .VK_NUMPAD9
KeyEvent .VK_OPEN_

KeyEvent .VK_CLOSE_
BRACKET
KeyEvent .VK_COMMA
KeyEvent .VK_CONTROL
KeyEvent .VK_CONVERT
KeyEvent .VK_DECIMAL
KeyEvent .VK_DELETE
KeyEvent .VK_DIVIDE
KeyEvent .VK_DOWN
KeyEvent .VK_END
KeyEvent .VK_ENTER
KeyEvent .VK_EQUALS
KeyEvent .VK_ESCAPE
KeyEvent .VK_F1
KeyEvent .VK_F2
KeyEvent .VK_F3

KeyEvent .VK_HOME
KeyEvent .VK_INSERT
KeyEvent .VK_KANA
KeyEvent .VK_KANJI
KeyEvent .VK_LEFT
KeyEvent .VK_META
KeyEvent .VK_
MODECHANGE
KeyEvent .VK_MULTIPLY
KeyEvent .VK_
NONCONVERT
KeyEvent .VK_NUM_LOCK
KeyEvent .VK_NUMPAD0
KeyEvent .VK_NUMPAD1
KeyEvent .VK_NUMPAD2
KeyEvent .VK_NUMPAD3

KeyEvent .VK_PAGE_UP
KeyEvent .VK_PAUSE
KeyEvent .VK_PERIOD
KeyEvent .VK_
PRINTSCREEN
KeyEvent .VK_QUOTE
KeyEvent .VK_RIGHT
KeyEvent .VK_SCROLL_
LOCK
KeyEvent .VK_SEMICOLON
KeyEvent .VK_SEPARATER
KeyEvent .VK_SHIFT
KeyEvent .VK_SLASH
KeyEvent .VK_SPACE
KeyEvent .VK_SUBTRACT
KeyEvent .VK_TAB
KeyEvent .VK_UNDEFINED
KeyEvent .VK_UP

Modifikatori (Modifier Keys)


Obje klase, KeyEvent i MouseEvent su podklase od java.awt.event.InputEvent .
Njezinaglavnaulogaje testiranjedodatnihuvjetakao, na primjer, da lije ALT tipka bila
pritisnutazajednos nekomdrugomtipkom, iliSHIFT tipka istovremenos miemi slicno.
Sljedece cetirimetode kau vamda lije ilinijeodredena tipka bilapritisnutau trenutku
kad je dogadaj poslan.
public
public
public
public

boolean
boolean
boolean
boolean

isShiftDown ()
isControlDown ()
isMetaDown ()
isAltDown ()

Sve se one mogupozivatii uz MouseEvent i uz KeyEvent objekte.


Tu je takoder i metoda getWhen () koja vraca vrijemekad je dogadaj nastao. Vrijeme
je dano u milisekundamaod ponoci1. sijecnja1970. UTC.
public long getWhen ()

Klase java.util.Date i java.util.Calendar imajumetode pomocukojihto


moetekonvertiratiu obicandatumi vrijeme. No najcece ce vas zanimatisamo
vremenskarazlikaizmedudva dogadaja.

Modifikatori uz tipke mia


Dogadajitipa InputEvent spremajuse kao int vrijednosti. Svakibit u takvombroju je
flag koji odgovaraodredenommodifikatoru.Vrijednostitihflagova su dane pomocu
int konstantikoje su public final static unutar InputEvent klase:

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
Moete ihdoznatipomocumetode getModifiers ():
public int getModifiers ()

Koristitebitovskioperator & kad elitetestiratida lije nekiflag podignut. Na primjer,


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

Dogadaji vezani uz fokus (Focus


Events)
U svakomtrenutkutocno jedna komponentau appletuimafokus, odnosno mogucnost
primanjainputas tastatureilimia. Dogadajiniskerazinebit ce, dakle, u tom trenutku
usmjereniprema toj komponenti.
Fokus je mogucepodesitina vienacina. Na primjer, kad korisnikpritisnetipkuTab,
fokusce opcenitobitipremjetens dotadanjekomponentena sljedecu. Ako pritisne
Shift- Tab, fokusce se vratitina prethodnukomponentu. Ako selektirakomponentu
miem, ona ce dobitifokus.
Bez obzirana koji nacinkomponentadobije iliizgubifokus, ona emitiradogadaj tipa
java.awt.event.FocusEvent . Promjenafokusamoebitipermanentnailiprivremena.
Permanentnapromjenanastajekad je fokusdirektnopremjetens jedne komponentena
drugu, bilopozivanjemkomponentinemetode requestFocus () iliakcijomkorisnika,
npr. pomocuTab tipke. Privremenapromjenafokusanastajekao indirektnirezultatdruge
operacije, na primjerdeaktiviranjaprozora. U tom slucajuoriginalnostanje fokusace biti
automatskirestauriranokad se operacijazavriiliprozor opet aktivira.
Metoda isTemporary () vraca true ako je promjenafokusaprivremena, a false ako
je permanentna:
public boolean isTemporary ()

Na dogadaje vezaneuz promjenufokusamoeteodgovoritiako uz komponentu


instaliratesucelje java.awt.event.FocusListener . To suceljedeklariradvije
metode:
public abstract void focusGained (FocusEvent e)
public abstract void focusLost (FocusEvent e)

Dogadaji vezani uz komponentu


(Component Events)
Klasa java.awt.event.ComponentEvent je nadklasasvimklasamadogadaja koje
smo do sad vidjeli. Ona takoder imai nekolikosvojihvlastitihdogadaja koji vam
omogucujuda reagiratekad se komponentaprikae, sakrije, pomakneilijoj se promijeni
velicina. Oni su reprezentiranikonstantama:
ComponentEvent .COMPONENT _MOVED
ComponentEvent .COMPONENT _RESIZED
ComponentEvent .COMPONENT _SHOWN
ComponentEvent .COMPONENT _HIDDEN

Kao i obicno, na te dogadaje moeteodgovaratiako uz svojukomponenturegistrirate


odgovarajuciobjekt izklase koja implementirasucelje
java.awt.event.ComponentListener . To suceljedeklariracetirimetode:
public
public
public
public

abstract
abstract
abstract
abstract

void
void
void
void

componentResized (ComponentEvent e)
componentMoved (ComponentEvent e)
componentShown (ComponentEvent e)
componentHidden (ComponentEvent e)

Klasa java.awt.event.ComponentEvent nemanekihvlastitihposebno korisnih


metoda, alimoetekoristitiraznemetode izklase java.awt.Component kad elite
ustanovitikamo je komponentapomaknutailina koju velicinuje preoblikovana.

Adapteri
Adapterisu klase koje implementirajupojedinasuceljatako da sve deklariranemetode iz
suceljaprekrijumetodamakoje ne cinenita. AWT osiguravavieadapterskihklasa za
razlicitevrste EventListener a. To su:
ComponentAdapter
ContainerAdapter
FocusAdapter
KeyAdapter
MouseAdapter
MouseMotionAdapter
WindowAdapter

Na primjer, znamoda sucelje MouseListener deklarirasljedecihpet metoda:


public
public
public
public
public

abstract
abstract
abstract
abstract
abstract

void
void
void
void
void

mouseClicked (MouseEvent e)
mousePressed (MouseEvent e)
mouseReleased (MouseEvent e)
mouseEntered (MouseEvent e)
mouseExited (MouseEvent e)

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

package java.awt.event;
import java.awt.*;
import java.awt.event.*;

public class MouseAdapter implements MouseListener


public
public
public
public
public

void
void
void
void
void

mouseClicked (MouseEvent e) {}
mousePressed (MouseEvent e) {}
mouseReleased (MouseEvent e) {}
mouseEntered (MouseEvent e) {}
mouseExited (MouseEvent e) {}

Ako sada napravitepodklasuklase MouseAdapter umjestoda direktnoimplementirate


MouseListener , izbjecicete pisanjemetoda koje vamzapravone trebaju. Pregazitcete
jedinoone metode koje stvarnoeliteimplementirati
. Adapterisu svojevrsno
pojednostavnjenjeposla prilikomimplementiranjasucelja. Moete ihkoristitiako elite,
alii ne morate.

Primjer uporabe adaptera


Ovdje imamoadapter za miakoji proizvodibeep signalkad kliknetemiem.
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>

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
public
public
public

void
void
void
void

mousePressed (MouseEvent e) {}
mouseReleased (MouseEvent e) {}
mouseEntered (MouseEvent e) {}
mouseExited (MouseEvent e) {}

Apsorbiranje dogadaja
Ponekad je potrebno neke dogadaje zadratikako ihkomponentane bi procesiralana
uobicajennacin. Na primjer, programza izraduvizualnogsuceljamodatreba dozvoliti
korisnikupovlacenjemiapo ekranu. U tom slucajune eliteda obicanklikna tipkumia
aktiviratu funkciju. Zato komponentamoeapsorbirati(consume) dogadaje tipa
InputEvent , dakle MouseEvent ilia KeyEvent , tako da pozove njihovumetodu
consume () :
public void consume ()

Jednomkad je dogadaj (objekt) tipa InputEvent apsorbiran, izvornakomponentaga


nece procesirati, alice taj dogadaj svejednobitidistribuiransvimregistriranimlistenerima
.

Prebacivanje dogadaja s niske na


visoku razinu
Svakinative operacijskisustavi korisnickosuceljealje samo dogadaje niskerazine.
Ono nece poslatiActionEvent , TextEvent , ItemEvent iliAdjustmentEvent .
Umjestotoga, svaka komponentakoja lansiratakve dogadaje prvo sluaodredene
dogadaje niskerazine. Kad ugledaodgovarajucidogadaj ilikombinacijudogadaja niske
razine, ona ihapsorbirai lansiranovidogadaj visokerazine.

Rad s repom dogadaja

Klasa java.awt.EventQueue predstavljarep dogadaja koji cekaju na procesiranje.


Moete kreirativlastiteinstanceove klase uz pomoc sljedecegkonstruktora:
public EventQueue ()

Na primjer:
EventQueue MyQueue = new EventQueue ();

Ipak, uglavnomce vas viezanimatisistemskirep dogadaja. Taj se kreira automatski.


Moete dobitireferencuna njegapomocumetode getSystemEventQueue () izklase
java.awt.Toolkit ovako:
EventQueue systemQueue = Toolkit .getDefaultToolkit ()
.getSystemEventQueue ();

Appletnece mocipozvatiovu metodua da pritomne generiraSecurityException .


Jednomkad dobijetereferencuna sistemskirep dogadaja, moetemanipuliratis njim
pomocusljedecihmetoda:
public
public
public
public

synchronized
synchronized
synchronized
synchronized

void postEvent (AWTEvent e)


AWTEvent getNextEvent ()
AWTEvent peekEvent ()
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 nti
dogadaj izrepa.

Osmo predavanje
komponenti

razmjetaj

Kontrola razmjetaja komponenti razne implementacije layout managera


razmjetaj tipa FlowLayout podeavanje poravnanja za FlowLayout razdvajanje
komponenti za FlowLayout razmjetaj tipa BorderLayout razmjetaj tipa
CardLayout uporaba CardLayout razmjetaja promjena karata razmjetaj tipa
GridLayout razmjetaj tipa BridBagLayout razmjetaj tipa GridBagConstraints
mrea (grid) za applet Calculator atributi gridx i gridy atributi gridwidth i
gridheight atribut fill atributi ipadx i ipady klasa Insets atribut anchor
atributi weightx i weighty primjer za GridLayout rucno pozicioniranje
komponenti Kontejneri dvije vrste kontejnera paneli ugnjedeni paneli
prozori (windows) okviri (frames) dogadaji vezani uz prozore primjer dogadaja
na prozorima kombiniranje appleta i aplikacija dijalozi metode za dijaloge
primjeri dijaloga pisanje podklasa klase Dialog

Kontrola razmjetaja komponenti


Kontrolunad pozicijamakomponentikoje dodajete razmjetajuomogucujevamsucelje
java.awt.LayoutManager . Buducida ne moeteunaprijedznatis kako velikom
povrinomcete raditiilikakvog ce ona bitioblika, kontrolace bitirelativna, dakle
uglavnomcete odlucivatio tome treba lineka komponentabitiiznadiliispod druge,
poravnatalijevoilidesno, aliu pravilunecete odredivatida se komponentatreba pojaviti
ba u nekoj specificnojtocki.

Razne implementacije LayoutManagera


Sucelje java.awt.LayoutManager implementiranoje u vierazlicitihklasa, kao to su:
java.awt.FlowLayout
java.awt.BorderLayout
java.awt.CardLayout
java.awt.GridLayout
java.awt.GridBagLayout

Appletiilikontejneriimajumogucnostkoristitiove i drugelayout managere da bi odlucili


gdje ce stavitikomponentekoje u njihdodajete.
Klasa java.awt.FlowLayout rasporedujekomponentes lijevana desno dok ima
prostora, a tada nastavljana istinacinu retku ispod. Svaka komponentau FlowLayout
razmjetajudobija upravoonolikoprostora kolikojoj minimalnotreba i nitavie. Takav
je razmjetajkoristanza rasporedivanjebuttona, aliza mnogedrugestvarinije. On je

pretpostavljeni(default) razmjetajza applete i panele(posebne kontejnereo kojimace


malokasnijebitirijeci).
Klasa java.awt.BorderLayout organiziraapplet na sekcijeprema stranamasvijeta:
North, South, East, West i Center. North, South, East i West su pravokutnicina
rubovimaappleta. Oni se kontinuiranoire prema velicinikomponenatau njima. Center je
ono to preostane u sreditu.
Klasa java.awt.CardLayout razbijaapplet u skupinupovrina(karata) koje imaju
svaka svoj vlastiterazmjetaj. U svakomtrenutkusamo se jedna karta pojavljujena
ekranu. Korisnikmoeprebacivatiizgledekrana s jedne na drugukartu, a svaka
prikazujerazliciteskupove komponenti. Obicno se to usporedujesa HyperCardom na
Macu iliToolbookom on Windowsima. U Javi se to moekoristitikao serijamaskiza
unos podataka ako sva polja ne mogustatina ekran.
Klasa java.awt.GridLayout dijeliapplet na odredenibroj redaka i stupaca te tako
formiramreucelijakao matricu. Kako se koja komponentadodaje, ona se smjetau
sljedecuslobodnuceliju, poceviod lijevoguglaprema desno i prema dolje. Svaka
komponentase podeava po velicinitako da pristajeu celiju. Takav razmjetajce neke
komponentenepotrebnostisnuti, a neke razvuci, alije jako pogodan za razmjetanje
panela.
Klasa java.awt.GridBagLayout daje najpreciznijiod svihAWT razmjetaja.
Razmjetajje kao i GridLayout , alikomponentene morajubitiiste velicine. Svaka
komponentamoezauzetijednuiliviecelija. tavie, komponentenisununosmjetene
u celijepoceviod gornjeglijevoguglanitise morajudodavatiprema desno i prema
dolje.
U jednostavnimappletimasa samo nekolikokomponentibit ce dovoljanjedan
razmjetaj. U kompliciranijima
, medutim, cesto cete razbitiapplet na panele, rasporeditiih
prema nekomrazmjetaju, a onda svakipanelsnabdjetivlastitimlayout managerom za
rasporedivanjekomponentiunutarnjega.

Razmjetaj tipa FlowLayout


Klasa java.awt.FlowLayout rasporedujekomponentes lijevana desno dok ima
prostora, a tada nastavljaistipostupak redak nie. Svaka komponentadobija upravo
tolikomjestakolikojoj treba i nitavie. Ovaj je tip razmjetajanajkorisnijiza
rasporedivanjebuttona.
FlowLayout je pretpostavljeni(default) razmjetajza java.awt.Panel koji je
nadklasaod java.applet.Applet . Prema tome ne trebate ucinitinitaposebno da
biste FlowLayout kreiraliunutarappleta. Medutim, ako ga elitekoristitiunutarprozora,
java.awt.Window , trebat ce vamodgovarajucikonstruktori.

Razmjetajiimajukonstruktorekao i ostale klase. Jedan od konstruktoraza


FlowLayout je:

public FlowLayout ()

Dakle, za kreiranjenovogobjekta tipa FlowLayout piete:


FlowLayout fl;
fl = new FlowLayout ();

Kao i obicno, to se moeskratitina:


FlowLayout fl = new FlowLayout ();

Appletucete reci koju specificnuinstancuklase LayoutManager elitekoristiti, tako da


taj objekt navedeteu appletovojmetodi setLayout (). Ovu metoduklasa
java.applet.Applet nasljeduje, kao i mnogedruge, izklase java.awt.Container .
this.setLayout (fl);

Metoda setLayout () se uglavnompozivau init() metodi. Uobicajenoje kreirati


primjerakrazmjetajadirektnounutarpozivametode setLayout () ovako:
this.setLayout (new FlowLayout ());

Podeavanje poravnanja za
FlowLayout
Poravnanjeza neki FlowLayout zadajetepomocuodgovarajucegkonstruktora.
Komponentesu u appletupo pretpostavcicentrirane. Moete umjestotoga odreditida
budu lijevoilidesno pozicionirane
. Za to moetekoristitigotovekonstante
FlowLayout .LEFT , FlowLayout .RIGHT iliFlowLayout .CENTER prilikompozivanja
konstruktora, npr.
this.setLayout (new FlowLayout (FlowLayout .LEFT));
this.setLayout (new FlowLayout (FlowLayout .RIGHT));
this.setLayout (new FlowLayout (FlowLayout .CENTER));

Pogledajmosljedeciprimjeru kojem se 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")) {

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" dobilibismocentriranii


desno pozicioniranirazmjetaj.

Razdvajanje komponenti za
FlowLayout
Vecina LayoutManager a omogucujevamkontrolunad minimalnim
vertikalnimi
horizontalnimprostoromkoji razdvajakomponente. Za FlowLayout zadajeteeljeni
prostor u pikseleima, putemodgovarajucihargumenatau konstruktoru:
public FlowLayout (int alignment , int hspace, int vspace);

Na primjer, da biste napraviliFlowLayout sa deset pikselahorizontalnogi dvadeset


pikselavertikalnograzmaka, sa lijevimporavnanjem, koristilibiste sljedecikonstruktor:
FlowLayout fl =

new FlowLayout (FlowLayout .LEFT, 20, 10);

Pogledajteprimjerappleta koji tako rasporedujebuttonenalikonimaza VCR:


import java.applet.*;
import java.awt.*;
public class SpaceTapeDeck extends Applet {

public void init() {


this.setLayout ( new FlowLayout (FlowLayout .LEFT, 20, 10));
this.add(
this.add(
this.add(
this.add(
this.add(

new
new
new
new
new

Button("Play"));
Button("Rewind"));
Button("Fast Forward "));
Button("Pause"));
Button("Stop"));

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

Razmjetaj tipa BorderLayout


Klasa java.awt.BorderLayout smjetaobjekte na NORTH, SOUTH, EAST, WEST
iliCENTER unutarappleta. Da biste kreiralinoviobjekt tipa BorderLayout , pozovite,
slicnokao i za FlowLayout unutarmetode init() metodu setLayout () ovako:
this.setLayout (new BorderLayout ());

U ovomtipurazmjetajanemacentriranjanilijevogilidesnog poravnavanja, no moete


dodati horizontalnei vertikalnerazmakemedukomponentama. Na primjer, za
horizontalnirazmakod 5 pikselai vertikalniod 10 piksela, stavilibismo:
this.setLayout (new BorderLayout (5, 10));

Kad elitedodati komponentuna odredenustranu, moeteto ucinitina primjerovako:


this.add(new Button("Start"), BorderLayout .SOUTH);

Kao to se izsljedecegprimjeramoevidjeti, sjevernai junasekcijaproteuse preko


appleta s lijevana desno. Istocna i zapadnase proteuod dna sjevernedo vrhajune
sekcije. Ove cetirikomponentebit ce onolikovelikekolikoje potrebno da bi u njihstale
komponentekoje imdodijelite. Ono to ostane, bitice za centralnusekciju. Tocne
velicinesu 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));

this.add(new
this.add(new
this.add(new
this.add(new
this.add(new

Button("North"),
Button("South"),
Button("East"),
Button("West"),
Button("Center"),

BorderLayout .NORTH);
BorderLayout .SOUTH);
BorderLayout .EAST);
BorderLayout .WEST);
BorderLayout .CENTER);

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

Razmjetaj tipa CardLayout


Razmjetajkoji implementiraklasa java.awt.CardLayout je maloneuobicajen. On
pretvaraapplet u snop karata, od kojihsvaka potencijalnoimasvoj vlastiti
LayoutManager . U svakomtrenutkuna ekranuje vidljivasamo jedna karta. Moete
prelazitis jedne karte na drugu, dovodecitako svakiput na ekran drugiskup
komponenti. Postojislicnostsa HyperCardom na Mac-u iliToolbookom na
Windowsima. U Javise takav razmjetajmoekoristitikao nizekrana za unos ako svi
podaci ne stanuna jedan. Ilise, ako treba prikazativiepodataka, moenapravitineto
kao slide show.
Na primjer, pogledajtesljedeciapplet, CardTest , jedan od Sunovihstandardnihdemo
appleta. Ovdje se koristiCardLayout za prebacivanjes jednograzmjetajana drugi, pri
cemuse na razlicitenacinerasporedujuistibuttoni:
<APPLET CODE="CardTest .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes "
ARCHIVE ="CardTest .jar"
WIDTH=400 HEIGHT=200>
</APPLET>

Uporaba CardLayout razmjetaja


Ovaj razmjetajkreiratepomocukonstruktoraCardLayout () ovako:
this.setLayout (new CardLayout ());

Na raspolaganjuvamje jo jedan konstruktorkojimmoeteodreditirazmakmedu


komponentama:
this.setLayout (new CardLayout (3, 4));

U ovomprimjerukomponentece bitirazmaknute3 pixelahorizontalnoi 4 pixela


vertikalno.
Svaka karta imaime. Nova karta se kreira kad dodate komponentukarti koja do tada
nijeuvedena. Komponentedodajete tako da navedeteimekarte i instancukomponenteu
metodi add():
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"));

Internose popis karata i njihovihimenasprema u objekt tipa java.util.Hashtable .


To znacida nemagarantiranogiliugradenogredoslijedakarata. O tome programtrebate
samivoditiracuna.

Promjena karata
U pravilusvakoj karti dodajete panelkoji imavlastitiLayoutManager . Svaka karta
treba bitisnabdjevenanekimuputnicamaza navigacijumedukartama. Sam AWT nema
gotovogtakvogalata. Primijetitetakoder da jednukomponentumoetedodati na vieod
jedne karte. To je korisno, na primjer, za kreiranjeChoice izbornikasa imenimasvih
karata kao navigacijskimpomagalom.
Sljedecihpet metoda klase java.awt.CardLayout omogucujepromjenuaktivnekarte.
U svimslucajevimatreba specificiratikontejnerunutarkojega prelazimos karte na kartu.
To moebitiapplet, prozor ilipanelkoji je uredenu skladus timrazmjetajem.
public
public
public
public
public

void
void
void
void
void

first(Container parent)
next(Container parent)
previous (Container parent)
last(Container parent)
show(Container parent, String name)

Razmjetaj tipa GridLayout


Klasa java.awt.GridLayout specificirabroj redaka i stupaca u koje ce komponente
bitismjetene. Appletse razbijana matricujednako velikihcelija.
je koristankad eliterazmjestitivieobjekata slicnevelicine. Jako je dobar
za sastavljanjelistecheckboxovailiradio buttonakao u appletu Ingredients izestog
predavanja. U sljedecemprimjerudonosimomaloizmijenjenuverzijutog appleta pa
cemo checkboxoverasporeditiunutarest redaka i jedne kolone, to ce appletudati
mnogoboljii urednijiizgled. Uklonjenje kod za obradu dogadaja jer nijebitanza ovaj
primjer.
GridLayout

import java.applet.*;
import java.awt.*;
public class Ingredients 2 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 "));

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="Ingredients 2.class"
CODEBASE ="http://student .math.hr/~vedris/java/classes "
WIDTH=200 HEIGHT=250>
</APPLET>

Razmjetaj tipa GridBagLayout


Klasa java.awt.GridBagLayout daje mreuza rasporedivanjekomponenti, slicno
kao GridLayout , alidoputa da pojedinakomponentazauzmevieod jedne celije.
Takoder, ovdje se velicinacelijeprilagodavavelicinikomponente, a ne obrnuto, kao to
smo do sada navikli.
Konstruktorza GridBagLayout je trivijalan,GridBagLayout () bez argumenata.
Koristitega ovako:

GridBagLayout gbl = new GridBagLayout ();


setLayout (gbl);

Za razlikuod konstruktoraza GridLayout () ovaj ne kae kolikoredaka ilistupaca


treba napraviti. To se odreduje prema celijamakoje va programreferencira. Ako stavite
komponentuu osmiredak i drugistupac, Java ce osiguratida bude bardevet redaka i tri
stupca (retcii stupcizapocinjuod nultog). Ako kasnijestavitekomponentuu deseti redak
i cetvrtistupac, Java ce dodati odgovarajucibroj celija. Moete zamiljatikonacnu
mreu, aliJava to ne mora znatikad kreirate GridBagLayout .
Za razlikuod vecineostalihrazmjetaja, referencana objekt tipa GridBagLayout trebat
ce vamkasnijeu programupa ga, dakle necete kreiratianonimno, unutarpozivametode
setLayout () .

Specifikacije GridBagConstraints
Svakoj komponentikoju kontroliraGridBagLayout pridruenje po jedan objekt iz
klase java.awt.GridBagConstraints koji specificirapoloajunutarpovrineza
prikaz. Takav objekt zajednosa minimalnomipreferiranomvelicinomkomponente
odreduje gdje se i kako povrinaza prikazsmjetaunutarappleta.
Konstruktorza GridBagConstraints () je trivijalan:
GridBagConstraints gbc = new GridBagConstraints ();

Interakcijas objektomtipa GridBagConstraints 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 primjeruappleta GridBagCalculatorApplet koji
predstavljamaskuza kalkulator.
<APPLET CODE="GridBagCalculatorApplet .class"
CODEBASE ="http://student .math.hr/~vedris/java/classes "
ARCHIVE ="GridBagCalculator .jar"
WIDTH=1 HEIGHT=1>
</APPLET>

Mrea (grid) za applet Calculator


Evo sada mreekoju koristimoza razmjetajkalkulatorovihkomponenti. Primijetiteda u
mreiimaviecelijanego komponentikalkulatora. Kalkulatorimajedan TextField i 18
buttonarazlicitihvelicina. Neke komponentezauzetce vieod jedne celijemree. Na
primjer, TextField koji predstavljakalkulatorovdisplay zauzetce cetiricelije, (0, 0),
(1, 0), (2, 0), and (3, 0).

(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 svaku komponentukreiratcemo po jedan objekt tipa GridBagConstraints


. Na primjer
za 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 pridruiti


komponentipomocumetode setConstraints () 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 ce
doci lijevigornjiugao komponente. Gornjalijevacelijau naemprimjeruje celija(0, 0).
Umjestoapsolutnihvrijednostimoemostavitii mnemonickukonstantu
GridBagConstraints .RELATIVE koja kae da ce komponentabitismjetena
neposrednodesno (gridx ) ilineposrednoispod (gridy ) u odnosu na komponentukoja
je prije toga posljednjabiladodana kontejneru.
Na kalkulatorimadisplay u lijevomgornjemugluappleta. Prema tome, gridx i gridy
prve komponente(to je TextField ) izgledatce ovako:
GBC_display .gridx = 0;
GBC_display .gridy = 0;

Isto tako, na primjer, tipka za znak jednakosti(equals key) imatce


GBC_bigequals .gridx = 3;
GBC_bigequals .gridy = 4;

Tipka za znamenku0 (zero key) imatce


GBC_0.gridx = 0;
GBC_0.gridy = 5;

Atributi gridwidth i gridheight


Atributigridwidth i gridheight specificirajubroj celijau retku (gridwidth ) ili
stupcu(gridheight ) koje ce komponentazauzeti. Ako ovdje upiemomnemonicku
konstantuGridBagConstraints .REMAINDER , onda ce komponentazauzetisve
preostalecelijeu retku (za gridwidth ) ilistupcu(za gridheight ).
Kalkulatorovdisplay ce zauzeticetiricelijepo irinii jednupo visini, dakle imatcemo
GBC_display .gridwidth = 4;
GBC_display .gridheight = 1;

Tipka za znak jednakosti(equals key) je dvijecelijevisoki jednucelijuirok, dakle


GBC_bigequals .gridwidth = 1;
GBC_bigequals .gridheight = 2;

Tipka za 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 koristite
za postavljanjeove varijablesu:
GridBagConstraints .NONE : komponentane mijenjavelicinu
GridBagConstraints .HORIZONTAL : Komponentace se protezatipreko cijele

irineprostora koji joj je dodijeljen, alinece promijenitisvojuvisinu


GridBagConstraints .VERTICAL : Komponentace se protezatipreko cijele
visineprostora koji joj je dodijeljen, alinece promjijenitisvojuirinu
GridBagConstraints .BOTH : irinai visinakomponentebit ce prilagodenetako
da komponentazauzmecijeliprostor koji joj je dodijeljen
U naemprimjeruodredilismo da se displayirihorizontalno,a tipke (pogledajmona
primjerzero key) u svimsmjerovima, dakle
GBC_display .fill = GridBagConstraints .HORIZONTAL ;
GBC_0.fill = GridBagConstraints .BOTH;

Atributi ipadx i ipady


Svaka komponentaimaodredenuminimalnuirinui visinui ne moese smanjivatiispod
tihvrijednosti. Ako su minimalnedimenzijekomponentevece od dimenzijapovrinekoje
joj stoje na raspolaganju, bit ce prikazansamo dio komponente.

Atributiipadx i ipady dozvoljavajuvamda povecate te minimalnedimenzijetako da se


rubovimakomponentedoda neto prostora . Na primjer, ako staviteipadx =2, to ce
garantiratida je komponentanajmanje4 pikselaira od svog normalnogminimuma
.U
naemprimjeruto nijepotrebno.

Atribut Insets
Atributinsets je instancaklase java.awt.Insets . On specificirarazmakizmedu
komponentei rubovapovrinena kojoj je smjetena. Za sve tipke u naemkalkulatoru
odredilismo da to bude 3 pikselasa svake strane (to osiguravada susjednetipke budu
razmaknuteza 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 komponentamanjenego raspoloivapovrina, atributanchor specificirapoloaj
unutarcelijekamo komponentutreba staviti. Mnemonickekonstantekoje za to koristite
slicnesu 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 naemprimjeruto nije
eksplicitnonavedenojer su komponentedovoljnovelikeu odnosu na raspoloive
povrine, tako da je centriranapozicijazadovoljavajuca.

Atributi weightx i weighty


Atributiweightx i weighty odredujukako su celijedistribuiraneunutarkontejneraako
njihovaukupnavelicinabude manjaod velicinekontejnera. Sa teinama0 (default) sve
celijezauzimajunajmanjeto mogui sve se sabije prema centru. Sav dodatniprostor je
izguranprema rubovimakontejnera.

Primjer za GridBagLayout

Pogledajmosada kompletnuinit() metoda sa razmjetajemkalkulatorovihtipaka.


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);

// 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);

// 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);

// 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);

// 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

Komponenteje mogucepostavitina tocno odredenupozicijuna ekranu, koristeci


koordinateu pikselima, u odnosu na appletovpanel. To, medutim, imavienedostataka.
Sve instancevaegappleta nece imatipaneljednake velicine. Velicinumoete
kontroliratisamo ako ce se applet pojavljivatijedinona vaimweb stranicama.
Slobodnimprozorimakorisnicimogumijenjativelicinuu hodu. Ako koristitelayout
manager, sve ce komponentebitiautomatskiprilagodenenovojveliciniprozora.
Bez toga vrloje teko posticitakvo ponaanje.
Komponentece na razlicitimplatformamazauzimatirazlicitekolicineprostora.
Rucnopozicioniranjece imatismislau aplikacijamakoje su namijenjene
izvravanjuna jednoj odredenoj platformi. Appletinisupogodniza to.
Rucnopozicioniranjekomponentitraimnogoposla, pogotovoako nematena
raspolaganjunekialat koji ce automatiziratitaj proces.
RazmjetajGridBagLayout u kombinacijisa ugnijedenimpanelimadovoljanje
za sve efekte koje biste inacemogliposticirucnimpozicioniranjem
.
Ako ipak eliterucnopozicioniratikomponente, onda prvo opozovitelayout manager
naredbom:
setLayout (null);

Nakon toga zadajte pozicijui velicinuza svaku komponentuunutarpaint() metode


(reklismo da se to inacene radi!), tako da pozovetemetode setLocation () and
setSize () :
public void setLocation (int x, int y)
public void setSize (int width, int height)

Ovdje su x i y koordinatelijevoggornjeguglakutijekoja omedujevau komponentu, a


width i height su njenairinai visinau pikselima.
Sljedeciapplet stavitce buttonvelicine30 x 40 piksela(tj. njegovlijevigornjiugao) u
tocku (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;

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

to je Container?
Kontejnerje komponentakoja moesadratidrugekomponente. On je uvijekinstanca
klase java.awt.Container koja je podklasa od java.awt.Component pa su dakle
kontejnerii samitakoder komponente.
Opcenito, komponentese nalazeu nekomkontejneru. Appletje primjerkontejnera, no
to mogubitii prozori(windows), okviri(frames), dijalozi(dialogs) i paneli(panels).
Kontejnerimogusadravatidrugekontejnere.
Svakikontejnerimasvoj Layout manager koji odreduje nacinpozicioniranja
komponenataunutarkontejnera.
Ukratko, kontejnerisadre komponente. Komponentesu pozicioniraneunutarkontejnera
u skladusa pridruenimLayout managerom. Buducida su kontejneritakoder
komponente, onise mogunaciunutardrugihkontejnera. Primijetimoda appleti
osiguravajuvec gotovkontejneri pretpostavljeniLayout manager. To je FlowLayout .

Dvije vrste Containera


Paket AWT definiravievrsta kontejneramedukojimecemo promotritipanelei prozore.
Paneli su podklase od java.awt.Panel . Panelse nalaziunutardrugogkontejneraili
modaunutarbrowserovogprozora. Panelinisusamostalni. Appletisu primjerpanela.
Prozorisu podklase od java.awt.Window . Prozor je samostalan. Ima ihvievrsta,
medunjimapromatratcemo okvire(frames) i dijaloge(dialogs). Okvirisu podklase od
java.awt.Frame . Predstavljajuobicne, prirodneprozore. Dialozisu podklase od
java.awt.Dialog . Dialogje privremeni
, nestalniprozor koji postojisamo da prenese
neke informacijeilipriminekiinputod korisnika.

Paneli
Svaki Panel je zapravogenerickiContainer cija je glavnaulogapodijelitiprikaznu
povrinuu odvojenepravokutnedijelove. Buducida svaki Panel moeimatisvoj vlastiti

LayoutManager ,

s panelimamoeteucinitimnogotoga to inacene biste moglisa samo


jednimLayout managerom.
Na primjer, pretpostavimoda eliteda se TextArea nalaziu centruappleta, a button
ispod nje, na "jugu":
To ne moeteposticis jednimjedinimLayout managerom. Na primjer, BorderLayout
bi proirioButton preko cijeleirinaappleta. S drugestrane FlowLayout ne bi ucinio
da TextArea bude dovoljnovelika.
Umjestotoga, moetekreiratiapplet koji ima BorderLayout , a TextArea muse nalazi
u centru. Zatimkreirate Panel , postavitenjegovLayoutManager na FlowLayout ,
dodate buttontom panelui onda dodate paneljunomdijeluappleta. 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 primjeruvanorazlikovatidodavanjekomponenteappletu(add(...) ili


this.add(...)) od dodavanjakomponentepanelu(p.add(...)).
S drugestrane, nijevanojeste liprvo dodalipanelappletupa onda buttonpaneluili
obrnuto.
Drugacesta uporaba panelaje za postavljanjenizacheckboxovakoji imajuGridLayout
s jednimstupcem.

Ugnijedeni paneli

Ponekad je potrebno nekolikoinstanciistog LayoutManager a. Pogledajmoopet primjer


kalkulatora.
S jedne strane izgledakao da ga je jednostavnoimplementirati
. Tu su naprosto 18
buttonai TextField . S drugestrane, gotovosve tipke su jednake velicine, samo su dvije
tipke i display neto veci. Gotovo bi se mogaokoristitiGridLayout , aliipak ne sasvim.
Panelisu jedan od nacinarjeavanjaovog problema.
Evo sada ponovnokalkulatora, aliovog puta smo koristilisamo GridLayout i
ugnijedenepanele. Da lije to jednostavnijenego GridBagLayout 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,
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,
// 1, 2 and 0
Panel B2 = new Panel();
B2.setLayout (new GridLayout (2,
// 1 and 2
Panel C1 = new Panel();
C1.setLayout (new GridLayout (1,

4, 3, 3));

2, 3, 3));

1, 3, 3));

2, 3, 3));

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 omogucujuvamkreiranjesamostalnih
prozora. Samostalniprozorisu cesti u aplikacijamakoje koje za komunikacijus
korisnikomkoristeAWT umjestokomandnelinije. Takoder osiguravajudodatniprostor
za applete.
Klasa java.awt.Window je podklasa od java.awt.Container , alije nezavisnaod
ostalihkontejnera, tj. sam nijesadranu drugimkontejnerima. Moete mudodavati
komponentekao to je Button iliTextField . Moe imatisvoj vlastitiLayoutManager .

Moete crtatidirektnopomocunjegovepaint() metode. Sve to moeteraditiu


appletovompanelu, moeteraditii u prozoru.
Uobicajenoje da se klasa java.awt.Window ne koristidirektno. Umjestotoga radites
njenimpodklasama, npr. java.awt.Frame ilijava.awt.Dialog , ovisnoo tome to
trebate. Frame je okvirkoji moeimatisvoj scrollbar, korisnikmumoemijenjativelicinu
ilipoloaji bit ce na ekranudok god korisnikazanimanjegovsadraj.
Nasuprot tome, dijalognece imatiizbornike, obicnomuse ne moemijenjativelicinaiako
se moepomicati. Njegova je ulogaprenoenjeodredene informacije(unosa) od
korisnikailipak upozoravanjena neto. Vidljivje samo dok ne dobije odgovarajuciinput
ilidok korisnikne potvrdida je procitaoinformacijus njega.

Okviri (frames)
Okvirisu korisniza kompleksnijeaplikacije. Omogucujuvamodvajanjerazlicitihfunkcija
ilipodataka u razliciteprozore. Na primjer, aplikacijaza crtanjemoeimatinekoliko
razlicitihslikas raznimstatusimazavrenostiu razlicitimprozorima. Ilimodamoeimati
jednusliku, aliu drugomprozorupaletus raznimcetkama i bojama. Svakiod tihprozora
bio bi Frame .
Sve to vamtreba za kreiranjeokvirai rad s njimanalazise u klasi java.awt.Frame . Za
kreiranjenovogokvirabez naslovneletvicekoristitcete konstruktorFrame() bez
argumenata.
Frame f = new Frame();

Cece ce ipak bitipotrebno dati okvirunaslov:


Frame f = new Frame("My Window");

Okvirinasljedujuklasu java.awt.Container pa imdakle moetedodavati


komponente. Za razlikuod panelai appleta, pretpostavljeniLayoutManager za okvireje
BorderLayout , a ne FlowLayout . To, naravno, moetepromijenitipomocumetode
setLayout () na primjerovako:
f.setLayout (new FlowLayout ());

Okvirinasljedujui klasu java.awt.Component pa dakle imajumetode paint() i


update() . Ako elitecrtatiunutarokvirai procesiratidogadaje rucnokao u appletima,
jednostavnokreirajtepodklasuod Frame i dodajte joj odgovarajucilistener. Gotovo sve
to ste radilisa vlastitimpodklasamaod java.awt.Applet moetetakoder raditii sa
svojimpodklasamaod java.awt.Frame .
Ipak, najcece cete htjetikoristitikomponente. Da bist komponentudodaliokviru, pozvat
cete njegovumetodu add() isto kao to st pozivaliappletovumetodu add(). Jedina
razlikaje to cete cesto trebatipozivatitu metoduizvanklase Frame , tako da ce biti

potrebno dodati odgovarajuciprefikskoji pokazujena okvir. Drugimrijecima, ako imate


okvir Frame 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 od


podklasa klase Frame , onda to nece bitipotrebno.
Kako je pretpostavljenilayoutza frame BorderLayout , trebat ce specificiratida li
komponentudodajete na North, South, East, West iliCenter. Evo primjerakoji pokazuje
kako se dodaje centriranalabelau centar okvira Frame f:
f.add("Center", new Label("This is a frame", Label.CENTER));

Ili
f.add(new Label("This is a frame", Label.CENTER),
BorderLayout .CENTER);

Velicinai pozicijabilokojeg danog okviraje nepredvidljivaako je ne specificirate.


Velicinase zadaje pomocumetode setSize () ovako:
f.setSize (150,150);

Ta velicinane ukljucujenaslovnuletvicu, pa to treba zasebnouzetiu obzir. Da biste


doznalivisinunaslovneletviceza okvir, pozvatcete njegovumetodu insets() i
pogledatiatributtop rezultirajucegobjekta iz java.awt.Insets . To ce bitivisina
naslovneletvice. Imat cemo, dakle
int TitleBarHeight = f.insets().top;

Postavljanjeokvirana eljenupozicijuna ekranuobavljase pomocumetode


setLocation (int x, int y). Ovdje se x i y racunajuprema ekranu, ne prema
appletu.
Kad se prozor kreira, on je u pocetku nevidljiv.Dodavanjekomponentidobro je obaviti
dok je prozor jo nevidljiv,inacece korisnikmoratigledatiskakanje komponentii
nepredvidljivopomicanjeprozora dok se slikane ustabili. Kad ste zavrilis dodavanjem
komponenti, uciniteokvirvidljivimtako da pozovetenjegovumetodu show():
f.show();

Dogadaji vezani uz prozore

Buducida je java.awt.Window podklasa od java.awt.Component , znacida objekti


tipa Window mogulansiratidogadaje. Ti dogadajisu objektitipa
java.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 biste mogliodgovaratina te dogadaje, morateuz objekt tipa java.awt.Window


registriratiodgovarajucilistener, dakle objekt neke klase koja implementirasucelje
java.awt.event.WindowListener . Ovo suceljepropisujesljedecemetode:
public
public
public
public
public
public
public

abstract
abstract
abstract
abstract
abstract
abstract
abstract

void
void
void
void
void
void
void

windowOpened (WindowEvent e)
windowClosing (WindowEvent e)
windowClosed (WindowEvent e)
windowIconified (WindowEvent e)
windowDeiconified (WindowEvent e)
windowActivated (WindowEvent e)
windowDeactivated (WindowEvent e)

Moete, naravno, koristitii odgovarajucijava.awt.event.WindowAdapter .

Primjer dogadaja na prozorima


Na primjer, prozorise ne zatvarajusamiod sebe nego ihmorateeksplicitnozatvoriti.
Sljedeca podklasa od Frame koja odgovarana pokuaj zatvaranjatako da pozove
metode setVisible (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) {}

public
public
public
public
public

void
void
void
void
void

windowClosed (WindowEvent e) {}
windowIconified (WindowEvent e) {}
windowDeiconified (WindowEvent e) {}
windowActivated (WindowEvent e) {}
windowDeactivated (WindowEvent e) {}

Moete 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 izvravao. U praviluweb browser osiguravatakav
okvir. No moetekreiratiinstancesvog appleta unutarnekog okviravae vlastite
aplikacije. Na taj nacinmoetepisatikod koji je istovremenoi applet i aplikacija.
Da bi applet pretvoriliu aplikaciju, dodajte musljedecu main() metodu(ovdje je
myApplet imevaegappleta):
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();

Redak 1 je deklaracijastandardne main() metoda koju koristiteza aplikacijes


komandnelinije. Ako se applet izvravaunutarweb browsera iliapplet viewera, ta ce
metoda bitiignorirana. Izvritce se samo ako applet pokrenete kao samostalniprogram.
Redak 3 kreira instancuvaegappleta. Tu trebate umjestomyApplet upisatipravo ime
svog appleta.
Nakon toga, retci4 i 5 pozivajuappletovuinit() i start() metodu. To inaceradi
web browser za vas, aliako se programizvravasamostalno, morateto samiuciniti.
Nakon to ste kreiraliaplet, treba vam Frame u koji cete ga smjestiti. Redak 7 to cini
pomocuuobicajenogkonstruktoraFrame(). Ovdje moetepromijenitinaslovokvirada
odgovaravaoj aplikaciji.
Redak 8 dodaje applet u taj Frame . Buducida je LayoutManager za Frame po
pretpostavciBorderLayout , applet ce bitidodan u centar. Sjetitese da je
java.applet.Applet podklasa od java.awt.Component pa je u redu dodati ga na
neki Frame .
Redak 9 zadaje velicinuza Frame . Ovdje smo stavili150 x 150 pixela. Ako se program
izvravakao applet, moetedobitite vrijednostiizparametarawidthi height, aliako se
izvravasamostalno, morateizmislitineke velicine. Moete iheventualnoucitatikao
argumentes komandnelinije.
Redak 10 postavljaFrame na poziciju(100, 100). Ako pozicijusamine zadate, ona ce
bitinepredvidljiva
,
Redak 11 ciniva Frame vidljivimi applet je sad spremanza izvravanje, unutar
browsera iliizvannjega.
Napomena: Cak i ako imajuFrame , appletiipak nisuisto to i aplikacije. Kad
konvertirateapplet u aplikacijuna opisaninacin, morateosiguratida se programne
oslanjana metode koje imajusmislajedinou appletima. Na primjer, metoda
getParameter () nemasmislaizvanappleta. Isto tako, argumentes komandnelinije
moeteucitavatisamo u aplikacijama. Nadalje, aplikacijeimajumanjesigurnosnih
restrikcijanego appletipa programkoji dobro radi kao aplikacijamoeproizvesti
mnotvosigurnosnihiznimaka(java.lang.SecurityException ).
Pogledajtekako to funkcionirana primjeruappleta Dots izsedmogpredavanjakoji smo
za ovu svrhumodificiraliu applet/aplikacijuDotsTest .

Dijalozi
Okvirisu korisnikao prozorikoji ce se neko vrijemezadratina ekranu, na primjeru
svrhueditiranjanekog teksta i slicno. Za razlikuod njih, dijalozikoje implementiraklasa

java.awt.Dialog ,

po prirodisu kratkotrajnii sluesamo kao sredstvo za kratki input


iliupozorenjekorisniku.
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, mnogo
toga to znateo okvirimaprimjenjujese i na dijaloge. Moete ihpomicati, mijenjatiim
velicinui dodavatiimkomponenteskoro isto kao i u slucajuokvira. Postoje, medutim,
dvijebitnerazlike:
1. Okvir (frame) moeimatiletvicuizbornika(menu bar) dok dijalogto ne moe
2. Dijalogmoebitimodalan, dok okvirne moe
O izbornicimacete naucitiu sljedecempredavanju. Za sada se zadrimona razliciizmedu
modalnihi ne-modalnihdijaloga. Modalnidijalogblokirakomunikacijusa svimdrugim
aplikacijamasve dok ne dobije odgovarajuciinputod korisnika. Ne moese pomicatii
ne dozvoljavakorisnikuprijelazu drugiprozor istogprograma. Na nekimplatformamane
dozvoljavacak i odlazaku prozore drugihprograma.
Sedamdesetihgodinaproiriose viruskoji bi periodickiprekidao korisnikovrad
podizanjemprozorcicana kojem je pisalo"I WANT A COOKIE." Rad se mogao
nastavititek kad bi korisnikupisaorijec"COOKIE" na to bi programrekao neto kao
"MMM, MMM, THATWAS GOOD." i tek tada vratiokontrolukorisniku.
Modalnidijalozise ponaajuprilicnoslicnotom virusu. Oni trae inputod korisnikai ne
dozvoljavajuda se ita dogodidok ga ne dobiju. Ne-modalnidijalozise podiu, aline
sprecavajukorisnikada radi drugestvaridok su onividljivi
. Buducida modalnidijalozi
djelujuponeto iritirajuce, treba ihu praviluizbjegavati.

Metode za dijaloge
Buducida su dijalozikomponente, onimogu, kao i okviri, koristitimetode kao to su
setLocation () ilisetSize () . Za dijalogeimamokonstruktorekoji imdaju iline daju
naslov, pa moemo, na primjer, staviti:
Dialog d = new Dialog(new Frame(), false);

Prviargumentje parent frame za taj dijalog, dok je drugi tipa boolean i odreduje hoce
lidijalogbitimodalan(true ) iline (false ). Modalnidijalozisu modalniu odnosu na svoj
parent frame, dakle privremenosprecavajuunos u taj okvir, aline i u drugeokvire.
Ako za prviargumentstavitenull dijalogce izbacitiiznimku,
java.lang.IllegalArgumentException .
Ako kreirateparent framedirektnounutarpozivakonstruktorakao u prethodnom
primjeru, dijalogne moebitiuistinumodalan.
Ima jo i nekihmanjihrazlikaizmeduokvirai dijaloga, npr.:

1. Korisnikmoemijenjatipoloaji velicinuveciniokvira, dok dijalozimau pravilune


moe.
2. Okviriobicnoimajunaslovneletvice, dok okvirinemaju.
Dijalogumoeteomogucitipromjenjivostvelicinepomocumetode setResizable ():
d.setResizable (true);

Moete mudati naslovnuletvicutako da ga kreiratepomocusljedecegkonstruktora::


Dialog d = new Dialog(new Frame(), "My Dialog Window", false);

Sve ostale metode i postupciza dijalogeiste su kao i za okvire.

Primjeri dijaloga
Sljedeciprogramprikazujejednostavnine-modalnidijalogsa OK buttonomi bez
naslovneletvice.
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 od
java.awt.Dialog i i instanciratiihizglavnogprograma. Na primjer, jedan od
jednostavnijihuobicajenihdijalogaje ispisporuke koju korisniktreba procitatii potvrditi
to pritiskomna OK button. Evo primjera:
import java.awt.*;
import java.awt.event.*;

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>

Deveto predavanje
slike i zvukovi

izbornici,

to je izbornik ? klase izbornika kreiranje izbornika primjer izbornika


dogadaji vezani uz izbornike izbornicke kratice padajuci izbornici (popup
menus) slike kamo staviti slike ? ucitavnje slika crtanje slika uporaba
povratne vrijednosti metoda drawImage () primjer crtanja slika promjena velicine
slike ustanovljavanje velicine slike paket java .awt.image Sucelja
ImageProducer , ImageObserver , ImageConsumer sucelje ImageConsumer
cekanje na ucitavanje slike prekrivanje metode imageUpdate () to je zapravo
slika ? operator << - kreiranje slika primjer kreiranja slika metoda getRGB()
pretapanje boja filtriranje slika klasa RGBImageFilter primjer plavog filtra
primjer filtra sivih tonova filtri koji ovise o poloaju filtri koji ovise o
adjungiranim pixelima audio kontinuirana izvedba

to je izbornik?
Java omogucujepostavljanjeizbornikana frameove(dijalozimase izbornicine mogu
dodavati). Za applete to i nijetako bitno, aliu aplikacijamaje najcece nuno.
Izbornicisu sastavljeniod tri hijerarhijskaelementaPrvielementje izbornickaletvica
(menu bar) i sastojise od razlicitihizbornika. Nalazise na gornjemrubu ekrana kod
Macintoshailina gornjemrubu prozora kod WindowsailiMotifa.

Svaka izbornickaletvicasadribar jedan izbornik(menu). Izbornicisu organiziranipoi


temama. Cesto susrecemoFile, Edit i tako dalje.
Svakiizborniksadribar jednuopciju(menu item). Opcije su obicnopojedinacneakcije
kao Open, Print, Cut iliCopy. Opcije nisuprikazanedok izborniknijeaktivan. Dva ili
vieizbornikane mogubitiistodobnoaktivni.

Na primjerovaj Edit izbornikimaonemogucenuUndo opcijunakon koje dolazi


separator, a iznjegaomoguceneopcije Cut, Copy, paste i Clear, zatimjo jedan
separator pa omogucenaopcija Select All.

Klase izbornika
Paket AWT sadrinekolikoglavnihklasa za upravljanjeizbornicima
:
java.awt.Menu
java.awt.MenuBar
java.awt.MenuItem
java.awt.PopupMenu

Da biste izbornikekoristiliu svojimaplikacijama, bit ce vampotreban bar jedan


primjerakizklase MenuBar sa jednimilivieprimjerakaklase Menu , a za svakog
nekolikoprimjerakaMenuItem . Izborniciizklase PopupMenu se pojavljujukao
samostalnielement.
Klasa java.awt.MenuComponent je zadnjanadklasasvihovihklasa, a ona je opet
podklasa od java.lang.Object . Prema tome, izbornickeletvice, izbornicii opcije nisu
komponentei 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 podklasa


od MenuItem (ovo zvucimaloneobicno, aliizbornikeje zaistaopcija, samo se dodaje
izbornickojletvici). Nadalje, MenuBar implementirasucelje
java.awt.MenuContainer .

Kreiranje izbornika
Izbornikeje poeljnopotpunoizgraditiprije nego ihprikaete. Tipicniredosljedje
ovakav:
1.
2.
3.
4.

kreirajtenoviobjekt tipa MenuBar .


kreirajtenoviobjekt tipa Menu .
dodajte opcije objektu tipa Menu .
ako je potrebno, ponovitekorake 2 i 3.

5. dodajte objekt tipa MenuBar objektu tipa Frame .


Konstruktorikoji su vampotrebnisu jednostavni. Novi objekt tipa MenuBar kreiratcete
ovako:
MenuBar myMenubar = new MenuBar ();

Za kreiranjenovogobjekta tipa Menu koristitekonstruktorMenu(String title).


Dodajte munaslovkoji elitedati izborniku. Na primjer, za kreiranjeizbornikaFile i
Edit, napravite:
Menu fileMenu = new Menu("File");
Menu editMenu = new Menu("Edit");

Opcije, MenuItem are kreirajuse slicno, pomocukonstruktoraMenuItem (String


menutext ). Dajte mupotreban naslov, na primjer:
MenuItem Cut = new MenuItem ("Cut");

Objekte tipa MenuItem kreirateunutarodgovarajucihobjekata tipa Menu kojima


pripadaju, isto kao to ste komponentekreiraliunutarodgovarajucihrazmjetaja.
Izborniciimajuadd() metode koje kao argumentuzimajuobjekte tipa MenuItem . Evo
kako biste napraviliEdit izborniki dodalimuoipcijeUndo, Cut, Copy, Paste, Clear i
Select All:
Menu editMenu = new Menu("Edit");
editMenu .add(new MenuItem ("Undo"));
editMenu .addSeparator ();
editMenu .add(new
editMenu .add(new
editMenu .add(new
editMenu .add(new

MenuItem ("Cut"));
MenuItem ("Copy"));
MenuItem ("Paste"));
MenuItem ("Clear"));

editMenu .addSeparator ();


editMenu .add(new MenuItem ("Select All"));

Metoda addSeparator () dodaje horizontalnucrtu preko izbornika. Koristise za


logickorazdvajanjefunkcijana izborniku.
Kad kreirateizbornike, dakle objekte tipa Menu , dodat cete ihletvici, objektu tipa
MenuBar koristeciMenuBar ovu metodu add(Menu m) ovako:
myMenubar .add(fileMenu );
myMenubar .add(editMenu );

Konacno, kad je MenuBar gotov, dodat cete ga okviru, dakle objektu tipa Frame
koristecise frameovommetodom setMenuBar (MenuBar mb). Ako imateFrame f
onda bi to izgledaloovako:
f.setMenuBar (myMenuBar );

Primjer izbornika
Aplikacijamoeimatimnogoopcija, cak i po viestotina. Sve njihstavitiu init()
metodubilobi neprakticno. Uobicajenoje kreiratiodvojenemetode koje grade svaki
pojediniizborniki dodaju ihizbornickojletvici. Sljedeciprogramkreira dva standardna
izbornika, 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");

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 tipa
java.awt.event.ActionEvent . Njega moepokupitibilokoji actionListener, dakle
objekt izklase koja implementirasucelje java.awt.event.ActionListener koji smo
registriraliuz opciju, dakle objekt tipa MenuItem . Actionkomandakoju moemo
procitatimetodom getActionCommand () sadrat ce tekst opcije.
Na primjer, sljedeciapplet stavljatekst odabrane opcije u tekstualnopolje theChoice .
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);

}
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>

Izbornicke kratice
Izbornickekratice, poznatei pod nazivomakceleratoriilitipovniekvivalentinaredbe,
obicnone ubrzavajunita, alibuducida ihkorisnicivole, komercijalneaplikacijeih
trebajusadravati.
Klasa java.awt.MenuShortcut predstavljatakve kraticeu Javi. Ima sljedece
konstruktore:
public MenuShortcut (int key)
public MenuShortcut (int key, boolean useShiftModifier )

U oba slucajaargumentkey je zapravokeycode tipke koja ce aktiviratitu opciju.


Ako je useShiftModifier postavljenna true , onda tipka shiftmora bitipritisnutada
bi kraticaaktiviralaopciju. Po pretpostavci, useShiftModifier je false .
Da biste opcijiizbornikapridruilikraticu, pozovitemetodu setShortcut () izklase
java.awt.MenuItem . Na primjer,
MenuShortcut pShortcut = new MenuShortcut (KeyEvent .VK_P);
MenuItem mi = new MenuItem ("Print...");
mi.setShortcut (pShortcut );

Kraticumoetedefiniratii pomocuodgovarajucegkonstruktoraMenuItem ()ovako:


MenuShortcut pShortcut = new MenuShortcut (KeyEvent .VK_P);
MenuItem mi = new MenuItem ("Print...", pShortcut );

Kraticumoeteuklonitipomocumetode deleteShortcut () izklase


java.awt.MenuItem , na primjer:
mi.deleteShortcut ();

Padajuci izbornici (Popup Menus)


Vec smo se susrelis klaslomalreadyencounteredthe java.awt.Choice cijise objekti
ponaajukao padajuciizbornici, no imajufiksnulokaciju.
Klasa java.awt.PopupMenu class, on the other hand, is activatedwhenthe user holds
the rightmousebuttonor otherwiseindicatesthat theywant to pop up a menu. Typically
thisis used for contextsensitivemenus.
Klasa java.awt.PopupMenu je podklasa od java.awt.Menu . Uglavnomje koristite
kao i obicneizbornike. Stavke se dodaju metodom add(), a na korisnikoveizbore
odgovarase pomocu ActionListener a instaliranogna MenuItem . Na primjer, da biste
napravilipadajuciizborniksa raznimURL-ovima, moetepostupitiovako:

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 pripadajunekomodredenom MenuBar u. Umjestotoga,


onise dodaju komponenti. Na primjer, za daniokvir, Frame f, instaliralibiste
PopupMenu pm u taj okvirtako da ga proslijeditemetodi add() izklase
java.awt.Component , ovako:
f.add(pm);

Primijetiteda to nijeona ista add() metoda koju koristiteza dodavanjekomponente


okviru.
Tocan nacinpokretanjapadajucihizbornikaovisio platformi. Na primjer, na
Windowsimase PopupMenu pokrece podizanjemdesne tipke mia. Na Motifuse
pokrece pritiskanjemdesne tipke mia. Neovisnoo egzaktnojsekvencidogadaja koja
pokrece padajuciizbornik, kad korisnikodabere neku opciju, odnosno kad odabere neki
MenuItem , lansirase ActionEvent kojeg treba uhvatitiodgovarajucilistenerregistriran
uz tu stavku.
Objekt tipa PopupMenu se moeuklonitiizkomponentetako da ga se proslijedi
komponentinojmetodi remove(), na primjerovako:
f.remove(pm);

Uz jednukomponentumoebitiinstalirannajviejedan padajuciizbornik. Ako je


instaliranuz kontejner, onda ce trigeriizkomponenatakoje se nalazeu tom kontejneru
takoder pokretatipadajuce izbornikepod uvjetomda kontejnernemasvoj vlastiti
padajuciizbornik.

Slike
Slikeu Javisu bitmapiraneGIF iliJPEG datoteke koje mogusadravatiproizvoljnusliku.
Moete ihkreiratibilokojimprogramomkoji je u stanjunapravitiGIF iliJPEG format.

Jednomkad su ucitaneu Javu, slikepostaju instanceapstraktneklase java.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 u


java.awt.Graphics , java.awt.Component , i java.awt.Toolkit . Metodamaiztih
klasa prosljedujeteobjekt tipa Image da biste ucitalii prikazalisliku.

Kamo staviti slike?


Skuje koje prikazujuJava appletiucitavajuse s weba preko URL-a koji pokazujena
datoteku sa slikom. Appletkoji prikazujeslikumora poznavatitaj URL. Slikemogubiti
spremljenena web posluitelju
, lokalnomdiskuilibilogdje kamo applet moestici
pomocuURL-a. Paziteda slikestavljatetamo gdje ihapplet moedohvatiti. URL koji
pokazujena va lokalnidisk moebitiod koristidok razvijateapplet, aline moeposluiti
nekometko dolazipreko weba.
Tipicno, slikese stavljajuu istidirektoriju kojem se nalaziapplet iliu onaj u kojem se
nalaziHTML document. Iako to nijeobavezno, stavljanjeslikana neku od tihlokacijaje
obicnoprakticno. Staviteslikuzajednosa appletovomclass datotekomako ce se ona
koristitisa sviminstancamaappleta. Ilije staviteu HTML direktorijako ce razneinstance
appleta koristitirazneslike. Treca alternativaje stavitisve slikena zajednickulokacijui
koristitioznaku <PARAM> za dojavljivanjemjestagdje se one nalaze.

Ucitavanje slika
Ako znatetocan URL slikekoju eliteucitati, moeteto ucinitiovako:
URL imageURL = new URL("http://student .math.hr/~vedris/java/images/
sun.jpg");
Image img = getImage (imageURL );

To se moezapisatii na kraci nacin:


Image img = getImage (new URL( "http://student .math.hr/~vedris/java/
images/sun.jpg"));

Metoda getImage () je izklase java.applet.Applet pa ona funkcioniraunutar


appleta. Izvanappleta moetekoristitimetodu getImage () izklase
java.awt.Toolkit .

URL imageURL = new URL("http://student .math.hr/~vedris/java/


images/sun.jpg");
Image img = Toolkit .getDefaultToolkit .getImage (imageURL );

Ako ne znatetocan URL slike, aliznatenjenoimei znateda se nalaziu istomdirektoriju


kao i applet, koristitcete appletovumetodu getCodeBase () koja ce vamvratitiURL
appletovogdirektorija:
Image img = getImage (getCodeBase (), "sun.jpg");

Konacno, ako je slikau istomdirektorijukao HTML datoteka, koristitcete appletovu


metodu getDocumentBase () koja ce vratitiURL direktorijaHTML stranice:
Image img = getImage (getDocumentBase (), "sun.jpg");

Ako se slikaucitavasa Interneta, to moepotrajati. U pravilune moratevoditiposebnog


racunao tom i moeteiscrtatislikucimste je povezalisa URL-om. Java ce sama, bez
vae intervencije,prikazatislikucimpristignedovoljnopodataka za to.
Sve slikekoje applet treba ucitajtevec u init() metodi. Posebno, nemojteihucitavatiu
paint() metodijer ce se tada ponovnoucitavatisvakiput kad applet napravirepaint
() , to ce drasticnosnizitiperformanse.
Slikukoja se koristiu sljedecimprimjerimamoeteskinutisa http://
student .math.hr/~vedris/java/images/sun.jpg .

Crtanje slika
Jednomkad ste slikuucitalis nekog URL-a, relativnoje jednostavnoiscrtatije. To cete
ucinitiu paint() metodi, koristecineku od metoda drawImage () izklase
java.awt.Graphics , npr.
public boolean drawImage (Image img, int x, int y, ImageObserver io)

Ovdje je img memberklase Image koji je u tom trenutkuvec ucita. Atributix i y su


koordinatelijevoggornjeguglaslike, dok je io instancaklase koja implementirasucelje
java.awt.image.ImageObserver .
To suceljepropisujekako Java rukujeasinhronimauriranjemslike. Ono je
implementiranou klasi java.awt.Component pa moeteza sada jednostavnostaviti
kljucnurijecthisu metodu drawImage (), cimecete naznacitida je sam applet taj koji ce
obavitiposloveauriranjaslike.
Metoda paint() ne radi nitadrugo osimcrtanjaslike, poceviod lijevoggornjeguglai
moeizgledatina primjerovako:
public void paint(Graphics g) {
g.drawImage (img, 0, 0, this);

Pretpostavljamoda atributimg referenciraobjekt koji je prethodnovec bio inicijaliziran


.

Uporaba povratne vrijednosti metode


drawImage()
Metoda drawImage () vraca vrijednosttipa boolean . Iako se na njucesto zaboravlja,
ona vamkae da lije slikauspjenonacrtanailinije. Ako jest, metoda ce vratititrue , u
protivnomfalse .
Na primjer, sljedeciapplet ucitavaslikus mree. Dok se slikaucitava, applet ce na
njenommjestuprikazivatitekst "Slika se ucitava . Molim, pricekajte ". Kad
slikabude 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

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.Sljedeca
varijacijapaint() metode doputa vamodredivanjeirinei visineslike, slicnoprimjeru
MagnifyImage 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 {

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 moe
bitiizoblicena.
Da bismoizbjeglinepravilnoskaliranjekoje dovodido izoblicenja, koristitcemo metode
getHeight () i getWidth () izklase java.awt.Image kako bismodoznalivelicinu

slike. Tada je moemo, ako je potrebno, skaliratiproporcionalno. Na primjer, ovako


biste smanjilislikuna jednucetvrtinuizvorneirinei visine:
g.drawImage (img, 0, 0, img.getWidth (this)/4, img.getHeight (this)
/4, this);

Pogledajmoprimjerkoji crta slikuu pravoj velicinibez obzirana velicinuappletovog


pravokutnika:
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 sadriklase i suceljakoje omogucujukreiranjenovihslikafrom
scratch umjestoucitavanjai modificiranjavec postojecihslika.

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 pozoveteappletovumetodu getImage (), slikase ne moeodmahpojaviti, vec
mora proci neko vrijemeda se ona ucita. Vece slikeucitavatce se due. Ako se slika
ucitavasa Interneta, to moepotrajatijo due.
Umjestocekanja da se slikaucita, metoda getImage () se vraca odmah, modai prije
nego to se veza s udaljenimracunalomuopce uspostavila. Ona vraca objekt tipa Image ,
alion inicijalnomodane sadrinikakvepodaatke. Raznemetode u paketu AWT koje
koristeslikeponaajuse u skladus tim. Na primjer, ako je samo gornjapolovicaslike
dostupnau trenutkukad se pozove neka od metoda drawImage () izklase Graphics ,
bit ce prikazanasamo ta gornjapolovica.
U meduvremenu,u pozadini, u odvojenomthreadu, nekiImageProducer, dakle objekt iz
klase koja implementirasucelje java.awt.image.ImageProducer , popunjavasliku
pixelimato bre moe. Kako viepixelapostane dostupno, bar za jedan redak, on ce
obavijestitio tome sve ImageObservere koji su registriranida imajuinteresza tu sliku.
Kako neki ImageObserver registrirasvoj interesza sliku? Tako da ga se proslijedi
metodikoja neto radi sa slikom. Na primjer, sjetitese da metode drawImage (), iz

klase Graphics , te getWidth () i getHeight () izklase Image primajuizmedu


ostalogai argumenttipa ImageObserver .
Klasa java.awt.Component implementirasucelje ImageObserver pa to cinei sve
njenepodklase. To znacida objektitipa Button, TextArea, CheckBox, Panel, Applet, i
drugimoguigratiuloguImageObserver a. Ipak, u pravilucete koristitionu komponentu
koja u tom trenutkupokuavacrtatisliku.
Sucelje ImageObserver propisujesamo jednumetodu, imageUpdate ():
public abstract boolean imageUpdate (Image img, int infoflags ,
int x, int y, int width, int height)

Sucelje ImageProducer koristitu metoduda bi obavijestioImageObserver a da je


pristiglojo podataka o slicipa se njenprikazmoeosvijeiti.

Sucelje ImageConsumer
Sucelje java.awt.image.ImageConsumer je manjeobicno. Dok ImageProducer
nekom ImageObserver u samo kae da je dio slikespreman, dotle zainteresiranom
ImageConsumer u daje stvarnepodatke o slici. Sucelje ImageConsumer propisuje
sljedecemetode:
public
public
public
public

abstract
abstract
abstract
abstract

void
void
void
void

setDimensions (int width, int height)


setProperties (Hashtable props)
setColorModel (ColorModel model)
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


Sucelje java.awt.image.ImageObserver omogucujevamnadziranjeprocesa
ucitavanja, tako da moeteinformiratikorisnikao statusuucitavanjai poceti koristitisliku
cimbude spremna.
Kad neki ImageProducer primidodatne podatke za neku sliku, pozvatce metodu
imageUpdate () kod svakog registriranogklijenta. Pretpostavljena(default)
imageUpdate () metoda u klasi java.awt.Component osvjeuje(repaints) prikaz
komponentekad se slikapromijeni.

Ipak, varijablekoje su postavljenepomocumetoda kao to getHeight () iligetWidth


() ne aurirajuse automatskipo pozivumetode imageUpdate () . Morate ih, dakle, sami
auriratikod promjeneslikeako je potrebno.
Tocna kolicinapodataka koju neki ImageProducer dobije prije nego pozove metodu
imageUpdate () je nepredvidljiva
.

Prekrivanje metode imageUpdate()


PretpostavljenaimageUpdate () metoda izklase java.awt.Component osvjeuje
prikazkomponentekad se slikapromijeni. Moete je, medutim, prekrititako da radi
neto drugo. Na primjer, sljedeciapplet ispisujeporuku na statusnojlinijibrowsera dok
prati ucitavanjeslike.
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;
}

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 pravokutnamreapixela. Ona imakonacnuirinui visinukoje se moguizraziti
brojem pixela. Svakipixelje kvadratickoji imafiksnuvelicinuna danomekranu. Velicina
pixelamoeovisitio ekranii racunalu.
Svakipixelimaneku boju. Boja je 32-bitniinteger. Prvihosam bitovaodreduje udio
crveneboje, drugihosam udiozelene, a trecihosam udioplaveboje. Preostalihosam
pixelaodreduje transparentnostpixela.
11111111 11111111 11111111 11111111
Transparency

Red

Green

Blue

Svaka od ovihvrijednostimoese interpretiratikao neoznacenibyte izmedu0 i 255.


Unutarneke boje, vecibrojevioznacavajusvijetliju(brighter), odnosno intenzivnijuboju.
Tako crvenaboja vrijednosti0 nijeuopce crvena, dok je ona koja imavrijednost255
intenzivnocrvena.
Trenutacnosu dostupnasamo dva stupnjatransparencije: potpunoneprozirno(255) i
potpunoprozirno(0). Vrijednostiod 1 do 254 interpretirajuse kao potpunoprozirno.
Razliciteboje dobijajuse mijeanjemosnovnihtrijuboja u razlicitimomjerima. Na
primjer, umjerenosivaje zapravo127 crveno(red), 127 zeleno(green) i 127 plavo
(blue):
255 127 127 127
Cista bijelaje 255 red, 255 green, 255 blue:

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 moeprakticno
iskoristitiu 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 boja
predstavljenacijelimbrojem 11111111011111110111111101111111 odnosno
-8,421,505. Naravno, cjelobrojnavrijednostnas ovdje ne zanima, bitnaje binarna
reprezentacija.
Dakle, kako se kreirajuovakve boje?. Jednostavnoinicijalizirajte
cijelebrojeve na
vrijednostikoje eliteza svakiod cetirikanala, uporabiteoperator << kojimcete iz
odvucina pravo mjestoi kombinirajtebitovskimOR operatorom, |. Taj operator
postavljaodredenibit u rezultatuna 1 ako je on tako postavljenu bilokojem operandu.
Na primjer, da bismokreiralicistuplavuboju, stavimo:
int
int
int
int
int

alpha = 255 << 24;


red = 0 << 16;
blue = 255 << 8;
green = 0;
pureblue = alpha | red | green | blue;

Moete to zapisivatii krace, u jednomretku, npr:


int pureblue = (255 << 24) |
(0 << 16) | (255 << 8) |
0;
cista plava
int halfgrey = (255 << 24) | (127 << 16) | (127 << 8) | 127;
umjereno siva

Kreiranje slika

//
//

Kad znamoda su slikezapravomreeintegera, ne bi trebalobititeko kreiratiih.


Naravno, to se odnosina one slikekoje se mogukreiratialgoritamski.
Ima vienacinaza kreiranjeslike, tj. objekta tipa Image izsirovihbyteova.
Najjednostavnijeje uporabitiklasu java.awt.image.MemoryImageSource . Ona
implementirasucelje java.awt.image.ImageProducer kao i sve klase koje kreiraju
slike. 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 irinaslikeu


pixelima, height je njezinavisina, a pixels je cjelobrojnopolje koje sadristvarne
podatke slike. Svakibroj u tom poljuje 32-bitnavelicinakoja sadriRGB-transparency
vrijednostza jedan pojedinacnipixel. Nadalje, offset je indexu tom poljuod kojega
pocinjupodaci za tu sliku, a scan je broj pixelau svakomretku polja. Uglavnomce taj
broj bitijednak vrijednostiatributawidth .
Da biste kreiralisliku, prvo cete napunitipolje podacimasame slike, a zatimpomocutog
polja konstruiratinoviobjekt tipa java.awt.image.MemoryImageSource . Zatimcete
taj MemoryImageSource predatimetodi createImage () izklase
java.awt.Component koja ce proizvestipravi Image objekt.

Primjer kreiranja slika


Pretpostavimoda elimonapravitislikuiroku100 pixelai visoku50 pixela, koja ce se
sastojatiod ciste ljubicastepovrine. Vrlo lijepaljubicastaboja dobije se sa. 217 red, 10
green, 186 blue.
Cjelobrojnuvrijednostove boje formiratcemo ovako:
int
int
int
int

red = 217;
green = 10;
blue = 186;
opaque = 255;

int purple = (opaque << 24 ) | (red << 16 ) | (green << 8 ) | blue;

Slikakoju elimoje 100 pixelairoka i 50 pixelavisoka, pa ce namza njubitipotrebno


polje sa 100 * 50 = 5000 elemenata, dakle
int[] pixels = new int[5000];

Sada moetepolje napunitiljubicastimpixelima, npr. pomocuovakve for petlje:


for (int i=0; i < pixels.length; i++) pixels[i] = purple;

Sad imamopolje i moemokreiratiMemoryImageSource .


MemoryImageSource purpleMIS = new MemoryImageSource (100, 50,
pixels, 0, 50));

Pod pretpostavkomda smo u appletuilinekoj drugojpodklasiod


java.awt.Component , ucinitcemo sljedece:.
Image purplebox = createImage (purpleMIS );

(Ako smo negdjedrugdje, trebat cemo pozivucreateImage () dodati prefix,


odgovarajucureferentnuvarijablu.) Sada moemoslikunacrtatina uobicajennacin, kao
da smo je ucitalis mree.
Jedan ImageProducer moetekoristitiza kreiranjevieslika, a jedno polje pixelaza
kreiranjevieobjekata tipa MemoryImageSource . Medutim, ako to radite, polje ne biste
smjelimijenjatinakon to je inicijalnokreirano.

Metoda getRGB()
Manipulacijubitovimane morateuvijekobavljatisami. Umjestotoga moetekreiratinovi
objekt tipa java.awt.Color i uporabitinjegovumetodu getRGB() da dobijete
odgovarajucuint 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 to
je prethodna, moese kreiratii na viedrugihi
efikasnijihnacinanego to je manipuliranje
pixelima. Medutim, neke je slikeipak

najjednostavnijenapravitiba takvim,
algoritamskimpristupom. Pogledajmosljedeci
applet koji kreira slikuvelicine256 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

Java podravafiltriranjeslika, skup postupaka kojimse slikatransformairana neki


predvidljivnacin. Na primjer, filtarmoeuklonitizelenuiliplavukomponentuslike,
ostavljajucisamo crvenu. Ilimoeizotriti, odnosno zamutitilinijeslike. Izucavanjefiltara
jo je otvorenopodrucje. Ovdje cemo demonstriratinekolikojednostavnihfiltara.
Kompliciranijise rade na istinacin, samo to koristekompliciranijealgoritmeza filtriranje
podataka.
U Javinamje, da bismoradilis filtrima,potrebna podklasa od
java.awt.image.ImageFilter i podklasa od
java.awt.image.FilteredImageSource . Ova drugaimplementirasucelje
java.awt.image.ImageProducer . Pocinjeraditisa postojecomslikom, alije provlaci
kroz odgovarajuciImageFilter prije nego poalje pixelenekom ImageObserver u ili
ImageConsumer u.

Klasa RGBImageFilter
Klasa java.awt.image.RGBImageFilter je apstraktnapodklasa od
java.awt.image.ImageFilter . Omogucujepisanjefiltarakoji modificirajupixele,
jedan po jedan. Koristise kad je filtriranjesvakog pixelanezavisnood ostalihpixela. Nije
pogodna za filteru kojimafiltriranjeovisio susjednimpixelimakao to je npr. filtarkoji
uprosjecujeokolnepixele.
Jedinametoda izte klase koju trebate prekritije filterRGB ()
public abstract int filterRGB (int x, int y, int rgb)

Zbog performansidobro je prekritii metodu filterRGBPixels () i postavitiatribut


canFilterIndexColorModel na true . Taj atributodreduje da lifiltarovisiiline ovisio
pozicijipixela. Ako je true , onda se umjestofiltriranjasvakog pixelaslikafiltrirasamo
ogranicenbroj stavaka u mapiboja, to je mnogobre. Po pretpostavcifiltarovisio
pozicijipa je taj atributinicijalnofalse .
public void filterRGBPixels (int x, int y, int w, int h,
int pixels[], int offset, int scan)

Metoda filterRGBPixels () prosljedujesvakipixelizpolja pixelametodi filterRGB


() jedan po jedan. Medutim, ponekad moetepoboljatiperformanseizbjegavanjem
nepotrebnihpozivametoda i filtriranjapixelajedan po jedan, posebno ako je
canFilterIndexColorModel postavljenna false .

Primjer plavog filtra


Evo jednogjednostavnogfiltrakoji proputa samo plavekomponenteslike.
import java.awt.image.*;

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 filtriranjeneovisnoo


poziciji. Bitovskioperator, &, koristise za selektiranjesamo prvihosam i zadnjihosam
bitovavrijednostibroja rgb . Stupanjtransparentnostije spremljenu prvih8 bitova. Plava
komponentase nalaziu zadnjih8 bitova. FF je 11111111 pa su svibitoviplaveboje i
prozirnostizadrani. Ostalice nestati.
Da bismokoristilitaj plavifiltar, kreiratcemo objekt tipa
java.awt.image.FilteredImageSource . Na primjer,
Image src = getImage (getDocumentBase (), filename );
picture = createImage (new FilteredImageSource (src.getSource (), new
BlueFilter ()));

Metoda getSource () vraca referencuna objekt tipa ImageProducer koji je proizveo


sliku(objekt tipa Image ).
Evo sada appleta koji ucitavaslikunavedenuu oznaci<PARAM> i zatimna njuprimjenjuje
plavifiltar.
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 {

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 su
ujednacene. 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 prije racunanjaprosjeka crvenai zelenakomponentapomaknutedesno


za 16, odnosno 8 bitovarespektivno. To ihbaca u raspon od 0 do 255 i omogucujeda
sa svakomod njihradimopojedinacno. Operator >>> pomicebitoveudesno bez
predznaka.
import java.awt.*;
import java.awt.image.*;
import java.applet.*;

public class GreyImage extends Applet {


private Image picture ;

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 poloaju


Mogu se pisatifiltrikoji oviseo poloajupixela. Na primjer, sljedecifiltarzatamnjujesliku
tako da je zatamnjenjeto vece to se vieudaljujemood 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;

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 vienijepostavljenna true . Svaki


pixelmora se tretiratiindividualno
. Takoder primijetiteda ovaj filtarimakonstruktor. Iako
nijenuan, 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 adjungiranim


pixelima

Do sad smo pretpostavljalida se svakipixelmoefiltriratineovisnoo susjednimpixelima.


To nijeuvijektako. Na primjer, filtriza izotravanje, zamagljivanjei slicno, trae znacajnu
kolicinupodataka o drugimdijelovimaslike.
Kad filtarmora uzimatiu obzirvrijednostine samo filtriranihpixelanego i drugih, nijevie
mogucekoristitijednostavnuklasu java.awt.image.RGBImageFilter . Umjestotoga
treba raditidirektnosa java.awt.image.ImageFilter . Da biste implementirali
svoj
filtar, potrebno je prekritidvijemetode setPixels ().
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 mogu
bitiAIFF, AU, WAV, MIDI, and RMF datoteke.
Klasa java.applet.Applet sadridvijemetode pomocukojihmoeteskinutizvucnu
datoteku sa nekog URL-a i izvestije.
public void play(URL soundfile )
public void play(URL directory , String filename )

Uobicajenoje da se te adrese zadajuu odnosu na codeBase ilidocumentBase , iliURL


moebitizadan pomocuoznake <PARAM>.
Audioprimjerza sljedeceapplete moeteskinetesa 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">

</APPLET>

Kontinuirana izvedba
Umjestopojedinacneizvedbeod pocetka do kraja, applet moeizvoditizvucniprimjer
kontinuirano,tako da ga ucitau objekt "tipa" java.applet.AudioClip (primijetiteda
je to sucelje, ne klasa!) i nakon toga izvvodipomocumetode loop(). Prvo treba snimiti
zvuku AudioClip na primjerovako:
AudioClip ac = this.getAudioClip (new URL(
"http://student .math.hr/~vedris/java/sounds/spacemusic .au"));

Tada, kad imateobjekt koji je AudioClip , pozovetenjegovumetodu loop():


ac.loop();

Kad elitezaustavitiizvedbu, pozvatcete metodu stop():


ac.stop();

Evo appleta koji 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>

Primijetiteda sam applet vodiracunao tome da izvedbaprestane kad korisniknapusti


stranicupa se pozove metoda stop(). U protivnombi se izvedbanastavilabeskonacno,
sve dok korisnikne ugasibrowser.

Deseto predavanje

ulaz i izlaz

Operacije ulaza i izlaza - to je stream? klase streamova odakle streamovi


dolaze ? klasa InputStream citanje byteova citanje vie byteova odjednom
prebrojavanje dostupnih byteova preskakanje byteova markiranje i resetiranje
zatvaranje streamova izlazni streamovi primjer izlaznog streama citanje iz
datoteke primjer citanja iz datoteke pisanje u datoteku primjer pisanja u
datoteku dodavanje na kraj datoteke filtriranje streamova filtrirani streamovi
bufferirani streamovi klase podatkovnih streamova klasa PrintStream klasa
PushBackInputStream klasa File konstruktori klase File metode klase File
primjeri metoda iz klase File klasa FileDialog klasa RandomAccessFile sucelje
FilenameFilter klase Reader i Writer klasa Reader klasa Writer klasa
InputStreamReader klasa OutputStreamWriter dostupne kodne stranice klasa
FileWriter klasa FileReader klasa BufferedReader klasa LineNumberReader
klasa BufferedWriter

Operacije ulaza i izlaza


Podaci se ponekad umjestona zaslonracunalaispisujuu datoteku. Unixi DOS za tu
svrhuimajuredirekcijskeoperatore < i >. Ponekad je potreban i finijipristup, na primjer
ako eliteneke podatke uputitiu datoteku, a drugeostavitina zaslonu. Ilimodaelite
istovremenoimatipristupu viedatoteka. Takoder, modaelitetraitiod korisnikada
unesepodatke ne samo preko komandnelinijenego i na nekidruginacin. Ilielite
procitatidatoteku koja je napisanau odredenomformatu, poslatipodatke preko mreeili
ihs nje ucitati. U Javise sve ove operacijeobavljajuuz pomoc streamova. Stream je na
primjeri System.out koji ste susrelivec u prvompredavanju.

to je Stream?
Stream je nizpodataka koji imaneodredenuduljinu. Nazivstream(struja, tok) je
odabran jer ta strukturanalikujestrujivode koja neprekidnotece i nemadefiniranog
kraja. Jo bolja analogijaje rep (red cekanja). Za vrijemedok se usluujuljudina
pocetku repa, novidolazena njegovkraj. Rep je diskretnastruktura, alito ne znacida
njegoviclanovinisumedusobnopovezaniraznimrelacijama.
U Javise streamsastojiod nizadiskretnihbyteova. Oni mogupredstavljatiznakoveili
neke drugevrste podataka. Mogu dolazitibre nego to ihje moguceobraditiilipak
process moecekati dok ne dode sljedeciza obradu.
Kljucobrade streamaje while petljakoja obraduje svakipojedinielementstreamadok
ne ucitaznak za kraj streamailidok se ne pojavinekidrugiiznimniuvjet. Na Unixuje
<Ctrl-D> znak za zavretakstreama. Windowsza tu svrhukoristi<Ctrl-Z>.

Klase streamova
Gotove sve klase koje izravnorade sa streamovimadijelovisu paketa java.io. (Postoji
takoder nekolikododatnihu paketimasun.io i sun.net , alite su namjernoskrivene.
Ima i nekolikoklasa u paketu java.util.zip .) Dvijeglavneklase su
java.io.InputStream i java.io.OutputStream . To su apstraktneklase i one cine
temeljmnogihpotklasa sa specijaliziranim
mogucnostima
. Medu njimase najcece
koriste:
BufferedInputStream
BufferedOutputStream
ByteArrayInputStream
ByteArrayOutputStream
DataInputStream
DataOutputStream
FileInputStream
FileOutputStream
FilterInputStream
FilterOutputStream
LineNumberInputStream
ObjectInputStream
ObjectOutputStream
PipedInputStream
PipedOutputStream
PrintStream
PushbackInputStream
SequenceInputStream
StringBufferInputStream

Odakle streamovi dolaze?


Stream System.out je, recimo, OutputStream ; i to posebno, PrintStream . Postoji
odgovarajuciSystem.in koji je InputStream namijenjencitanjupodataka s konzole.
Podaci za streamovedolazetakoder i izdatoteka. Kasnijecete vidjetikako koristitiklasu
File te klase FileInputStream i FileOutputStream za citanjepodataka izdatoteka
i pisanjeu njih.
Mrenekonekcijeobicnodaju streamove. O tome ce bitirijeciu zasebnompredavanju.
Kad se poveetena nekiweb iliftp ilinekidrugiposluitelj,citatepodatke koje on alje
tako da s njimpoveetejedan InputStream i jedan OutputStream .
Java programii samiproizvodestreamove. Na primjer, ByteArrayInputStream ,
ByteArrayOutputStream , StringBufferInputStream , PipedInputStream , i
PipedOutputStrea m se koristeza prijenospodataka izjednogdijelaJava programau
drugi.

Poneto neocekivano, komponentekao to je TextArea ne proizvodestreamove.


Medutim, stringovekoje onistvarajuuvijekmoetekoristitida biste kreirali
ByteArrayInputStream iliStringBufferInputStream .

Klasa InputStream
Klasa java.io.InputStream je apstraktnaklasa koja sadriosnovnemetode za
citanjecistihbyteovapodataka izstreama. Iako je to apstraktnaklasa, mnogemetode u
bibliotecivracajuobjekt tipa InputStream , tako da cete cesto trebatiraditidirektnos
nekomod metoda deklariranihu toj klasi.
public abstract int read() throws IOException
public int read(byte[] data) throws IOException
public int read(byte[] data, int offset, int length) throws
IOException
public long skip(long n) throws IOException
public int available () throws IOException
public void close() throws IOException
public synchronized void mark(int readlimit )
public synchronized void reset() throws IOException
public boolean markSupported ()

Primijetiteda gotovosve ove metode moguizbacitiIOException . To vrijediza


uglavnomsve to se odnosina ulazi izlaz. Jedinaiznimkaod tog pravilaje klasa
PrintStream koja ce progutatisve iznimke
.

Citanje byteova
Osnovna read() metoda izklase java.io.InputStream cita pojedinacnineoznaceni
byte podataka i vraca njegovuint vrijednost. To je broj izmedu0 i 255. Kad se naide
na kraj streama, vraca se -1, i to moetekoristitikao flagpomocukojeg cete ustanoviti
da ste dolido kraja streama.
public abstract int read() throws IOException

Evo jednogjednostavnogprogramakoji vraca kao echo korisnikovunos na komandnoj


liniji. Byte se prije ispisapretvarau ekvialentniISO Latin-1 znak. Ovaj programnece
pravilnoraditisa Unicodeznakovima. Moete ga dakle koristitisamo za ciste podatke, a
za tekstove i osobito ne-ASCII podatke koristitiklase java.io.Reader i
java.io.Writer .
/* Note that as a general rule on most platforms characters
are only sent to System.in a line at a time, not as each character
is 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.*;

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 Echo
abcdefg
abcdefg
<Ctrl-C>
%

Citanje vie byteova odjednom


Dok osnovna read() metoda cita byte po byte, sljedecedvijeoverloadedvarijante
citajupolja byteova.
public int read(byte[] data) throws IOException
public int read(byte[] data, int offset, int length) throws
IOException

Prva metoda cita onolikobyteovakolikojoj treba da napunipolje data . Drugacita


onolikobyteovaizulaznogstreamakolikojoj je zadano u argumentulength i sprema ih
u polje data poceviod pozicijeoffset .
Te su metode blokoranedok ne stignuraspoloivipodaci. Tada ucitajuonolikopodataka
kolikostane u polje ilikolikoje navedenou length .
Nakon toga vracajubroj byteovakoje su ucitale. Ne smijetepretpostavitida ce polje biti
uvijeknapunjenoilida ce zaistabitiucitanolength byteova. Ako naidekraj streama,
vraca se -1.

Prebrojavanje dostupnih byteova


Metoda available () ispitujukolikobyteovasa uzlaznogstreamaje spremnoza
ucitavanjebez blokiranja.
public int available () throws IOException

Na primjer, sljedeciprogramje efikasnijaverzijaprethodnogprograma Echo jer koristi


metodu available () za ispitivanjekolikobyteovaje spremnoza ucitavanje, a zatim
kreira polje tocno te velicine, ucitavabyteoveu polje i konvertiraga u String koji zatim
ispisuje.
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);
}

}
}
% javac Echo.java
% java Echo
abcdefg
abcdefg
<Ctrl-C>
%

Preskakanje byteova
Metoda skip() cita i odbacuje specificiranibroj byteova.
public int skip(long n) throws IOException

Moete je koristiti, na primjer, ako elitebrzo prodi standardniheader iliprefiksnekih


podataka. U sljedecemfragmentukoda koristise skip() za preskakanjepraznina
ukljucenihu 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 moeteucitatinekolikobyteova, a zatimse vratitinatragi ucitatiih
ponovo. Na primjer, pri oblikovanjunekog kompajlerane moeteznatida litrebate
ucitatiznak <, <<, ili<<= sve dok ne ucitatedva iliviebyteova. Bilobi korisnoako
biste se moblivratitinatragi ponovo ucitatitoken nakon to ste okrilio kojem se radi.
Dizajniranjekompajlerai problemiparsiranjauvijekosiguravajumnotvoprimjera, no
slicnepotrebe se pojavljujui drugdje.
Neki, aline svistreamovidoputajuvamda markirateodredenupozicijuu streamui onda
se vratitena nju. To se radi pomocusljedecihmetoda:
public synchronized void mark(int readlimit )
public synchronized void reset() throws IOException
public boolean markSupported ()

Metoda markSupported () vraca true ako taj streampodravamarkiranje, a false


inace.
Pod pretpostavkomda je markiranjepodrano, metoda mark() stavljabookmark na
mjestogdje se kasnijeelitevratitipomocumetode reset(). Istodobno u jednom
streamumoepostojatisamo jedan takav bookmark. Sljedece markiranjeizbrisatce
prethodno. Ako markiranjenijepodrano, ove ce metode izbacitiIOException .

Zatvaranje streamova
Kad ste zavrilis nekimstreamom, trebalibiste ga zatvoritikako bi se otpustiliresursikoji
su s njimpovezani. Jednomkad je streamzatvoren, svakipokuaj citanjaiznjegaizbacit
ce IOException .
Stream (u ovomslucajuulazni) zatvaratepomocumetode close():
public void close() throws IOException

Ako se streamne moezatvoriti, izbacitce se IOException .

Izlazni streamovi
Klasa java.io.OutputStream alje ciste byteovepodataka na neko odredite, npr.
konzoluilimreniposluitelj.Ova je klasa apstraktna, isto kao i InputStream . Medutim,
mnogemetode u biblioteciklasa napravljenesu tako da vracajuobjekte tipa
OutputStream umjestoobjekte iznjenihspecificnihpodklasa. Takoder, mnogemetode
klase OutputStream su opcenitokorisne. To su:
public abstract void write(int b) throws IOException
public void write(byte[] data) throws IOException
public void write(byte[] data, int offset, int length) throws
IOException
public void flush() throws IOException
public void close() throws IOException

Nekolikorazlicitihwrite() metoda aljuciste byteovepodataka svakomprocesu koji


oslukujedanistream.
Ponekad operacijskisustavbufferiraizlaznestreamovezbog boljihperformansi. To znaci
da se byteoviprije ispisaakumulirajuu spremnikcija velicinamoebitiod nekoliko
byteovado nekolikotisucabyteova. Kad se on napuni, svipodaci se ispisujuodjednom.
Metoda flush() pokrenutce, medutim, ispisbez obzirada lije spremnikpun ilinije.
Primijetiteda to nije isto to i bufferiranjekoje provodiklasa BufferedOutputStream
koje izvodiJava runtime. Ovdje se radi o native bufferiranju
, dakle procesu na razini

operacijskogsustava. Medutim, pozivmetode flush() trebao bi ispraznitioba


spremnika.
Metoda close() zatvarastreami otputa resurse koji su s njimpovezani. Jednomkad je
streamzatvoren, pokuaj pisanjau njegaizbacitce IOException .

Primjer izlaznog streama


Jediniizlaznistreamovikoje ste do sad upoznalisu System.out i System.err . Sljedeci
primjerkoristimetode write() and flush() izklase OutputStream da bi na
System.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 ocekivalonego progutaprviznak.

Citanje iz datoteke
Klasa java.io.FileInputStream predstavljaInputStream koji cita byteoveiz
datoteke. Ima sljedecepublickonstruktorei metode:
public FileInputStream (String name) throws FileNotFoundException
public FileInputStream (File file) throws FileNotFoundException

public FileInputStream (FileDescriptor fdObj)


public native int read() throws IOException
public int read(byte[] data) throws IOException
public int read(byte[] data, int offset, int length) throws
IOException
public native long skip(long n) throws IOException
public native int available () throws IOException
public native void close() throws IOException
public final FileDescriptor getFD() throws IOException

S iznimkomkonstruktorate metode getFD(), ove metode samo prekrivajuistoimene


metode klase java.io.InputStream . Jedinaje razlikato citajupodatke izdatoteke.

Primjer citanja iz datoteke


Novi objekt tipa FileInputStream konstruiratetako da konstruktoruproslijediteime
datoteke, na primjer:
FileInputStream fis = new FileInputStream ("ulaz.txt");

Ako datoteka ne postoji, izbacitce se iznimkaFileNotFoundException , podklasa od


IOException . Opcenito, Java ce traitidatoteke u aktivnomdirektoriju, no one se ne
morajununonalazitiu direktorijuu kojem se nalazi.class datoteka.
Sljedeca aplikacijacita datoteke koje su navedenena komandnojlinijii ispisujenjihov
sadraj na 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) {

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 upisujebyteoveu
datoteku. Ima sljedecepublickonstruktorei metode:
public FileOutputStream (String name) throws IOException
public FileOutputStream (String name, boolean append) throws
IOException
public FileOutputStream (File file) throws IOException
public FileOutputStream (FileDescriptor fdObj)
public native void write(int b) throws IOException
public void write(byte[] data) throws IOException
public void write(byte[] data, int offset, int length) throws
IOException
public native void close() throws IOException
public final FileDescriptor getFD() throws IOException

S iznimkomkonstruktorate metode getFD(),ove metode samo prekrivajuistoimene


metode klase java.io.OutputStream . Jedinaje razlikato piupodatke u datoteku.

Primjer pisanja u datoteku


Novi objekt tipa FileOutputStream konstruiratetako da konstruktoruproslijediteime
datoteke, na primjer:
FileOutputStream fos = new FileOutputStream ("izlaz.txt");

Ako datoteka postojiu aktivnomdirektoriju, bit ce prebrisanai u njuupisaninovipodaci.


Ako ne postoji, kreiratce se.

U sljedecemprimjerucita se korisnikovinputsa System.in i ispisujese u datoteke


specificiranena 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
}

% javac MultiType .java


% java MultiType izlaz1.txt izlaz2.txt
nebo je plavo
<Ctrl-C>
%
% ls izlaz*.txt
izlaz1.txt
izlaz2.txt
% more izlaz1.txt
nebo je plavo
% more izlaz2.txt
nebo je plavo
%

Dodavanje na kraj datoteke


Ako eliteda se novisadraj doda na kraj datoteke umjestoda prebrieprethodni
sadraj, proslijeditcete vrijednosttrue kao drugiargumentkonstruktoru
FileOutputStream () . Na primjer:
FileOutputStream fos = new FileOutputStream ("izlaz.txt", true);

U sljedecemprimjerucita se korisnikovinputsa System.in i dodaje na kraj datoteka


specificiranihna 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);

}
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.txt
a trava je zelena.
<Ctrl-C>
% more izlaz1.txt
nebo je plavo
a trava je zelena.
% more izlaz2.txt
nebo je plavo
a trava je zelena.
%

Filtriranje streamova
Klase java.io.FilterInputStream i java.io.FilterOutputStream su
konkretnepodklase od InputStream i OutputStream koje na nekinacinmodificiraju
podatke osnovnihstreamova. Rijetkocete ihkoristitiizravno, alinjihovesu podklase
iznimnovane, posebno DataInputStream i DataOutputStream .
Filtar-streampovezujetes osnovnimtako da da osnovniproslijeditekonstruktorufiltarstreama. Na primjer, da biste kreiralinoviobjekt tipa DataOutputStream izobjekta
FileOutputStream moglibiste postupitiovako:
FileOutputStream fos = new FileOutputStream ("ln.txt");
DataOutputStream dos = new DataOutputStream (fos);

To se moekombiniratii u jednoj liniji:

DataOutputStream dos = new DataOutputStream (new FileOutputStream


("ln.txt"));

Filtrirani streamovi
i BufferedOutputStream
Ove klase bufferirajucitanjei pisanjetako da podatke najprijeucitavajuu
spremnik(buffer, interrnopolje byteova). Tako neka aplikacijamoecitati
byteoveizstreamabez pozivanjanative metoda koje izatoga stoje. Podaci se
ucitavajuizbufferailiu njegaupisujuu blokovima, a naknadnipristupi
usmjeravajuse direktnoprema spremniku.

BufferedInputStream

i DataOutputStream
Ove klase citajui piupodatke koji pripadajuprimitivnimJava tipovima, kao i
podatke tipa Stringna nacinkoji ne ovisio maini(Big-endianza integer,
IEEE-754 za floati double, UTF-8 za Unicode)

DataInputStream

PrintStream

Ova ste klasuvec susretalipreko njenihimplementacijaSystem.out i


System.err . Omogucujevrlojednostavnoispisivanjeprimitivnih
vrijednosti,
objekata i stringliterala. Klasa hvatasve iznimketipa IOException i
namijenjenaje ponajprijeza debugging.
PushbackInputStream

Ova klasa osiguravapushback spremnikpomocukojeg je moguce"ponititi"


citanjebyteovasa streama. Kod sljedecegcitanjasa streamabit ce ucitaniti
poniteni byteovi.
i GZIPOutputStream
Ovo su klase izpaketa java.util.zip i obavljajukompresijui dekompresiju
podataka.

GZIPInputStream

i DigestOutputStream
Ovo su klase izpaketa java.security i izracunavajutzv. MessageDigest za
streamovekoristecineku jaku hash funkciju, npr SHA.

DigestInputStream

i CipherOutputStream
Klase su izpaketa javax.crypto koji je dio Java CryptographyExtension
(JCE), standardnogproirenjaJave, a ukljucenje u JavaTM 2 Platform Std.
Ed. v1.4.0. i izracunavajuenkripcijei dekripcijestreamovakoristecirazne
algoritmekao DES, RSA, Blowfishi druge.

CipherInputStream

i ObjectOutputStream
Podklase od of DataInputStream i DataOutputStream koje mogu
serijaliziratii deserijaliziratiJava objekte u ciste byteove(i obratno). Koristise
kod udaljenogpozivanjametoda (RMI) i za JavaBeans.

ObjectInputStream

Moete kreiratii svoje vlastitepodklase od java.io.FilterInputStream i


java.io.FilterOutputStream koje ce izvoditifiltriranjaprema vaimpotrebama.

Bufferirani streamovi
Klase java.io.BufferedInputStream i java.io.BufferedOutputStream
omogucujucitanjei pisanjena nacinda se podaci prvo spremajuu spremnik(buffer) koji
je zapravointernopolje byteova. Programtada cita byteoveizstreamabez prethodnog
pozivanjanative metode dok god imapodataka u spremniku. Podaci se citajuiz
spremnikailipiuu njegau blokovima, a nakon toga su dostupniizravnoizspremnika.
Sa stanovitaprogramera, jedinarazlikaizmeduobicnogi bufferiranogstreamaje u
konstruktorima:
public
public
public
public

BufferedInputStream (InputStream in)


BufferedInputStream (InputStream in, int size)
BufferedOutputStream (OutputStream out)
BufferedOutputStream (OutputStream out, int size)

Argumentsize je broj byteovau spremniku. Ako nijenaveden, podrazumijevase 512.


Optimalnavelicinaspremnikajako ovisio platformii opcenitoje povezanasa velicinom
bloka na disku, barem za datotecne streamove. Manje od 512 ce vjerojatnobitipremalo,
a vieod 4096 previe. Idealnobi biloda velicinaspremnikabude cjelobrojniviekratnik
velicinebloka diska. Za nepouzdanemrenekonekcijebolje je odabratimanjuvelicinu
spremnika. 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 piu
primitivneJava tipovepodataka i stringovena nacinkoji ne ovisio maini. Opcenitocete
DataInputStream koristitiza citanjepodataka koji su napisanipomocu
DataOutputStream . Taj formatkorististandard IEEE754 za floatingpoint, big-endian
za integer, i modificiraniUTF-8 za Unicode.
DataOutputStream

deklarirasljedecekonstruktorei metode:

public DataOutputStream (OutputStream out)


public synchronized void write(int b) throws IOException
public synchronized void write(byte[] data, int offset, int length)
throws IOException
public final void writeBoolean (boolean b) throws IOException
public final void writeByte (int b) throws IOException
public final void writeShort (int s) throws IOException

public
public
public
public
public
public
public
public
public

final void writeChar (int c) throws IOException


final void writeInt (int i) throws IOException
final void writeFloat (float f) throws IOException
final void writeDouble (double d) throws IOException
final void writeBytes (String s) throws IOException
final void writeChars (String s) throws IOException
final void writeUTF (String s) throws IOException
final int size()
void flush() throws IOException

Metoda size() vraca broj byteovakoji su ispisanina izlaznistream.

Klasa PrintStream
Klasa java.io.PrintStream je podklasa od FilterOutputStream . Implementirana
je u System.out i System.err . Omogucujejednostavanispisprimitivnihvrijednosti,
objekata i stringliterala. Za konvertiranjeznakovau byteovekoristikodiranjekoje je na
danoj platformidefault.
Ta klasa ce uhvatitisve iznimketipa IOException , Status pogreke moeteuvijek
doznatipomocumetode checkError (). Ona ce vratititrue ako se greka pojavila,
false inace.
public boolean checkError ()

Ono to se najviekoristiu ovoj klasisu (overlodaded) metode print() i println ().


Metode println () dodaju znak za zavretaklinijesvemuto ispisuju, za razlikuod
metoda print() koje to ne cine.
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public
public

void
void
void
void
void
void
void
void
void
void
void
void
void
void
void
void
void
void

print(boolean b)
print(int i)
print(long l)
print(float f)
print(double d)
print(char s[])
print(String s)
print(Object obj)
println ()
println (boolean x)
println (char x)
println (int x)
println (long x)
println (float x)
println (double x)
println (char x[])
println (String x)
println (Object x)

Klasa PrintStream je uglavnomnamijenjenadebagiranjuprograma. Inace je


neslubenodeprecated u Javi1.1. i dalje. Umjestonje cete viekoristitiklasu
PrintWriter .

Klasa PushbackInputStream
Klasa PushbackInputStream osiguravapushback spremnikpomocukojeg je moguce
"ponititi" citanjebyteovasa streama. Kod sljedecegcitanjasa streamabit ce ucitaniti
poniteni byteovi.
public void unread(int b) throws IOException
public void unread(byte[] data, int offset, int length) throws
IOException
public void unread(byte[] data) throws IOException

Po pretpostavci, spremnikimavelicinuod jednogbytea pa ce pokuaj ponitavanjavie


byteovaizbacitiIOException . No velicinuspremnikamoetezadatiako uporabitedrugi
od sljedecadva konstruktora.
public PushbackInputStream (InputStream in)
public PushbackInputStream (InputStream in, int size)

Iako i PushbackInputStream i BufferedInputStream koristespremnike, jedino


PushbackInputStream doputa ponitavanje, a jedino BufferedInputStream
doputa markiranjei resetiranje. Za streamovetipa PushbackInputStream metoda
markSupported () vraca false .
public boolean markSupported ()

Metode read() i available () rade jednako kao s obicnimulaznimstreamovima,


jedinoto najprijepokuavajucitatiizpushback spremnika.
public int read() throws IOException
public int read(byte[] data, int offset, int length) throws
IOException
public int available () throws IOException

Klasa File
Klasa java.io.File predstavljaeksterno imedatoteke na racunalu. Njome se
pokuavajuapstrahiratidijeloviimenakoji su zavisnio racunalu, na primjerput, separator
i slicno.
Dva su nacinareferenciranjadatoteka, relativnii apsolutni. Apsolutnoimenovanjedaje
potpuniput do datoteke, poceviod imenadiska pa dalje. Detaljioviseo operacijskom
sustavu. Na primjer:
Unix:
DOS:
MacOS:

"/math/vedris/file1"
"C:\math\vedrisfile 1"
"Macintosh HD:math:vedris:file1"

Sva ova tri stringareferencirajudatoteku file1 na glavnomdiskuu direktoriju/math/


vedris/. Razlikujuse na primjerpo separatoru. Unixkoristi/, Dos i Windows\,
MacOS :. Drugisustavimogukoristitineto posve drugo.
Takoder, nemagarancijeda se glavnidisk na Macu zove ba Macintosh HD ilida
uopce postojidisk s timimenom. Na Unixu / i /math moggubitina razlicitim
diskovima, pa cak i na razlicitimmainama. Zbog takvihrazlogaapsolutnaimenatreba
uglavnomizbjegavati.
Relativnoimenovanjekoje treba koristitikad god je moguce, ne daje potpuniput do
datoteke. Umjestotoga daje put koji je relativanprema nekoj poznatojdatoteci. Relativni
put moepokazivatidatoteku u istomdirektorijuu kojem se nalazipoznatadatoteka
jednostavnonavodenjemnjenogimena. Ilimoepokazivatina datoteku u poddirektoriju
poznatogdirektorija.
Opcenitose jedan direktorijuzimaza radni i metode koje trae datoteke cinitce to u
odnosu na taj direktorij. Uobicajenoje da to bude direktorijizkojeg zapocinjete
izvravatiaplikaciju.
Objekt tipa java.io.File moebitiimedirektorijaisto kao i imedatoteke.

Napomena za C programere
Primijetiteda objekt tipa File nijeisto to i file handle. Postojanjetakvogobjekta nije
ekvivalentnopostojanjustvarnedatoteke na disku. Postoje metode kojimamoete
utvrditida lidani File objekt zaistareferencirastvarnudatoteku iline (metoda exists
() ).

Konstruktori klase File


Trisu konstruktoraza klasu File . Svakiuzimaneku varijacijuimenadatoteke kao
argument. Najjednostavnijije
public File(String path)

Ovdje je path naprosto String koji sadripotpuniilirelativniput do datoteke, napisan


na istinacinkao za operacijskisustavracunala. Na primjer:
File f1 = new File("ulaz.txt");
File f2 = new File("/etc/passwd");

Ako elite, moeteput do datoteke odvojitiod njenogimenakoristecisljedeci


konstruktor:
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");

Na kraju, imamoi konstruktor


public File(File dir, String name)

koji se ponaa kao i prethodni, alije dir ovdje objekt tipa File , a ne naprosto String .
Neke metode u drugimklasamatakoder vracajuobjekt tipa File , na primjermetode iz
klase java.awt.FileDialog . Takvice objektipotovatisve konvencijeoperacijskog
sustavana kojem se aplikacijaizvrava.

Metode klase File


Kad jednomimateobjekt tipa File , postojimnogostvarikoje o njemumoetepitatii
koje s njimmoeteuciniti.
public String getName ()

Elementarnopitanjeo datotecije ono o njenomimenu. Ime cete doznatipomocumetode


getName () koja ne uzimanikakveargumente, a vraca String koji sadrieksterno ime
datoteke (bez puta). Na primjer, dobit cete "file1" umjesto"/math/vedris/
file1".
public String getPath ()

Metoda getPath () vraca a String koji sadriput do datoteke. Bitce relativanili


apsolutan, 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 forma


zavisnao operacijskomsustavui maini.
public String getParent ()

Metoda getParent () vraca String koji sadriimejedinstvenognadredenog


direktorijau odnosu na onaj u kojem se datoteka nalazi, ilinull ako je vec dosegnutvrh
hijerarhije.
public boolean exists() throws SecurityException

Metoda exists() naznacujeda liodredena datoteka postojina mjestugdje je


ocekujete.
public boolean canWrite () throws SecurityException

Metoda canWrite () daje odgovor da liimatepravo pisanjau datoteku. To nijeloe


provjeritiprije nego stvarnopokuatineto upisati.
public boolean canRead () throws SecurityException

Metoda canRead () daje odgovor da liimatepravo citanjaizdatoteke. Dobro ju je


koristitiprije stvarnogpokuaja 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 pravi


datumdugacka, a procedura ovisnao platformi, to treba koristitiuglavnomza usporedbu
vremenazadnjepromjenedvajurazlicitihdatoteka.
public long length() throws SecurityException

Metoda length() daje velicinudatoteke u byteovima.


public boolean mkdir()

Metoda mkdir() pokuavakreiratidirektorijsa zadanimimenom. Ako uspije, vratitce


true , inace false .
public boolean mkdirs() throws SecurityException

Metoda mkdirs() za dano imekreira ne samo jedan, nego sve potrebne nadredene
direktorijekoji cineput do datoteke. Ako sva kreiranjauspiju, vratitce se true , inace
false (cak ako su neka kreiranjai uspjela).
public boolean renameTo (File destination ) throws SecurityException

Metoda renameTo () pokuavapreimenovatidatoteku. Na primjer, f1.renameTo (f2)


pokuavapreimenovatif1 u f2. To moeznacitii premijetanjeu drugidirektorijako
imenatako naznacuju. Ako f2 vec postoji, bit ce prebrisanasa f1 (pod uvjetomda imate
odgovarajucedozvole). Ako preimenovanjeuspije, vraca se true , inace false .
public String[] list() throws SecurityException

Metoda list() vraca polje stringovakoji sadre imenadatoteka u navedenom


direktoriju. Korisnaje za procesiranjesvihdatoteka unutardirektorijaodjednom.

public String[] list(FilenameFilter filter) throws


SecurityException

Ova varijantametode list() ciniisto to i prethodna, alimoetekoristitiobjekt klase


koja implementirasucelje FilenameFilter (pogledajtepoglavljeo tome) za filtriranje
imenadatoteka.
public boolean delete() throws SecurityException

Metoda delete() pokuavaizbrisatidatoteku na koju se odnosi. Vraca true ako je


datoteka postojalai sad je izbrisana, inace false .
Klasa File sadrii uobicajenemetode equals(), hashCode () i toString () koje se
ponaajutocno onako kao to biste ocekivali. Ne sadriposebnu metodu clone().

Primjeri metoda iz klase File


Sljedeciprogramcita imenadatoteka s komandnelinijei vraca razneinformacijeo njima,
koristecimetode izklase File .
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 {

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 .html
getPath : ../html/TricksterApplet .html
getAbsolutePath : /math/vedris/public_html/java/classes /../html/
TricksterApplet .html
getCanonicalPath : /math/vedris/public_html/java/html/
TricksterApplet .html
getParent : ../html
TricksterApplet .html is writable .
TricksterApplet .html is readable .
TricksterApplet .html is a file.
TricksterApplet .html is not an absolute path.
Last Modified 1005656988000
TricksterApplet .html is 151 bytes.
%

Klasa FileDialog
Klasa java.awt.FileDialog je podklasa od java.awt.Dialog koja se koristiza
otvaranjeilispremanjedatoteka. Ona korististandardnedijalogeza open i save koji vec
postoje na racunalu. Ne dodajete joj komponentei ne brinetese o tome kako je
implementiranainterakcijas korisnikom. Jednostavnodobijeterezultatkoji ce bitiimei
direktorijdatoteke. Buducida se appletine moguoslonitina to da imajudostup u file
system, ova je klasa korisnauglavnomu aplikacijama.
Trisu koraka potrebna da biste koristiliFileDialog :

1. Kreiratinovi FileDialog
2. UcinitiFileDialog vidljivim
.
3. Odabrati imedirektorijai imedatoteke.
Novi objekt tipa FileDialog kreiratepomocukonstruktora:
public FileDialog (Frame parent, String title, int mode)

Okvir Frame je roditeljdijaloga. To ce obicnobitiglavniprozor aplikacije, appletov


okvirilinajistaknutijiprozor aplikacije. Takoder moetenaprosto kreriratii novi Frame .
Argumenttitle je naslovza na FileDialog , obicnoneto kao "Please choose the file
to open:" Nadaljue, mode je jedna od dvijemnemonickihkonstanti, FileDialog .LOAD
iliFileDialog .SAVE . Prvu cete koristitiako eliteda korisnikodabere datoteku koju ce
otvoriti, a druguako eliteda odabere datoteku u koju ce spremitipodatke. Tipican
primjerizgledaobi ovako:
FileDialog fd = new FileDialog (new Frame(), "Please choose a
file:", FileDialog .LOAD);

Konacno, ucinitcete FileDialog vidljivimna istinacinkao i drugekomponente.


Proslijeditcete true njegovojmetodi setVisible () koju je naslijedioizklase
java.awt.Component .
fd.setVisible (true);

Odavde na dalje operacijskisustavpreuzimakontrolunad interakcijoms korisnikomsve


dok on ne odabere datoteku iliizadeizdijaloga. Va programce ovdje statii cekati da
korisnikodabere datoteku. Kad on to ucini, dijalogce nestatis ekrana i va programce
se nastaviti. Tada cete ustanovitito je korisnikodabrao, tako da pozovetemetode
getDirectory () i getFile () . Iskoristiteova dva stringada biste kreiralinoviobjekt
tipa File . 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 korisnikotkae spremanje, obje metode, getDirectory () i getFile () vracaju


null. Buditesigurnida ste provjerilitu mogucnost.

Klasa RandomAccessFile
Pomocuklase java.io.RandomAccessFile pristupase datotekamakoje podravaju
slucajnipristup. One se mogucitatiilise u njihmoepisatipoceviod odredene pozicije
bytea u datoteci. Tu pozicijuspecificirapokazivacdatoteke (file pointer).
Dva su konstruktorau ovoj klasi:

public RandomAccessFile (String name, String mode) throws


IOException
public RandomAccessFile (File file, String mode) throws IOException

Prviargumentje datoteka kojoj elitepristupiti. Drugije nacinpristupa. To moebiti


string"r" za read-only ili"rw" za pristupkoji omogucujecitanjei pisanje. Java ne
podravawrite only pristup. Na primjer,
RandomAccessFile raf = new RandomAccessFile ("ulaz.txt", "r");

Metode getFilePointer (), length(), i seek() omogucujuvamda utvrditei


modificiratepozicijuu datotecina kojoj se citanjei pisanjedogada. Pokuaj traenja
pozicijeizakraja datoteke pomaknutce pointerna kraj. Pokuaj pisanjana kraj datoteke
proiritce datoteku, a pokuaj citanjas kraja datoteke izbacitce EOFException .
public native long getFilePointer () throws IOException
public native void seek(long pos) throws IOException
public native long length() throws IOException

Za citanjei pisanjekoristese metode koje rade identicnokao i metode iz


DataInputStream i DataOutputStream , osimto izmedupozivametoda za citanjei
pisanjemoetezadatipozicijuod koje citateilipiete.
public native int read() throws IOException
public int read(byte[] input, int offset, int length) throws
IOException
public int read(byte[] input) throws IOException
public final void readFully (byte[] input) throws IOException
public final void readFully (byte[] input, int offset, int length)
throws IOException
public native void write(int b) throws IOException
public void write(byte[] data) throws IOException
public void write(byte[] data, int offset, int length) throws
IOException
public final boolean readBoolean () throws IOException
public final byte readByte () throws IOException
public final int readUnsignedByte () throws IOException
public final short readShort () throws IOException
public final int readUnsignedShort () throws IOException
public final char readChar () throws IOException
public final int readInt () throws IOException
public final long readLong () throws IOException
public final float readFloat () throws IOException
public final double readDouble () throws IOException
public final String readLine () throws IOException
public final String readUTF () throws IOException
public
public
public
public
public
public
public
public
public

final
final
final
final
final
final
final
final
final

void
void
void
void
void
void
void
void
void

writeBoolean (boolean b) throws IOException


writeByte (int b) throws IOException
writeShort (int s) throws IOException
writeChar (int c) throws IOException
writeInt (int i) throws IOException
writeLong (long l) throws IOException
writeFloat (float f) throws IOException
writeDouble (double d) throws IOException
writeBytes (String s) throws IOException

public final void writeChars (String s) throws IOException


public final void writeUTF (String s) throws IOException

Konacno, imajo nekolikoraznihmetoda:


public final FileDescriptor getFD() throws IOException
public int skipBytes (int n) throws IOException
public native void close() throws IOException

Sucelje FilenameFilter
Sucelje java.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 je
primjerklase 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"

OK
Java source datoteka
% java JavaFilterTest "." "JavaFilter .class"
Nije Java source datoteka
%

Ime ne mora bitijedinikriterijfiltriranja


. Moete testiratidatumzadnjepromjene, dozvole,
velicinui drugo. Na primjer, sljedecaaccept() metoda testirada lidatoteka zavrava
ekstenzijom.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 apstraktnenadklaseklasamakoje
obavljajucitanjei pisanjepodataka zasnovanihna znakovima(characters). Znacajnesu
za konvertiranjeznakovaizmedurazlicitihznakovnihsustava(character sets).
Ulaznii izlaznistreamovisu opcenitozasnovanina byteovima, no klase Reader i Writer
su zasnovanina znakovimakoji moguimatirazlicitevelicine, ovisnoo sustavuznakova.
Na primjerASCII i ISO Latin-1 koristeznakovevelicinejedan byte. Unicodekoristi
znakoveod dva bytea. UTF-8 koristiznakovevarijabilneduljine, od jednogdo tri bytea.
Reader i Writer znajukako rukovatitimznakovnimsustavimakao i mnogimdrugim.

Klasa Reader
Metode izklase java.io.Reader namjernosu napravljenetako da budu slicne
metodamaizklase java.io.InputStream . Medutim, umjestoda rade s byteovima,
one rade sa znakovima(char ).
Osnovna read() metoda cita pojedinacniznak (koji moezauzimatiod jednogdo cetiri
bytea, ovisnoo znakovnomsustavu) i vraca ga kao intizmedu0 i 65535. Ako naidena
kraj strama, vraca -1.
public int read() throws IOException

Moete ucitatii vieznakovaodjednomu polje znakova. Metode koje to rade vracaju


broj uspjenoucitanihznakovaili-1 ako naiduna kraj streama.
public int read(char[] text) throws IOException
public abstract int read(char[] text, int offset, int length)
throws IOException

Sve read() metode blokirajuse ako nijedostupannekiinput, ako se pojaviI/O error ili
ako naiduna kraj streama.
Moete preskocitiodredenibroj znakovapomocumetode skip(). Ona ce se takoder
blokiratiako nemadostupnoginputa. Vraca broj preskocenihznakovaili-1 ako je naila
na kraj streama.
public long skip(long n) throws IOException

Metoda ready() vraca true ako je Reader spremanza citanje, false inace. Opcenito
ce to bitiako pripadnistreamimadostupnihpodataka.
public boolean ready() throws IOException
Reader moeiline mora podravatimarkiranjei resetiranje. Metoda markSupported ()
vraca true ako pripadnistreampodravamarkiranjei resetiranje, false inace.
public boolean markSupported ()
public void mark(int readAheadLimit ) throws IOException
public void reset() throws IOException

Konacno, metoda close() zatvarastreami otputa resurse koji su s njimpovezani.


public abstract void close() throws IOException

Klasa Writer
Metode izklase java.io.Writer namjernosu napravljenetako da budu slicne
metodamaiz java.io.OutputStream . Medutim, umjestoda rade s byteovima, one
rade sa znakovima(char ).
Osnovna write() metoda ispisujepojedinacniznak od dva bytea s vrijednocuizmedu
0 i 65535. Vrijednostse uzimaizdva niabytea argumentac (preostaladva viabytea se
ignoriraju). Podklase koje eleefikasnopisatiznakovemorat ce prekritiovu metodu.
public void write(int c) throws IOException

Moete takoder ispisatipolje znakova, podpolje znakova, stringilisubstring.


public void write(char[] text) throws IOException
public abstract void write(char[] text, int offset, int length)
throws IOException
public void write(String s) throws IOException
public void write(String s, int offset, int length) throws
IOException

Kao sviizlaznistreamovi, i ovice modabitibufferiranina razinioperacijskogsustava.


Ako elitesamiodreditikad ce se ispisizvriti, pozovitemetodu flush().
public abstract void flush() throws IOException

Konacno, metoda close() zatvarastreami otputa resurse koji su s njimpovezani.


public abstract void close() throws IOException

Klasa InputStreamReader
Klasa java.io.InputStreamReader sluikao most izmedustreamovabyteovai
streamovaznakova. Cita byteoves ulaznogstreamai prevodiihu znakoveu skladusa
zadanimznakovnimsustavom.
Znakovnisustav(encoding) moese zadatiu konstruktoruilise moeprihvatitidefault
sustavs racunala.
public InputStreamReader (InputStream in)
public InputStreamReader (InputStream in, String encoding ) throws
UnsupportedEncodingException

Na primjer, da biste prikljuciliInputStreamReader na System.in sa pretpostavljenim


znakovnimsustavom(najcece ISO Latin-1), stavilibiste:
InputStreamReader isr = new InputStreamReader (System.in);

S drugestrane, ako elitecitatidatoteku koja je bilanapisanau fontuMacintoshSymbol,


moeteto ucinitiovako:
FileInputStream fis = new FileInputStream ("symbol.txt");
InputStreamReader isr = new InputStreamReader (fis, "MacSymbol ");

Metoda getEncoding () vraca stringkoji sadriimeznakovnogsustavakoji se trenutno


koristi.
public String getEncoding ()

Ostale metode prekrivajumetode iz java.io.Reader , alise, izprogramerove


perspektive, ponaajuna istinacinkao i one.
public
public
public
public

int read() throws IOException


int read(char c[], int off, int length) throws IOException
boolean ready() throws IOException
void close() throws IOException

Klasa OutputStreamWriter
Klasa java.io.OutputStreamWriter povezujeizlaznebyte streamovei znakovne
streamove. Ispisujebyteovena pripadniizlaznistreamnakon prevodenjaznakovau
skladusa zadanimznakovnimsustavom.

Znakovnisustavmoese zadatiu konstruktoruilise moeprihvatitidefault sustavsa


platforme.
public OutputStreamWriter (OutputStream out, String enc) throws
UnsupportedEncodingException
public OutputStreamWriter (OutputStream out)

Na primjer, da biste prikljuciliOutputStreamWriter na System.out sa


pretpostavljenimznakovnimsustavom(najcece ISO Latin-1), stavilibiste:
OutputStreamWriter osw = new OutputStreamWriter (System.out);

S drugestrane, ako elitepisatiu datoteku u MacintoshSymbolfontu, moeteto uciniti


ovako:
FileOutputStream fos = new FileOutputStream ("symbol.txt");
OutputStreamWriter osw = new OutputStreamWriter (fos, "MacSymbol ");

Metoda getEncoding ()vraca stringkoji sadriimeznakovnogsustavakoji se trenutno


koristi.
public String getEncoding ()

Ostale metode prekrivajumetode iz java.io.Writer , alise, izprogramerove


perspektive, ponaajuna istinacinkao i one.
public void
public void
IOException
public void
IOException
public void
public void

write(int c) throws IOException


write(char c[], int offset, int length) throws
write(String s, int offset, int length) throws
flush() throws IOException
close() throws IOException

Dostupne kodne stranice

Ime
8859_3
8859_4
8859_5
8859_6
8859_7
8859_8
8859_9
Big5
CNS11643
Cp037
Cp273
Cp277
Cp278
Cp280
Cp284
Cp285
Cp297
Cp420
Cp424
Cp437
Cp500
Cp737
Cp775
Cp850
Cp852
Cp855
Cp856
Cp857
Cp860
Cp861
Cp862
Cp863
Cp864
Cp865
Cp866
Cp868
Cp869

Znakovnisustav
ISO 8859-3 (LatinExtended-B) Pinyin, Sami, Croatian, and a few
others
ISO 8859-4 (LatinExtended-C)
ISO 8859-5 Latin/Cyrillic
ISO 8859-6 Latin/Arabic
ISO 8859-7 Latin/Greek
ISO 8859-8 Latin/Hebrew
ISO 8859-9 Latin/Turkish
The Big5 encodingfor Chinese
Chinese
EBCDIC AmericanEnglish
IBM273
EBCDIC Danish/Norwegian
EBCDIC Finnish/Swedish
EBCDIC Italian
EBCDIC Spanish
EBCDIC UK English
EBCDIC French
EBCDIC Arabic1
EBCDIC Hebrew
the originalDOS IBM PC characterset, essentiallyASCII witha
few extra charactersfor drawinglinesand boxes
EBCDIC Flemish/Romulsch
DOS Greek
DOS Baltic
DOS Latin-1
DOS Latin-2
DOS Cyrillic
IBM856
DOS Turkish
DOS Portuguese
DOS Icelandic
DOS Hebrew
DOS CanadianFrench
DOS Arabic
IBM865
IBM866
EBCDIC Arabic
DOS modernGreek

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
WindowsWestern European(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
Zapf Dingbats
MacGreek
The MacintoshmodernGreek characterset
MacHebrew
The MacintoshHebrew characterset
MacIceland
The MacintoshIcelandiccharacterset
MacRoman
The MacintoshRomancharacterset

MacRomania
MacSymbol
MacThai
MacTurkish
MacUkraine
SJIS
UTF8
Unicode
UnicodeBig

The MacintoshRomaniancharacterset
The Symbolfont(includesa completeGreek alphabetinplace of the
usualRomanletters)
The MacintoshThaicharacterset
The MacintoshTurkishcharacterset
The MacintoshUkrainiancharacterset
WindowsJapanese
UCS TransformationFormat, 8-bit form
NormalUnicode
Unicodewithbig-endianbyte order

Primijetiteda to to Java zna raditis odredenimznakovnimsustavomjo ne znacida na


racunaluautomatskipostoje fontovikoji su potrebnida bi se znakoviiztog sustava
prikazali.

Klasa FileWriter
Klasa java.io.FileWriter sluiza pisanjetekstualnihdatoteka koristeci
pretpostavljeniznakovnisustavi velicinuspremnikas platforme. Ako elitepromijenitite
vrijednosti, konstruirajteOutputStreamWriter i prikljucitega na FileOutputStream .
Ova klasa nemavlastitihmetoda (samo naslijedene), a deklariranisu samo konstruktori.
public FileWriter (String fileName ) throws IOException
public FileWriter (String fileName , boolean append) throws
IOException
public FileWriter (File file) throws IOException
public FileWriter (FileDescriptor fd)

Pogledajmoprimjer:
FileWriter fw = new FileWriter ("izlaz.txt");

Klasa FileReader
The java.io.FileReader sluiza citanjetekstualnihkoristecipretpostavljeniznakovni
sustavi velicinuspremnikas platforme. Ako elitepromijenitite vrijednosti, konstruirajte
InputStreamReader i prikljucitega na FileInputStream . Ova klasa nemavlastitih
metoda (samo naslijedene), a deklariranisu samo konstruktori.
public FileReader (String fileName ) throws FileNotFoundException
public FileReader (File file) throws FileNotFoundException
public FileReader (FileDescriptor fd)

Pogledajmoprimjer:

FileReader fr = new FileReader ("36.html");

Klasa BufferedReader
Klasa java.io.BufferedReader je podklasa od java.io.Reader koju moete
ulancitis drugomReader klasomzbog bufferiranjaznakova. To omoucujeefikasnije
citanjeznakovai linija.
Klasa BufferedReader takoder je znacajnai zbog svoje readLine () metode koja
omogucujecitanjeteksta linijupo liniju.
Kod svakog citanjas nebufferiranogReader a, obavljase i odgovarajucecitanjes
pridruenogulaznogstreama. Zato nijeloa ideja prikljucitiBufferedReader na svaki
Reader 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)

Jedinanova metoda u toj klasije readLine ():


public String readLine () throws IOException

Ona vraca String koji sadrilinijuteksta iztekstualnedatoteke. Nizovi\r, \n, i \r\n


su pretpostaljeniznakoviza prijelazu noviredak i nisuukljuceniu vraceniString . U
sljedecemprimjerucita se tekstualnadatoteka, redak po redak i ispisujese na
System.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 );

} // 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 doputa markiranjei resetiranje, barem do duljinespremnika.


public boolean markSupported ()
public void mark(int readAheadLimit ) throws IOException
public void reset() throws IOException

Konacno, BufferedReader prekrivanekolikometoda izsvoje nadklase Reader , alise


nacinnjihoveuporabe uopce ne mijenja.
public
public
public
public
public

int read() throws IOException


int read(char c[], int off, int length) throws IOException
long skip(long n) throws IOException
boolean ready() throws IOException
void close() throws IOException

Klasa LineNumberReader
Klasa java.io.LineNumberReader je podklasa od java.io.BufferedReader koja
vodiracunao tome s koje linijetrenutacnocitate. Ima sve metode kao i
BufferedReader ukljucjujcii readLine () . Ima dva konstruktorai dvijenove metode,
getLineNumber () i setLineNumber () :
public LineNumberReader (Reader in)
public LineNumberReader (Reader in, int size)
public void setLineNumber (int lineNumber )
public int getLineNumber ()

Metoda setLineNumber () ne mijenjafilepointer. Ona samo mijenjavrijednostkoju


vraca getLineNumber (). To vam, na primjer, omogucujeda pocnete brojitiod -5 ako
znateda imaest linijaheadera za koje ne eliteda udu u numeraciju.
U sljedecemprimjerucita se tekstualnadatoteka, redak po redak i ispisujese na
System.out no ispred svake 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

Klasa java.io.BufferedWriter je podklasa od java.io.Writer koju moete


ulancitis drugomWriter klasomzbog bufferiranjaznakova. To omogucujeefikasnije
ispisivanjeteksta.
Svakiput kad piete na nebufferiraniWriter , obavljase i pisanjena pridrueniizlazni
stream. Zato nijeloa ideja prikljucitiBufferedWriter na svaki Writer cije operacije
pisanjasu skupe, a ne trae trenutacniodziv. Pogledajmotaj postupak npr. za
FileWriter :
BufferedWriter bw = new BufferedWriter (new FileWriter ("izlaz.txt"))
;

There are two constructors, one witha defaultbuffersizeof 8192 characters, and one
that lets you specifythe buffersize:
public BufferedWriter (Writer out)
public BufferedWriter (Writer out, int size)

U ovoj klasinova je metoda newLine () koja ispisujestringza zavretaklinije. On je


ovisano platformipa tako imamo\n za Unix, \r za Mac, \r\n za Windows.
public String newLine () throws IOException

Konacno, BufferedWriter prekrivanekolikometoda izsvoje nadklase Writer ; ali


nacinnjihoveuporabe ostaje isti:
public void
public void
public void
IOException
public void
public void

write(int c) throws IOException


write(char c[], int off, int length) throws IOException
write(String s, int offset, int length) throws
flush() throws IOException
close() throws IOException

Klasa PrintWriter
Klasa java.io.PrintWriter je podklasa od java.io.Writer koja omogucuje
koritenjepoznatihmetoda print() i println (). Vrlo je slicnaklasi
java.io.PrintStream . Glavnarazlikaje u pravilnomrukovanjuviestrukimbyteovima
i znakovnimsustavimakoji nisuISO Latin-1. Drugarazlikaje u tome to se automatski
ispis(flushing) obavljatek kad se pozove neka od println () metoda, a ne svakiput
kad se pojaviznak za noviredak.
Tendencijaproizvodacaje izbacitiizuporabe PrintStream i umjestonjegakoristiti
PrintWriter , no to bi dovelodo pucanjavelikekolicinevec postojecegkoda.
public
public
public
public

PrintWriter (Writer out)


PrintWriter (Writer out, boolean autoFlush )
PrintWriter (OutputStream out)
PrintWriter (OutputStream out, boolean autoFlush )

public void flush()

public void close()


public boolean checkError ()
protected void setError ()
public
public
public
public
public

void
void
void
void
void

write(int c)
write(char buf[], int offset, int length)
write(char buf[])
write(String s,
write(String s)

public
public
public
public
public
public
public
public
public

void
void
void
void
void
void
void
void
void

print(boolean b)
print(char c)
print(int i)
print(long l)
print(float f)
print(double d)
print(char s[])
print(String s)
print(Object obj)

public
public
public
public
public
public
public
public
public
public

void
void
void
void
void
void
void
void
void
void

println ()
println (boolean x)
println (char x)
println (int x)
println (long x)
println (float x)
println (double x)
println (char x[])
println (String x)
println (Object x)

Jedanaesto predavanje threadovi


Multitasking i multithreading to je thread ? - kako Java koristi threadove ? klase
threadova jednostavni thread viestruki threadovi imenovanje threadova
prioriteti threadova metoda sleep() sinkronizacija : problem sinkronizacija :
nekoliko pokuaja rjeenja - kljucna rijec synchronized sinkroziniranje na
objektima primarni thread grupe threadova threadovi demoni ustupanje
kontrole spajanje threadova sucelje Runnable animacija pravovremenost
titranje slike pokretanje i zaustavljanje animacije viestruke nezavisne animacije

Multitasking i multithreading
Prvikompjuterimoglisu obavljatizadace samo jednupo jednu. Svi su se programi
izvravalisekvencijalno, jedan po jedan i svakije zauzimaosve resurse racunala. Takav
se nacinrada nazivabatch obrada. To je efikasannacinza postizanjemaksimalne
iskoristivostiskupihracunalajer se gotovosve CPU vrijemetroina stvarnuobradu.
Medutim, batch obrada je nepovoljnaako programikoji traju nekolikosekundimoraju
cekati na zavretakprogramaod nekolikodana.
Time sharing operacijskisustavisu izmiljenikako bi se omoguciloda vieljudi
istodobnokoristijedno racunalo. Operacijskisustavovdje upravljaraspodjelomvremena
izmedurazlicitihprogramakoji se istodobnoizvravaju.
Jednomkad su sustaviomogucavalirazlicitimkorisnicimaistodobnoizvravanje
programa, preostao je jo samo malikorak do toga da istikorisnikizvravaistodobno
vieprograma(multitasking). Svakiaktivniprogram, uobicajenoje reci proces, imaoje
svoj vlastitimemorijskiprostor, svoj skup varijabli, svoj stack i heap i tako dalje. Jedan
process je mogaolansiratidrugiprocess, alinakon toga svakiod njihse ponaao manjeili
vienezavisno. Mehanizmikao to je pozivudaljenihprocedura (remote procedure call,
RPC) razvijenisu kako bi omoguciliprocesimamedusobnuinterakciju, alitakva je
interakcijabilaskupa i komplicirana. Takvo stanje potrajaloje nekihdvadesetak godina.
Medutim, nisusamo korisniciti koji imajupotrebu obavljativieposlovaistodobno.
Mnogiprogramipo svojoj su priroditakoder takvi. Web browser na primjer, moe
ispisivatidatoteku u pozadinidok istodobnoskida stranicuu jednomprozorui formatira
je kako sadraj pristie. Sposobnost individualnogprogramada radi vieod jedne stvari
istodobnonajefikasnijese implementirakroz koncept threadova(multithreading).

to je thread?

Thread (u prijevodu: nit, konac, trag, staza) moemodefiniratikao tok izvodenja


operacijakoji se dogada nezavisnood procesa ilidogadaja u okolini. Thread je poput
klasicnogprogramakoji zapocinjeu tocki A i zavravau tocki B. On nemau sebi petlju
koja ocekuje dogadaje vec se izvravane gledajucito se dogada oko njega. Bez
threadovacijelibi programpovremenomorao stajatizbog nekog procesa koji intenzivno
koristiCPU ilizbog neke beskonacnepetlje, stavljeneu njeganamjernoilipogrekom.
Koncept threadovaomogucujeda zahtjevniprocesi ne ometajuostale procese u
njihovomizvravanju.
Pokazujese da je implementiranjethreadovasloenijeod implementiranjamultitaskingau
operacijskomsustavu. Razlogrelativnojednostavnomimplementiranjumultitaskingaje to
su programiu praviluizoliranijedniod drugih. Threadoviu jednomprogramu, medutim,
nisumedusobnoizoliranii morajuvoditiracunajedan o drugome. Na primjer, ako za
vrijemedok se u jednomthreaduispisujenekitekst, orisniku drugomthreaduobrie dio
tog istogteksta, nastajeproblem: to u tom slucajutreba bitiispisano?
Okruenjakoja, poput Jave, podravajuthreadoveimajumehanizamsinkronizacije.
Threadovimaje, naime, omogucenoprivremenozakljucavanjeresursa koje dijeles
drugimthreadovima, cimese osiguravaintegritetpodataka. Sinkronizaciju
, medutim, valja
koristitis mjeromjer ce prednostikoje donose threadovibitiponiteneako cijelisustav
bude cesto morao cekati dok se pojediniresurs ne otkljuca. Pravilniodabir objekata i
metoda koje treba sinkroniziratipripada vjetiniprogramiranjai osjecaj za njegastjece se
vjebom.

Kako Java koristi threadove?


Java aplikacijei appletisu po prirodithreadovski. Runtime okolinazapocinjeizvravanje
programasa main() metodomunutarjednogthreada. Garbage collection se obavljau
drugomthreadu. Screen updating se pojavljujeu trecemthreadu. Mogu se takoder
pojavljivatii drugithreadovi, uglavnomvezaniuz zadace koje obavljaapplet viewerili
web browser. Sve se to dogada bez eksplicitnogznanjaprogramera. Dio vremena
zanimatce vas samo ono to se dogada u primarnomthreadukoji sadri main() metodu
programa. Tada se ne moratenioptrerecivatikonceptomthreadova.
Ponekad, medutim, elitedodati svoje vlastitethreadovenekomappletuiliaplikaciji.
Najjednostavnijirazlogza to bio bi, na primjer, izdvojitiduga racunanjaod ostatka
programa. Ako elitepronacidesetmilijuntiprimbroj, ne eliteprisiljavatikorisnikada
ceka besposlendok racunaloobavljato traenje. Isto vrijedii za cekanje da nekiresurs
postane dostupan, recimovelikagrafickadatoteka koju skidate s mree. Svaka
vremenskizahtjevnaoperacijatrebalabi bitismjetenau zasebnithread.
Drugirazlogza koritenjethreadovaje ravnomjernaraspodjelamogucnostiracunala
izmedurazlicitihzadaca. Ako eliteiscrtavatislucajnepravokutnikena ekranu, svejedno
eliteostavitikorisnikumogucnostda komuniciras appletom. Ako se sav CPU troina
crtanje, to nece bitimoguce. Na natjecateljskim(preemptive) operacijskimsustavima
kao to je SolarisiliWindowsNT, korisnikmoeu slucajupotrebe, ako nitadrugo,
prekinutiaplikaciju. Na kooperativnim(cooperative) sustavimakao to je MacOs ili

Windows, to nece bitimoguceako se ne ucinireboot maine, a to je, naravno, loe.


Uporabomthreadovaomogucitcete da korisnickiunos dobije visokprioritet, a crtanje
slicicanizak. Tada ce korisnikmocizaustavitiapplet i bez gaenjaracunalana glavnom
prekidacu.

Klase threadova
U Javipostoje dva nacinada klasupretvorimou thread. Jedan je da je ucinimo
podklasomklase java.lang.Thread . Ako je naa klasa vec podklasa neke druge
klase, onda to, naravno, nece bitimoguce, pa cemo koristitidruginacin, a to je
implementiranjesucelja java.lang.Runnable .
Klasa Thread imatri glavnemetode koje se koristeza upravljanjethreadovima:
public native synchronized void start()
public void run()
public final void stop()

Metoda start() pripremathread za izvravanje. Metoda run() je ta koja obavlja


zadacunamijenjenuthreadu. Thread se normalnozavravakad ona zavri. Thread se
moezaustavitii pomocumetode stop(), alise taj nacinpokazao nesigurnimi zbog toga
je ova metoda deprecated (v. objanjenjau bibliotecipotprograma). Zbog istograzloga
deprecated su i metode suspend () i resume().
Metoda run() se ne pozivaeksplicitno. Ona ce, nakon to ste pozvalimetodu start()
bitiautomatskipozvanakad za to dode vrijeme.
Sucelje Runnable omogucujeuporabukoncepta threadovau klasamakoje ne mogubiti
podklase klase Thread . Ono deklarirasamo jednumetodu, run():
public abstract void run()

Ako za argumentkonstruktoraThread() supstituirateobjekt izklase koja implementira


Runnable , mocicete njegovurun() metodukoristitiumjestorun() metode izklase
Thread .

Jednostavni thread
Kad piete programkoji sadrithreadove, moetezamiljatida piete vierazlicitih
programaod kojihsvakiimasvoju run() metodu. Pogledajmoslucajkad je svakitakav
thread podklasa od java.lang.Thread . Sljedeciprogramje thread koji ispisuje
brojeve iod-10 do 9.
public class BytePrinter extends Thread {
public void run() {
System.out.println ("pocinjem !");

for (int b = -10; b < 10; b++) {


System.out.println (b);
}
System.out.println ("gotovo!");
}
}

Thread cete lansiratitako da ga proizvedeteinstanciranjemodgovarajuceklase, a zatim


pozovetenjegovustart() metodu. Na primjer, da bismoinstanciraliklasu
BytePrinter , postupitcemo ovako:
BytePrinter bp = new BytePrinter ();

Ova klasa imasamo pretpostavljenikonstruktorbez argumenata, alinemanikakvog


razlogada klase threadovanemajui drugacijekonstruktore, ba kao i bilokoje druge
klase.
Sad moetepozvatinjegovu start() metodu:
bp.start();

Jednomkad je start() metoda pozvana, izvravanjeprogeramase dijelina dva dijela.


Jedan dio CPU vremenakoristise za naredbe koje dolazeiza bp.start(), a drugidio
za izvravanjethreada bp. Ne moese unaprijedpredvidjetikoje ce naredbe bitiizvrene
prve. Najvjerojatnijeje da ce bitipomijeane. Thread bp ce se nastavitiizvravatisve
dok ne nastupijedan od sljedecihsedam uvjeta:
bp -ova run() metoda je zavrila.
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 nedostupniresurs
bp je istisnut(preempted) od nekog drugogthreada.
Jednomkad programskakontroladosegnekraj bp-ove run()

metode, thread se gasi.


Ne moetega ponovo pokrenuti, alimoetekreiratinovuinstancuodgovarajuceklase i
njupokrenuti.

Viestruki threadovi
Sljedeciprogramlansiratri threada tipa BytePrinter :
public class ThreadsTest {
public static void main(String args[]) {
BytePrinter bp1 = new BytePrinter ();
BytePrinter bp2 = new BytePrinter ();
BytePrinter bp3 = new BytePrinter ();
bp1.start();

bp2.start();
bp3.start();
}
}

Redosljedispisakoje proizvodiovaj programovisio implementacijiiuglavnomje


nepredvidljiv
. Moe izgledatiotprilikeovako:
% javac BytePrinter .java
% javac ThreadsTest .java
% java ThreadsTest
pocinjem !
-10
. . .
-4
pocinjem !
pocinjem !
-10
-10
-9
. . .
9
gotovo!
3
. . .
9
gotovo!
-3
-2
. . .
9
gotovo!
%

Imenovanje threadova
Cesto je korisnodati razlicitimthreadovimaiste klase imenapo kojimaihmoete
razlikovati. Sljedecikonstruktorklase Thread vamto omogucuje:
public Thread(String name)

Uobicajenoga je pozvatiizkonstruktorapodklase s kojom radimo, kao to je ucinjenou


sljedecemprimjeru:
public class NamedBytePrinter extends Thread {
public NamedBytePrinter (String name) {
super(name);
}
public void run() {
System.out.println (this.getName () + ": pocinjem !");

for (int b = -10; b < 10; b++) {


System.out.println (this.getName () + ": " + b);
}
System.out.println (this.getName () + ": gotovo!");
}
}

Metoda getName () izklase Thread vratitce imethreada. Sljedeciprogramomogucuje


razlikovanjeispisanihredaka 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 NamedThreadsTest
Frank: pocinjem !
Frank: -10
. . .
Frank: -4
Mary: pocinjem !
Chris: pocinjem !
Mary: -10
. . .
Mary: 9
Mary: gotovo!
Chris: 3
. . .
Chris: gotovo!
Frank: -3
. . .
Frank: 9
Frank: gotovo!
%

Prioriteti threadova
Nisu svithreadovijednako vani. Ponekad je potrebno nekomthreadudodijelitivie
vremenanego drugom. Threadovikoji komunicirajus korisnikomtrebajuimativrlovisok

prioritet. S drugestrane, threadovimakoji obavljajuracunanjau pozadinitreba dodijeliti


nizakprioritet.
Prioritetthreada zadaje se cijelimbrojem izmedu1 i 10. Deset je najviiprioritet, jedan je
najnii. Normalniprioritetje pet. Threadovis viimprioritetomdobit ce vieCPU
vremena.
Napomena: primijetiteda je ovo izravnosuprotnonacinuna koji se prioritetidefinirajuu
UNIXu, gdje vecibroj oznacavamanjiprioritet.
Zbog udobnosti, klasa Thread definiratri mnemonickekonstante, Thread.MAX_
PRIORITY , Thread.MIN_PRIORITY i Thread.NORM_PRIORITY koje moetekoristiti
umjestonumerickihvrijednosti.
Prioritetthreada zadajetepomocumetode setPriority ():
setPriority (int newPriority )

Sljedeciprogramdodjeljujethreadovimafrank , mary i chris razliciteprioritete. Iako je


chris pokrenutzadnji, vjerojatnoce bitigotovprvi, buducida muje dodijeljennajvii
prioritet.
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 MixedPriorityTest
Chris: pocinjem !
Chris: -10
. . .
Chris: 9
Chris: gotovo!
Mary: pocinjem !
Mary: -10
. . .
Mary: 9
Mary: gotovo!
Frank: pocinjem !
Frank: -10
. . .

Frank: 9
Frank: gotovo!
%

Metoda sleep()
Ponekad je brzinaizvrvanjaveca nego to elite. U tom slucajubit ce potrebno usporiti
izvravanjepojedinihthreadova. To se radi pomocumetode sleep():
public static void sleep(long millis) throws InterruptedException

Ovdje je millis broj milisekundikoji treba proci prije nego thread nastavis
izvravanjem
. Metoda sleep() moeodbacitijava.lang.InterruptedException
koju je potrebno uhvatitipa pozivove metode mora bitiunutartry-catch bloka. Na
primjer, ako elimoodgoditiizvravanjeza jednusekundu, stavilibismo:
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
}

Sinkronizacija: problem
Do sad smo promatralithreadovekoji se izvravajunezavisnojedan od drugoga. Ni
jedan thread nijemorao znatito rade ostali. Ponekad, medutim, threadovimorajudijeliti
podatke. U tom slucajuvanje osiguratida jedan thread ne promijenipodatke u vrijeme
dok ihdrugithread koristi. Klasicniprimjerje pristupdatoteci. Ako jedan thread pie u
datoteku u vrijemedok je drugithread cita, vjerojatnoje da ce ovaj drugithread dobiti
nekonzistentnepodatke. 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;
}

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 ponaatiposve nedeterministicki


. Nema pravilapo kojemubismomogli
predvidjetikakav ce bitiizlaz.
%
%
%
.
%

javac Counter .java


javac CounterThread .java
java CounterThread
. . ? ? ? . . .

Sinkronizacija: nekoliko pokuaja


rjeenja
Kljucnije problemu prethodnomprogramuto dva threada modificirajuattributeistog
objekta. Pri tome, redosljedmodificiranjaje neodreden.
Postojiviemogucihrjeenjaovog problema. Nisu, medutim, sva rjeenjadobra u svim
situacijama. Na primjer, jedno od najjednostavnijihi najizravnijihje ucinitiobjekt
nepromjenjivim(immutable), dakle ne dozvolitida se mijenjanakon to je jednom
konstruiran. Nepromjenjivostmoeteposticitako da sve attributeproglasiteza private ,
klasune snabdijetenikakvomsetter metodomi ne dozvolitenijednoj metodiizklase
(osimkonstruktorima) da mijenjajuvrijednostiatributa. Medutim, takvo rjeenjeje
neprikladnoza na problemjer metoda count() mora mijenjatiatributi.
Slicnustvar moeteucinititako da attributedeklariratekao final . Na taj nacinonise ne
mogumijenjatinakon to je objekt konstruiran. No to je takoder neprikladno.
U naemprimjerubilobi jednostavnoucinitivarijablui lokalnomumjestoda bude atribut:
public class Counter {
public void count() {
int i = 0;
int limit = 100;
while (i++ != limit)
}

System.out.println (i);

Timeto smo i ucinililokalnomvarijablom, svakithread koji pozivametodu count() na


tom objektu dobit ce svojuvlastituvarijablui. Svakiput kad se metoda pozove, zasebni
stack se konstruiraza njenevarijablei argumente. Razlicitipozivimetode ne dijele
varijable.
Medutim, semantikaprogramavienijeista. Sada svakithread broji od 0 do 100. Ako je
to bilanamjera, rjeenjeje dobro, aliako smo htjelida prvithread broji od 0 do 100, a
drugiod 101 do 200, rjeenjene valja.
Poneto opcenitijerjeenjekoje kombiniraprethodnadva bilobi kopirativrijednost
atributau lokalnuvarijablu, a zatimmijenjatisamo nju, ostavljajuciatributnepromijenjen
unutarmetode. 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 referiramopomocu


kljucnerijecithis .
Ovaj trik je uglavnomkoristankad ne trebate vratitipromijenjenuvrijednostvarijable
natragu atributnakon to je metoda zavrila. Sljedeca varijantasacuvatce stanje, alije
jo uvijekpodlonanekim, 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 nego originalniprimjerjer ce u 99% slucajevaraditidobro i


problemce bitigotovonemoguceuocitiako ga se ne primijetiu izvornomkodu.

Kljucna rijec synchronized


Java vamomogucujeda pod odredenimuvjetimamoetegarantiratida neka metoda nece
istodobnobitipozvanaod viethreadova. Ostalithreadovimorat ce cekati dok prvi
thread ne zavri. U meduvremenuonistoje blokirani.
Ovo se postieprimjenomkljucnerijecisynchronized 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, sinkroniziranemetode su tri do deset puta sporijeod ekvivalentnih
nesinkroniziranih
. Sinkronizacijatakoder ne otklanjaautomatskisve pogreke koje
proizlazeizthreadovskognacinaizvravanja.

Sinkroniziranje na objektima
Svakomobjektu dodijeljenje tzv. monitor. Kad kljucnurijec synchronized primjenite
na neku metodu, dobijetemonitorodredenogobjekta, odnosno zakljucavatega. Dok
god jedan thread posjeduje monitor, odnosno lokot nekog objekta, nijedan drugithread
ne moedobititaj lokot. (Drugithreadovice, eventualnomocidobitilokote drugih
objekata iziste klase).
Kad koristitekljucnurijec synchronized kako biste specificiralida je neka metoda
sinkronizirana
, zakljucavateodredeniobjekt kojemuta metoda pripada. (Statickemetode
mogutakoder bitisinkronizirane
. U tom slucajulokot se stavljana objekt izklase
java.lang.Class koji je pridruenklasivaegobjekta.) Kako postojisamo jedan
lokot za svakiobjekt, nijesamo sinkroniziranametoda ta koju ne mogupozvatiostali
threadoviistodobno. Takoder se to odnosina ostale inkroniziranemetode iliblokove
koda u tom objektu.
Sinkroniziratimoetei na niimrazinamanego to je razinametode. Na primjer, sljedeci
programiamobi problemaako bi drugithread promijeniovrijednostod i ilithis.i u
vrijemedok se obavljapridruivanje
.
public class Counter {
int i = 0;
public void count() {
int i = this.i;
int limit = i + 100;

while (i++ != limit)


this.i = i;

System.out.println (i);

}
}

To se moeispravititako 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 . Moete takoder sinkroniziratii


drugeobjekte. Na primjer, sljedecastatickametoda koristijednostavnibubblesort za
sortiranjepolja cijelihbrojeva. Sinkroniziratcemo to polje da bismobilisigurnida ga
drugithreadovinece 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 tome da se this objekt modane promijeniod strane drugog


threada. Na kraju, metoda je staticka. Brinetese o tome da drugithreadovine promijene
polje dok ga sortirate.
Takoder primijetiteda u pravilune znatenitao tome to se dogada u programuizvan
vae metode. Moda ce bitisamo jedan thread koji elipristuppolju, a modace ihbiti
mnogo. Da litreba iline treba sinkroniziratimetodukao to je ova, ovisio tome gdje ce
se ona koristiti. Ako piete metode i klase opce namjenekoje ce se koristitiu mnogim
razlicitimprogramima, moratepretpostavitida ce razlicitithreadovipozivatimetodu
istodobno.

Polja moetesinkroniziratijer su to objekti. Ne moetesinkroniziratiprimitivnetipove


podataka kao to su int , float , ilichar .
Stringovemoetesinkroniziratijer su objekti, alije to nepotrebnojer su onii tako
nepromjenjivi
. (Stringne moetepromijeniti
, moetesamo napravitinovi.)

Primarni thread
U pravilu, prilikomizvravanjaJava programaaktivnasu bar tri threada. Najprije, tu je
glavnithread unutarkojeg se va programizvrava. To je thread koji ukljucujemain()
metodukoja je pokrenulavau aplikaciju. U appletu, to ce bitithread unutarkojeg su
lansiraniapplet vieweriliweb browser.
Zatim, tu je garbage collector, thread koji za programomcistimemorijui obavljarazne
finalizacije
. Taj thread u praviluimaniskiprioritet.
U programimakoji koristeAWT aktivanje jo jedan thread koji se brineo auriranju
ekrana i otprilike100 puta u sekundiprovjeravatreba lineto bitiobnovljeno(repainted)
.
Konacno, tu su svithreadovikoje eksplicitnopokrene va program. U svako doba
programradi u nekomthreadui nikadne izlaziizsustavathreadova. Moete ustanoviti
koji thread se trenutnoizvravapomocustatickemetode currentThread ():
public static Thread currentThread ()

Na primjer, sljedeciprogramispisujeimeprimarnogthreada izvravanja:


public class PrimaryThread {
public static void main(String[] args) {
System.out.println (Thread.currentThread ());
}
}
% javac PrimaryThread .java
% java PrimaryThread
Thread[main,5,main]
%

Metodu currentThread () koristiteda biste dobilireferencuna trenutacnoaktivni


thread i njimemanipulirali
.

Grupe threadova

Threadovisu organiziraniu grupe. Grupa threadovaje jednostavnokolekcijapovezanih


threadova. Na primjer, izsigurnosnihrazlogasvithreadovikoje lansiranekiapplet
smjetajuse u jednugrupu. Appletuje dozvoljenomanipuliratithreadovimaizsvoje
grupe, aline i onimaizdrugihgrupa. Na taj nacinapplet moe, na primjer, iskljuciti
sistemskigarbage collector, a da pri tome ne smeta ostalimprogramima.
Grupe threadovaorganiziranesu u hijerarhijuroditelj- djeca.
Sljedeciprogramispisujesve aktivnethreadove. Uz pomoc metoda getThreadGroup ()
izklase java.lang.Thread i getParent () iz java.lang.ThreadGroup popet ce se
do najviegrupethreadova, a zatimpomocu activeCount () ustanovitikoliko
threadovaimau grupite pomocumetode enumerate () ispisatisve threadoveizglavne
grupei njenedjece (to ovdje pokrivasve grupethreadova, inacepostojii rekurzivna
varijantametode enumerate ()).
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 moeizgledatina primjerovako:


% javac AllThreads .java
% java AllThreads
Thread[Reference Handler ,10,system]
Thread[Finalizer ,8,system]
Thread[Signal Dispatcher ,10,system]
Thread[main,5,main]
%

Threadovi demoni
Threadovikoji rade u pozadinikao podrka runtime okruenjunazivajuse demoni
(daemon threads). Na primjer, clock handler, idle, garbage collector, screen updater
su demoni. that work inthe backgroundto support the runtimeenvironmentare called
daemon threads. Virtualnamainase zaustavljakad su svinon-demonthreadovizavrili.

Po pretpostavci, threadovikoje kreiratenisudemoni. Ako eliteda onito postanu,


posluitcete se metodom setDaemon (true). Da biste ustanovilije linekithread demon
ilinije, pozovitemetodu isDaemon ().
public final void setDaemon (boolean isDaemon )
public final boolean isDaemon ()

Ustupanje kontrole
Buducida u pravilune moetepredvidjetida lice va programraditiu kooperativnomili
natjecateljskom(preemptive) okruenju, treba omogucitida threadovikoji intenzivno
koristeCPU s vremenana vrijemeprepuste kontroluostalimthreadovima. Cetirisu
situacijeu kojimace thread prepustitikontrolu:
ako je blokiran.
Ako je ustupiokontrolupomocumetode yield().
Ako je uspavanpomocumetode sleep().
Ako je suspendiran(to izbjegavajte: metode suspend () i resume() su
depricated).
Blokiranjenastajeako thread mora cekati da se neka operacijazavri. Obicno su to I/O
operacije, posebno one koje ukljucujupristuppreko mree. Moguceje blokiranjei zbog
cekanja na korisnikovunos. Obicno je dobro stavitiI/O operacijeu odvojenethreadove
visokogprioritetajer ce racunalona taj nacinbitiefikasnijeiskoriteno. Ostalithreadovi
koji intenzivnokoristeCPU obavitce mnogoposla dok cekaju na podatke koji trebaju
doci preko mreeiliod korisnikakoji treba neto utipkati.
Kad aktivnithread pozove metodu yield(), on ce se privremenozaustavitii ustupiti
kontroludrugimthreadovima. Virtualnamainace potraitiimalithreadovaistogilivieg
prioritetakoji cekaju i ako ima, dodijelitce kontrolusljedecemu redu. Ako nema,
kontrolace se vratitithreadukoji ju je prepustio. Znacida yield() samo signalizira
spremnostza preputanjekontrolei ne garantirada ce thread zaistabitizaustavljen. To
ovisiu potpunostio drugimthreadovima.
Ako thread bezuvjetnoelipredatikontroluna neko vrijeme, bez obzirada lidrugi
threadovicekaju iline, on moepozvatimetodu sleep(). Ona ce ga uspavatina
odredeno vrijemetijekomkojega drugithreadoviimajuprilikuza izvravanje.
public static void sleep(long milliseconds ) throws
InterruptedException
public static void sleep(long milliseconds , int nanoseconds )
throws InterruptedException

Konacno, thread moebitisuspendiranna neodredenovrijeme. On sam, a jo cece neki


drugithread, moepozvatimetodu suspend () koja ce izazvatizaustavljanjethreada sve
dok ga nekidrugithread ne aktivirapozivanjemmetode resume(). Medutim, kao to
smo vec rekli, ove dvijemetode su se pokazalenesigurminai zato su sada deprecated
kao i metoda stop() pa ih, dakle, nemojtenikoristiti.

Spajanje threadova
Spajanje threadovaznacida jedan thread ceka dok drugine zavri. Za to postoje tri
overloaded join() metode koje blokirajuthread koji ihje pozvao, tako dugo dok se
thread cija join() 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 pozove t.join() cekat ce da se thread t zavripa tek onda


nastaviti. Ako pozove t.join(1000) cekat ce bar jednusekundudok se thread t ne
zavrii tada ce nastaviti.
Spajanje threadovakorisnoje u situacijamakad threadoviovisejedan o drugom. Na
primjer, moese cekati na ucitavanjepodataka izdatoteke ilina ucitavanjeslikes mree.

Sucelje Runnable
Do sada su svithreadovis kojimasmo radilibilipodklase od java.lang.Thread .
Ponekad, medutim, eliteda se kao threadoviponaajui klase koje su vec podklase
drugihklasa. Tipicanprimjerje kad eliteda se applet ponaa kao thread. U takvim
slucajevimaimplementiratcete u vaoj klasisucelje java.lang.Runnable . Ono
deklarirajednujedinumetodu, run().
public void run()

Tu cete metoduimplementiratiisto kao to biste to ucinilida je vaa klasa podklasa od


Thread , samo cete jo deklariratida implementiratesucelje Runnable .
public class MyThreadedClass extends SomeClass implements Runnable
{
.
.
.
public void run() {
.
.
.
}
}

Sad cete prvo kreirativa Runnable objekt, a zatimnoviobjekt tipa Thread tako da
kao argumentkonstruktorudate va objekt. Nakon toga moetepozvatistart()
metoduizklase Thread :
MyThreadedClass mtc = new MyThreadedClass ();

Thread t = new Thread(mtc);


t.start();

Animacija
Animacijaje jedna od glavnihprimjenasucelja Runnable . Da biste pokrenuliobjekte u
Javi, kreiratethread koji racunasukcesivneframeove na ekranui pozivametodu
repaint () za obnovuslike. Moete takoder postavitii beskonacnupetljuu vau paint
() metodu, alito nijedobro, osobito na non-preemptivesustavimakao to je Mac. To
takoder ne osiguravadobru pravovremenost(timing).
Pocnimosa jednostavnomanimacijomodbijanjacrveneloptice(prikazanekao krug) od
unutranjihrubovakutije(prikazanekao pravokutnik). Njene koordinatebit ce
spremljeneu atributur koji je tipa java.awt.Rectangle . Metoda paint() gledatce
taj pravokutniki iscrtatimuupisanikrug.
Appletovarun() metoda mjestoje gdje se akcija zapravodogada. Ovdje ce se
povecavatikoordinatelopticei provjeravatida lise ona primaklarubu vidljivogpodrucja.
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 ();
}
}

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

Pravovremenost
Prava animacijamora osiguratimehanizam
pravovremenosti.Animacijakoju smo upravo
napravilibit ce na nekimsustavimaprebrza, a na
nekimamodai prespora. Potrebno je na nekinacin
reguliratitu brzinu.
Filmskistandard je 24 framea u sekundi. Filmovise
tom brzinomi snimaju, a kod projekcijene elimoda
brzinaprojektora utjece na brzinuizmjeneframeova,
pogotovoako razlicitiprojektoriimajurazlicitebrzine. To je, inace, razlog, zato stari
nijemifilmoviizgledajuneprirodnobrzo. Oni su snimanibrzinomod 15 frameovau
sekundi, dok dananjiprojektorirade sa 24 frameau sekundi. Televizijskaslikase
obnavljabrzinomod 30 frameovau sekundina vie.
Iako ne moeteubrzatianimacijuiznadmogucnostivirtualnemaine, moeteje usporiti
koristecimetodu sleep(). Sljedeciapplet ogranicavabrzinukretanjalopticena 50
pixela(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);
}

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
Moda ste primijetilititranjeslikekod izvravanjaovog appleta. To je uobicajeniproblem
animacijskihappleta. Nastaje zbog nesinkroniziranosti
obnavljanjaslikena fizickom
ekranui obnavljanjaslikekoje diktiraapplet. Kad to dvoje nijeu skladu, nastajetitranje.
Dva su nacinana koje moeterijeititaj problem. Najjednostavnijerjeenjeje definiranje
tzv. clipping podrucja. To je pravokutnikunutarkojeg moetecrtati, a izvannjegane
moete. Definiranjemclipping podrucja omedujeteprostor u koji moetecrtati. To znaci
da nitaizvantog podrucja nece titrati. Titranjeje ogranicenosamo na to podrucje.
Nadalje, malapovrinase moebrzo iscrtatipa je i vjerojatnosttitranjamanja.
Da biste definiraliclipping pravokutnik, pozvatcete metodu g.clipRect (Rect r)
unutarvae paint(). Ovaj applet je upravoi pogodan za to jer vec imagotov
pravokutnikkoji treba biticlipping. Pogledajmosada revidiraniapplet:
import java.awt.*;
import java.applet.*;
import java.util.*;

public class ClipBounce 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.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 koritenjutehniketzv.


offscreen slikai update() metode. Pregazitelitu metodu, moeteobavitisve crtanjena
offscreen sliku, tj. objekt tipa Image , a zatimkopiratigotoviobjekt na ekran. Kopiranje
slikeodvijase puno bre i glatkijenego iscrtavanjepojedinihelemenatana ekran pa u
tom slucajunemavidljivogtitranja.

Recept je jednostavan. Kopirajtesljedeciblok koda u svoj programi titranjece nestati.


Dodaliste tri private atributai publicmetodu update().
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);
}

Imat cemo, 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);
}

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 izvrava. Sa
jednostavnimanimacijamakao to je ova iznaegprimjera, uobicajenoje da se animacija
zaustavljai pokrece klikanjemmia.
Da bismoto implementirali
, dodat cemo booleovskiatributbouncing koji ce biti true
ako i samo ako se thread izvrava. Zatimcemo dodati MouseListener metodukoja
zaustavljathread ako je pokrenuti pokrece ga ako je zaustavljen. Primijetiteda smo se

ovdje ipak koristilideprecated metodamasuspend () i resume(). Pokuajte preraditi


ovaj applet tako da ihizbjegnete!
import
import
import
import

java.awt.*;
java.awt.event.*;
java.applet.*;
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);
}

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
public
public
public

void
void
void
void

mousePressed (MouseEvent e) {}
mouseReleased (MouseEvent e) {}
mouseEntered (MouseEvent e) {}
mouseExited (MouseEvent e) {}

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

Viestruke nezavisne animacije


Ponekad imasmislapokrenutivieanimacijaistodobno.
U tom slucaju, applet ce implementiratisucelje
Runnable , a klase animiranihobjekata bit ce podklase
od Thread . Sljedeciprogramdemonstrirato pomocu
appleta u kojem se dvijelopticenezavisnoodbijajuod
rubova.

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 ();

try {
Thread.sleep(10);
}
catch (InterruptedException e) {
}
}
}

}
class Ball extends Thread {
private
private
private
private

Rectangle r;
int deltaX = 1;
int deltaY = 1;
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) {
}

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

u pripremi

Dvanaesto predavanje
programiranje
Portovi protokoli internet adrese
InetAddress objekata URL -

mreno

kreiranje InetAddress objekata

parsiranje

Portovi
U pravilu(koje imamnogoiznimaka) svako racunaloimasamo jednuInternetadresu.
Medutim, svako racunalocesto treba komuniciratis vieod jednogracunalaistodobno.
Na primjer, u isto vrijememoese odvijatinekolikoftp sesija, nekolikoweb konekcija,
chat i tako dalje.
Da bi se to omogucilo, mrenosuceljeracunalapodijeljenoje na 65536 ulaza, takozvanih
portova. Port je apstrakcija. To nijenikakvifizickiulazkao to su serijskiiliparalelni
portovina osobnimracunalima. No podaci putujuInternetomu paketima, pri cemusvaki
paket nosine samo adresu hosta nego i broj porta na koji treba stici. Host ce na osnovi
specificiranogporta odreditikojem programuje namijenjendoticnipaket podataka.
Ako elite, IP adresu moetezamiljatikao ulicnuadresu, a portove kao brojeve stanova
u kucama. Routerikoji transportirajupakete brinuse samo o ulicnojadresi , dakle ne
citajubroj porta. To je preputenolokalnomracunalu.
Na Unixupotrebne su vamroot privilegijeza oslukivanjekonekcijana portovimaod 0
do 1023. Konekcijena portovimaod 1024 do 65535 moeoslukivatisvatko, dok god
odredeniport nijezauzet(na istomportu ne moevieod jednogprogramaistodobno
oslukivatikonekcije). Na operacijskimsustavimaWindowsNT, Windows95 i Mac bilo
koji korisnikmoebez posebnihprivilegijaoslukivatibilokoji port.
Bilokoji udaljenihost moeostvaritikonekcijuna posluiteljkoji oslukujenekiport
ispod 1024. Nadalje, viestrukesimultanekonekcijemoguse ostvaritina udaljenihost i
udaljeniport. Na primjer, web posluiteljkoji oslukuje(u pravilu) na portu 80 moe
istovremenoobradivatidesetke konekcijaistodobno, sve usmjerenena port 80.
Ukratko, samo jedan process na lokalnomhostumoekoristitinekiport. Naprotiv,
mnogoudaljenihhostovamoeostvarivatikonekcijena jedan te isti(udaljeni) port.
Mnogiservisirade na tzv. opcepoznatim(well-known), portovima. To znacida protokoli
specificirajuda nekiservismoeilimora koristitiodredeniport. Na primjer, http
posluiteljiobicnooslukujuna portu 80, SMTP posluiteljina portu 25, Echo posluitelji

na portu 7, a Discardposluiteljina portu 9. Nemajusviservisiopcepoznateportove. Na


primjerNFS dozvoljavada se portoviotkrivajuu vrijemeizvravanja.

Protokoli
Neformalnogovoreci, protocol definirakakodva hosta medusobnokomuniciraju
. U radio
komunikaciji
, na primjer, protokolispecificirajuda po zavretkuporuke treba reci over
ili kraj . Kod racunalnihmreaprotokol definirato jest, a to nijeprihvatljivoza jednog
ilidrugogsudionikakomunikacijeu odredenomvremenskomtrenutku.
Na primjer, daytime protokol, specificiranu RFC 867, kae da se klijentpovezujes
posluiteljemna portu 13. Posluiteljtada kae klijentutocno vrijemeu formatukoji je za
covjeka citljiv, a nakon toga prekida konekciju.
S drugestrane, time protokol, specificiranu RFC 868, propisujebinarnureprezentaciju
vremenakoja je citljivaza racunala.
Daytime i time aljuistuinformaciju
. Medutim, onikoristerazliciteformatei razlicite
protokole da bi je poslali.
Postojionolikorazlicitihvrsta protokola kolikoimaservisakoji se njimakoriste.
Lockstep protokolitrae jedan odgovor za svakiupit. Neki protokolikao to je FTP
koristeviestrukekonekcija. Vecinakoristisamo jednu. Neki protokoli, kao HTTP
dozvoljavajusamo jedan upiti jedan odgovor po konekciji. Drugi, kao FTP,
dozvoljavajuviestrukekonekcijei vieodgovoraunutarsvake konekcije.

Internet adrese
Svako racunalona Internetuidentificirase pomocujedinstvene, cetverobajtneIP adrese.
Ona se obicnozapisujeu tzv. dotted quad formatukao npr. 161.53.8.14 gdje je svaki
byte neoznacenavrijednostizmedu0 i 255.
Buducida je ovakve brojeve teko zapamtiti, adrese se mapirajuu imenakao
student.math.hr , jagor.srce.hr i tako dalje. Medutim, bitnaje numerickaadresa, ne
ime.
Klasa java.net.InetAddress predstavljatakve adrese. Izmeduostalog, ona sadrii
metode za konvertiranjenumerickihadresa u imenahostovai obrunuto.
public static InetAddress getByName (String host) throws
UnknownHostException
public static InetAddress [] getAllByName (String host) throws
UnknownHostException
public static InetAddress getLocalHost () throws
UnknownHostException
public boolean isMulticastAddress ()
public String getHostName ()

public
public
public
public
public

byte[] getAddress ()
String getHostAddress ()
int hashCode ()
boolean equals(Object obj)
String toString ()

Kreiranje InetAddress objekata


Klasa InetAddress je maloneobicnajer nemanijedan public konstruktor. Umjesto
toga imehosta ilidotted quad adresu u stringformatuprosljedujetestatickojmetodi
InetAddress .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 hostoviimajuvieadresa. Ako pretpostavljateda je to slucajsa hostomkojeg


ispitujete, moetedobitipolje objekata tipa InetAddress pomocustatickemetode
InetAddress .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");
}
}
}

Imat cemo:
% javac HostAddresses .java
% java HostAddresses student .math.hr
student .math.hr/161.53.8.14
student .math.hr/161.53.29.70
%

Konacno, statickametoda InetAddress .getLocalHost () vraca objekt tipa


InetAddress koji sadriadresu racunalana kojem se programizvrava:
try {
InetAddress me = InetAddress .getLocalHost ();
}
catch (UnknownHostException e) {
System.err.println (e);
}

Parsiranje InetAddress objekata


Za objekt tipa InetAddress moetedobitiimehosta kao string, IP adresu kao stringili
kao polje byteova, a takoder moeteispitatije lito tzv. multicast adresa (adresa klase
D, cija su prva cetiribita 1110). To se rjeava sljedecimmetodama:
public
public
public
public

String getHostName ()
String getHostAddress ()
byte[] getAddress ()
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");
}
}
}

% javac LocalHost .java


% java LocalHost
Ime lokalnog hosta -----> student .math.hr
Adresa lokalnog hosta ---> 161.53.8.14
Adresa po byteovima -----> -95 53 8 14
nije multicast
%

Primijetiteda su byteovikoje vraca metoda getAddress () oznaceniiako se, prema


konvenciji, za dotted quad adrese koristeneoznacenibyteovi.

URL
URL, kraticaza "UniformResourceLocator", je nacinza jednoznacnoidentificiranje
lokacijenekog resursa na 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 .shtml
ftp://ftp.carnet.hr/pub/
mailto:Mladen.Vedris@student .math.hr
telnet://student .math.hr

VecinaURL-ova moese rastavitina sljedecekomponente(koje ne morajusve biti


prisutneu svakomURL-u):
protokol
host
port
datoteka
referenca, sekcijailisidro (anchor)

Klasa URL
URL-ovisu u Javipredstavljeniklasom java.net.URL . Postoje konstruktoriza
kreiranjenovogURL-a i metode za parsiranjerazlicitihdijelovaURL-a. Ipak, bitnidio
ove klase su metode koje vamomogucujuda sa nekog URL-a dobijete InputStream i
na taj nacincitatepodatke s posluitelja.
Klasa URL usko je povezanas handlerima protokola i sadraja. Ciljje odvojitisnimljene
(downloaded) podatke od protokola koji je koritenza njihovosnimanje. Handler
protokola je odgovoranza komuniciranjesa posluiteljem
, tj. prenoenjebyteovaod
posluiteljado klijenta. On obavljapotrebne pregovore (negotiations) oko posluiteljai
svihpotrebnihheadera. Njegov je posao dobavitibyteovetraenihpodataka. Handler
sadrajapreuzimate byteovei prevodiihu neku vrstuJava objekta kao to je
InputStream iliImageProducer .

Kad konstruirateobjekt tipa URL , Java ce potraitihandlerprotokola koji razumije


protokolski dio URL-a, kao to je npr. "http" ili"mailto". Ako ne pronade takav
handler, izbacitce MalformedURLException . Koji su protokolipodrani, ovisio
implementaciji
, no http i filesu podraniuglavnomsvagdje. Sun-ov JDK 1.1. razumije
sljedecihdeset:
file
ftp
gopher
http
mailto
appletresource
doc
netdoc
systemresource
verbatim
Posljednjihpet su specificniSun-oviprotokolii koristeihinternoJDK i HotJava.

Konstruiranje URL objekata


Pogledajmoneke od konstruktoraklase URL . Svi oniizbacuju
MalformedURLException .
public URL(String u) throws MalformedURLException
public URL(String protocol , String host, String file) throws
MalformedURLException
public URL(String protocol , String host, int port, String file)
throws MalformedURLException
public URL(URL context , String u) throws MalformedURLException

Za potpuni, apsolutniURL kao to je


http://student .math.hr/~vedris/java/java-predavanja /javapredavanje -01.htm
konstruirateodgovarajuciURL objekt ovako:
URL u = null;
try {
u = new URL("http://student .math.hr/~vedris/java/javapredavanja /java-predavanje -01.htm ");
}
catch (MalformedURLException e) {
}

You can also constructthe URL by passingits pieces to the constructor, likethis:
URL u = null;
try {
u = new URL("http", "student .math.hr",
"~vedris/java/java-predavanja /javapredavanje -01.htm");

}
catch (MalformedURLException e) {
}

U pravilune moratespecificiratiport za URL. Vecinaprotokola imapretpostavljeni


(default) URL , pa tako za http pretpostavljamo80. Medutim, ako traimoneto to nije
na defaultportu, posluitcemo se trecimkonstruktorom:
URL u = null;
try {
u = new URL("http", "student .math.hr", 80,
"~vedris/java/java-predavanja /javapredavanje -01.htm");
}
catch (MalformedURLException e) {
}

Konacno, mnogeHTML datoteke sadre relativneURL-ove. Na primjer, URL ove


straniceje
http://student .math.hr/~vedris/java/java-predavanja /javapredavanje -12.htm

Ako bismohtjelimiroriratiove stranicena nekomdrugomracunalu, moglibismoumjesto


apsolutnihkoristitirelativneURL-ove koji nasljedujuimehosta itd.. Na primjer, ako na
ovoj straniciimamolinkjava-predavanje -02, onda on zapravopokazujena http://
student .math.hr/~vedris/java/java-predavanja /javapredavanje -02.htm , medutim, na racunaluregoc.srce.hr pokazivaobi na
http://regoc.srce.hr/~vedris/java/java-predavanja /javapredavanje -12.htm

i tako dalje. Cetvrtiod gore navedenihkonstruktorakreira URL koji je relativanu


odnosu na zadaniURL. Na primjer:
URL u1, u2;
try {
u1 = new URL("http://student .math.hr/~vedris/java/javapredavanja /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 koristisljedecemetode za rastavljanjeURLa na njegove
komponente:
public String getProtocol ()
public String getHost ()

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 pokuava


napravitikonekcijana (nepostojeci) port 1, nego jednostavnoda se koristidefault port.
Ako ne postojireferenca(anchor), onda je ona naprosto null , pa treba uhvatiti
NullPointerException ili, jo bolje, ispitatida je non-nullprije nego lije koristimo.
Konacno, ako je izostavljenfile, kao na primjeru http://student .math.hr,
odgovarajucase vrijednostpostavljana "/".

Citanje podataka sa URLa


Metoda openStream () otvara konekcijuna posluiteljkojeg URL specificirate vraca
InputStream s podacimaizte konekcije. To omogucujesnimanjepodataka sa
posluitelja.Svi headeri koji dolazeprije stvarnihpodataka ilitraenedatoteke bit ce
obrisaniprije nego streambude otvoren. Dobitcete samo ciste podatke.
public final InputStream openStream () throws IOException

Stream cete procitatikoristecise metodamaizpaketa java.io o kojem smo govoriliu


desetom predavanju. Primijetiteda vecinamrenihkonekcijapredstavljamanjepouzdani
sporijiizvorpodataka nego to su to datoteke. Bitce dakle potrebno izvritibufferiranje,
koristecise pri tom klasama BufferedInputStream iliBufferedReader .
Programizsljedecegprimjeracita nizURLa sa komandnelinije. Iz svakog argumenta
pokuavaformiratiURL, povezatise na specificiraniposluitelji snimitipodatke koje ce
onda ispisatina System.out .
import java.net.*;
import java.io.*;
public class Webcat {

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)
Prije nego se podaci aljupreko Internetas jednoghosta na drugiuz pomoc TCP/IP, oni
se pakirajuu pakete razlicitih
, alikonacnihvelicinakoji se nazivajudatagrami. Velicina
datagramavariraod nekolikodesetaka byteovapa do oko 60,000 byteova. Sve to je
vece od toga, a cesto i ono to je manjeod toga, treba podijelitiu manjedijeloveprije
odailjanja. Prednost takvogslanjapodataka je u tome to ako se jedan paket putem
izgubi, on se moeposlatiponovo bez da se opet aljusviostalipaketi. Takoder, ako
paketi stignuizvanporetka, onise mogupravilnoporedatii kod primatelja.
Ipak, sve je ovo transparentnoza Java programera. Hostov ugradenimrenisoftverce
transparentnoobavitirazdiobupodataka u pakete na stranipoiljateljate ihponovo
spojitina straniprimatelja. Umjestotoga, Java programerse susrece s vrlovisokom
apstrakcijomkoju nazivamouticnica(socket). Uticnicapredstavljapouzdanukonekciju
za prijenospodataka izmedudva hosta. Ona vas izoliraod detaljakodiranjapaketa,
gubitkai ponovnogslanjapoiljki, te uspostavljanjaporetka medupristiglimpaketima.

Uticnicaobavljasljedececetirifundamentalneoperacije:
1. uspostavljanjeveze s udaljenimracunalom
2. slanjepodataka
3. primanjepodataka
4. prekidanjeveze
Uticnicane moebitiprikljucenana viehostovaistodobno.

Klasa Socket
Klasa java.net.Socket omogucujeizvodenjesvihcetirijufundamentalnihoperacijana
uticnicama. Moete ostvaritikonekcijuna udaljenoracunalo, slatii primatipodatke te
prekinutikonekciju.
Konekcijase obavljauz pomoc konstruktora. Svakomobjektu tipa Socket pridruenje
tocno jedan udaljenihost. Da biste ostvarilikonekcijuna drugihost, moratekreiratinovi
objektitipa Socket .
public Socket(String host, int port) throws UnknownHostException ,
IOException
public Socket(InetAddress address , int port) throws IOException
public Socket(String host, int port, InetAddress localAddress , int
localPort ) throws IOException
public Socket(InetAddress address , int port, InetAddress
localAddress , int localPort ) throws IOException

Slanjei primanjepodataka obavljase pomocuizlaznihi ulaznihstreamova. Sljedece


metode daju odgovarajucestreamoveza danu uticnicu.
public InputStream getInputStream () throws IOException
public OutputStream getOutputStream () throws IOException

Sljedeca metoda zatvarauticnicu:


public synchronized void close() throws IOException

Postojii nekolikometoda koje postavljanjurazliciteopcije vezaneuz uticnicu, no


uglavnomcete otkritida su default vrijednostisasvimzadovoljavajuce.
public void setTcpNoDelay (boolean on) throws SocketException
public boolean getTcpNoDelay () throws SocketException
public void setSoLinger (boolean on, int val) throws SocketException
public int getSoLinger () throws SocketException
public synchronized void setSoTimeout (int timeout ) throws
SocketException
public synchronized int getSoTimeout () throws SocketException
public static synchronized void setSocketImplFactory
(SocketImplFactory fac) throws IOException

Sljedece metoda daju razliciteinformacijeo uticnici:


public InetAddress getInetAddress ()

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 konstruktoreklase Socket .
public Socket(String host, int port) throws UnknownHostException ,
IOException
public Socket(InetAddress address , int port) throws IOException
public Socket(String host, int port, InetAddress localAddr , int
localPort ) throws IOException
public Socket(InetAddress address , int port, InetAddress
localAddr , int localPort ) throws IOException

Potrebno je, dakle, specificiratiu najmanjuruku host i port na koji se elitekonektirati.


Host moebitispecificiranbilokao string, npr "student .math.hr" ilikao objekt tipa
InetAddress . Port mora biticijelibroj izmedu1 i 65535. Ne moebitibilokoji, vec ga
trebate znatiisto kao i imehosta. Na primjer,
Socket webStudent = new Socket("student .math.hr", 80);

Posljednjadva konstruktoratakoder specificirajuhost i port sa kojega ostvarujete


konekciju. Na sistemusa vieIP adresa, kao to su mnogiweb posluitelji
, to vam
omogucujeda odaberete svoje mrenosuceljei IP adresu. Moete specificiratii broj
porta, alikako svakipojediniport moebitizauzet, najboljeje stavitiport 0. To ce reci
sistemuda izaberebilokoji slobodniport. Ako eliteznatis kojeg porta ste napravili
konekciju, pozvatcete metodu getLocalPort ().
Socket webStudent = new Socket("student .math.hr", 80, "pcmladen.srce.hr", 0);

Ovi konstruktorinece samo kreiratinoviobjekt tipa Socket . Oni ce takoder pokuati


ostvaritikonekcijuna specificiraniudaljeniposluitelj.Svi onizato odbacuju
IOException u slucajuda se konekcijaizbilokojeg razlogane moeuspostaviti.

Port Scanner
Ne moetese naprosto konektiratina bilokoji port na bilokojem hostu. Konekcijaje
mogucasamo na one portove na kojimaudaljenoracunalooslukuje dolaznekonekcije.
Konstruktoreuticnicamoetekoristitida biste ustanovilina kojimportovimaracunalo
oslukuje. Pogledajteprimjer:
import java.net.*;

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);
}
}

Izvritcemo ovu ogranicenuverzijuPortScannerakoja ispitujesamo portove od 78 do


81. Primijetitcete da racunalosluana portu 80. To je standardniport za web posluitelj.

% javac PortScanner .java


% java PortScanner localhost
Racunalo ne slusa na portu 78
Racunalo ne slusa na portu 79
Server slusa na portu 80 racunala localhost
Racunalo ne slusa na portu 81
%

Upozorenje: Ne pokuavajte usmjeritikompletniPortScanner

prema
maini koja nije vaa vlastita bez dozvole vlasnika / sistem inenjera, jer ce se to
smatratihakerskim napadomi ugroavanjemsigurnostiracunala!!!

Citanje ulaza sa uticnice


Jednomkad je uticnicakonektirana, moeteslatipodatke na posluiteljputemizlaznog
streamailiihprimatisa posluiteljapomocuulaznogstreama. Koje tocno podatke aljete
iliprimateobicnoovisio protokolu.
Metoda getInputStream () vraca objekt tipa InputStream koji cita podatke iz
uticnice. Moete koristitiuobicajenemetode klase InputStream o kojimaste uciliu
desetom predavnju. Uglavnomce bitipotrebno povezatiInputStream sa nekimdrugim
ulaznimstreamomilireaderomkako bi se lake moglorukovatipodacima.
Na primjer, sljedecifragmentkoda radi konekcijuna daytime posluiteljna portu 13
racunalastudent .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 daytime
posluiteljracunalastudent .math.hr na portu 13 i ispisujepodatke koje od njega
dobije.
import java.net.*;
import java.io.*;
import java.util.Date;

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 Daytime
Tue Jan 22 16:16:31 MET 2002

Pisanje izlaza preko uticnice


Metoda getOutputStream () vraca objekt tipa OutputStream pomocukojeg se
ispisujupodaci na uticnicu. Moete koristitisve uobicajenemetoed klase OutputStream
o kojimaste uciliu desetom predavanju. Uglavnomce bitipotrebno povezati
OutputStream sa nekimdrugimizlaznimstreamomilireaderomkako bi se lake moglo
rukovatipodacima.
Na primjer, sljedeciprogramse konektirana discard posluiteljna portu 9 racunala
student .math.hr i alje mupodatke 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 Discard
posluiteljracunalastudent .math.hr na portu 9 i alje mupodatke koje cita sa
standardnogulazaSystem.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();
}

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 Discard
asdf
<Ctrl-C>
%

Citanje i pisanje kroz uticnicu


Nije uobicajenoda se s uticnicesamo cita ilida se na njusamo pie. Vecinaprotokola
traida klijenti cita i pie. Neki protokolitrae da citanjei pisanjebude naizmjenicno
,
npr.

write
read
write
read
write
read

Drugiprotokoli, npr. HTTP 1.0, trae viestrukeispisenakon kojihslijedeviestruka


citanja, npr.:
write
write
write
read
read
read
read

Neki protokolidozvoljavajuda klijentoviupitii posluiteljeviodgovoribudu slobodno


izmijeani
.
Java ne stavljanikakverestrikcijena citanjei pisanjepo uticnicama. Jedan thread moe
citatis uticnice, a drugimoepo njoj istodobnopisati. (Primijetiteda to nijeisto kao kad
jedan thread cita datoteku, a drugipie u nju.)

Citanje i pisanje uticnice za HTTP


Programu sljedecemprimjerualje upitHTTP posluiteljukoristeciizlaznistream
uticnice, a zatimcita odgovor koristeciulaznistreamuticnice. HTTP posluiteljisami
zatvarajukonekcijukad poaljuodgovor.
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);

// 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 odgovor sa tipicnimpocetkom, karakteristicnimza HTTP


posluitelje:
% java Grabber "http://student .math.hr:80/~vedris/java/html/
TricksterApplet .html"
HTTP/1.1 200 OK
Date: Tue, 22 Jan 2002 15:32:38 GMT
Server: Apache/1.2.6
Last-Modified : Tue, 13 Nov 2001 13:09:48 GMT
ETag: "213be-97-3bf11b9c"
Content -Length: 151
Accept-Ranges: bytes
Connection : close
Content -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

The echo protocol simplyechoes back anythingits sent. The followingecho clientreads
data froman inputstream, thenpasses it out to an outputstreamconnectedto a socket,
connectedto a networkecho server. A second thread reads the inputcomingback from
the server. The main() methodreads some filenamesfromthe commandlineand passes
themintothe 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);

}
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) {
}

}
}

Server Sockets
Server Sockets

Uticnice posluitelja (server sockets)


There are two ends to each connection: the client, that is the host that initiatesthe
connection, and the server, that is the host that responds to the connection. Clientsand
servers are connectedby sockets.
On the server side insteadof connectingto a remotehost, a programwaitsfor other hosts
to connectto it. A server socket binds to a particularport on the localmachine. Once it
has successfullybound to a port, it listens for incomingconnectionattempts. When it
detects a connectionattempt, it accepts the connection. Thiscreates a socket between
the clientand the server over whichthe clientand the server communicate.
Multipleclientscan connectto the same port on the server at the same time. Incoming
data is distinguishedby the port to whichit is addressed and the clienthost and port from
whichit came. The server can tellfor whichservice(likehttp or ftp) the data is intended
by inspectingthe port. It can tellwhichopen socket on that servicethe data is intended
by lookingat the clientaddress and port stored withthe data.
No more thanone server socket can listento a particularport at one time. Therefore,
sincea server mayneed to handlemanyconnectionsat once, server programstend to be
heavilymulti-threaded. Generallythe server socket listeningon the port willonlyaccept
the connections. It thenpasses offthe actualprocessingof connectionsto a separate
thread.
Incomingconnectionsare stored ina queue untilthe server can accept them. (On most
systemsthe defaultqueue lengthis between 5 and 50. Once the queue fillsup further
incomingconnectionsare refuseduntilspace inthe queue opens up.)

The java.net.ServerSocket Class

Klasa ServerSocket

The java.net.ServerSocket class representsa server socket. It is constructedon a


particularport. Thenit calls accept() to listenfor incomingconnections. accept()
blocks untila connectionis detected. Then accept() returnsa java.net.Socket
object you use to performthe actualcommunicationwiththe client.
There are three constructorsthat let you specifythe port to bindto, the queue lengthfor
incomingconnections, and the IP address to bindto:
public
public
public
throws

ServerSocket (int port) throws IOException


ServerSocket (int port, int backlog ) throws IOException
ServerSocket (int port, int backlog , InetAddress bindAddr )
IOException

The accept() and close() methodsprovidethe basic functionalityof a server socket.


public Socket accept() throws IOException
public void close() throws IOException

On a server withmultipleIP addresses, the getInetAddress () methodtellsyou which


one thisserver socket is listeningto. The getLocalPort() methodtellsyou whichport
you're listeningto.
public InetAddress getInetAddress ()
public int getLocalPort ()

There are three methodsto set and get variousoptions. The defaultsare generallyfine.
public synchronized void setSoTimeout (int timeout ) throws
SocketException
public synchronized int getSoTimeout () throws IOException
public 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 create
server sockets on allof them, and seeingwhere that operationfails.
import java.net.*;
import java.io.IOException ;

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.ServerSocket Constructors

Konstruktori klase ServerSocket


The java.net.ServerSocket class has three constructorsthat let you specifythe port
to bindto, the queue lengthfor incomingconnections, and the IP address to bindto:
public
public
public
throws

ServerSocket (int port) throws IOException


ServerSocket (int port, int backlog ) throws IOException
ServerSocket (int port, int backlog , InetAddress bindAddr )
IOException

Normallyyou onlyspecifythe port you want to listenon, likethis:

try {
ServerSocket ss = new ServerSocket (80);
}
catch (IOException e) {
System.err.println (e);
}

When you create a ServerSocket object, it attemptsto bindto the port on the local
host 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. Thisincludes
non-Java processes or threads. For example, ifthere's alreadyan HTTP server running
on port 80, you won't be able to bindto port 80.
On Unixsystems(but not Windowsor the Mac) your programmustbe runningas root to
bindto a port between 1 and 1023.
0 is a specialport number. It tellsJava to pick an availableport. You can thenfindout
what port it's picked withthe getLocalPort () method. Thisis usefulifthe clientand
the server have alreadyestablisheda separate channelof communicationover whichthe
chosenport numbercan be communicated.
For example, the ftp protocol uses two sockets. The initialconnectionis made by the
clientto the server to send commands. One of the commandssent tellsthe server the
nameof the port on whichthe clientis listening
. The server thenconnectsto the clienton
thisport to send data.
try {
ServerSocket ftpdata = new ServerSocket (0);
int port = ftpdata .getLocalPort ();
}
catch (IOException e) {
System.err.println (e);
}

Adjustingthe queue length

Podeavanje duljine repa


public ServerSocket (int port, int backlog ) throws IOException

The operatingsystemstores incomingconnectionsfor each port ina first- in, first- out
queue untiltheycan be accepted. The defaultqueue lengthvariesfromoperatingsystem
to operatingsystem. However, it tends to be between 5 and 50. Once the queue fillsup
furtherconnectionsare refuseduntilspace opens up inthe queue. If you thinkyou aren't

goingto be processingconnectionsveryquicklyyou maywishto expand the queue when


you constructthe server socket. For example,
try {
ServerSocket httpd = new ServerSocket (80, 50);
}
catch (IOException e) {
System.err.println (e);
}

Each systemhas a maximumqueue lengthbeyond whichthe queue cannotbe expanded.


If you ask for a queue longerthanthe maximumqueue sizeon a particularplatform,
(generallyaroundfiftyto a hundred) thenthe queue is merelyexpanded to its maximum
size.
Once the server socket has been constructed, you cannotchangethe queue lengthit uses.

Choosinga localaddress

Odabir lokalne adrese


Many hosts have more thanone IP address. Thisis especiallycommonat web server
farmswhere a singlemachineis shared by multiplesites. By default, a server socket binds
to allavailableIP addresses. That is it accepts connectionsaddressed to any of the local
IP addresses on a givenport. Howeveryou can modifythat behaviorwiththis
constructor:
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 wouldyou bindto some but not allIP addresses on the server?

WritingData to a Client

Ispis podataka na klijent


The followingsimpleprogramrepeatedlyanswersclientrequestsby sendingback the
client'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 on


aktivan, 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.

Escape character is '^]'.


Hello student .math.hr/161.53.8.14 on port 51546
This is pc-mladen.srce.hr/161.53.2.93 on port 2345
Connection closed by foreign host.
% telnet pc-mladen.srce.hr 2345
Trying...
Connected to pc-mladen.srce.hr.
Escape character is '^]'.
Hello student .math.hr/161.53.8.14 on port 51547
This is pc-mladen.srce.hr/161.53.2.93 on port 2345
Connection closed by foreign host.

Primijetiteda se dolazniport promijenikod svakog novogtelneta. Kad HelloServer


prestane s radom, port koji je on oslukivaobit ce opet slobodan, to moeteprovjeriti
pomocuprograma LocalPortScanner . Takoder, pokuamlisada napravititelnetna
port 2345, dobit cu:
% telnet pc-mladen.srce.hr 2345
Trying...
telnet: Unable to connect to remote host: Connection refused
%

Kad HelloServer prestane s radom, port koji je on oslukivaobit ce opet slobodan,


to moeteprovjeritipomocuprograma LocalPortScanner .

ReadingData witha ServerSocket

Citanje podataka pomocu uticnice


posluitelja
The port scannerpretty muchexhaustswhat you can do withjust the constructors.
Almostall ServerSocket objects you create willuse their accept() methodto connect
to a client.
public Socket accept() throws IOException

There are no getInputStream () or getOutputStream () methodsfor ServerSocket.


Instead you use accept() to returna Socket object, and thencallits getInputStream
() 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.);

s.close();
}
catch (IOException e) {
System.err.println (e);
}

Notice inthisexample, I closed the Socket s, not the ServerSocket ss. ss is still
bound to port 2345. You get a new socket for each connectionbut it's easy to reuse the
server 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 server needs to both read a clientrequest and writea response. The
followingprogramreads whateverthe clientsends and thensends it back to the client. In
short 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 ;

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 2346
Trying...
Connected to pc-mladen.srce.hr.
Escape character is '^]'.
jedan
jedan
dva
dva
^]
Connection closed by foreign host.

Ako ne moeteizaciiztelneta, prekiniteEchoServerna lokalnomracunalusa <Ctrl-C>,


pa ce se telnetautomatskiotkvaciti.

AddingThreadingto a Server

Dodavanje threadova posluitelju


The last two programscouldonlyhandleone clientat a time. That wasn't so muchof a
problemfor HelloServer because it had onlya verybriefinteractionwitheach client.
Howeverthe EchoServer mighthangon to a connectionindefinitely
. In thiscase, it's
better to make your server multi-threaded. There shouldbe a loop whichcontinually
accepts new connections. However, rather thanhandlingthe connectiondirectlythe
Socket shouldbe passed to a Thread object that handlesthe connection.
The followingexampleis a threaded echo 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() {

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 2347
Trying...
Connected to pc-mladen.srce.hr.
Escape character is '^]'.
jedan-student
jedan-student
dva-student
dva-student
^]
Connection closed by foreign host.
%

Istodobno, na racunaluregoc.srce.hr:
% telnet pc-mladen.srce.hr 2347
Trying 161.53.2.93...
Connected to pc-mladen.srce.hr.
Escape character is '^]'.
jedan-regoc
jedan-regoc
dva-regoc
dva-regoc
^]
Connection closed by foreign host.
%

Ako ne moeteizaciiztelneta, prekiniteEchoServerna lokalnomracunalusa <Ctrl-C>,


pa ce se telnetautomatskiotkvaciti.
Note that explicityieldsare not requiredbecause allthe differentthreads willtend to
block on callsto read() and accept().

Addinga Thread Pool to a Server

Dodavanje Thread Poola posluitelju


Multi- threadingis a good thingbut it's stillnot a perfectsolution. For example, let's take a
look at the accept loop of the ThreadedEchoServer:
while (true) {
try {
Socket s = ss.accept();
ThreadedEchoServer tes = new ThreadedEchoServer (s);
tes.start();
}
catch (IOException e) {
}

Everytimeyou pass throughthisloop, a new thread gets created. Everytimea


connectionis finishedthe thread is disposed of. Spawninga new thread for each
connectiontakes a non-trivialamountof time, especiallyon a heavilyloaded server. It
wouldbe better not to spawn so manythreads.
An alternativeapproach is to create a pool of threads whenthe server launches, store
incomingconnectionsina queue, and have the threads inthe pool progressivelyremove
connectionsfromthe queue and process them. Thisis particularlysimplesincethe
operatingsystemdoes infact store the incomingconnectionsina queue. The mainchange
you need to make to implementthisis to call accept() inthe run() methodrather than
inthe main() method. The programbelow demonstrates.
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 ;

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 adjusted for
performancereasons. How wouldyou go about testingthe performanceof thisprogram
relativeto the one that spawns a new thread for each connection? How wouldyou
determinethe optimumnumberof threads to spawn?

UDP
IntroducingUDP

to je UDP?

The User Datagram Protocol, UDP for short, providesunguaranteed, connectionless


transmissionof data across an IP network. By contrast, TCP, providesreliable,
connection-orientedtransmissionof data.
Both TCP and UDP splitdata intopackets calleddatagrams. HoweverTCP includes
extra headers inthe datagramto enableretransmissionof lost packets and reassemblyof
packets intothe correct order iftheyarriveout of order. UDP does not providethis. If a
UDP packet is lost, it's lost. It willnot be retransmitted. Similarly
, packets appear inthe
receivingprograminthe order theywere received, not necessarilyinthe order theywere
sent.
Giventhese disadvantagesyou maywellwonder whyanyonewouldprefer UDP to TCP.
The answer is speed. UDP can be up to three timesfasterthanTCP; and there are many
applicationsfor whichreliabletransmissionof data is not nearlyas importantas speed.
For examplelost or out of order packets mayappear as staticinan audioor videofeed,
but the overallpictureor sound couldstillbe intelligible
.
Telephonevs. snailmailanalogy.
Protocolsthat use UDP includeNFS, FSP, and TFTP.

The UDP Classes

UDP klase
Java's support for UDP is containedintwo classes, java.net.DatagramSocket and
java.net.DatagramPacket . A DatagramSocketis used to send and receive
DatagramPackets. SinceUDP is connectionless, streamsare not used. You mustfityour
data intopackets of no more thanabout 60,000 bytes. You can manuallysplitthe data
across multiplepackets ifnecessary.
The DatagramPacket class is a wrapper for an array of bytes fromwhichdata willbe
sent or intowhichdata willbe received. It also containsthe address and port to whichthe
packet willbe sent.
The DatagramSocket class is a connectionto a port that does the sendingand receiving.
UnlikeTCP sockets, there is no distinctionbetween a UDP socket and a UDP server
socket. The same DatagramSocket can both and receive. Also unlikeTCP sockets, a
DatagramSocket can send to multiple
, differentaddresses. The address to whichdata
goes is stored inthe packet, not inthe socket.
UDP ports are separate fromTCP ports. Each computerhas 65,536 UDP ports as well
as its 65,536 TCP ports. You can have a ServerSocket bound to TCP port 20 at the
same timeas a DatagramSocket is bound to UDP port 20. Most of the timeit should
be obviousfromcontextwhetheror not I'm talkingabout TCP ports or UDP ports.

java.net.DatagramPacket

Klasa DatagramPacket
The DatagramPacket class is a wrapper for an array of bytes fromwhichdata willbe
sent or intowhichdata willbe received. It also containsthe address and port to whichthe
packet 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 number
of 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 whichyou want 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 you
cahngeit's contentselsewhere, the contentsof the DatagramPacket changeas well.
DatagramPacket s themselvesare not immutable
. You can changethe data,

the data, the port, or the address at any timewiththese fourmethods:


public
public
public
public

synchronized
synchronized
synchronized
synchronized

void
void
void
void

setAddress (InetAddress host)


setPort (int port)
setData (byte buffer[])
setLength (int length)

You can retrievethese itemswiththese fourget methods:


public
public
public
public

synchronized
synchronized
synchronized
synchronized

InetAddress getAddress ()
int getPort ()
byte[] getData ()
int getLength ()

the lengthof

These methodsare primarilyusefulwhenyou're receivingdatagrams.

java.net.DatagramSocket

Klasa DatagramSocket
The java.net.DatagramSocket class has three constructors:
public DatagramSocket () throws SocketException
public DatagramSocket (int port) throws SocketException
public DatagramSocket (int port, InetAddress laddr) throws
SocketException

The firstis used for datagramsockets that are primarilyintendedto act as clients; that is
sockets that willsend datagramsbefore receivingany. The secned two that specifythe
port and optionallythe IP address of the socket, are primarilyintendedfor servers that
mustrun on a well- knownport.
The LocalPortScannerdevelopedearlieronlyfoundTCP ports. The followingprogram
detects UDP ports inuse. As withTCP ports, you mustbe root on Unixsystemsto bind
to ports below 1024.
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++) {

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. The


onlyway you know whetheror not a UDP server is listeningon a remoteport is ifit
sends somethingback to you.

SendingUDP Datagrams

Slanje UDP Datagrama


To send data to a particularserver, you firstmustconvertthe data intobyte array. Next
you pass thisbyte array, the lengthof the data inthe array (most of the timethiswillbe
the lengthof the array) and the InetAddress and port to whichyou wishto send it into
the 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 you create 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);
}

ReceivingUDP Datagrams

Primanje UDP Datagrama


To receivedata sent to you, you constructa DatagramSocket object on the port on
whichyou want to listen. Thenyou pass an empty DatagramPacket object to the
DatagramSocket 's receive () method.
public synchronized void receive (DatagramPacket dp) throws
IOException

The callingthread blocks untilthe a datagramis received. Then dp is filledwiththe data


fromthat datagram. You can thenuse getPort () and and getAddress () to tellwhere
the packet came from, getData () to retrievethe data, and getLength () to see how
manybytes were inthe data. If the receivedpacket was too longfor the buffer, thenit's
truncatedto 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. For
example, the UDP echo servicelistenson port 7. When it receivesa datagramit copies
the data out of the datagramintoa new datagramand sends it back to the sendinghost.
(Why can't it just resend the same datagram?)
The followingUDPEchoClient reads what the user types on System.in and sends it to
an echo server specifiedon the commondline. Note that preciselybecause UDP is

unreliable, you're not guaranteedthat each lineyou type willinfact be echoed back. It
maybe lost goingbetween clientand server or 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);

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);
}
}
}
}

u pripremi
Trinaesto predavanje - ispis i prijenos
podataka
Printing
Printing

Printing
Java 1.1 implementsprintingthroughthe java.awt.PrintGraphics interfaceand the
abstract java.awt.Printjob class.
To begina printjob you callthe staticmethod Toolkit .getPrintJob (). Thisreturnsa
platformspecificinstanceof the abstract PrintJob class. (Platformspecificdetailsare
hiddeninsidethe sun classes.)
The PrintJob object givesyou informationabout the page sizeand the printer
resolution. It also has a getGraphics () methodthat returnsa Graphics object that
implementsthe PrintGraphics interface. Oftenyou'lldraw the page by passingthis
object to your paint() method. Other timesyou'llwant to specializefor printing. For
example, you mightwant to draw inblack and whiteinsteadof color. (RegrettablyJava
does not providea methodto determinethe availablecolors on the printer.)
A page is sent to the printerwhenyou invokeits Graphics 's object's dispose ()
method. You can printmultiplepages by repeatedlycallinggetGraphics () and the
disposingeach Graphics object.

SecurityRestrictionson Printing

Security Restrictions on Printing


As a generalruleapplets are not allowedto initiateprintjobs. Onlyapplicationscan do
that. You wouldn't want a maliciousapplet to churnyour printerwithmanypages of pure
black, wastingallyour toner, for example.
The checkPrintJobAccess () methodof the SecurityManager class is used to
determinewhetheror not printingis allowed.

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 abstract java.awt.PrintJob class has a singlepublicnoragsconstructor,
PrintJob () . Howeverbecause it's an abstract class you can't instatiateit. Instead you
mustcallthe getPrintJob () methodinthe java.awt.Toolkit class.
public abstract PrintJob getPrintJob (Frame parent, String title,
Properties props)

The Frame willholdthe platformspecificprintdialog. The title stringidentifiesthisjob


inthe printqueue and on the cover page. The props argumentsis a
java.awt.Properties object You can use to request differentprintingoptionson
Unix. Howeverthisdoesn't work on Windows, and inany case printingoptionsare
platformspecific.
PrintJob Dialog

A PrintJob dialog

For example:
PrintJob pj =
Toolkit .getDefaultToolkit ().getPrintJob (new Frame(),
"Hello World", null);

Thisreturnsa platformspecificsubclassof the PrintJob class. If the user cancelsthe


PrintJobinthe dialogbox, thenthismethodshouldreturn null . (Thismaybe a little
buggyunderWindows, though.)

Methods of 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'llwant


to do withthisobject is determinethe characteristicsof the printer. There are three
methodsfor this:
public abstract int getPageResolution ()
public abstract Dimension getPageDimension ()
public abstract boolean lastPageFirst ()

The getPageResolution () methodreturnsthe numberof dots per inchof thee printer,


typically300 or 600 for most laser printers. getPageDimension () returnsa
java.awt.Dimension object givingthe sizeof the printablearea of the page inpixels
(not inches!). For example, the followingcode fragmentprintsthe totalnumberof pixels
on 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 last page willbe printedfirst, false


otherwise.
You use thisinformationto prepare your imageto be drawn on the page. dependingon
the sizeof the page and the type of the image, you mayneed to spiltit across multiple
pages. Sometimesit's easier to just draw the entireimageon each page, but use
clipRect () to set the fractionof the imageto actuallybe drawn.

The drawingitselfis done witha java.awt.Graphics object likethe one you use inthe
paint() methodof an applet. Thisis returnedby getGraphics () , and has allthe usual
methodof the Graphics class, drawLine (), drawString (), and so on.
public abstract Graphics getGraphics ()

There's one importantcaveat: Unilkethe Graphicsobjects passed as argumentsto a


paint() method, thisobject does not intiallyhave a fontset. You'llgenerallywant to set
its fontbefore usingit likethis:
Font courier = new Font("Courier ", Font.PLAIN, 12);
g.setFont (courier );

When you're done witha PrintJob callits end() methodto performany necessary
flushingand 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;

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 trick to printingtext is to measureit and compare it to the page sizeand resolutionin
a 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 or
import 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 () );

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 ();

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");
}
}

} 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 most buttons, lists, scrollbars, panels, and so on inyour paint()
method. You don't have to printthemthere either. The java.awt.Component class has
print() and printAll () methods
public void print(Graphics g)
public void printAll (Graphics g)
java.awt.Container

adds a printComponents () methodthat printsallcomponents

inthe container:
public void printComponents (Graphics g)

For example, to printa Frame f, you mightdo 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 alwayswhat you want since printComponents () onlyprintsthe


visiblearea. for example, inthe text editingapplicationthe TextArea mayonlyshow part
of the text at one time, but you reallywant to printallthe text.

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

The Clipboard

The Clipboard
Modern, multitaskingoperatingsystemsand graphicaluser interfacesallowyou to
transferdata between programsat the request of the user througha systemfacilitycalled
a clipboard. In general, clipboardscan containtext, pictures, sound, formattedtext, data
inparticularformatsand more. However, not allprogramsknow how to interpretalldata
formats.
Most of the timethe user somehowselectsthe data to be placed on the clipboard. The
data maythenbe copied to the clipboard, generallyby selecting"Copy" fromthe Edit
menuor by usingthe C shortcutkey. Alternatelydata can be cut out of the running
programand placed on the clipboard. Copied data remainsinthe originaldocumentwhile
cut data is deleted fromthe originaldocument. The data is thenplaced back intothe same
documentor intoa differentdocumnentby pastingit fromthe clipboard. On most
operatingsystems(thoughOpenWindowsis a notableexception) pastingdoes not
removethe data fromthe clipboard.
As wellas the systemclipboardmanyapplicationshave privateclipboardsthat are used
for intra-applicationdata transfer. The systemclipboardis used for inter-applicationdata
transfer.

The java.awt.datatransferPackage

The java.awt.datatransfer Package


The java.awt.datatransfer package providesclassesto support transferof data to
and fromthe systemclipboard. Support for the clipboardis stillinits infancyinJava 1.1.
Onlystringdata is supported, and onlycut, copy, and paste. Other data types and drag
and drop willbe added inthe future.
The java.awt.datatransfer .Transferable interfaceis implementodby classes
that representdata to be transferred. It includesmethodsto determinethe possibledata
flavorsof the object and to retrievethe data itself.
The java.awt.datatransfer .DataFlavor class providesa MIME type based
systemfor 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 thrownwhenyou
ask a Transferable object to returnits contentsinan incompatibleflavor.

The java.awt.datatransfer .Clipboard class allowsthe transferof data through


cut, copy, and paste operations. Althoughthere's onlyone systemclipboard, your
programmaycreate manydifferentClipboard objects for internaluse.
For synchronizationpurposes each clipboardmustbe the exclusiveproperty of one
object. Thisobject mustimplementthe java.awt.datatransfer .ClipboardOwner
interface. Thisinterfacedeclaes a singlemethod, lostOwnership (), whichis whichis
used to warn an object that it no longerowns the clipboard.
The java.awt.datatransfer .StringSelection class is the one concrete
implementationof Transferable and ClipboardOwner includedinJava 1.1. It allows
you to transferplaintext to and fromthe systemclipboard.

Other classesand methodsfor Copy and Paste

Other classes and methods for Copy


and Paste
There are a few methodsand classesoutsidethe java.awt.datatransfer package
that are relevantto copy and paste.
The getSystemClipboard () methodof the java.awt.Toolkit class returnsa
Clipboard object whichrepresentsthe systemclipboard:
public abstract Clipboard getSystemClipboard ()

The java.lang.SecurityManager class includesa checkSystemClipboardAccess


() methodthat determineswhetheror not thisprogramis allowedto access the system
clipboard. The methodis voidbut throwsa SecurityException ifaccess is not
allowed.
public void checkSystemClipboardAccess ()

The concernis that the clipboardmaycontainprivatedata whichthe user wouldnot want


revealedto the server. As a generalrule, applets loaded fromweb servers willnot be
allowedto access the systemclipboard. Thisdoes not, however, applyto private
clipboardsyou create. For example,
try {
SecurityManager sm = SecurityManager .getSecurityManager ();
if (sm != null) sm.checkSystemClipboardAccess ();
Clipboard cb = Toolkit .getDefaultToolkit ().getSystemClipboard ()
;
//... handle clipboard
}
catch (SecurityException e) {

System.err.println ("Cannot access the system clipboard ");


}

The java.awt.TextComponent class, whichboth TextArea and TextField extend,


has a getSelectedText () methodthat returnsthe currentvalueof the selectionas a
String:
public synchronized String getSelectedText ()

You'lloftenuse thismethodto decide what to copy or cut. Severalother


TextComponent 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 ()

The TextArea class (but not the TextField class) also has insert() and
replaceRange () methodsyou can use for pasting:
public synchronized void insert(String s, int pos)
public synchronized void replaceRange (String s, int start, int
end)

What's the differencebetween these two methods? When wouldyou use insert() and
whenwouldyou use replaceRange ()?

ImplementingCopy and Paste

Implementing Copy and Paste


Implementing Copying
1. Get the systemclipboardusingthe getSystemClipboard () methodof the
java.awt.Toolkit class.
2. Create a new object, such as a StringSelection , whichimplementsthe
transferableinterfaceand containsthe data you want to copy.
3. Put that object on the clipboardusingthe setContents () methodof the
Clipboardclass.
For example,
public void copy(TextField tf)

StringSelection data = new StringSelection (tf.getText ());


Clipboard clipboard = Toolkit ().getDefaultToolkit ()
.getSystemClipboard ();
clipboard .setContents (data, data);
}

Implementing Pasting
1. Get the systemclipboardusingthe getSystemClipboard () methodof the
java.awt.Toolkit class.
2. Get the clipboard's contentsusingusingthe getContents () methodof the
Clipboardclass.
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
import
import
import

java.io.*;
java.awt.*;
java.awt.datatransfer .*;
java.awt.event.*;

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")) {

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
, even the same kindof data. For
examplemost word processors support some formof formattedtext withdifferentfonts,
styles, sizesand so on. HoweverMicrosoftWord 6.0 for the Mac is not able to read
formattedtext produced by ClarisWorksand viceversa. PicturesfromPhotoshopcan be
copied and pasted intomanyprograms, but the layerstend to get flattenedwhenyou do
that.
The clipboardonlyreallyunderstandsraw bytes. It does not inherentlyknow how
whetherthose bytes are text or a pictureor a table or somethingelse. The
java.awt.datatransfer .DataFlavor class uses MIME types and subtypesto
identifythe kindof data stored inthe clipboard.
MIME, the MultipurposeInternetMailExtensions, is an Internetstandard definedin
RFCs 2045 through2049 for transferringmultimedia
, binarydata through7-bit ASCII
email. RFC 2046 inparticularspecifiesthe MIME type systemand definesthe base set
of mediatypes. New MIME types are registoeredwithand approved by the Internet
AssignedNumbersAuthority(IANA). The currentlistof standardizedtypes is available
fromftp://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-javaserialized-object, or image/gif. There are fivedefinedtypes: text, image, audio, video,
multipart, message, model, and application. The firstsevenare self-explanatory. The last
is used for arbitrarybinarydata. Subtypesthat beginwithan x such as "x-java-serialized-

object" are unofficial


, applicationspecificextensions. Two differentprogramsare not
guaranteedto interpretthe same x type as representingthe same kindof data.

The java.awt.datatransfer.DataFlavorclass

The java.awt.datatransfer .DataFlavor class


The java.awt.datatransfer .DataFlavor class encapsulatesa MIME type to
representthe data formatof an object stored on the clipboardas raw bytes. Each data
flavorhas a representation class , a MIME type, and a humanpresentablename.
The representationclass is the Java class whichapproximatesthe data. For example, the
plaintext flavoruses the representationclass java.io.InputStream and the MIME
type "text/plain; charset=unicode". The humanpresentablenameis just a slightlymore
reader-friendlyvariantof the MIME type like"JPEG picture" insteadof "image/jpeg".
Currentlytwo specificdata flavorsare defined, DataFlavor .plainTextFlavor and
DataFlavor .stringFlavor .
There are two constructorsthat allowyou to create new data flavors:
public DataFlavor (Class representationClass ,
String humanPresentableName )
public DataFlavor (String mimeType , String humanPresentableName )

The firstconstructorspecifiesthe representationclass and the humanpresentablename.


Howeverthe MIME type is normallyset to "application/x-java-serialized-object". The
second constructorlets you set the MIME type but uses the representationclass
InputStream .
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

The java.awt.datatransfer .Clipboard class


The java.awt.datatransfer .Clipboard class representsan object onto whichyou
can put transferableobjects and fromwhichyou can get transferableobjects.
There's one constructoryou can use to create privateclipboards. Howevermost of thhe
timeyou'lljust get the systemclipboardinstead:
public Clipboard (String name)

There are also three methodsthat allowyou to get the nameof the object currentlyon the
clipboard(onlyone object can be on a clipboardat a time), to get the contentsof the
clipboard(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 exclusiveproperty of one
object. Thisobject mustimplementthe java.awt.datatransfer .ClipboardOwner
interface. Thisinterfacedeclaes a singlemethod, lostOwnership (), whichis whichis
used 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


The java.awt.datatransfer .Transferable interfacemustbe implementedby any
class that willrepresentthe 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)

throws UnsupportedFlavorException , IOException

You can ask a Transferable object whetherit supports a particulardata flavoryou


want with isDataFlavorSupported () or you can ask it to listallthe data flavorsit
supports with getTransferDataFlavors ().
Note especiallythat one object maysupport multipledata flavors. For example, most
objects shouldprovidea plaintext flavoras a lowestcommondenominatorall
applicationscan handle. However, the same data mayalso be availableinan HTML
flavorfor applicationsthat can handlethe additonalformatting.
Finallyyou request an object of a particularflavorwith getTransferData (). If the
flavoryou request is not availablean UnsupportedFlavorException is thrown.

The java.awt.datatransfer.StringSelectionclass

The java.awt.datatransfer .StringSelection class


The java.awt.datatransfer .StringSelection class is the onlyconcrete
implementationof the java.awt.datatransfer .Transferable interfaceand the
java.awt.datatransfer .ClipboardOwner interfaceinJava 1.1. It lets you transfer
a 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 constructoryou use to create a new StringSelection object:


public StringSelection (String data)

Continuing Onward
FutureDirections
Object OrientedAnalysisand Design
Java 2D API
Java 3D API
The VirtualMachineand Byte Code

Java's SecurityModel
Code signingand encryptionwiththe java.securitypackage
NativeMethods
JDBC
RemoteMethod Invocation(RMI)
Java Web Server
JavaBeans
The Java Media API
Java TelephonyServicesAPI
JavaOS
Java ElectronicCommerceFramework
JavaSpaces
Protocol and ContentHandlers
The Java Namingand DirectoryInterface(JNDI)
CORBA and IDL
JavaScript

You might also like