10. Metodit

Metodi

Metodi on tietyn asian tekevä koodinpätkä. Olemme jo käyttäneet monia metodeita, vaikka niitä ei ole kutsuttu sillä nimellä. Esimerkiksi ArrayListin add on metodi, jolla saa lisättyä arvon listalle. Samoin merkkijonon length on metodi, jolla saa selville merkkijonon pituuden.

Tähän asti kaikki ohjelmamme on tehty seuraavaan runkoon:

import java.util.*;

public class OhjelmanNimi {
    private static Scanner input = new Scanner(System.in);

    public static void main(String[] args) {
	...
    }
}

Jokaisen Java-ohjelman osana on metodi main, joka on ohjelman tärkein metodi. Heti kun ohjelma käynnistyy, metodi main aloittaa toimintansa. Sitten kun metodi main päättyy, myös ohjelman suoritus päättyy.

Periaatteessa minkä tahansa ohjelman voisi kirjoittaa kokonaan main-metodiin, mutta suurista ohjelmista tulisi hyvin sekavia tällä tavalla toteutettuina. Nyt onkin aika opetella tekemään omia metodeita vanhan tutun main-metodin tueksi.

Esimerkki

Seuraavassa ohjelmassa on oma metodi tulostaViesti:

import java.util.*;

public class ViestinTulostus {
    private static Scanner input = new Scanner(System.in);

    public static void tulostaViesti(String viesti) {
        System.out.println(viesti);
    }

    public static void main(String[] args) {
        tulostaViesti("Tervetuloa!");
        tulostaViesti("Kappas kippis!");
        tulostaViesti("Hei hei!");
    }
}

Ohjelman tulostus on seuraava:

Tervetuloa!
Kappas kippis!
Hei hei!

Metodin tulostaViesti tehtävänä on tulostaa sille annettu merkkijono. Ohjelma kutsuu metodia kolmesti antaen sille kolme eri viestiä. Metodin kutsussa suoritetaan metodin sisällä oleva koodi. Metodin päättymisen jälkeen ohjelman suoritus jatkaa kohdasta, jossa metodia kutsuttiin.

Metodin rakenne

Metodin alussa olevat sanat public static void saavat selityksen myöhemmin. Toistaiseksi meidän riittää tietää, että kaikki toimii, kun aloitamme metodimme näillä sanoilla.

Näiden jälkeen tulee kiinnostava asia eli metodin nimi. Tällä nimellä metodia voi kutsua muualta koodista. Yllä olevassa esimerkissä metodin nimi oli tulostaViesti.

Metodin parametrit ovat sulkeissa nimen jälkeen. Parametrien avulla metodille voi välittää tietoa muualta koodista. Jokaisesta parametrista ilmoitetaan tyyppi ja nimi. Yllä olevassa esimerkissä metodin parametrin tyyppi oli String ja nimi oli viesti. Parametrin avulla metodille annettiin tulostettava viesti.

Esimerkki: Viestin toistaminen

Laajennetaan edellistä esimerkkiä lisäämällä siihen uusi metodi toistaViesti:

import java.util.*;

public class ViestinTulostus {
    private static Scanner input = new Scanner(System.in);

    public static void tulostaViesti(String viesti) {
        System.out.println(viesti);
    }
    
    public static void toistaViesti(String viesti, int kerrat) {
        for (int i = 0; i < kerrat; i++) {
            tulostaViesti(viesti);
        }
    }

    public static void main(String[] args) {
        toistaViesti("Tervetuloa!", 3);
        toistaViesti("Kappas kippis!", 4);
        toistaViesti("Hei hei!", 2);
    }
}

Ohjelman tulostus on seuraava:

Tervetuloa!
Tervetuloa!
Tervetuloa!
Kappas kippis!
Kappas kippis!
Kappas kippis!
Kappas kippis!
Hei hei!
Hei hei!

Metodille toistaViesti annetaan kaksi parametria: tulostettava viesti ja toistokertojen määrä. Metodissa toistaViesti on silmukka, joka kutsuu edelleen metodia tulostaViesti.

Seuraava kuva havainnollistaa, kuinka ohjelma kutsuu metodeja:

Metodien hyödyt

Metodien käyttämisestä on kaksi hyötyä:

Palautusarvo

Metodin palautusarvo on arvo, jonka metodi palauttaa sen kutsukohtaan muualla koodissa.

Palautusarvon tyyppi merkitään metodin määrittelyssä metodin nimen eteen. Jos metodilla ei ole palautusarvoa, käytetään sanaa void. Muuten merkitään arvon tyyppi tavalliseen tapaan.

Metodi palauttaa arvon kutsukohtaan komennolla return.

Esimerkki

Seuraavassa ohjelmassa on kaksi arvon palauttavaa metodia:

import java.util.*;

public class ArvonPalautus {
    private static Scanner input = new Scanner(System.in);

    public static int tuplaa(int n) {
        return n * 2;
    }
    
    public static int suurempi(int a, int b) {
        if (a > b) {
            return a;
        } else {
            return b;
        }
    }

