Metode u Javi: parametri, povratna vrednost i rekurzija

Lekcija 8 od 16 · Java

Metoda je imenovani deo programa koji obavlja jedan zadatak – kao funkcija u C-u ili Python-u. Metode skraćuju program, sprečavaju ponavljanje koda i olakšavaju traženje grešaka. Ovde su statičke metode, koje se pozivaju bez objekta; metode objekata dolaze u lekciji o klasama.

Pre nego što počneš: potrebno predznanje – petlje, nizovi.
Kako da učiš: svaki primer prekucaj i pokreni, a zadatke na kraju prvo reši sam/a; uputstvo i rešenje otvori tek posle toga. Svi programi su u Javi (Java 17 ili novija); svaki je preveden i pokrenut i daje navedeni izlaz.

Definisanje i poziv metode

Metoda ima zaglavlje (modifikatori, tip povratne vrednosti, ime, parametri) i telo u vitičastim zagradama. Naredba return vraća rezultat i završava metodu.

public class Main {
    // static: metoda pripada klasi, poziva se bez objekta
    // int: tip vrednosti koju vraća; (int x): parametar
    static int kvadrat(int x) {
        return x * x;
    }

    // void: metoda ne vraća vrednost, samo nešto uradi
    static void linija(int duzina, char znak) {
        for (int i = 0; i < duzina; i++)
            System.out.print(znak);
        System.out.println();
    }

    public static void main(String[] args) {
        linija(20, '=');
        for (int i = 1; i <= 4; i++)
            System.out.println(i + " na kvadrat je " + kvadrat(i));
        linija(20, '-');
        int zbir = kvadrat(3) + kvadrat(4);      // rezultat se koristi u izrazu
        System.out.println("3^2 + 4^2 = " + zbir);
    }
}

Pri pozivu se argumenti (stvarne vrednosti) dodeljuju parametrima redom: u pozivu linija(20, '=') parametar duzina dobija 20, a znak dobija '='.

Metode koje odgovaraju sa da/ne

Metoda tipa boolean čini uslov čitljivim: if (jeProst(n)) se čita kao rečenica.

import java.util.Scanner;

public class Main {
    static boolean jeProst(int n) {
        if (n < 2) return false;
        for (int d = 2; (long) d * d <= n; d++)
            if (n % d == 0)
                return false;          // return odmah završava metodu
        return true;
    }

    static int zbirCifara(int n) {
        int zbir = 0;
        while (n > 0) {
            zbir += n % 10;
            n /= 10;
        }
        return zbir;
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int a = sc.nextInt(), b = sc.nextInt();
        // prosti brojevi iz intervala čiji je zbir cifara takođe prost
        for (int x = a; x <= b; x++)
            if (jeProst(x) && jeProst(zbirCifara(x)))
                System.out.print(x + " ");
        System.out.println();
    }
}

Prenos argumenata: kopija vrednosti

Java argumente uvek prenosi po vrednosti: metoda dobija kopiju. Promena prostog parametra (int, double…) ne utiče na promenljivu iz poziva. Kod nizova i objekata kopira se referenca – metoda radi sa istim nizom, pa promene elemenata ostaju vidljive.

import java.util.Arrays;

public class Main {
    static void uvecaj(int x) {
        x = x + 10;                      // menja se samo kopija
    }

    static void uvecajSve(int[] niz) {
        for (int i = 0; i < niz.length; i++)
            niz[i] += 10;                // menja se originalni niz
    }

    public static void main(String[] args) {
        int a = 5;
        uvecaj(a);
        System.out.println("a = " + a);

        int[] brojevi = {1, 2, 3};
        uvecajSve(brojevi);
        System.out.println(Arrays.toString(brojevi));
    }
}

Preklapanje metoda (overloading)

Više metoda može imati isto ime ako se razlikuju po broju ili tipovima parametara. Java bira metodu prema argumentima u pozivu:

public class Main {
    static int max(int a, int b) {
        return a > b ? a : b;
    }

    static int max(int a, int b, int c) {        // isto ime, tri parametra
        return max(max(a, b), c);
    }

    static double max(double a, double b) {      // isto ime, drugi tip
        return a > b ? a : b;
    }

    static int max(int[] niz) {                  // niz kao parametar
        int m = niz[0];
        for (int x : niz)
            m = max(m, x);
        return m;
    }

    public static void main(String[] args) {
        System.out.println(max(3, 8));
        System.out.println(max(3, 8, 5));
        System.out.println(max(2.5, 1.5));
        System.out.println(max(new int[]{4, 9, 1, 7}));
    }
}

Upravo zato System.out.println radi i sa brojem, i sa tekstom, i sa znakom – postoji više preklopljenih verzija.

Rekurzija: metoda koja poziva samu sebe

Rekurzivna metoda rešava problem tako što ga svodi na manji problem iste vrste. Mora imati izlazni slučaj u kome se više ne poziva, inače se poziva beskonačno (greška StackOverflowError).

public class Main {
    // n! = n · (n-1)!,  0! = 1
    static long faktorijel(int n) {
        if (n == 0) return 1;              // izlazni slučaj
        return n * faktorijel(n - 1);      // svođenje na manji problem
    }

    // NZD(a, b) = NZD(b, a % b),  NZD(a, 0) = a  (Euklidov algoritam)
    static int nzd(int a, int b) {
        return b == 0 ? a : nzd(b, a % b);
    }

    // ispis broja u binarnom zapisu
    static void binarno(int n) {
        if (n > 1)
            binarno(n / 2);                // prvo ispiši više cifre
        System.out.print(n % 2);
    }

    public static void main(String[] args) {
        System.out.println("10! = " + faktorijel(10));
        System.out.println("NZD(84, 36) = " + nzd(84, 36));
        binarno(37);
        System.out.println();
    }
}

Više o rekurziji i o tome kada je bolja petlja: Rekurzija.

Zadaci za vežbu

Za svaki zadatak postoji primer, uputstvo i rešenje. Rešenja su provereno tačna na primerima iz teksta.

ZADATAK 01Težina: lako

Savršeni brojevi

Broj je savršen ako je jednak zbiru svojih delilaca manjih od sebe (6 = 1 + 2 + 3). Napisati metodu static int zbirDelilaca(int n) i pomoću nje ispisati sve savršene brojeve do n, razdvojene razmakom.

Primer

Ulaz

1000

Izlaz

6 28 496
ZADATAK 02Težina: srednje

Stepen brzo

Napisati rekurzivnu metodu static long stepen(long a, int n) koja računa an u log n koraka: ako je n paran, an = (an/2)2, a ako je neparan, an = a · an−1. Učitati a i n i ispisati rezultat (rezultat staje u long).

Primer 1

Ulaz

2 62

Izlaz

4611686018427387904

Primer 2

Ulaz

3 5

Izlaz

243
Česte greške i saveti
  • Metoda se piše van metode main, ali unutar klase.
  • Metoda koja nije void mora vratiti vrednost u svakom slučaju – inače greška „missing return statement“.
  • Promenljive deklarisane u metodi (lokalne) ne vide se u drugim metodama; podatke prenosi kroz parametre i povratnu vrednost.
  • Rekurzija bez izlaznog slučaja završava se greškom StackOverflowError.

Proveri znanje

Otvori kviz

Metode u Javi

1. Šta znači void u zaglavlju metode?




2. Metoda promeni vrednost parametra tipa int. Šta se dešava sa promenljivom iz poziva?




3. Kada dve metode smeju imati isto ime?




4. Šta svaka rekurzivna metoda mora da ima?