John Squirrels
Niveau
San Francisco

Metoder i Java

Udgivet i gruppen
Hej igen! I den sidste lektion stiftede vi bekendtskab med klasser og konstruktører, og lærte at skabe vores egne. I dag vil vi blive bedre bekendt med Java Methods, en væsentlig del af undervisningen. En Methods in Java er et sæt kommandoer, som giver dig mulighed for at udføre en specifik handling i et program. Med andre ord er en metode en funktion; noget som din klasse er i stand til. I andre programmeringssprog kaldes metoder ofte for "funktioner", men i Java er ordet "metode" mere almindeligt. :) Hvis du husker det, lavede vi i sidste lektion enkle metoder til en Katteklasse , så vores katte kunne sige mjav og hoppe:
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() og jump() er metoder i vores klasse. Og at køre disse metoder resulterer i følgende konsoloutput:
Meow!
Pounce!
Vores metoder er ret enkle: de udsender simpelthen tekst til konsollen. Men i Java har metoder en vigtig opgave: de udfører handlinger på et objekts data. De ændrer objektets data, transformerer dem, viser dem og gør andre ting med dem. Vores nuværende metoder gør ikke noget med Cat -objektets data. Lad os se på et mere illustrativt eksempel:
public class Truck {

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

    public int getVolume() {
        int volume = length * width * height;
        return volume;
    }
}
For eksempel har vi her en klasse, der repræsenterer en lastbil . Semilastbilen har en længde, bredde, højde og vægt (som vi skal bruge senere). I getVolume() metoden udfører vi beregninger, konverterer vores objekts data til et tal, der repræsenterer dets volumen (vi ganger længden, bredden og højden). Dette tal vil være resultatet af metoden. Bemærk, at metodens erklæring er skrevet som public int getVolume . Det betyder, at denne metode skal returnere en int . Vi har beregnet metodens returværdi, og nu skal vi returnere den til det program, der kaldte vores metode. For at returnere en metodes resultat i Java, bruger vi søgeordet return. returvolumen;

Java-metodeparametre

Vi kan sende værdier kaldet "argumenter" til en metode, når vi kalder den. En metodes erklæring indeholder en liste over variabler, som fortæller os typen og rækkefølgen af ​​variabler, som metoden kan acceptere. Denne liste kaldes "metodeparametrene". Vores lastbilklasses getVolume()- metode definerer i øjeblikket ingen parametre, så lad os prøve at udvide vores lastbileksempel . Opret en ny klasse kaldet BridgeOfficer . Dette er en politibetjent på vagt ved en bro, som tjekker alle forbipasserende lastbiler for at se, om deres last overstiger den tilladte vægt.
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;
        }
    }
}
CheckTruck - metoden accepterer ét argument, et lastbilobjekt , og bestemmer, om betjenten vil tillade lastbilen på broen eller ej. Inde i metoden er logikken simpel nok: Hvis lastbilens vægt overstiger det maksimalt tilladte, så returnerer metoden falsk . Det bliver nødt til at finde en anden vej :( Hvis vægten er mindre end eller lig med maksimum, kan den passere, og metoden returnerer sand. Hvis du ikke helt forstår sætningerne "retur" eller "metoden returnerer en værdi" endnu, lad os tage en pause fra programmeringen og overveje dem ved at bruge et simpelt eksempel fra det virkelige liv. :) Lad os sige, at du bliver syg og bliver hjemme fra arbejde i et par dage. Du går til regnskabsafdelingen med din lægeerklæring, for sygemelding skal jo betales. Hvis vi sammenligner denne situation med metoder, så har revisoren sygefravær ()metode. Du sender en lægeerklæring som argument for denne metode (uden den fungerer metoden ikke, og du får ikke løn!). Derefter foretages de nødvendige beregninger inde i metoden ved hjælp af dit notat (revisoren bruger den til at beregne, hvor meget virksomheden skal betale dig), og resultatet af dit arbejde (et beløb) returneres til dig. Vores program fungerer på samme måde. Den kalder en metode, sender data til den og modtager i sidste ende et resultat. Her er vores BridgeOfficer- programs main() metode:
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);
}
Vi laver to lastbiler med læs på 10.000 og 20.000. Og broen, hvor betjenten arbejder, har en maksimal vægt på 15.000. Programmet kalder officer.checkTruck(first) metoden. Metoden beregner alt og returnerer derefter true , som programmet så gemmer til i den boolske variabel canFirstTruckGo . Nu kan du gøre, hvad du vil med det (ligesom du kan med de penge, revisoren gav dig). I slutningen af ​​dagen, koden
boolean canFirstTruckGo = officer.checkTruck(first);
koges ned til
boolean canFirstTruckGo =  true;
Her er en meget vigtig pointe: return -sætningen returnerer ikke bare metodens returværdi, den stopper også metoden i at køre! Enhver kode, der kommer efter returneringserklæringen , vil ikke blive udført!
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!");
    }
}
Betjentens kommentarer vil ikke blive vist, fordi metoden allerede har returneret et resultat og afsluttet! Programmet vender tilbage til det sted, hvor metoden blev kaldt. Du behøver ikke at være opmærksom på dette: Java-kompileren er smart nok til at generere en fejl, når du forsøger at skrive kode efter en return- sætning.

