CodeGym /Java Blog /Willekeurig /Methoden in Java
John Squirrels
Niveau 41
San Francisco

Methoden in Java

Gepubliceerd in de groep Willekeurig
Welkom terug! In de laatste les hebben we kennis gemaakt met klassen en constructors, en geleerd hoe we onze eigen kunnen maken. Vandaag maken we kennis met Java Methods, een essentieel onderdeel van de lessen. Een methode in Java is een set opdrachten waarmee u een specifieke bewerking in een programma kunt uitvoeren. Met andere woorden, een methode is een functie; iets dat uw klas kan doen. In andere programmeertalen worden methoden vaak "functies" genoemd, maar in Java komt het woord "methode" vaker voor. :) Als je het je herinnert, hebben we in de vorige les eenvoudige methoden voor een kattenklas gemaakt , zodat onze katten miauwen en springen konden zeggen:

public class Cat {

    String name;
    int age;

    public void sayMeow() {
        System.out.println("Meow!");
    }

    public void jump() {
        System.out.println("Pounce!");
    }

    public static void main(String[] args) {
        Cat smudge = new Cat();
        smudge.age = 3;
        smudge.name = "Smudge";

        smudge.sayMeow();
        smudge.jump();
    }
}
sayMeow() en jump() zijn methoden van onze klasse. En het uitvoeren van deze methoden resulteert in de volgende console-uitvoer:
Meow!
Pounce!
Onze methoden zijn vrij eenvoudig: ze voeren gewoon tekst uit naar de console. Maar in Java hebben methoden een belangrijke taak: ze voeren acties uit op de gegevens van een object. Ze veranderen de gegevens van het object, transformeren het, tonen het en doen er andere dingen mee. Onze huidige methoden doen niets met de gegevens van het Cat- object. Laten we eens kijken naar een meer illustratief voorbeeld:

public class Truck {

    int length;
    int width;
    int height;
    int weight;

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
Hier hebben we bijvoorbeeld een klasse die een vrachtwagen vertegenwoordigt . De semi-vrachtwagen heeft een lengte, breedte, hoogte en gewicht (die we later nodig zullen hebben). Met de methode getVolume() voeren we berekeningen uit, waarbij we de gegevens van ons object converteren naar een getal dat het volume vertegenwoordigt (we vermenigvuldigen de lengte, breedte en hoogte). Dit nummer is het resultaat van de methode. Merk op dat de declaratie van de methode is geschreven als public int getVolume . Dat betekent dat deze methode een int moet teruggeven . We hebben de retourwaarde van de methode berekend en nu moeten we deze terugsturen naar het programma dat onze methode heeft aangeroepen. Om het resultaat van een methode in Java te retourneren, gebruiken we het sleutelwoord return. retourvolume;

Java-methodeparameters

We kunnen waarden die "argumenten" worden genoemd doorgeven aan een methode wanneer deze wordt aangeroepen. De declaratie van een methode bevat een lijst met variabelen die ons het type en de volgorde van variabelen vertellen die de methode kan accepteren. Deze lijst wordt de "methodeparameters" genoemd. De methode getVolume() van onze klasse Truck definieert momenteel geen parameters, dus laten we proberen ons vrachtwagenvoorbeeld uit te breiden. Maak een nieuwe klasse met de naam BridgeOfficer . Dit is een politieagent van dienst op een brug, die alle passerende vrachtwagens controleert om te zien of hun lading het toegestane gewicht overschrijdt.

public class BridgeOfficer {

    int maxWeight;

    public BridgeOfficer(int normalWeight) {
        this.maxWeight = normalWeight;
    }

