Praktikum nr. 2
Teemad
Eclipse.
Java põhikonstruktsioonid: valikulaused, tsüklid.
Staatilised meetodid. Signatuur. Java massiiv.
Pärast selle praktikumi
läbimist üliõpilane
- oskab keskkonnaga Eclipse koostada ja
käivitada elementaarseid Java programme;
- oskab sooritada aritmeetilisi tehteid;
- oskab kasutada klassi Math meetodeid;
-
teab, mis on formaalsed parameetrid, meetodi tüüp, naasmisdirektiiv;
- oskab koostada ja kasutada lihtsaid staatilisi meetodeid
(sh. samanimelisi);
- tunneb
ühemõõtmelise järjendi
(massivi) ülesehitust;
- oskab järjendit erineval moel luua ja selle
elementidele uusi väärtusi anda;
- oskab koostada ja rakendada lihtsamaid meetodeid
järjendi uurimiseks ühekordse tsükli abil;
- oskab käsurealt saadud andmeid kasutada neid
vajadusel teisendades sobivasse algtüüpi.
Praktikumi materjal on kohandatud kasutamiseks Linuxiga arvutiklassis 205,
mujal võib olla väikesi erinevusi.
Keskkond Eclipse
Esimeses praktikumis kirjutasime programme tavalise lihtsa
tekstiredaktoriga
ja kompileerisime ning käivitasime käsurealt. Alguses
on see
õpetlik - näeme, et programmi tekst ongi lihtsalt
tekst ja
programmi töölepanemisel on mitu etappi. Kui aga teha
rohkem
ja suuremaid programme, siis on mõistlik kasutada
spetsiaalseid
keskkondi, mis osa tööd programmeerija eest
"ära teeb".
Käesoleva kursuse nö. ametlik keskkond on Eclipse.
Lubatud on
kasutada ka teisi keskkondi, aga neid eraldi ei tutvustata.
Eclipse on vabavara, mis töötab
erinevatel
operatsioonisüsteemidel (Windows,
Linux, Solaris ..). Eclipse
toetab erinevates programmeerimiskeeltes töötamist
(Java, PHP, C++, ...), samuti
saab tema abil töötada
nt. UML-ga. Eclipse
evib hästi palju võimalusi.
Meie vaatleme (ja esialgu vajame) neist vaid osasid.
Meie tegutseme Java projektidega.
Põhieesmärgiks on
algtekstide toimetamine, süntaktiline silumine ja
käivitamine. Silumise hõlbustamiseks saab panna
katkestuspunkte, mille abil saab jälgida muutujate
väärtuste muutumist. Teie andmed asuvad
töökataloogis (workspace).
Sinna
peab kasutajal olema õigus kirjutada. Meie puhul sobib
selleks nt. kodukataloogi alamkataloog oop.
Iga projekt paigutub eraldi alamkataloogi, milles siis on erinevad
failid.
Ülesanne A1
Püüdkem nüüd Eclipse
käivitada
- Arvutiklassis Eclipse'i
saab kätte valides Computer --> More Applications --> Development
--> Eclipse.
- Töökataloogiks määrake nt. oma kodukataloogi alamkataloog
oop
- Tervitusaknad võite sulgeda, aga
võite ka neid soovi korral lugeda.
- Valige Window --> Open Perspective --> Others
...--> Java(default) või ärge
valige midagi, sest Java ongi vaikimisi.
- Looge uus Java projekt
File --> New --> Java Project või
File --> New --> Project ... --> Java Project
- Pange projektile mõistlik nimi. Esialgu
võiks aktsepteerida vaikimisi vastuseid loomisdialoogis.
- Nüüd peaks Package Explorer aknas
olema teie loodud projekt olemas. Kui sellel hiire parema klahviga
klõpsata, siis avaneb menüü.
- Looge uus klass: New --> Class, nimi alaku
suurtähega. Klassi loomise dialoogis
- jätke Package tühjaks,
- Modifiers olgu public,
- Superclass olgu java.lang.Object,
- loodavatest
meetoditest märgime ära public static void main(String[]
args).
- Toimetiaknas
on nüüd teksti toorik.
- Kirjutage main-meetodisse
midagi mõistlikku, mis ka midagi ekraanile
väljastab, ja salvestage.
- Käivitage Run --> Run
või Run --> Run As --> Java
Application
- Tulemus peaks ilmuma konsooliaknasse.
Kui soovite töötada juba varem tehtud failidega, siis
kasutage importimist File
--> Import...
--> General -->
File system.
Eclipse'i
koduleht on http://www.eclipse.org.
Ingliskeelse juhendi leiab vastavalt aadressilt http://help.eclipse.org/kepler/index.jsp.
Ülesanne A2
Harjutame nüüd aritmeetilisi tehteid. Alustame
täisarvuliste (int-tüüpi)
muutujatega. Täisarvuliste muutujatega saab teha
mitmesuguseid tehteid, millest siinkohal tulevad vaatluse alla
- liitmine (+)
- lahutamine (-)
- korrutamine (*)
- jagamine (/)
- jäägi leidmine (%)
Enamasti toimivad need nii nagu matemaatikas kombeks, kuid on ka
erinevusi. Koostage programm nende tehete omadustega tutvumiseks.
Selleks kirjeldage täisarvulised muutujad a,
b,
c,
d,
e
ning omistage muutujale a
väärtus 2147483647,
ülejäänute väärtused
valige ise.
1. Liitke, lahutage, korrutage, jagage muutujate
väärtusi. Leidke ka jääki.
2. Mis saab siis, kui muutuja a
väärtusele liita 1? Kuidas seda tulemust seletada?
Tulemused väljastage näiteks nii:
System.out.println("Arvude
" + b + " ja " + c + " summa on " + (b + c));
Mis muutub, kui avaldises (b + c)
sulud ära jätta?
Kui täisarvudega on lihtsam, siis ujukomaarvudega on ka Javas
täpsuse küsimus. Proovige näiteks System.out.println(1-0.9);
Ülesanne P1
Kirjutage lühidalt paberile,
- miks 2147483647 ühte liites just selline vastus
tuli;
- miks on 1-0.9 vastus selline.
Klass Math
Kui on vaja ümardada, siis saame kasutada meetodit Math.round.
Näiteks
Math.round(0.7)
või
Math.round(m1),
kui m1
on enne väärtustatud. Klass Math
on juba valmis tehtud ja vajadusel saame selle klassi meetodeid
kasutada. Näiteks juhusliku reaalarvu leidmiseks
võib
kasutada meetodit Math.random
,
mis
tagastab (pseudo)juhusliku double
-tüüpi
arvu poollõigust [0,0; 1,0) (st 0
on kaasa arvatud, 1 aga
mitte). Omistamisdirektiivi
double
juhuarv = Math.random();
täitmisel omandab muutuja juhuarv
konkreetse väärtuse, mida me ette ei
tea. Kui on vaja
juhuslikku arvu mingis teises poollõigus, siis saab selle
moodustada korrutamise ja liitmise abil. Näiteks
avaldise Math.random()*10+20
väärtus ei ole väiksem kui 20.0 ja on
väiksem kui
30.0.
Kui on tarvis juhuslikku täisarvu, siis oleks sobivaks teeks
näiteks reaalarvulise juhusliku arvu ümardamine. Tähele
tuleb panna, et Math.random
tagastab double-tüüpi
arvu, kuid Math.round
tagastab double-tüüpi
argumendi puhul long
-tüüpi
täisarvu. Niisiis toimivad kenasti järgmised omistamised:
double reaalJuhuarv = Math.random()*5+15;
long longJuhuarv = Math.round(Math.random()*5+15);
Kui aga tahaksime int-tüüpi juhuslikku arvu, siis on vajalik tüübiteisendus:
int taisJuhuarv = (int)Math.round(Math.random()*5+15);
Ülesanne P2
Proovige, kas eeltoodud variandid toimivad ja annavad vajalikud juhuarvud. Proovige ka varianti
int valeJuhuarv = (int)Math.random()*5+15;
ning kommenteerige paberil viimase näite olemust.
Selleks, et teada saada, millised on mingi konkreetse
klassi Math
meetodi võimalikud argumentide ja tagastatavate
väärtuste tüübid ja millised
meetodid klassis Math
üldse olemas on, avage Java API
veebileht
ja otsige raamist All
classes üles
link Math.
Pärast klassi üldist tutvustust on
väljade ja
meetodite loetelu koos lühitutvustustega. Näeme, et mõningaid meetodinimesid on korduvalt,
näiteks abs
on neli korda ja round
kaks korda. Tõesti saab ühes klassis olla mitu
samanimelist
meetodit. Aga ainult sellisel juhul, kui formaalsete parameetrite
(argumentide) arvus ja/või tüüpides on
erinevused. Antud juhul siis on eraldi meetodid
absoluutväärtuse leidmiseks double-,
float-,
int-
ja long-tüüpi
argumendi jaoks. Ja erinevused on siis ka
tagastustüübis.
Meetodi iseloomustust, mis koosneb meetodi nimest ja formaalsete
parameetrite tüüpide loetelust, nimetatakse signatuuriks.
Niisiis ühes klassis peavad meetodite signatuurid olema
erinevad.
Ülesanne A3 --> P3
Proovige erinevate klassi Math
meetodite tööd. Proovige mõnda
ühe ja
mõnda kahe argumendiga meetodit. Proovige ka kasutada
väärtusi e
ja π.
Proovige ja tutvuge ka vähemalt ühe sellise
funktsiooniga, millest te varem kuulnud pole. Palun kirjutage paberile,
mis meetoditega tutvusite ja mida teeb teile seni
võõras
olnud funktsioon.
Teeme ise meetodeid
Kuigi olemasolevates sadades klassides on tuhandeid meetodeid,
mida
saame kasutada, peame oskama ka ise neid juurde teha. Selles
praktikumis piirdume staatiliste
meetoditega (nimetatakse ka klassimeetoditeks).
Eristatavad on need seeläbi, et piiritlejaks on
võtmesõna static.
Kui vaadata klassi Math
meetodeid, siis need on kõik staatilised, mida kasutades
tuleb
meetodi ette lisada klassinimi. Staatiline on ka peameetod main.
Signatuur
on meetodi (või
konstruktori) iseloomustus, mis koosneb nimest ning formaalsete
parameetrite tüüpide loetelust. Näiteks kui
meetodi päis on static
double korrutaKolmArvu (double a, double b, double c),
siis signatuur on korrutaKolmArvu(double,
double, double).
Meetodi igal väljakutsel väärtustatakse
vastavate
argumentide väärtusega muutujad (formaalsed
parameetrid),
mis on meetodi formaalsete parameetrite loetelus
kirjeldatud. Need muutujad on kasutatavad ainult selle meetodi kehas.
Rõhutame, et kui meetod ei tagasta väärtust, siis on
tagastustüübiks void
(tühitüüp). Kõigil teistel
juhtudel aga peab tagastustüüp olema
kooskõlas sellega, mis tüüpi
väärtuse meetod tagastab. Tagastatakse aga selle
avaldise väärtus, mis asub naasmisdirektiivis
võtmesõna return
järel.
Meetodeid võib ühes klassis olla mitmeid, näiteks
järgmises klassis on kolm meetodit, kõik staatilised.
class KolmArvu {
static double korrutaKolmArvu(double a, double b, double c){
return a*b*c;
}
static void valjasta(double a, double b, double c){
System.out.println("Antud arvud: " + a + ", " + b + ", " + c);
}
public static void main(String[] args) {
double x = 1.5;
double y = 2.25;
double z = 3;
valjasta(x, y, z);
System.out.println("Nende korrutis: " + korrutaKolmArvu(x, y, z));
}
}
Ülesanne A4 --> P4
Ühes klassis võivad olla ka samanimelised meetodid. Koostage kolm
samanimelist (aga muidugi erineva signatuuriga) staatilist
meetodit,
mis vastavalt sellele, millist tüüpi ja kui palju on
argumente, tagastaksid erinevat tüüpi
väärtuse. Näiteks
- kui argumentideks on kaks int-tüüpi
arvu, siis tagastatakse nende summa;
- kui argumentideks on üks double-tüüpi
arv, siis tagastatakse selle arvu ruut, mis on ümardatud
täisarvuks;
- kui argumentideks on sõne ja int-tüüpi
arv, siis ei tagastataks midagi, aga see sõne
väljastatakse
ekraanile vastav arv kordi (kasutage tsüklit).
Rakendage loodud meetodeid peameetodis. Palun kirjutage paberile
koostatud meetodite signatuurid.
Järjend, massiiv
Lineaarselt järjestatud hulka nimetatakse jadaks,
igal jada elemendil on tema järjenumbrit näitav indeks.
Järjendiks
nimetatakse lõplikku jada.
Programmeerimises
on järjendeid sageli vaja ning nende kujutamiseks
sobib
ühemõõtmeline massiiv. Javas
saab järjend
(massiiv) koosneda
vaid üht tüüpi elementidest.
Võime
rääkida näiteks täisarvude
massiivist. Kuna
järjend ja massiiv on tihedalt seotud, siis järgnevas
tekstis
ongi neid käsitletud praktiliselt
sünonüümidena.
Näitena vaatleme viieelemendilist järjendit a
,
mis koosneb Javas
elementidest
a[0]
a[1]
a[2]
a[3]
a[4]
Kõik elemendid on ühte ja sama
tüüpi, arvu nurksulgudes (järjekorranumbrit)
nimetatakse elemendi indeksiks. Iga element
võib sõltumata teistest elementidest sisaldada
korraga ühte väärtust
– täisarvujärjendi puhul täisarvu,
reaalarvujärjendi puhul reaalarvu jne, ning igale elemendile
võib väärtuse omistada teistest
elementidest sõltumatult. Javas kehtib
reegel, et
järjendi elementide numeratsioon algab
alati nullist. Kui järjendis on kokku n
elementi,
siis viimase elemendi indeks on n-1
.
Niisugust ühekohalist „nihet“
võrreldes harjunud loendamisviisiga tuleb Java-programmide
koostamisel silmas pidada. (Järjendi elemendid
võivad olla
ka ise järjendid (kõik siis muidugi üht
tüüpi järjendid, küll aga
võib nende pikkus
olla erinev). See lause on lugemiskontrolliks - palun kirjutage paberile
ennustus, kas pärast oktoobrikuiseid valimisi jääb Tartu linnapea koht
reformierakonnale ja Tallinna linnapea koht keskerakonnale.
Sellisel juhul kujutatakse seda Javas
kahemõõtmelise
massiivina ja konkreetsele elemendile viidatakse kahe indeksiga, nt. b[2][3].)
Järjendi kirjeldamiseks (programmis
kasutuselevõtmiseks) on mitu võimalust,
kõige lihtsam on seda teha massiivialgati
abil. Näiteks kui oleme viiel päeval lugenud
kraadiklaasilt temperatuuri väärtused
10 9 12
11 8
siis võime nendest moodustada järjendi
int[] a
= {10, 9, 12, 11, 8};
Niisuguse kirjelduse toimel võtab arvuti kasutusele
täisarvujärjendi a
ja
omistab selle elementidele järjestikku loogelistes sulgudes
antud väärtused (seega näiteks a[0]
väärtuseks saab 10
ja
a[1]
väärtuseks 9
).
Ühtlasi määratakse kindlaks
järjendi elementide arv ehk massiivi pikkus,
mis saab konstandi a.length
väärtuseks (praegusel juhul on selleks 5
).
(Tegelikult on lubatud ka nurksulgude teine paigutus: int a[]
= ...)
Teine võimalus järjendi
kasutuselevõtuks on massiiviloome.
Eelneva näitega samaväärse tulemuse saame ka
nii, et moodustame kõigepealt käsuga
int[] a
= new int[5];
tühja viieelemendilise järjendi. Selle
kõigi elementide algväärtuseks
määratakse automaatselt 0
.
Seejärel omistame elementidele nullide asemel vajalikud
väärtused:
a[0] =
10;
a[1]
= 9;
a[2]
= 12;
a[3]
= 11;
a[4]
= 8;
Järjendi ühe elemendi
väärtust võib väljastada
standardsel viisil nagu iga teise muutuja väärtust.
Näiteks korraldus
System.out.println("Jarjendi
esimene element on " + a[0]);
väljastab ekraanile järjendi a
(tavamõttes) esimese elemendi väärtuse.
Järjend ja tsükkel
Järjendi kõigi väärtuste
väljastamiseks tuleb terve järjend, alates algusest,
elementhaaval läbida. Väga sobiv vahend selleks on
for-tsükkel,
millel on siinkohal isegi kaks varianti. Näiteks
programmilõik
for (int
i = 0; i < a.length; i++) {
System.out.println(a[i]);
}
teeb just vajalikku tegevust – igal sammul, kui
tsüklimuutuja i
saab
järjekordse väärtuse, trükitakse
ekraanile järjekordse indeksiga element. Muutuja i
algväärtus on 0
ja
lõppväärtus ühe võrra
väiksem kui järjendi pikkus. Indeksi nihke
tõttu vaadatakse läbi parajasti kõik
järjendi elemendid esimesest viimaseni. Näiteks
5-elemendilise järjendi puhul on:
i
väärtus
|
ekraanile
väljastatakse
|
märkus
|
0 |
10 |
a[0]
väärtus |
1 |
9 |
a[1]
väärtus |
2 |
12 |
a[2]
väärtus |
3 |
11 |
a[3]
väärtus |
4 |
8 |
a[4]
väärtus |
5 |
|
tsükli
lõpp |
Nagu eelnevast programmitekstist näha,
võib elemendi indeksiks olla ka muutuja. Kui muutuja i
on saanud mingi väärtuse, siis on arvutil lihtne
kindlaks teha, millist elementi järjendis tähistab a[i]
.
Samamoodi võib indeksis esineda keerukam aritmeetiline
avaldis, sel juhul arvutab arvuti kõigepealt välja
avaldise väärtuse ja siis otsib järjendist
üles vastava järjenumbriga elemendi.
Kui on vaja järjend läbida nii, et erinevaid elemente
pole
vaja võrrelda, asendada või eemaldada, siis on
kasutatav for-tsükli
nö. for-each
versioon. Ülaltoodud lõigu saab siis kirja panna ka
nii:
for
(int elem : a){
System.out.println(elem);
}
Ülesanne A5 --> P5
- Looge peameetodis massiiviloome abil täisarvude järjend, mis
sisaldab kümne
matkaja masse, mis on juhuslikult genereeritud vahemikus
50 kuni 110. Kasutage juhuarvu genereerimisel ja ümardamisel
klassi Math
vastavaid meetodeid. (Tegelikult on olemas ka klass Random,
aga ärgem seda veel puutugem, kuna seal pole staatilisi
meetodeid.)
- Koostage ka sama tegevust sooritav meetod, mille
argumentideks oleksid matkajate arv, masside alumine ja
ülemine
piir. Meetodi tagastustüüp peaks olema int[]. Seda
meetodit peameetodis rakendades luua 20-liikmeline järjend.
- Väljastage peameetodis eraldi tsüklite abil ekraanile
kummagi järjendi kõik elemendid. Seejärel väljastada
tsükli ja valikulause (if)
abil ainult need esimese järjendi elemendid, mille
väärtus on üle 80. Katsetage
mõlemat for-tsükli
versiooni.
- Koostage ja rakendage meetod, mis leiab matkajate masside harmoonilise keskmise.
Formaalseks parameetriks on siis täisarvude massiiv. (Harmooniline keskmine
on aritmeetilisest ja geomeetrilisest keskmisest vähem tuntud, aga mitmetel
juhtudel siiski väga kasulik (näiteks keskmise kiiruse arvutamisel, kui
võrdne teepikkus läbitakse erinevate ühtlaste kiirustega). Käesolevas
masside näites on see küll pigem kunstlik.)
Paberile kirjutada harmoonilise
keskmise definitsioon ja koht, kust te selle leidsite (kui te seda
peast ei teadnud).
Ülesanne P6
<-->A6
Palun kirjutage paberile ilma arvutis katsetamata, mida
väljastatakse ekraanile.
int[]
jarj1 = {1, 3, 6};
int[]
jarj2;
jarj2
= jarj1;
System.out.println(jarj1[1]);
System.out.println(jarj2[1]);
jarj2[1]=4;
System.out.println(jarj2[1]);
System.out.println(jarj1[1]);
Katsetage arvutis ja analüüsige oma vastust.
Sõnejärjend
Kui vaadata peameetodit, siis selle signatuuris paistab ka
järjend
- sõnejärjend. Peameetodil ongi formaalne
parameeter, mille
nime võib vabalt valida, aga sageli on selleks valitud args.
Tegelikult saamegi selle abil kasutada käsurealt saadud
sõnesid. Näiteks kui programm käivitada
käsurealt: java Klassinimi Tartu Riia
saame sõnejärjendi, mille pikkus on kaks ja
tema elemendid omandavad väärtused args[0]
= "Tartu", args[1]
= "Riia".
Käsurealt saadud elemendid on sõned. Kui
tahame neid
kasutada näiteks täisarvudena või
reaalarvudena, peame
neid enne teisendama. Selleks saab kasutada vastavates mähisklassides olevaid
meetodeid. Näiteks sõne täisarvuks
teisendamisel on kasutatav meetod Integer.parseInt, mille
argumendiks tulebki sõne anda. Näiteks oletame, et
kui käsureal on argumendiks reaalarv 1.67 (java
Matkajapikkus 1.67), siis
double pikkus = Double.parseDouble(args[0]);
muudab selle reaalarvuks, millega saame tehteid teha.
Kui kasutame Eclipse'it,
siis saame käsurea argumente
anda valides Run-menüüst Run Configurations...
--> (x)=Arguments
ja sisestades argumendid kasti Program
arguments.
Kui on
vaja luua sõnejärjendit programmi sees, siis toimub
nii järjendi loomine kui ka tema elementidele
väärtuste samamoodi kui arvujärjendite
korral:
String[]
sõned = {"Ilus", "punane", "maasikas"};
või
String[] sõned = new
String[pikkus];
Ülesanne A7 --> P7
Koostage programm, mis saab käsurealt inimese eesnime,
kehamassi
(kilogrammides, täisarvuna) ja pikkuse (meetrites,
reaalarvuna)
ning arvutaks tema kehamassiindeksi ning annaks vastavalt tulemusele
vähemalt kolme sorti soovitusi (näiteks,
"Söö
rohkem", "Kasva pikemaks" jms.)
Kirjutage paberile,
millised on
käsurealt lugemise ja eelmises praktikumis käsitletud
klaviatuurilt sisestamise põhilised erinevused. Milliste
programmide puhul võiks neid rakendada?
Kodune ülesanne!
- Kontrollige, kas Te olete kõik selle ja eelmise
praktikumi
ülesanded ära teinud. Kui pole, siis tehke. Kui olete
kahekesi teinud, siis veenduge, et ka üksi suudaksite.
- Kui midagi selgusetuks jäi, siis palun
küsige
järgmisel praktikumil praktikumijuhendajalt või
kirjutage
Moodle'i foorumisse.
- Kas oskate mõnele foorumis olevale vastuseta
küsimusele vastata? Vastake.
- Vaadake Moodle'is
olevat Pythoni
ja Java
võrdlust.