Avengers: Parameter War

Der er situationer, hvor vi vil have flere måder at kalde en metode på. Hvorfor ikke skabe vores egen kunstige intelligens? Amazon har Alexa, Apple har Siri, så hvorfor skulle vi ikke have en? :) I filmen Iron Man skaber Tony Stark sin egen utrolige kunstige intelligens, Jarvis. Lad os hylde den fantastiske karakter og navngive vores AI til hans ære. :) Det første, vi skal gøre, er at lære Jarvis at sige hej til folk, der kommer ind i lokalet (det ville være mærkeligt, hvis sådan et fantastisk intellekt viste sig at være uhøfligt).
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");
    }
}
Konsoludgang:
Good evening, Tony Stark. How are you?
Meget godt! Jarvis er nu i stand til at byde gæster velkommen. Selvfølgelig vil det oftere end ikke være hans mester, Tony Stark. Men hvad nu hvis han ikke kommer alene! Vores sayHi() -metode accepterer kun ét argument. Og så kan den kun hilse på én person, der kommer ind i rummet, og vil ignorere den anden. Ikke særlig høflig, er du ikke enig? :/

Java-metodeoverbelastning

I dette tilfælde kan vi løse problemet ved blot at skrive 2 metoder med samme navn, men forskellige parametre:
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?");
    }
}
Dette kaldes metodeoverbelastning. Metodeoverbelastning gør vores program mere fleksibelt og rummer forskellige måder at arbejde på. Lad os gennemgå, hvordan det virker:
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");
    }
}
Konsoludgang:
Good evening, Tony Stark. How are you?
Good evening, Tony Stark and Captain America. How are you?
Fremragende, begge versioner fungerede. :) Men vi løste ikke problemet! Hvad hvis der er tre gæster? Vi kunne selvfølgelig overbelaste sayHi() metoden igen, så den accepterer tre gæstenavne. Men der kunne være 4 eller 5. Helt til det uendelige. Er der ikke en bedre måde at lære Jarvis at håndtere et vilkårligt antal navne uden at overbelaste sayHi() -metoden en million gange? :/ Selvfølgelig er der! Hvis der ikke var, tror du, at Java ville være det mest populære programmeringssprog i verden? ;)
public void sayHi(String...names) {

    for (String name: names) {
        System.out.println("Good evening, " + name + ". How are you?");
    }
}
Når ( String... names ) bruges som en parameter, indikerer det, at en samling af Strings vil blive videregivet til metoden. Vi behøver ikke på forhånd at angive, hvor mange der bliver, så nu er vores metode meget mere fleksibel:
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");
    }
}
Konsoludgang:
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?
Noget kode her vil være ukendt for dig, men du skal ikke bekymre dig om det. Det er enkelt i sin kerne: Metoden tager hvert navn efter tur og byder hver gæst velkommen! Plus, det vil fungere med et vilkårligt antal beståede strenge! To, ti, endda tusind - metoden vil fungere korrekt med et hvilket som helst antal gæster. Meget mere praktisk end at overbelaste metoden for alle mulighederne, synes du ikke? :) Her er et andet vigtigt punkt: rækkefølgen af ​​argumenterne betyder noget! Lad os sige, at vores metode tager en streng og et tal:
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!
    }
}
Hvis Person -klassens sayYourAge- metode tager en streng og et tal som input, så skal programmet videregive dem i den specifikke rækkefølge! Hvis vi sender dem i en anden rækkefølge, vil compileren generere en fejl, og personen vil ikke være i stand til at sige sin alder. Forresten, konstruktører, som vi dækkede i sidste lektion, er også metoder! Du kan også overbelaste dem (dvs. oprette flere konstruktører med forskellige sæt af parametre), og rækkefølgen af ​​beståede argumenter er også fundamentalt vigtig for dem. Det er rigtige metoder! :)

Endnu en gang med hensyn til parametre

Ja, undskyld, vi er ikke færdige med dem endnu. :) Emnet, som vi vil studere nu, er meget vigtigt. Der er 90 % chance for, at du bliver spurgt om dette ved hver fremtidig samtale! Lad os tale om at overføre argumenter til metoder. Overvej et simpelt eksempel:
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);
    }
}
Tidsmaskinen har to metoder. De tager begge tallet, der repræsenterer det aktuelle år, som input og enten øger eller mindsker dets værdi (afhængigt af om vi ønsker at gå til fortiden eller fremtiden). Men som du kan se på konsoludgangen, virker metoden ikke! Konsoludgang:
What year is it?
2018
How about now?
2018
Vi sendte variablen currentYear til goToPast() -metoden, men dens værdi ændrede sig ikke. Vi var i 2018, og her er vi blevet. Men hvorfor? :/ Fordi primitiver i Java overføres til metoder efter værdi. Hvad betyder det? Når vi kalder goToPast()- metoden og sender int -variablen currentYear (=2018) til den, får metoden ikke selve currentYear -variablen, men snarere en kopi af den. Selvfølgelig er værdien af ​​denne kopi også 2018, men eventuelle ændringer af kopien påvirker ikke vores originale nuværende Årsvariabel på nogen måde! Lad os gøre vores kode mere eksplicit og se, hvad der sker med 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);
    }
}
Konsoludgang:
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
Dette viser tydeligt, at variablen, der overføres til goToPast()- metoden, kun er en kopi af currentYear . Og ændring af kopien påvirker ikke den "oprindelige" værdi. "Bestå ved henvisning" betyder det stik modsatte. Lad os øve os på katte! Jeg mener, lad os se, hvordan det at gå forbi reference ser ud ved at bruge et kat-eksempel. :)
public class Cat {