    public static void main(String[] args) {
        System.out.print("Anna luku: ");
        int luku = Integer.parseInt(input.nextLine());
        int tulos = tuplaa(luku);
        System.out.println("Tuplattu: " + tulos);

        System.out.println("Anna kaksi lukua:");
        int eka = Integer.parseInt(input.nextLine());
        int toka = Integer.parseInt(input.nextLine());
        System.out.println("Suurempi: " + suurempi(eka, toka));
    }
}

Ohjelman suoritus voi olla seuraava:

Anna luku: 3
Tuplattu: 6
Anna kaksi lukua:
2
5
Suurempi: 5

Metodille tuplaa annetaan luku, ja metodi palauttaa luvun kaksinkertaisena. Metodille suurempi annetaan kaksi lukua, ja metodi palauttaa luvuista suuremman.

Huomaa kaksi erilaista tapaa käyttää metodin palautusarvoa: sen voi sijoittaa muuttujaan tai suoraan tulostuskomennon osaksi.

Esimerkki: Merkkijonon kääntäminen

Seuraava metodi kääntää merkkijonon ympäri:

public static String kaanna(String merkkijono) {
    String tulos = "";
    for (int i = 0; i < merkkijono.length(); i++) {
        char merkki = merkkijono.charAt(i);
        tulos = merkki + tulos;
    }
    return tulos;
}

Metodia voi kutsua koodissa vaikkapa seuraavasti:

System.out.println(kaanna("esimerkki"));

Tämän koodin tulostus on seuraava:

ikkremise

Metodi muodostaa käännetyn merkkijonoon muuttujaan tulos. Se käy läpi merkkijonon merkit alusta loppuun ja lisää joka kerta merkin muuttujan tulos alkuun. Varmista vielä, että ymmärrät metodin toiminnan.

Esimerkki: Palindromin tarkistaminen

Merkkijono on palindromi, jos se on sama alusta loppuun ja lopusta alkuun luettuna. Esimerkiksi merkkijono "saippuakauppias" on palindromi. Seuraava metodi tarkistaa, onko merkkijono palindromi:

public static boolean palindromi(String merkkijono) {
    return merkkijono.equals(kaanna(merkkijono));
}

Metodia voi käyttää koodissa seuraavasti:

System.out.println("Anna sana: ");
String sana = input.nextLine();
if (palindromi(sana)) {
    System.out.println("Sana on palindromi.");
} else {
    System.out.println("Sana ei ole palindromi.");
}

Ohjelman suoritus voi olla seuraava:

Anna sana: enne
Sana on palindromi.

Metodi palindromi palauttaa arvon true, jos merkkijono on palindromi, ja muuten arvon false. Metodi vertaa keskenään kahta asiaa: alkuperäistä merkkijonoa ja metodin kaanna tuottamaa käännettyä merkkijonoa. Metodin equals palauttama totuusarvo soveltuu sellaisenaan palautusarvoksi.

Metodin lopettaminen

Komento return lopettaa metodin suorituksen välittömästi, vaikka se olisi keskellä metodia. Komentoa voi käyttää myös silloin, kun metodi ei palauta arvoa. Silloin komennon ainoa vaikutus on, että metodin suoritus päättyy.

Esimerkki: Onko negatiivista lukua?

Seuraava metodi tarkistaa, onko listalla negatiivista lukua:

public static boolean onNegatiivinen(ArrayList<Integer> lista) {
    for (int luku : lista) {
        if (luku < 0) {
            return true;
        }
    }
    return false;
}

Metodia voi käyttää koodissa seuraavasti:

ArrayList<Integer> luvut = new ArrayList<Integer>();
luvut.add(5);
luvut.add(9);
luvut.add(-4);
luvut.add(6);    
if (onNegatiivinen(luvut)) {
    System.out.println("Listalla on negatiivinen luku.");
} else {
    System.out.println("Listalla ei ole negatiivista lukua.");
}

Ohjelman tulostus on seuraava:

Listalla on negatiivinen luku.

Metodi onNegatiivinen käy läpi listalla olevia lukuja. Heti jos vastaan tulee negatiivinen luku, metodi palauttaa arvon true ja päättyy. Silmukan jälkeen metodi palauttaa arvon false, koska silloin listalla ei ollut negatiivista lukua.

Rekursiivinen metodi

Rekursiivinen metodi on siitä erikoinen, että se kutsuu itseään. Tyypillinen esimerkki rekursiivisesta metodista on kertoman laskeva metodi. Kokonaisluvun n kertoma n! tarkoittaa tuloa 1 · 2 · 3 · ... · n, eli esimerkiksi 5! = 1 · 2 · 3 · 4 · 5 = 120. Lisäksi on sovittu, että 0! = 1.

Seuraava rekursiivinen metodi laskee kertoman:

public static int kertoma(int n) {
    if (n == 0) {
        return 1;
    } else {
        return n * kertoma(n - 1);
    }
}

Mieti, miten metodi saa laskettua esimerkiksi luvun 5 kertoman.