Ylös Edellinen Seuraava Otsikkosivu Hakemisto Sisällys

8.6.5 Parametrinvälitysmekanismi

Ainoa Java- kielen tuntema parametrinvälitysmekanismi on parametrien välittäminen arvoina. Tämä tarkoittaa sitä, että aliohjelma saa käyttöönsä vain (luku)arvoja, ei muuta. Olkoon meillä esimerkiksi ongelmana tehdä aliohjelma, jolle viedään parametreinä tunnit ja minuutit sekä niihin lisättävä minuuttimäärä. Jos ensimmäinen yritys olisi seuraava:

java-muut\Aikalisa.java - yritys lisätä arvoja

	/**	:-(
	 * Yritetään lisätä metodissa parametrien arvoja
	 * @author  Vesa Lappalainen
	 * @version 1.0, 18.01.2003
	 */
	public class Aikalisa {
	
	  private static void lisaa(int h, int m, int lisa_min) {
	    int yht_min = h*60 + m + lisa_min;
	    h = yht_min / 60;
	    m = yht_min % 60;
	  }
	  
	  private static void tulosta(int h, int m) {
	    System.out.println("" + h + ":" + m);
	  }
	  
	  public static void main(String[] args) {
	    int h=12,m=15;
	    tulosta(h,m);
	    lisaa(h,m,55);
	    tulosta(h,m);
	  }
	  
	}

Tämä ei tietenkään toimisi! Hyvä (C-) - kääntäjä jopa varoittaisi että:

	Warn :  aikalisa.cpp(8,2):'m' is assigned a value that is never used
	Warn :  aikalisa.cpp(7,2):'h' is assigned a value that is never used

Mutta miksi ohjelma ei toimisi? Seuraavan selityksen voi ehkä ohittaa ensimmäisellä lukukerralla. Tutkitaanpa tarkemmin mitä aliohjelmakutsussa oikein tapahtuu. Oikaisemme seuraavassa hieman joissakin kohdissa liian tekniikan kiertämiseksi, mutta emme kovin paljoa. Esimerkki on kirjoitettu vastaavasta C++-ohjelmasta. Javassa periaatteessa tapahtuu samalla tavalla. Katsotaanpa ensin miten kääntäjä kääntäisi aliohjelmakutsun ( Borland C++ 5.1, 32-bittinen käännös, rekisterimuuttujat kielletty jottei optimointi tekisi konekielisestä ohjelmasta liian monimutkaista):

	lisaa(h,m,55);
	
	muistiosoite assembler         selitys
	-------------------------------------------------------------------------
	004010F9     push 0x37           pinoon 55
	004010FB     push [ebp-0x08]     pinoon m:n arvo 
	004010FE     push [ebp-0x04]     pinoon h:n arvo
	00401101     call lisaa          mennään aliohjelmaan lisää
	00401106     add esp,0x0c        poistetaan pinosta 12 tavua (3 x int)

Kun saavutaan aliohjelmaan lisaa, on pino siis seuraavan näköinen:

	muistiosoite  sisältö          selitys
	------------------------------------------------------------------------
	064FDEC       00401106 <-ESP   paluuosoite kun aliohjelma on suoritettu
	064FDF0       0000000C         h:n arvo, eli 12
	064FDF4       0000000F         m:n arvo, eli 15
	064FDF8       00000037         lisa_min, eli 55

Eli aliohjelmaan saavuttaessa aliohjelmalla on käytössään vain arvot 12,15 ja 55. Näitä se käyttää tässä järjestyksessä omien parametriensa arvoina, eli m,h,lisa_min.

Esimerkiksi Pascal ja C/C++ -kielissä olisi tarjota tähän sellainen ratkaisu, että aliohjelman parametrit olisivatkin viitteitä (tai osoittimia) kutsuvan ohjelman muuttujiin ja niihin tehty muutos muuttaisi suoraan kutsuvan ohjelman muuttujia. Javassa tämä on mahdollista vain olioille, koska oliot välitettiin viitteinä.

	C++:    void lisaa(int &h, int &m, int lisamin);           kutsu: lisaa(h,m,55);
	Pascal: procedure lisaa(var h,m:integer; lisamin:integer); kutsu: lisaa(h,m,55);
	C:      void lisaa(int *h, int *m, int lisamin);           kutsu: lisaa(&h,&m,55)

Tehtävä 8.20 Muotoilu?

Kokeilepa laittaa ajaksi esim. 12:05. Mitä tulostuu? Miten vian voisi korjata?

Tehtävä 8.21 Tiedon lukeminen

Kirjoita aliohjelma lue_kello, joka kysyy ja lukee arvon kellonajalle, syöttö muodossa 12:15.


Ylös Edellinen Seuraava Otsikkosivu Hakemisto Sisällys