    int age;

    public Cat(int age) {
        this.age = age;
    }
}
Nu vil vi med hjælp fra vores tidsmaskine sende Smudge , verdens første tidsrejsende kat, ind i fortiden og fremtiden! Lad os ændre TimeMachine- klassen, så den fungerer med Cat- objekter;
public class TimeMachine {

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

    public void goToPast(Cat cat) {
        cat.age -= 10;
    }
}
Nu ændrer metoderne ikke bare det beståede nummer. I stedet ændrer de det specifikke kats aldersfelt . Du kan huske, at dette ikke fungerede for os med primitiver, fordi det oprindelige nummer ikke ændrede sig. Lad os se, hvad der vil ske!
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);
}
Konsoludgang:
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
Wow! Nu gjorde metoden noget andet: Vores kat ældes drastisk, men så blev den ung igen! :) Lad os prøve at finde ud af hvorfor. I modsætning til eksemplet med primitiver, når objekter sendes til en metode, videregives de ved reference. En reference til det originale smudge -objekt blev videregivet til metoden changeAge() . Så når vi ændrer smudge.age inde i metoden, refererer vi til det samme hukommelsesområde, hvor vores objekt er gemt. Det er en reference til den samme Smudge, som vi oprettede i starten. Dette kaldes "henvisning"! Men ikke alt med referencer er så nemt. :) Lad os prøve at ændre vores eksempel:
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);
    }
}
Konsoludgang:
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
Det virker ikke igen! О_О Lad os finde ud af, hvad der skete. :) Det har alt at gøre med goToPast / goToFuture metoderne og hvordan referencer fungerer. Nu, din opmærksomhed, tak! Dette er den vigtigste ting at forstå om, hvordan referencer og metoder fungerer. Faktum er, at når vi kalder goToFuture(Cat cat) -metoden, er det en kopi af referencen til katteobjektet, der bliver bestået, ikke selve referencen. Når vi sender et objekt til en metode, er der således to referencer til objektet. Dette er meget vigtigt for at forstå, hvad der sker. Det er netop derfor, at kattens alder ikke ændrede sig i vores sidste eksempel. I det forrige eksempel, når vi ændrede alderen, tog vi blot referencen, der blev sendt til goToFuture()metode, og brugte den til at finde objektet i hukommelsen og ændre dets alder ( kat.alder += 10 ). Men nu, inde i goToFuture()- metoden, opretter vi et nyt objekt ( cat = new Cat(cat.age) ), og dette objekt er tildelt den samme referencekopi, som blev sendt til metoden. Som resultat:
  • Den første reference ( Cat smudge = new Cat (5) ) peger på den originale kat (med en alder af 5)
  • Efter det, da vi passerede cat-variablen goToPast()- metoden og tildelte den et nyt objekt, blev referencen kopieret.
Og dette bragte os til det endelige resultat: to referencer, der peger på to forskellige objekter. Men vi ændrede kun alderen på den ene af dem (den der blev oprettet inde i metoden).
cat.age += 10;
Og selvfølgelig kan vi i main() -metoden se på konsollen, at kattens alder, smudge.age , ikke har ændret sig. Smudge er trods alt en referencevariabel, der stadig peger på det gamle, originale objekt med en alder af 5, og vi gjorde ikke noget med det objekt. Alle vores aldersændringer blev udført på det nye objekt. Så det viser sig, at objekter videregives til metoder ved reference. Kopier af objekter oprettes aldrig automatisk. Hvis du sender en kat genstand til en metode og ændrer dens alder, vil du ændre dens alder. Men referencevariabler kopieres, når man tildeler værdier og/eller kalder metoder! Lad os her gentage, hvad vi sagde om at overføre primitiver: "Når vi kalder changeInt() -metoden og videregiver int'envariabel x (=15) , metoden får ikke selve x -variablen, men snarere en kopi af den. Derfor påvirker eventuelle ændringer i kopien ikke vores originale xvil stadig ende med at skændes mere end én gang om, hvordan argumenter sendes i Java (selv blandt erfarne udviklere). Men nu ved du præcis, hvordan det fungerer. Bliv ved! :) For at styrke det, du har lært, foreslår vi, at du ser en videolektion fra vores Java-kursus
Kommentarer
  • Populær
  • Ny
  • Gammel
Du skal være logget ind for at skrive en kommentar
Denne side har ingen kommentarer endnu