    public boolean checkTruck(Truck truck) {
        if (truck.weight > maxWeight) {
            return false;
        } else {
            return true;
        }
    }
}
De checkTruck- methode accepteert één argument, een Truck- object, en bepaalt of de officier de truck al dan niet op de brug toelaat. Binnen de methode is de logica eenvoudig genoeg: als het gewicht van de vrachtwagen het toegestane maximum overschrijdt, retourneert de methode false . Het zal een andere weg moeten vinden :( Als het gewicht kleiner is dan of gelijk is aan het maximum, kan het passeren en geeft de methode true terug. Als je de uitdrukkingen "teruggeven" of "de methode retourneert een waarde" nog niet helemaal begrijpt, laten we dan even stoppen met programmeren en ze bekijken aan de hand van een eenvoudig voorbeeld uit het echte leven. :) Laten we zeggen dat je ziek wordt en een paar dagen thuisblijft van je werk. Je gaat met je doktersbriefje naar de boekhouding, want ziekteverlof hoort doorbetaald te worden. Vergelijken we deze situatie met methoden, dan heeft de accountant een paySickLeave()methode. U geeft een doktersverklaring door als argument voor deze methode (zonder deze werkt de methode niet en krijgt u er niet voor betaald!). Vervolgens worden binnen de methode de nodige berekeningen gemaakt met behulp van uw notitie (de accountant gebruikt deze om te berekenen hoeveel het bedrijf u zou moeten betalen), en het resultaat van uw werk (een geldbedrag) wordt aan u geretourneerd. Ons programma werkt op een vergelijkbare manier. Het roept een methode aan, geeft er gegevens aan door en ontvangt uiteindelijk een resultaat. Dit is de methode main() van ons BridgeOfficer- programma :

public static void main(String[] args) {
    Truck first = new Truck();
    first.weight = 10000;
    Truck second = new Truck();
    second.weight = 20000;

    BridgeOfficer officer = new BridgeOfficer(15000);
    System.out.println("Truck 1! Can I go, officer?");
    boolean canFirstTruckGo = officer.checkTruck(first);
    System.out.println(canFirstTruckGo);

    System.out.println();

    System.out.println("Truck 2! And can I?");
    boolean canSecondTruckGo = officer.checkTruck(second);
    System.out.println(canSecondTruckGo);
}
We creëren twee vrachtwagens met ladingen van 10.000 en 20.000. En de brug waar de officier op werkt heeft een maximaal gewicht van 15.000. Het programma roept de methode officer.checkTruck(first) aan . De methode berekent alles en retourneert dan true , dat het programma vervolgens opslaat in de booleaanse variabele canFirstTruckGo . Nu kun je ermee doen wat je wilt (net zoals je kunt met het geld dat je van de accountant hebt gekregen). Aan het eind van de dag de code

boolean canFirstTruckGo = officer.checkTruck(first);
komt neer op

boolean canFirstTruckGo =  true;
Hier is een heel belangrijk punt: de return- instructie retourneert niet alleen de geretourneerde waarde van de methode, het stopt ook de uitvoering van de methode! Elke code die na de return -instructie komt, wordt niet uitgevoerd!

public boolean checkTruck(Truck truck) {

    if (truck.weight > maxWeight) {
        return false;
        System.out.println("Turn around, you're overweight!");
    } else {
        return true;
        System.out.println("Everything looks good, go ahead!");
    }
}
De opmerkingen van de officier worden niet weergegeven, omdat de methode al een resultaat heeft geretourneerd en is beëindigd! Het programma keert terug naar de plaats waar de methode werd aangeroepen. Hier hoef je niet op te letten: de Java-compiler is slim genoeg om een ​​fout te genereren wanneer je code probeert te schrijven na een return statement.

Avengers: Parameteroorlog

Er zijn situaties waarin we verschillende manieren willen om een ​​methode aan te roepen. Waarom creëren we niet onze eigen kunstmatige intelligentie? Amazon heeft Alexa, Apple heeft Siri, dus waarom zouden wij er geen hebben? :) In de film Iron Man creëert Tony Stark zijn eigen ongelooflijke kunstmatige intelligentie, Jarvis. Laten we hulde brengen aan dat geweldige personage en onze AI ter ere van hem noemen. :) Het eerste dat we moeten doen, is Jarvis leren hallo te zeggen tegen mensen die de kamer binnenkomen (het zou raar zijn als zo'n geweldig intellect onbeleefd zou blijken te zijn).

public class Jarvis {

    public void sayHi(String name) {
        System.out.println("Good evening, " + name + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
    }
}
Console-uitvoer:
Good evening, Tony Stark. How are you?
Erg goed! Jarvis kan nu gasten verwelkomen. Natuurlijk zal het vaker wel dan niet zijn meester zijn, Tony Stark. Maar wat als hij niet alleen komt! Onze methode sayHi() accepteert slechts één argument. En dus kan het maar één persoon begroeten die de kamer binnenkomt, en zal het de ander negeren. Niet erg beleefd, vind je ook niet? :/

Java-methode overbelasting

In dit geval kunnen we het probleem oplossen door simpelweg 2 methoden te schrijven met dezelfde naam, maar met verschillende parameters:

public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }
}
Dit wordt methode-overbelasting genoemd. Methode-overloading maakt ons programma flexibeler en biedt plaats aan verschillende manieren van werken. Laten we eens kijken hoe het werkt:

