Predavanje br. index|1|2|3|4|5|6|7|8|9|10|11|12|13|14|HOME
Primitivni tipovi podataka – operatori – razmak – literali – identifikatori – kljuène rijeèi – separatori – zbrajanje cijelih brojeva – zbrajanje brojeva tipa double – množenje i dijeljenje – neoèekivani kvocijenti – raèunanje ostatka, modulo – prioritet izvršavanja operatora – zagrade – miješanje 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 izvršavanja relacijskih operatora – ispitivanje jednakosti objekata – naredba break – naredba continue – labelirane petlje – naredba switch-case – kondicionalni operator (? :) – logièki operatori – prioritet izvršavanja logièkih operatora – deklariranje polja – kreiranje polja – inicijaliziranje polja – metoda System.arraycopy() – deklariranje, alociranje i inicijaliziranje dvodimenzionalnih polja – višedimenzionalna i neuravnotežena polja
Primitivni tipovi podataka u Javi vrlo su slièni onima u C i C++. To su boolean, byte, short, int, long, float, double i char. Tip boolean je dodan u Javi. Implementacija je meðutim bitno proèišæena na nekoliko naèina.
int
),
Java specificira sve.boolean
1-bit. Može poprimiti vrijednosti
true
ili false
.
true
i false
su definirane konstante jezika i
nisu isto što i True
i False
,
TRUE
i FALSE
,
nula i ne-nula, 1 i 0 ili bilo koja druga numerièka vrijednost. Ne može se
pretvoriti ni u jedan drugi tip varijable niti se drugi tipovi mogu pretvoriti
u boolean
.
byte
1 oznaèeni byte (komplenent od 2). Pokriva vrijednosti od -128 do 127.
short
2 bytea, oznaèena (komplement od 2), -32,768 to 32,767
int
4 bytea, oznaèena (komplement od 2), od -2,147,483,648 do 2,147,483,647. Kao kod svih numerièkih tipova, moguæe je pretvaranje (casting) u ostale numerièke tipove (byte, short, long, float, double). Kod pretvaranja s gubitkom informacija (lossy casts), npr int u byte, konverzija se obavlja modulo duljina “kraæeg” tipa.
long
8 bytea oznaèenih (komplement od 2), od -9,223,372,036,854,775,808 do +9,223,372,036,854,775,807.
float
4 bytea, IEEE 754, od 1.40129846432481707e-45 do 3.40282346638528860e+38 (positivni ili negativni).
Kao kod svih numerièkih tipova, moguæe je
pretvaranje (casting) u ostale numerièke tipove (byte
, short
, long
, int
, double
). Kod
pretvaranja s gubitkom informacija (lossy casts), npr float
u short,
decimalni dio se odbacuje, i konverzija se obavlja modulo duljina “kraæeg”
tipa.
double
8 bytea IEEE 754, od 4.94065645841246544e-324d do 1.79769313486231570e+308d (positivni or negativni).
char
2 bytea, neoznaèena, Unicode, od 0 do 65,535
Vrijednosti tipa char nisu isto što i vrijednosti tipa byte, int, short ili Strings.
Operator |
Akcija |
|
Zbrajanje brojeva, konkatenacija stringova |
|
Zbrajanje i pridruživanje brojeva, konkatenacija i pridruživanje stringova |
|
Oduzimanje |
|
Oduzimanje i pridruživanje |
|
Množenje |
|
Množenje i pridruživanje |
|
Dijeljenje |
|
Dijeljenje i pridruživanje |
|
Bitovski OR |
|
Bitovski OR i pridruživanje |
|
Bitovski XOR |
|
Bitovski XOR i pridruživanje |
|
Bitovski AND |
|
Bitovski AND i pridruživanje |
|
Modulo (raèunanje ostatka) |
|
Modulo i pridruživanje |
|
Veæe |
|
Veæe ili jednako |
|
manje |
|
Manje ili jednako |
|
booleovski NOT |
|
razlièito |
|
Poveæavanje za jedan |
|
Smanjivanje za jedan |
|
Shift – pomak bitova u desno, zajedno sa znakom |
|
Shift – pomak bitova u desno, zajedno sa znakom i pridruživanje |
|
Shift – pomak bitova u lijevo |
|
Shift – pomak bitova u lijevo i pridruživanje |
|
Neoznaèeni bitovski shift u desno |
|
Neoznaèeni bitovski shift u desno i pridruživanje |
|
Booleovski AND |
|
Booleovski OR |
|
Booleovska jednakost |
|
Pridruživanje |
|
Bitovski NOT |
|
Uvjet |
|
Provjera tipa |
Razmak je u pravilu znak [space], koji dobijete kad pritisnete <spacebar> no u Javi postoje još 4 znaka za razmak: [horizontal tab], [form feed], [carriage return] i [linefeed]. Ovisno o platformi, kad pritisnete tipku <return> ili <enter>, dobit æete [carriage return] (MAC), [linefeed] (UNIX) ili oboje (DOS, Windows, VMS). To æe proizvesti tvrdi prijelom linije u tekstu izvornog programa.
Osim u literalima tipa String
,
jedan razmak je ekvivalentan nizu uzastopnih razmaka bilo koje vrste.
Unutar literala tipa String
i char
jedini dozvoljeni razmak je znak [space].
Umjesto znakova [horizontal tab], [form feed], [carriage
return] i [linefeed] moraju se
stavljati odgovarajuæe escape-sekvence, npr. \t
, \r
, \f
i \n
. Ne
možete razlomiti string ovako:
String poem = "Mary had a little lamb
whose fleece was white as snow
and everywhere that Mary went
the lamb was sure to go.";
Umjesto
toga trebate koristiti znakove \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.";
Primijetite
da naredbe možete razlomiti kroz nekoliko redaka, jedino ne možete to uèiniti
sa literalima tipa String
.
Takoðer primijetite da \n funkcionira samo na UNIX-u. Ako želite svoj
kod uèiniti neovisnim o platformi, umjesto \n upotrijebit æete metodu System.getProperty("line.separator")
koja æe vratiti odgovarajuæi znak za danu platformu. Pogledajte takoðer i
metodu System.getProperties()
.
Java nema sve escape-sekvence koje ima C. Osim veæ spomenutih, to su još samo \b za [backspace] i \\ za sam [backslash]. No mogu se koristiti i \u sekvence koje dozvoljavaju umetanje bilo kojeg Unicode znaka.
Literali
tipa String
oznaèavaju se dvostrukim navodnicima, npr “Hello
World!”. Takoðer, “dva” + “dva”
je isto što i “dvadva”. Navodnici,
meðutim nisu dio literala. Vrijednost literala “Hello World!” je Hello World!, a ne “Hello World!”. Takoðer
formatiranje znakova nema utjecaja na vrijednost stringa, dakle “Hello World!” je isto što i “Hello World!”.
Literali
tipa char
oznaèavaju se jednostrukim navodnicima i smiju sadržavati toèno jedno slovo,
npr. ¸’c’ je literal tipa char
èija
vrijednost je slovo c.
Booleovski
literali su true
i false
,
a znaèe istinu i laž.
Brojevi
mogu takoðer biti literali. Npr. 34 je
literal tipa int
i njegova je vrijednost broj 34, dok je 1.5
literal tipa double
, a to
su i 45.6
, 76.4E8
(76.4 puta 10 na osmu) i
-32.0.
Nadalje, 34L
je literal tipa long
i oznaèava broj 34, dok su
1.5F
,
45.6f
i 76.4E8F
literali tipa float.
Identifikatori
su imena variabli, metoda, klasa, paketa i suèelja. Za razliku od literala to
nisu same stvari nego naèin njihovog referenciranja. U programu HelloWorld
identifikatori su HelloWorld
, String
, args
,
main
i System.out.println
.
Identifikatori moraju biti sastavljeni od slova, brojeva i znakova _ (underscore) i “$ (dollar sign). Poèetno slovo identifikatora smije biti samo slovo, _ ili $. Mala i velika slova se razlikuju. Ime ne može sadržavati razmak.
Ovo su primjeri legalnih varijabli u Javi:
MyVariable
myvariable
MYVARIABLE
x
i
_myvariable
$myvariable
_9pins
andros
ανδρος
OReilly
This_is_a_very_long_variable_name
Sljedeæih nekoliko primjera nisu valjana imena varijabli:
My Variable // sadrzi
razmak
9pins // pocinje brojem
a+c // + nije
alfanumericki znak
testing1-2-3 // - nije
alfanumericki znak
O'Reilly // ' nije
alfanumericki znak
OReilly_&_Associates
// & nije alfanumericki znak
Postoji 50 rezerviranih kljuènih rijeèi koje u Javi 1.1 (51 u Javi 1.2). U tablici je navedeno njih 48 koje se stvarno koriste.
Keyword |
Purpose |
|
Deklarira apstraktnu klasu ili metodu |
|
Deklarira booleovsku varijablu ili povratni tip (return type) |
|
Prijevremeni izlazak iz petlje |
|
Deklarira byte varijablu ili povratni tip |
|
Jedna od grana u naredbi switch |
|
Obrada iznimke |
|
deklarira char variablu ili povratni tip |
|
Oznaèava poèetak definiranja klase |
|
Prijevremeni povratak na poèetak petlje |
|
default akcija za switch naredbu |
|
Poèetak do while petlje |
|
deklarira double variablu ili povratni tip |
|
Oznaèava dio koda koji se izvršava ako uvjet u if naredbi nije istinit |
|
Oznaèava da je promatrana klasa potklasa neke druge klase |
|
Deklarira da klasa ne može imati podklasu ili da varijabla ili metoda ne može bit pregažena |
|
Deklarira blok koda koji æe garantirano biti izveden |
|
deklarira float variablu ili povratni tip |
|
Poèetak for petlje |
|
Izvršava kod ako je uvjet istinit |
|
Deklarira da promatrana klasa implementira dano suèelje |
|
Dopušta pristup klasi ili grupi klasa unutar paketa |
|
Ispituje da li je objekt instanca neke klase |
|
deklarira int (integer) variablu ili povratni tip |
|
Oznaèava poèetak definiranja suèelja |
|
deklarira long (long integer) variablu ili povratni tip |
|
Deklarira da je metoda implementirana u drugom programskom jeziku |
|
Alocira novi object |
|
Definira paket kojemu pripada datoteka sa promatranim izvornim kodom |
|
Deklarira metodu ili member varijablu kao privatnu |
|
Deklarira klasu, metodu ili member varijablu kao zaštiæenu |
|
Deklarira klasu, metodu ili member varijablu kao javnu |
|
Vraæa vrijednost iz metode |
|
deklarira short (short integer) variablu ili povratni tip |
|
Deklarira da varijabla ili metoda pripada klasi, a ne objektu |
|
Referenca na roditelja promatranog objekta |
|
Ispituje istinitost nekoliko moguæih uvjeta |
|
Oznaèava da je promatrani dio koda osjetljiv na threadove |
|
Referenca na sam promatrani objekt |
|
Odbacivanje iznimke |
|
Deklarira iznimke koje metoda odbacuje |
|
Varijabla ne smije biti serijalizirana |
|
Pokušava izvršiti operaciju koja može eventualno odbaciti iznimku |
|
Deklarira da metoda ne vraæa nikakvu vrijednost |
|
Upozorava kompajler da se varijabla mijenja asinhrono |
|
Poèetak while petlje |
Još
dvije, const
i goto
,
rezervirane su, ali nisu implementirane. To omoguæuje kompajleru bolje
kreiranje poruka o pogreškama u sluèaju krive upotrebe ovih uobièajenih
kljuènih rijeèi jezika C++ u Java programima.
Java
1.2 dodaje kljuènu rijeè strictfp
kojom se deklarira da metoda ili klasa mora biti izvršena sa egzaktnom IEEE 754
semantikom.
Primijetite
da true
and false
nisu kljuène rijeèi nego booleovski literali. Svejedno, ni njih ne možete
koristiti kao imena varijabli.
Separatori
pomažu u definiranju structure programa. U programu HelloWorld koriste se
zagrade, ( )
,
vitièaste zagrade, {
}
, toèka, .
,
toèka-zarez, ;
.
Separator |
Svrha |
( ) |
Zatvara argumente u definicijama i pozivima metoda; podešava prioritete izvršavanja u aritmetièkim izrazima; okružuje umjetno pretvorene tipove podataka (cast types); izdvaja uvjetne izraze u naredbama za kontrolu toka |
{ } |
Definira blokove koda; automatski inicijalizira polja |
[ ] |
Deklarira polje tipova; izdvaja vrijednosti elemenata polja |
; |
Završava naredbu |
, |
Razdvaja nanizane identifikatore u deklaracijama varijabli; ulanèava naredbe u uvjetnom dijelu for petlje |
. |
Selektira varijablu ili metodu nekog objekta; separira imena paketa od imena podpakete i imena klasa |
: |
Koristi se nakon labela u petljama |
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 dogaða kad izvršite AddInts
:
% javac AddInts.java
% java AddInts
i je 1
j je 2
i + j je 3
i - j je -1
%
double
Brojevi
tipa double
sadrže decimalnu toèku .
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:
% javac AddDoubles.java
% java AddDoubles
x je 7.5
y je 5.4
x + y je 12.9
x - y je 2.0999999999999996
Operatori množenja i dijeljenja su * (množenje) i / (dijeljenje).
class MultiplyDivide {
public static void main (String args[]) {
int i = 10;
int j = 2;
int k;
System.out.println("i je " + i);
System.out.println("j je " + j);
k = i/j;
System.out.println("i/j je " + k);
k = i * j;
System.out.println("i * j je " + k);
}
}
Rezultat:
% javac MultiplyDivide.java
% java MultiplyDivide
i je 10
j je 2
i/j je 5
i * j je 20
%
Realni brojevi tipa float i double množe se i dijele na isti naèin. U sluèaju cjelobrojnog dijeljenja, rezultat se zaokružuje prema dolje. Npr. cjelobrojno dijeljenje 10 sa 3 daje 3.
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
Operator
za raèunanje ostatka dijeljenja dvaju brojeva (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
%
Primijetite da se operacija modulo može u Javi primijeniti i na realne brojeve. Npr. 5.5 % 1.5 je 1.
Više operatora može biti u istom izrazu:
int m = 1
+ 2 + 3 + 4 + 5;
Sljedeæi program raèuna energiju ekvivalentnu masi jednog elektrona uz pomoæ Einsteinove formule E = 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 sluèaju razlièitih operatora, prioritet je uobièajen: Sljedeæe tri naredbe su ekvivalentne
int n = 1 - 2 * 3 - 4 + 5;
int n = 1 - (2 * 3) - 4 + 5;
int n= -4;
Unutar do sada spomenutih operatora, operacije se izvršavaju sljedeæim prioritetom:
Zagrade se koriste za mijenjanje uobièajenog redosljeda operacija. Sljedeæi primjer pokazuje pretvaranje Fahrenheitovih stupnjeva u Celsiusove po formuli C = (5/9) (F - 32) gdje su C stupnjevi Celsiusa a F stupnjevi Fahrenheita. Program ispisuje tablicu konverzija izmeðu 0 i 300 stupnjeva Fahrenheita za svakih 20 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 ovom programu nema mnogo novog u odnosu na prethodne primjere, no pažnju obratimo na sljedeæu liniju:
celsius = (5.0 / 9.0) * (fahr-32.0);
To je prijevod formule C = (5/9)(F - 32) gdje je dodana * za množenje jer Java ne podržava implicitno množenje faktora u zagradama. Zagrade se koriste kao i u obiènoj algebri, za prilagodbu pravila prioriteta. Za operacije koje koriste uobièajene aritmetièke operatore (+, -, *, /), pravila prioriteta su ista kao i u obiènoj algebri.
Razlièiti
tipovi podataka mogu se pojaviti u istoj naredbi. Primjer pokazuje istovremenu
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 + x je " + k);
k = i * x;
System.out.println("i * x je " + k);
k = i - x;
System.out.println("i - x je " + k);
k = x - i;
System.out.println("x - i je " + k);
k = i / x;
System.out.println("i / x je " + k);
k = x / i;
System.out.println("x / i je " + k);
}
}
Izlaz:
% javac IntAndDouble.java
% java IntAndDouble
i je 10
x je 2.5
i + x je 12.5
i * x je 25.0
i - x je 7.5
x - i je -7.5
i / x je 4.0
x / i je 0.25%
Redoslijed može imati utjecaja na rezultat kad se tipovi podataka miješaju. Na primjer,
1
/ 2 * 3.5 = 0.0
3.5 * 1 / 2 = 1.75
3.5 / 2 = 1.75
Kod miješanja tipova podataka, uobièajeni matematièki zakoni komutacije opæenito ne vrijede, posebno ne kad se miješaju cjelobrojne (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
Ako
int
podijelimo sa int
dobijemo int
.
Ako
double
podijelimo sa double
dobijemo double
.
Ako
int
podijelimo sa double
ili double
sa double
,
dobijemo double
jer u sluèaju nejednakosti tipova Java teži dodjeljivanju što šireg tipa kako
se sprijeèilo gubljenje informacija.
Pravilo:
·
Ako je bilo koja varijabla u aritmetièkoj binarnoj
operaciji (zbrajanje, oduzimanje množenje, dijeljenje, modulo) tipa double
onda
Java tretira obje vrijednosti kao double
.
·
Ako ni jedna nije double
, ali je jedna float
, Java
tretira obje vrijednosti kao float
.
·
Ako ni jedna nije ni float
ni double
, ali je jedna long
, Java
tretira obje vrijednosti kao long
.
·
Konaèno, ako ni jedna nije double
, float
ni long
, Java
tretira obje vrijednosti kao int
, èak ako u jednadžbi uopæe nema cijelih
brojeva.
Dakle,
rezultat æe biti double
,
float
,
long
ili int
,
ovisno o tipovima argumenata.
U
naredbi pridruživanja, dakle ako postoji znak jednakosti, Java usporeðuje tip
na lijevoj strani sa konaènim tipom na desnoj strani. Tip na lijevoj strani
neæe se promijeniti, ali æe se provjeriti da li vrijednost sa desne strane (double
, float
, int
or long
) odgovara
tipu na lijevoj strani. Sve se može smjestiti u double.
Sve osim double
može se
smjestiti u float.
Svaki cjelobrojni tip može se smjestiti u long, ali float
i double
ne mogu, dok se sve tipa int, short i byte
može smjestiti u int. Ako se desna strana može smjestiti u
lijevu, pridruživanje se normalno obavlja.
Pridruživanje
vrijednosti tipa long
varijablama tipa int
ili pak vrijednosti tipa double
varijablama tipa float
može uzrokovati probleme i kompajler vam takva pridruživanja neæe dopustiti
osim ako eksplicitno navedete da želite pretvaranje (casting). Prisilno
pretvaranje tipova oznaèava se navoðenjem odgovarajuæeg tipa u okruglim
zagradama neposredno prije izraza koji treba pretvoriti. Na primjer,
int i = (int) 9.0/4.0;
Kad
se vrijednost pretvara u drugi tip prije pridruživanja, niz operacija se
poduzima da bi se desna strana “skratila” na pravu velièinu. Za konverziju
izmeðu realnih (floating point) i cijelih brojeva (npr. int
ili long
), razlomljeni
dio se odbacuje (zaokružuje na nulu). To æe proizvesti cijeli broj. Ako je on
dovoljno mali da stane u lijevu stranu, pridruživanje je završeno. U suprotnom,
ako je prevelik, bit æe mu pridružena najveæa, a ako je premali, najmanja
moguæa vrijednost za odgovarajuæi tip.
Valja voditi raèuna o tome da prisilno pretvaranje može uzrokovati pogreške kojima æe biti vrlo teško uæi u trag i zato ovu moguænost treba koristiti s oprezom.
Prilikom
obrade korisnièkog inputa èesto je potrebno neki String
pretvoriti u int
. To se
radi uz pomoæ statièke metode Integer.valueOf(String
s)
u kombinaciji s (nestatièkom) metodom intValue()
koje pripadaju klasi java.lang.Integer
.
Npr. String
"22"
pretvorili bismo u int
22
na sljedeæi naèin:
int i = Integer.valueOf("22").intValue();
S
tipovima double
,
float
i long
postupamo slièno, koristeæi statièke metode Double.valueOf(String
s)
, Float.valueOf(String
s)
i Long.valueOf(String
s)
u kombinaciji s odgovarajuæim metodama doubleValue()
,
floatValue()
i longValue()
koje pripadaju, respektivno, klasama java.lang.Double
,
java.lang.Float
i java.lang.Long
.
String
"22" pretvorili bismo u long
22 ovako:
long l = Long.valueOf("22").longValue();
String
"22.5"
pretvorili bismo u float
ili double
ovako:
double x = Double.valueOf("22.5").doubleValue();
float y = Float.valueOf("22.5").floatValue();
Razlièite
valueOf()
metode relativno su inteligentne i mogu prepoznati znakove plus i minus,
eksponente i ostale uobièajene brojèane formate. Meðutim, ako kao argument
dobiju nešto potpuno ne-numerièko, npr. "Hello World"
,
vjerojatno æe izbaciti NumberFormatException
.
Za sad još niste uèili kako baratati s iznimakama pa u svojim programima
izbjegavajte takve situacije.
Preradit æemo sada program E = mc2 tako da o masi u kilogramima bude prihvaæen kao korisnièki input sa komandne linije. Ovaj postupak tipièan je za mnoge programe.
class mc2 {
public static void main (String args[]) {
double mass;
double c = 2.998E8; // meters/second
double E;
mass = Double.valueOf(args[0]).doubleValue();
E = mass * c * c;
System.out.println(E + " Joules");
}
}
Obrada i rezultati:
% javac mc2.java
% java mc2 0.0456
4.098529824E15 Joules
%
Primijetite da ne bi bilo dovoljno staviti
Mass = Double.valueOf(args[0]); // izostavljena je metoda doubleValue()
Statièka metoda Double.valueOf(args[0]) vratit æe vrijednost tipa Double, a tek æe metoda doubleValue() pretvoriti tu vrijednost u vrijednost tipa double. Zato bi navedena linija izazvala grešku u kompajliranju:
% javac mc2.java
mc2.java:8: incompatible types
found : java.lang.Double
required: double
mass = Double.valueOf(args[0]);
^
1 error
%
Podatak tipa char je pojedinaèni znak, tj. slovo, brojka, toèka, tab, praznina i slièno. Literali tipa char su pojedinaèni znakovi zatvoreni unutar jednostrukih navodnika, npr.
char myCharacter = 'g';
Za
znakove koji se ne mogu utipkati Java osigurava escape sekvence. To je
backslash iz kojeg slijedi alfanumerièki kod. Npr. '\n'
je znak
za novi reda, '\t'
je znak za tab, '\\'
je sam backslash. Definirane su sljedeæe escape sekvence:
\b |
backspace |
\t |
tab |
\n |
linefeed |
\f |
formfeed |
\r |
carriage return |
\" |
Dvostruki navodnici, " |
\' |
Jednostruki navodnici, ' |
\\ |
backslash, \ |
Escape sekvenca za dvostruke navodnike koristi se uglavnom u stringovima gdje bi pojava navodnika inaèe terminirala string. Npr.
System.out.println("And then Jim said, \"Who's at the door?\"");
Dvostruki navodnici unutar jednostrukih bit æe prepoznati i bez escape sekvence. Npr. sljedeæi redak je posve legalan u Javi.
char doublequote = '"';
Java koristi Unicode skup znakova. Unicode je dvobajtni znakovni kod koji reprezentira gotovo sve znakove u gotovo svim alfabetima i pismovnim sustavima svijeta, ukljuèujuæi engleski, arapski, kineski i druge. Problem je, meðutim, što mnogi operacijski sustavi i web preglednici ne podržavaju Unicode. Java æe uglavnom pravilno tretirati input ne-Unicode znakova. Prvih 128 znakova u Unicode tablici identièni su sa uobièajenim ASCII znakovima. Drugih 128 znakova podudara se sa gornjih 128 znakova u ISO Latin1 proširenom ASCII skupu. Ostalih 65,280 predstavlja problem.
Pojedinaène Unicode znakove možete referencirati koristeæi escape sekvancu \u iz koje slijedi èetverocifreni heksadecimalni broj. Npr.
\u00AE |
|
© |
|
Znak za copyright |
\u0022 |
|
" |
|
Dvostruki navodnici |
\u00BD |
|
1/2 |
|
Razlomak ½ |
\u0394 |
|
Δ |
|
Veliko grèko delta |
\u00F8 |
|
ø |
|
Malo o prekriženo znakom slash |
Možete èak koristiti potpune Unicode znakovne nizove za imenovanje varijabli. Npr.
String Mj\u00F8lner = "Hammer of Thor";
if
else
else if
while
for
do while
switch case
break
continue
Primijetite
da je goto
je rezervirana rijeè ali nije implementirana. O obradi iznimaka bit æe rijeèi
kasnije.
Primijetimo
da smo se u klasi emc2 koristili argumentom s komandne linije, ali
nismo provjeravali je li on uopæe unešen. Sljedeæi program ispisuje prvi
argument sa komandne linije, ali prvo uz pomoæ varijable arrayname.length
provjerava ima li argumenata.
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 umetnuta unutar testa, if (args.length > 0) { }
. Blok koda unutar
vitièastih zagrada, System.out.println(args[0])
,
bit æe izvršen ako i samo ako je duljina polja args veæa od nule.
Argumenti za kondicionalne naredbe kao što je if moraju biti booleovski, dakle izrazi koji se evaluiraju na true ili false. Cjelobrojni argumenti nisu dopušteni.
% javac Hello.java
% java Hello
%
% java Hello world!
% Hello world!
%
Testiranje jednakosti je nešto složenije. Oèekivali biste da se za ispitivanje jesu li dva broja jednaki koristi znak jednakosti =. Meðutim, on je rezerviran za operator pridruživanja pa je za ispitivanje jednakosti uveden novi znak, dvostruka jednakost, ==. Taj je znak posuðen iz C-a.
Ta se dva znaka greškom lako mogu zamijeniti, no kako u Javi nisu dozvoljeni na istim mjestima, kompajler æe to otkriti. Ipak, sljedeæa situacija može biti problematièna:
boolean b = true;
if
(b = false) {
System.out.println("b is false");
}
Da bi to izbjegli, neki programeri pišu testiranje uvjeta ovako:
boolean b = true;
if
(false = b) {
System.out.println("b is false");
}
Kako literalu ne možete pridružiti nikakvu vrijednost, kompajler æe u tom sluèaju otkriti da je ste umjesto == napisali =.
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!
%
Naredba
if
nije ogranièena na samo dva sluèaja. Kombiniranjem else
i if
dobije se else if
kako
bi se mogle ispitati sve moguænosti. Preradimo sada Hello program tako da
barata sa 4 imena s komandne linije.
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 naèin ispitivanja brzo postaje kompliciran. Postoje i bolja rješenja, kao što pokazuju sljedeæi primjeri.
class Hello {
public static void main (String args[]) {
int i;
System.out.print("Hello "); // Ispis Hello
i = 0; // Inicijaliziramo brojac prolaza kroz petlju
while (i < args.length) { // Testiramo i iteriramo
System.out.print(args[i]);
System.out.print(" ");
i = i + 1; // Povecamo brojac prolaza za 1
}
System.out.println(); // Zavrsimo liniju
}
}
% javac Hello.java
% java Hello
% Hello
%
% java Hello prvi drugi treci cetvrti
% Hello prvi drugi treci cetvrti
%
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 petlji potrebno inicijalizirati i inkrementirati više varijabli odjednom. U tom sluèaju se inicijalizatori i inkrementori odvajaju zarezima kao u sljedeæem primjeru:
for (
int i = 1, j = 100; i < 100;
i = i+1, j = j-1) {
System.out.println(i + j);
}
Ipak, višestruko ispitivanje uvjeta na ovaj naèin nije dopušteno. Sljedeæa naredba rezultirala bi porukom o greški u kompilaciji:
for (int i = 1, j = 100;
i <= 100, j > 0; i = i-1, j = j-1) { // pogresno !!!
Za višestruko ispitivanje uvjeta koriste booleovski logièki operatori && i || o kojima æe biti rijeèi kasnije.
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
%
Svaka
booleovska varijabla može poprimiti jednu od dvije vrijednosti true
ili false
.
Primijetite da te vrijednosti nisu isto što i String
ovi "true" i
"false", a nisu ni numerièke vrijednosti kao 1 i 0. Takoðer
primijetite da su rijeèi true i false rezervirane rijeèi u Javi, nazivaju se
booleovski literali i osjetljive su na velika i mala slova.
boolean test1 = true;
boolean test2 = false;
Java
ima 6 relacijskih operatora koji usporeðuju dva broja i vraæaju booleovsku
vrijednost. To su <
,
>
,
<=
,
>=
,
==
,
i !=
.
|
Manje |
True ako je x manje od y, inaèe false. |
|
Veæe |
True ako je x iveæe od y, inaèe false. |
|
Manje ili jednako |
True ako je x manje ili jednako y, inaèe false. |
|
Veæe ili jednako |
True ako je x veæe ili jednako + y, inaèe false. |
|
Jednako |
True ako je x jednako y, inaèe false. |
|
Nejednako |
True ako je x razlièito od y, inaèe false. |
Sljedeæi primjeri koda pokazju uporabu relacijskih operatora:
boolean test1 = 1 < 2; // True
boolean test2 = 1 > 2; // False
boolean test3 = 3.5 != 1; // True
boolean test4 = 17*3.5 >= 67.0 - 42; // True
boolean test5 = 9.8*54 <= 654; // True
boolean test6 = 6*4 == 3*8; // True
boolean test7 = 6*4 <= 3*8; // True
boolean test8 = 6*4 < 3*8; // False
To, meðutim ne ilustrira tipiènu uporabu booleovskih varijabli. U praksi se one gotovo jedino koriste u kondicionalnim naredbama i ispitivanjima uvjeta u petljama. Veæ smo vidjeli primjer:
if (args.length > 0) {
System.out.println("Hello " + args[0]);
}
gdje
je args.length
> 0
booleovska vrijednost, dakle true
ili false
. Zato
možemo takoðer pisati:
boolean
test = args.length > 0;
if (
test) {
System.out.println("Hello " + args[0]);
}
Pogledate li primjere u prethodnom odlomku, vidjet æete da se aritmetièke operacije obavljaju prije usporeðivanja. Inaèe bi npr.
boolean test8 = 6*4 < 3*8; // False
izazvalo
grešku u kompiliranju jer 4 < 3 vraæa false
, a to se ne može množiti sa 6
ili 8. Relacijski operatori izvršavaju se nakon aritmetièkih, a prije
operatora pridruživanja. Operator ==
ima nešto manji prioritet nego <, >, <= i >=. Pogledajte revidiranu
tablicu prioriteta:
Na primjer:
boolean b1 = 7 > 3 == true;
boolean b2 = true == 7 > 3;
b = 7 > 3;
Operatori
<, >, <= i >= mogu se primijeniti jedino na brojeve i znakove. Ne
mogu se koristiti sa String
ovima,
booleovskim varijablama poljima (arrays) kao ni s drugim neprimitivnim tipovima
za koje nije definiran linearni ureðaj. Za jednakost == vrijedi pravilo da je true
jednako true
i
razlièito od false
.
Isto tako je “Jack went up the hill” razlièito od “Jill went up the hill”.
Meðutim, pokušajte izvršite sljedeæi program:
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.");
}
}
}
Vidjet æete da je rezultat (neoèekivano):
Stringovi nisu jednaki.
To
nije ono što oèekujemo. Da bismo usporeðivali stringove ili objekte bilo koje
druge vrste, koristimo se metodom equals(Object
o)
iz paketa java.lang.String
.
Pogledajmo ispravnu verziju programa koja æe raditi onako kako oèekujemo.
Razlozi za ovo sežu prilièno duboko u filozofiju Jave i prirodu objekata kakvi
su 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
uzrokuje izlazak izpetlje prije nego što uvjet za ulazak u sljedeæu iteraciju
postane lažan. Na primjer, u sljedeæoj varijanti programa CountWheat
koji raèuna parcijalne sume reda Si=1,…,64(2i) pri èemu se
ispisuje poruka o pogreški i for
petlja se prekida èim nastane overflow
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!");
}
}
Pogledajmo obradu i izlaz:
% javac CountWheat.java
% java CountWheat
2 6 14 30
62 126 254 510
1022 2046 4094 8190
16382 32766 65534 131070
262142 524286 1048574 2097150
4194302 8388606 16777214 33554430
67108862 134217726 268435454 536870910
1073741822 2147483646 Overflow: grains = -2147483648
Gotovo!
%
Naredba
break
najèešæe se koristi unutar naredbe switch
.
Naredba
continue
vraæa kontrolu na poèetak najbliže unutarnje petlje kojom je obuhvaæena, ne
izvršavajuæi pri tom ostatak naredbi u tijelu petlje. Ako je to for
petlja,
brojaè se inkrementira. Sljedeæi primjer pokazuje kako se može preskoèiti
obrada parnih elemenata u polju:
for (int i = 0; i < m.length; i++) {
if (m[i] % 2 == 0)
continue;
// obrada neparnih elemenata...
}
U
praksi se nardba continue
ipak rjeðe koristi jer se u veæini sluèajeva problem može riješiti i bez nje.
Prethodni primjer mogao je izgledati i ovako:
for (int i = 0; i < m.length; i++) {
if (m[i] % 2 != 0) {
// obrada neparnih elemenata...
}
}
U
pravilu unutar ugnjiježdenih petlji naredbe break
i continue
uzrokuju napuštanje
najunutarnjije petlje koja ih obuhvaæa. Pogledajte sljedeæi primjer dvije
ugniježdene petlje:
for (int i=1; i < 10; i++) {
for (int j=1; j < 4; j++) {
if (j == 2) break;
System.out.println(i + ", " + j);
}
}
Rezultat izvršavanja bio bi
1, 1
2, 1
3, 1
4, 1
5, 1
6, 1
7, 1
8, 1
9, 1
jer se unutarnja petlja prekine svaki put kad j postane 2, ali se vanjska petlja izvrši do kraja. Ako želimo prekinuti obje petlje, labelirajmo vanjsku petlju i navedimo tu labelu u 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 rezultat izvršavanja bio
1, 1
jer
je j
postao 2, a vanjska petlja je prekinuta.
Switch-case
naredba je zapravo kratica za odreðene vrste if naredbi. Pogledajmo sljedeæi
niz if
naredbi koje se sve odnose na istu velièinu:
if (x == 0) doSomething0();
else if (x == 1) doSomething1();
else if (x == 2) doSomething2();
else if (x == 3) doSomething3();
else if (x == 4) doSomething4();
else doSomethingElse();
Ovaj bi se kod uz pomoæ switch-case naredbe mogao zapisati ovako:
switch (x) {
case 0:
doSomething0();
break;
case 1:
doSomething1();
break;
case 2:
doSomething2();
break;
case 3:
doSomething3();
break;
case 4:
doSomething4();
break;
default:
doSomethingElse();
}
U
ovom primjeru x mora biti varijabla ili izraz koji se izraèunava ili pretvara u
int
bez gubitka informacija To znaèi da varijabla mora biti, odnosno da izraz mora
vraæati rezultat tipa int
,
byte
,
short
ili char
.
Izraz x
usporeðuje se redom s vrijednostima navedenim u svakoj case
naredbi
dok se ne naiðe na podudarnost. U našem primjeru se x
usporeðuje s
literalima, ali to takoðer mogu biti varijable ili izrazi koji vraæaju rezultat
tipa int
,
byte
,
short
ili char
.
Ako se ni u jednom sluèaju ne pronaðe podudarnost izvršava se akcija naznaèena
sa default
.
Kad
je podudarnost pronaðena, izvršava se sve što slijedi do kraja switch
bloka
ili naredbe break
.
Uobièajeno je stavljati break
naredbu na kraj svakog case
bloka kako bi se izbjegli razni neoèekivani efekti.
Vrijednost neke varijable èesto ovisi samo o tome je li neka booleovska varijabla istinita ili ne. Npr. jedna od uobièajenih operacija je traženje maksimuma izmeðu dvije vrijednosti i pridruživanje te velièine nekoj varijabli:
if (a > b) {
max = a;
}
else {
max = b;
}
Kako
je ovo èesta situacija, uveden je kondicionalni operator ? : kao kratica za
ovakvu if-else
strukturu. Ovaj bismo primjer mogli pisati ovako:
max
= (a > b)
?
a :
b;
pri
èemu je (a >
b) ? a : b;
izraz koji vraæa jednu od dvije vrijednosti, a ili b,
ovisno o tome je li uvjet (a
> b)
istinit ili lažan. Ako je istinit, vraæa se
a
, u suprotnom
b
.
Uvjet može biti bilo koji izraz koji vraæa booleovsku vrijednost.
Kondicionalni operator funkcionira jedino kod pridruživanja vrijednosti nekoj varijabli, korištenja vrijednosti za pozivanje metode ili u nekim drugim situacijama kad je tip njegovog drugog i treæeg argumenta definiran. Pogledajmo sljedeæi primjer:
if (name.equals("Rumplestiltskin")) {
System.out.println("Give back child");
}
else {
System.out.println("Laugh");
}
Ovo se ne može zapisati ovako:
name.equals("Rumplestiltskin")
// ovo je primjer pogresne upotrebe operatora ?:
? System.out.println("Give back child")
: System.out.println("Laugh");
Prije svega, drugi i treæi argument su void (ne vraæaju vrijednost). Takoðer, nikakvo pridruživanje ne naznaèuje tip koji bi trebalo oèekivati za drugi i treæi operator (iako se zna da to ne može biti void).
Prvi argument mora vraæati regularni booleovski tip, a drugi i treæi argument moraju vraæati vrijednosti koje su kompatibilne sa cijelim oèekivanim povratnim izrazom. Nikad ne možete koristiti void metode kao argumente kondicionalnog operatora.
Do
sada uvedeni relacijski operatori (<, <=, >, >=, !=) dovoljni su za
testiranje pojedinaènog uvjeta.Za ispitivanje višestrukih uvjeta, morali bismo
koristiti više if
naredbi:
if (x == 2) {
if (y != 2) {
System.out.println("Oba uvjeta su true.");
}
}
To,
meðutim, može biti nepregledno, a taj nedostatak rješava se uporabom logièkih
operatora &&
,
||
i !
.
Operator
&&
je logièki and koji za dvije booleovske vrijednosti i vraæa 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 logièki or koji za dvije booleovske vrijednosti vraæa true
ako je
bar jedan operand true
.
Npr.
boolean b;
b = 3 > 2
|| 5 < 7; // b je true
b = 2 > 3
|| 5 < 7; // b je i dalje true
b = 2 > 3
|| 5 > 7; // now b je false
Operator
!
je logièka negacija koja za booleovsku vrijednost vraæa true
ako je
operand false
i obrunuto. Npr.
boolean b;
b =
!(3 > 2); // b je false
b =
!(2 > 3); // b je true
Ovi operatori omoguæuju jednostavnje ispitivanje višestrukih uvjeta. Naš prvi primjer može se sada zapisati mnogo preglednije:
if (x == 2
&& y != 2) {
System.out.println("Oba uvjeta su true.");
}
Prilikom
izvršavanja operatora &&
ili||
,
prvo se izraèunava izraz na lijevoj strani operatora. Pogledajmo sljedeæi
primjer:
boolean b, c, d;
b = !(3 > 2); // b je false
c = !(2 > 3); // c je true
d = b && c; // d je false
Kad
se izraèunava izraz d
= b && c;
, prvo se provjerava da li je b
true
. Ovjdjeje
b
false,
pa onda takoðer b
&& c
mora biti false
bez obzira je li c
true
ili nije.
Zato se vrijednost varijable c u ovom izrazu uopæe ne provjerava.
Na
isti naèin, kad Java naiðe na operator ||
, pokušat æe skratiti izraèunavanje
èim ustanovi da je lijevi operand true
, jer onda i cijeli rezultat mora
biti true
.
boolean b = (n == 0) || (m/n > 2);
boolean b = (n != 0) && (m/n > 0);
Èak
ako je n jednako nuli, neæe se dogoditi dijeljenje s nulom jer se lijeva strana
prva izraunava, a ako je istinita, onda se desna neæe ni raèunati. Ova
skraæivanja nisu za Javu toliko znaèajna kao za C jer u Javi oba operanda za &&
i ||
moraju biti
booleovska pa to reducira sporedne efekte koji ovise o tome jesu li ili
operandi stvarno izraèunati. No svejedno, moguæe je eksplicitno specificirati
raèunanje oba operanda, tj. izbjeæi skraæivanje.
Ako
želite izraèunavati vrijednosti booleovskih izraza bez obzira na istinosnu
vrijednost možete se koristiti operatorima &
i |
(bitovski and i bitovski
or) umjesto &&
i ||
.
Meðutim, pazite da operandi budu zaista booleovski jer ovi operatori imaju svoj
smisao i za numerièke tipove, a znaèenje im je ondje posve drugaèije.
Dodajmo
konaèno operatore &&
,
||
,
&
,
|
i ?
u tablicu prioriteta:
Polja
moraju imati odreðeni tip, npr. byte
, int
, String
ili double
. Samo
varijable odgovarajuæeg tipa mogu biti spremljene u isto polje. Jedno polje ne
može istodobno sadržavati recimo brojeve i stringove. Polja moraju kao i ostale
varijable biti deklarirana. Deklariraju se dodavanjem uglatih zagrada []
kao sufiks
tipu varijable. Na primjer:
int[] k;
float[] yt;
String[] names;
Ovo znaèi da je k polje int-ova, yt polje float-a, a names polje String-ova. Uglate zagrade možete po vlastitom izboru dodati i varijabli umjesto tipu ili èak jednom i drugom.
int k[];
float yt[];
String names[];
int[] k[];
float[] yt[];
String[] names[];
Deklarirajuæi
polje samo smo rekli koje vrste vrijednosti æe polje sadržavati. Time ga još nismo
kreirali. Polja se kao i ostali objekti u Javi kreiraju pomoæu kljuène rijeèi new.
Varijable
koje smo maloprije deklarirali možemo kreirati ovako:
k = new int[3];
yt = new float[7];
names = new String[50];
Brojevi u uglatim zagradama specificiraju duljinu polja, tj. Koliko ima komponenata koje æe sadržati vrijednosti. Polje k može imati 3 broja tipa int, polje yt može sadržati 7 brojeva tipa float, a polje names može sadržati 50 String-ova. Ovaj se korak ponekad naziva alociranjem polja jer se njime izdvaja potrebna memorija za polje.
Pojedinaène
komponente polja referenciraju se imenom polja i cijelim brojem koji
predstavlja poziciju komponente unutar polja. Ovi se brojevi nazivaju subskriptima
ili indeksima komponenti u polju. Indeksi su cijeli brojevi poèevši od 0
(nula). Dakle gore deklarirano polje k ima komponente k[0], k[1]
i k[2].
Buduæi da se poèinje od nule, ne postoji k[3]. Pokušaj
referenciranja nepostojeæe komponente rezultirat æe odbacivanjem iznimke ArrayIndexOutOfBoundsException
.
Komponente polja mogu se upotrebljavati kao i druge varijable koje nisu
komponente polja.
k[0] = 2;
k[1] = 5;
k[2] = -2;
yt[17] = 7.5f;
names[4] = "Fred";
Ovaj se korak naziva inicijaliziranjem polja, preciznije inicijaliziranjem komponenata polja. Pod inicijaliziranjem polja obièno se podrazumijeva inicijaliziranje svih komponenata polja. Naravno da za iole veæa polja neæemo inicijalizirati jednu po jednu komponentu, nego æemo se poslužiti petljom kao u sljedeæem primjeru:
float[] squares;
squares = new float[101];
for (int i=0; i <= 100; i++) {
squares[i] = i*i;
}
Primijetimo da æe brojevi tipa int kad budu spremljeni u ovo polje postati float jer je polje tako deklarirano.
Kopiranje
polja nije neki težak zadatak, ali je efikasnije ako je implementirano u samom
sustavu. Zato java.lang.System
sadrži statièku metodu System.arraycopy()
koju možete koristiti za kopiranje jednog polja u drugo. Definirana je ovako:
public static void arraycopy(Object source, int sourcePosition,
Object destination, int destinationPosition, int numberOfElements)
Metoda
System.arraycopy()
kopira numberOfElements
elemenata iz polaznog poja source
, poèevši s elementom na poziciji sourcePosition
,
na polje destination
poèevši od pozicije destinationPosition
.
Polje destination
mora veæ postojati u trenutku pozivanja metode System.arraycopy()
jer ga ona
sama neæe kreirati.. Polja source
i destination
moraju biti istog tipa. 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);
Dvodimenzionalna polja se deklariraju, alociraju i inicijaliziraju slièno kao jednodimenzionalna. Specificirat æete dvije dimenzije umjesto jedne i vjerojatno koristiti dvije ugniježdene petlje. U sljedeæem primjeru se svakom elementu dvodimenzionalnog polja dodjeljuje suma njegovih indeksa.
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, algoritam za punjenje polja ovisi iskljuèivo o namjeni pojedinog polja. U sljedeæem primjeru raèunamo jediniènu matricu zadane velièine (kvadratnu matricu koja po dijagonali ima jedinice, a ostali elementi su 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 polju iznimka ArrayIndexOutOfBoundsException
pojavljuje se kad god prekoraèite maksimalni indeks bilo po recima bilo po
stupcija.
Dvodimenzionalno polje možete takoðer deklarirati, alocirati i inicijalizirati u jednom koraku, zadajuæi listu inicijalnih vrijednosti unutar ugniježdenih vitièastih zagrada. Npr. jedinièna 3x3 matrica može se zadati ovako:
double[][] ID3 = {
{1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, 0.0, 1.0}
};
Razmaci i prijelomi redaka su iskljuèivo zbog programera. Sljedeæi zapis bio bi posve ekvivalentan prethodnom:
double[][] ID3 = {{1.0, 0.0, 0.0},{0.0, 1.0, 0.0},{0.0, 0.0, 1.0}};
Ne morate se ogranièavati na dvodimenzionalna polja. Java dopzšta polja od 3, 4 ili više dimenzija. Ipak, ako trebate više od 3 dimenzije za polje, vjerojatno koristite pogrešnu strukturu podataka. Èak su i trodimenzionalna polja rijetka osim u programima za znanstvene i inženjerske aplikacije.
Sintaksa za trodimenzionalna polja je direktna ekstenzija sintakse za dvodimenzionalna. Sljedeæi program deklarira, alocira i inicijalizira jedno trodimenzionalno polje. U svaki element spremljena je suma njegovih indeksa.
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 ugniježdena for
petlja za baratanje dodatnom dimenzijom.
Sintaksa za još više dimenzije je slièna.
Java kao ni C nema pravih višedimenzionalnih polja. Java simulira višedimenzionalna polja koristeæi polja èiji su elementi druga polja. To znaèi da je moguæe imati i neuravnotežena polja, dakle polja u kojima dimenzija nije jednaka za sve retke. U praksi, meðutim, takve strukture valja izbjegavati.