public class Jarvis {

    public void sayHi(String firstGuest) {
        System.out.println("Good evening, " + firstGuest + ". How are you?");
    }

    public void sayHi(String firstGuest, String secondGuest) {
        System.out.println("Good evening, " + firstGuest + " and " + secondGuest + ". How are you?");
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark");
        jarvis.sayHi("Tony Stark", "Captain America");
    }
}
Console-uitvoer:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Uitstekend, beide versies werkten. :) Maar we hebben het probleem niet opgelost! Wat als er drie gasten zijn? We kunnen de methode sayHi() natuurlijk opnieuw overbelasten, zodat deze drie gastnamen accepteert. Maar het kunnen er 4 of 5 zijn. Helemaal tot in het oneindige. Is er geen betere manier om Jarvis te leren omgaan met een willekeurig aantal namen, zonder de methode sayHi() een miljoen keer te overbelasten? :/ Natuurlijk is dat zo! Als dat niet zo was, zou Java dan de populairste programmeertaal ter wereld zijn? ;)

public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
Wanneer ( String... names ) als parameter wordt gebruikt, geeft dit aan dat een verzameling Strings aan de methode zal worden doorgegeven. We hoeven niet van tevoren aan te geven hoeveel het er zullen zijn, dus nu is onze methode veel flexibeler:

public class Jarvis {

    public void sayHi(String...names) {
        for (String name: names) {
            System.out.println("Good evening, " + name + ". How are you?");
        }
    }

    public static void main(String[] args) {
        Jarvis jarvis = new Jarvis();
        jarvis.sayHi("Tony Stark", "Captain America", "Black Widow", "Hulk");
    }
}
Console-uitvoer:
Good evening, Tony Stark. How are you?
Good evening, Captain America. How are you?
Good evening, Black Widow. How are you?
Good evening, Hulk. How are you?
Sommige code hier zal u niet bekend voorkomen, maar maak u er geen zorgen over. In de kern is het eenvoudig: de methode neemt elke naam om de beurt en begroet elke gast! Bovendien werkt het met een willekeurig aantal doorgegeven strings! Twee, tien, zelfs duizend - de methode werkt goed met een willekeurig aantal gasten. Veel handiger dan de methode te overbelasten voor alle mogelijkheden, vind je niet? :) Hier is nog een belangrijk punt: de volgorde van de argumenten is belangrijk! Laten we zeggen dat onze methode een string en een nummer nodig heeft:

public class Person {

    public static void sayYourAge(String greeting, int age) {
        System.out.println(greeting + " " + age);
    }

    public static void main(String[] args) {
        sayYourAge("My age is ", 33);
        sayYourAge(33, "My age is "); // Error!
    }
}
Als de methode sayYourAge van de klasse Person een tekenreeks en een getal als invoer gebruikt, moet het programma ze in die specifieke volgorde doorgeven! Als we ze in een andere volgorde doorgeven, genereert de compiler een fout en kan de persoon zijn leeftijd niet zeggen. Trouwens, constructors, die we in de vorige les hebben behandeld, zijn ook methoden! Je kunt ze ook overbelasten (dwz verschillende constructors maken met verschillende sets parameters) en de volgorde van doorgegeven argumenten is ook voor hen van fundamenteel belang. Het zijn echte methoden! :)

Nogmaals met betrekking tot parameters

Ja, sorry, we zijn er nog niet mee klaar. :) Het onderwerp dat we nu gaan bestuderen is erg belangrijk. Er is 90% kans dat je hier bij elk volgend sollicitatiegesprek naar wordt gevraagd! Laten we het hebben over het doorgeven van argumenten aan methoden. Overweeg een eenvoudig voorbeeld:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        currentYear = currentYear-10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What year is it?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("How about now?");
        System.out.println(currentYear);
    }
}
De tijdmachine heeft twee methoden. Ze nemen allebei het getal dat het huidige jaar vertegenwoordigt als invoer en verhogen of verlagen de waarde ervan (afhankelijk van of we naar het verleden of de toekomst willen gaan). Maar zoals je kunt zien aan de console-uitvoer, werkt de methode niet! Console-uitvoer:
What year is it?
2018
How about now?
2018
We hebben de variabele currentYear doorgegeven aan de methode goToPast() , maar de waarde is niet veranderd. We waren in 2018 en hier zijn we gebleven. Maar waarom? :/ Omdat primitieven in Java op waarde worden doorgegeven aan methoden. Wat betekent dat? Wanneer we de methode goToPast() aanroepen en de int- variabele currentYear (=2018) eraan doorgeven, krijgt de methode niet de variabele currentYear zelf, maar eerder een kopie ervan. De waarde van deze kopie is natuurlijk ook 2018, maar wijzigingen aan de kopie hebben op geen enkele manier invloed op onze oorspronkelijke variabele currentYear ! Laten we onze code explicieter maken en kijken wat er gebeurt met currentYear:

public class TimeMachine {

    public void goToFuture(int currentYear) {
        currentYear = currentYear+10;
    }

    public void goToPast(int currentYear) {
        System.out.println("The goToPast method has started running!");
        System.out.println("currentYear inside the goToPast method (at the beginning) = " + currentYear);
        currentYear = currentYear-10;
        System.out.println("currentYear inside the goToPast method (at the end) = " + currentYear);
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        int currentYear = 2018;

        System.out.println("What was the year when the program started?");
        System.out.println(currentYear);

        timeMachine.goToPast(currentYear);
        System.out.println("And what year is it now?");
        System.out.println(currentYear);
    }
}
Console-uitvoer:
What was the year when the program started?
2018
The goToPast method has started running!
currentYear inside the goToPast method (at the beginning) = 2018
currentYear inside the goToPast method (at the end) = 2008
And what year is it now?
2018
Dit laat duidelijk zien dat de variabele die is doorgegeven aan de methode goToPast() slechts een kopie is van currentYear . En het wijzigen van de kopie heeft geen invloed op de "originele" waarde. "Pass by reference" betekent precies het tegenovergestelde. Laten we oefenen op katten! Ik bedoel, laten we eens kijken hoe het doorgeven van referentie eruitziet met behulp van een kattenvoorbeeld. :)

public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Nu sturen we met behulp van onze tijdmachine Smudge , 's werelds eerste tijdreizende kat, het verleden en de toekomst in! Laten we de klasse TimeMachine aanpassen zodat deze werkt met Cat- objecten;

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }    
}
Nu veranderen de methoden niet alleen het doorgegeven nummer. In plaats daarvan veranderen ze het leeftijdsveld van die specifieke kat . U zult zich herinneren dat dit niet werkte voor ons met primitieven, omdat het oorspronkelijke nummer niet veranderde. Laten we kijken wat er zal gebeuren!

public static void main(String[] args) {

    TimeMachine timeMachine = new TimeMachine();
    Cat smudge = new Cat(5);

    System.out.println("How old was Smudge when the program started?");
    System.out.println(smudge.age);

    timeMachine.goToFuture(smudge);
    System.out.println("How about now?");
    System.out.println(smudge.age);

    System.out.println("Holy smokes! Smudge has aged 10 years! Back up quickly!");
    timeMachine.goToPast(smudge);
    System.out.println("Did it work? Have we returned the cat to its original age?");
    System.out.println(smudge.age);
}
Console-uitvoer:
How old was Smudge when the program started running?
5
How about now?
15
Holy smokes! Smudge has aged 10 years! Back up quickly!
Did it work? Have we returned the cat to its original age?
5
Wauw! Nu deed de methode iets anders: onze kat werd drastisch ouder, maar werd daarna weer jong! :) Laten we proberen erachter te komen waarom. In tegenstelling tot het voorbeeld met primitieven, worden objecten die aan een methode worden doorgegeven, door middel van referentie doorgegeven. Er is een verwijzing naar het oorspronkelijke smudge- object doorgegeven aan de changeAge()- methode. Dus als we smudge.age binnen de methode veranderen, verwijzen we naar hetzelfde geheugengebied waar ons object is opgeslagen. Het is een verwijzing naar dezelfde Smudge die we in eerste instantie hebben gemaakt. Dit heet "passing by reference"! Niet alles met referenties is echter zo eenvoudig. :) Laten we proberen ons voorbeeld te veranderen:

public class TimeMachine {

    public void goToFuture(Cat cat) {
        cat = new Cat(cat.age);
        cat.age += 10;
    }

    public void goToPast(Cat cat) {
        cat = new Cat(cat.age);
        cat.age -= 10;
    }

    public static void main(String[] args) {
        TimeMachine timeMachine = new TimeMachine();
        Cat smudge = new Cat(5);

        System.out.println("How old was Smudge when the program started?");
        System.out.println(smudge.age);

        timeMachine.goToFuture(smudge);
        System.out.println ("Smudge went to the future! Has his age changed?");
        System.out.println(smudge.age);

        System.out.println ("And if you try going back?");
        timeMachine.goToPast(smudge);
        System.out.println(smudge.age);
    }
}
Console-uitvoer:
How old was Smudge when the program started running?
5
Smudge went to the future! Has his age changed?
5
And if you try going back?
5
Het werkt weer niet! О_О Laten we uitzoeken wat er is gebeurd. :) Het heeft alles te maken met de goToPast / goToFuture- methoden en hoe referenties werken. Nu uw aandacht alstublieft! Dit is het belangrijkste om te begrijpen hoe referenties en methoden werken. Het feit is dat wanneer we de goToFuture(Cat cat) methode aanroepen, het een kopie is van de verwijzing naar het cat-object dat wordt doorgegeven, niet de verwijzing zelf. Dus wanneer we een object doorgeven aan een methode, zijn er twee verwijzingen naar het object. Dit is erg belangrijk om te begrijpen wat er gebeurt. Dit is precies waarom de leeftijd van de kat niet veranderde in ons laatste voorbeeld. In het vorige voorbeeld hebben we bij het wijzigen van de leeftijd gewoon de referentie overgenomen die is doorgegeven aan de goToFuture()methode, en gebruikte het om het object in het geheugen te vinden en de leeftijd te wijzigen ( cat.age += 10 ). Maar nu maken we binnen de methode goToFuture() een nieuw object ( cat = new Cat(cat.age) ), en aan dit object wordt dezelfde referentiekopie toegewezen die aan de methode is doorgegeven. Als gevolg:
  • De eerste verwijzing ( Cat smudge = nieuwe Cat (5) ) verwijst naar de originele kat (met leeftijd 5)
  • Daarna, toen we de cat-variabele doorgaven aan de methode goToPast() en er een nieuw object aan toewezen, werd de referentie gekopieerd.
En dit bracht ons bij het uiteindelijke resultaat: twee verwijzingen die naar twee verschillende objecten verwijzen. Maar we hebben alleen de leeftijd van een van hen gewijzigd (degene die binnen de methode is gemaakt).

cat.age += 10;
En natuurlijk kunnen we in de methode main() op de console zien dat de leeftijd van de kat, smudge.age , niet is veranderd. Smudge is tenslotte een referentievariabele die nog steeds verwijst naar het oude, originele object met de leeftijd van 5, en we hebben niets met dat object gedaan. Al onze leeftijdsveranderingen werden uitgevoerd op het nieuwe object. Het blijkt dus dat objecten door verwijzing aan methoden worden doorgegeven. Kopieën van objecten worden nooit automatisch gemaakt. Als je een kattenobject doorgeeft aan een methode en zijn leeftijd verandert, verander je zijn leeftijd. Maar referentievariabelen worden gekopieerd bij het toewijzen van waarden en/of aanroepmethoden! Laten we hier herhalen wat we zeiden over het doorgeven van primitieven: "Als we de methode changeInt() aanroepen en de int doorgevenvariabele x (=15) , krijgt de methode niet de variabele x zelf, maar eerder een kopie ervan. Daarom hebben eventuele wijzigingen in de kopie geen invloed op onze originele xJe zult nog steeds meer dan eens ruzie krijgen over hoe argumenten worden doorgegeven in Java (zelfs onder ervaren ontwikkelaars). Maar nu weet je precies hoe het werkt. Ga zo door! :) Om te versterken wat je hebt geleerd, raden we je aan een videoles van onze Java-cursus te bekijken
Opmerkingen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION