Tot nu toe heb je in Java alleen een stukje code geschreven in de main-methode. Dit is de methode die in Java het startpunt van een programma aangeeft. In een Java-project is er een klasse die wordt gestart, daarin wordt gezocht naar de methode zoals hieronder: Als je programma uitgebreider wordt en je zou alle code in de methode main zetten wordt dit een heel lange en onoverzichtelijke code. Het eerste wat je gaat doen om dit op te lossen is aparte methoden maken voor stukken code.
public class ConsoleApp {
public static void main(String[] args) {
int dobbel;
dobbel = gooiDobbelsteen();
System.out.println(dobbel);
}
private static int gooiDobbelsteen() {
return (int)(1 + 6 * Math.random());
}
}
Binnen de klasse ConsoleApp
wordt een tweede methode geplaatst die een worp met een dobbelsteen nadoet en het resultaat van de worp teruggeeft.
Math.random()
geeft een willekeurig kommagetal tussen 0 en 1.return
wordt dit getal teruggegeven als resultaat van de functie.In de definitie van de methode staat private static int
:
private
betekent dat de methode alleen bestaat binnen de klasse waarin hij staat. Dus gooiDobbelsteen
mag alleen gebruikt worden binnen de klasse ConsoleApp
.static
geeft aan dat deze methode gebruikt mag worden zonder eerst een object te maken van de klasse waarin de methode staat. Deze methode moet static zijn omdat de methode die hem gebruikt, de main-methode, ook static is. Later gaan we dat aanpassen door meerdere klassen te gebruiken.int
geeft het returntype van de methode aan. In dit geval is het resultaat van de methode een integer dus een geheel getal. De methode mag daardoor met return alleen een integer waarde teruggeven, en de methode moet een waarde van het type integer teruggeven. Zonder het juiste return statement zie je foutmelding en kun je je code niet compileren. Als je wilt dat een methode is doet maar geen resultaat teruggeeft, gebruik je als returntype void Engels voor leegte (niets).Voor de volgende oefeningen kan je een video bekijken:
Maak een methode met de naam maakVierkant
die als resultaat een String
geeft. De string bevat een vierkant van 5 x 5 plussen. Als je het op de console print zie het er uit als:
Maak een methode met de naam evenDag
die als resultaat geeft of de datum van vandaag een even getal is, resultaat is true of false (boolean).
Uit het Calendar object kun je de datum van vandaag halen.
Maak een methode met de naam getOsInfo
die uit de systeemeigenschappen de naam, de versie en de architectuur van het besturingssysteem (os) haalt. Als resultaat krijg je een String met daarin de gevraagde info gescheiden door een spatie.
https://docs.oracle.com/javase/tutorial/essential/environment/sysprop.html
Het voorbeeld van de dobbelsteen voert de code uit en geeft het resultaat terug. Hierbij wordt bij de aanroep van de methode geen informatie meegeven, maar dat wil je vaak wel. Dit kun je doen door argumenten te gebruiken.
public class ConsoleApp {
public static void main(String[] args) {
int voorbeeld = 10;
int resultaat = verhoogMetEen(voorbeeld);
System.out.println(voorbeeld);
System.out.println(resultaat);
}
private static int verhoogMetEen(int invoer) {
return ++invoer;
}
}
De methode verhoogMetEen
gebruikt de waarde die wordt meegegeven en verhoogt deze met 1, daarna wordt het resultaat weer teruggegeven.
++invoer
verhoogt de waarde in invoer met 1 voor dat de waarde wordt gebruikt. Dit is wat anders dan invoer++, want daar wordt de waarde van invoer eerst gebruikt en daar pas verhoogt met 1. In dit voorbeeld zou invoer++ er voor zorgen dat de methode als resultaat de waarde teruggeeft dit in het argument invoer is meegegeven. Probeer dat zelf maar eens.(int invoer)
geeft aan dat deze methode bij de aanroep gewacht dat er een integer waarde wordt meegegeven. Deze waarde wordt binnen de methode opgeslagen in de variabele invoer. Deze variabele kun je alleen binnen de methode gebruiken.
public class ConsoleApp {
public static void main(String[] args) {
int a = 10;
int b = 5;
int som = telOp(a,b);
System.out.println(som);
}
private static int telOp(int getal1, int getal2) {
return getal1 + getal2;
}
}
De methode telOp
tel de twee argumenten bij elkaar op en geeft het resultaat (de som) terug.
(int getal1, int getal2)
de argumenten worden gescheiden door een komma. Elk argument wordt voorafgegaan door het type, in dit geval allebei int.Maak oefening 1 nogmaals, maar nu moet je de grootte van het vierkant als argument aan de methode kunnen meegeven.
Maak een methode met de naam getMax
die als argument een array van integer waarden krijgt en als resultaat de grootste waarde uit de lijst geeft.
Maak een methode met de naam countChar
die als argumenten een String en een Char mee krijgt. De methode telt hoe vaak het teken in het tweede argument (char) in het eerste argument (String) voorkomt en geeft de waarde als resultaat.
Maak een methode met de naam reverseString
die als argument een String mee krijgt. Het resultaat van de methode is de invoer in omgekeerde volgorde, dus ‘oefening’ wordt ‘gninefeo’.
// ConsoleApp.java
public class ConsoleApp {
public static void main(String[] args) {
Dobbelsteen dobbelsteen = new Dobbelsteen();
int dobbel;
dobbel = dobbelsteen.gooi();
System.out.println(dobbel);
}
}
// Dobbelsteen.java
public class Dobbelsteen {
public int gooi() {
return (int)(1 + 6 * Math.random());
}
}
Er wordt nu een twee bronbestand binnen het project gemaakt voor de klasse Dobbelsteen. Het bestand moet dezelfde naam hebben als de publieke klasse die er in staat. Dus in dit geval heet het bronbestand Dobbelsteen.java (let op de hoofdletters).
In de klasse Dobbelsteen maken we de methode gooi met de code die een dobbelsteen worp nadoet. Deze methode hoeft niet static te zijn, omdat we eerst een object gaan maken van de klasse Dobbelsteen. Dat gebeurt in de main methode van de ConsoleApp klasse. Een object gemaakt op basis van een klasse heet een instantie van de klasse.
Dobbelsteen dobbelsteen = new Dobbelsteen()
;
Op deze regel worden drie dingen tegelijk gedaan:
Dobbelsteen dobbelsteen
- Er wordt een variabele met de naam dobbelsteen gemaakt van het type Dobbelsteen (kan een Dobbelsteen object bevatten).new Dobbelsteen()
- Er wordt een nieuwe instantie van de klasse Dobbelsteen gemaakt, het resultaat is een Dobbelsteen-object.... = ...
- Het nieuwe Dobbelsteen-object wordt opgeslagen in de dobbelsteen variabeleint dobbel
maakt een integer variabele met de naam dobbel waar we later de waarde van de gegooide dobbelsteen in kunnen opslaan.dobbel = dobbelsteen.gooi()
roept de methode gooi van het object dobbelsteen aan en zet het resultaat in de variabele dobbel.Voor oefening 8, 9 en 10 is een video:
Maak een project met een start klasse als in het voorbeeld. Maak een tweede klasse aan met de naam Test. In de klasse test maak je een methode containsNumbers
die een String als argument mee krijgt en test of er in de invoer getallen voorkomen. Het resultaat van de test is een boolean.
Voeg aan de klasse Test van de vorige oefening een methode getNumbers
toe die een String als argument mee krijgt en alleen de getallen uit de invoer als resultaat geeft. Het resultaat van de methode is een String.
Voeg aan de klasse Test van oefening 8 een methode countDecimals
toe die een double als argument mee krijgt en als resultaat geeft hoeveel getallen achter de komma (punt) staan. Het resultaat is een integer.
Bij het maken van een variabele of een methode geef je aan wat de scope is. De scope bepaald waar je de variabele of methode kunt gebruiken. Dit doe je door de gereserveerde woorden public, private of protected er voor te zetten. Wat protected betekent komt later als je meer leert over klassen en objecten.
Behalve de declaratie met public of private wordt de scope van een variabele ook bepaald door de plek waar je de variabele maakt.
public class Main {
public static void main(String[] args) {
Scope scope = new Scope();
System.out.println(scope.string1);
System.out.println();
System.out.println(scope.getStringsFromVariables());
System.out.println();
System.out.println(scope.getStringsFromMethods());
System.out.println();
System.out.println(scope.getOtherString());
}
}
public class Scope {
public String string1 = "Een tekenreeks in scope";
private String string2 = "Nog een tekenreeks in scope";
private String getString(int i) {
if(i == 1) {
return string1;
} else {
return string2;
}
}
public String getStringsFromVariables() {
return string1 + "\n" + string2;
}
public String getStringsFromMethods() {
return getString(1) + "\n" + getString(2);
}
public String getOtherString() {
String other = "Een andere tekenreeks";
return other;
}
}
string1
is public gedeclareerd en mag binnen de klasse gebruikt worden maar ook in Main waar een object van de klasse Scope is gemaakt.string2
is private gedeclareerd en mag binnen de klasse gebruikt worden, in de klasse Main is deze variabele niet beschikbaar.getOtherString()
en is alleen daar te gebruiken. Voor elke variabele binnen een methode geldt dat hij alleen te gebruiken is binnen het eerste blok waar hij in staat, dus binnen de accolades die de variabele als eerste omsluiten.getString(int i)
is private gedeclareerd en mag binnen de klasse gebruikt worden, daar buiten, bijvoorbeeld in Main is deze methode niet beschikbaar.getStringsFromVariables()
en getStringsFromMethods()
zijn public gedeclareerd en kunnen binnen de klasse gebruikt worden en zijn ook in Main beschikbaar via het object scope van de klasse Scope.Neem het voorbeeld over en test de code. Verplaats de StringBuffer output = new StringBuffer()
naar boven in de klasse en verwijder hem uit de andere methode. Kijk wat het resultaat is.
Recursie is een truc om code van met name problemen met een wiskundige achtergrond simpeler te maken. Bij recursie wordt in een methode dezelfde methode weer aangeroepen, maar dan met een andere parameter. Dit klinkt ingewikkeld, dus bespreken we een voorbeeld.
Vermenigvuldigen is iets wat je al op de basisschool hebt geleerd. Nu gaan we er iets wiskundiger naar kijken. We stappen even bewust er over heen, dat vermenigvuldigen in een programmeertaal heel gemakkelijk is (er zijn trouwens nog steeds programmeertalen die niet kunnen vermenigvuldigen, dit heeft meestal met de simpelheid van het platform te maken)
Stel je voor: je wilt 4*3 berekenen, we weten allemaal dat de uitkomst 12 is, maar bereken je dat?
Uitkomst = 4 + 4 + 4
Dus: je neemt 4 (1e keer) en dan tel je daar 4 bij op (2e keer) en daar bij tel je nog een keer 4 op. Je hebt dus 3 vieren bij elkaar opgeteld. Hieronder vind je de voorbeeld code:
public class Vermenigvuldiging {
public int vermenigvuldig(int aantalkeer, int getal) {
if (aantalkeer == 0) {
return 0;
} else if (aantalkeer == 1) {
return getal;
} else {
return vermenigvuldig(aantalkeer-1, getal) + getal;
}
}
}
Stel je roept deze methode aan met vermenigvuldig(0, 3):
Daarna proberen we een aanroep met vermenigvuldig(1, 3):
Tot slot de laatste mogelijkheid, de aanroep met vermenigvuldig(2, 3):
Niet oneindig doorgaan
Een van de belangrijkste eigenschappen van een recursieve methode is dat er ook een stop-conditie in zit. Want anders zou het kunnen zijn dat je oneindig doorgaat, omdat je steeds weer dezelfde methode aanroept die zichzelf aanroept die zichzelf aanroept….
Uiteindelijk het programma of erger je computer vastloopt. In bovenstaande code wordt dit geregeld door de regels
if (aantalkeer == 0) {
return 0;
} else if (aantalkeer == 1) {
return getal;
}
We weten dat er elke keer -1 gedaan wordt, en dus zul je een keer bij aantalkeer = 1 aankomen, en dan springt de methode weer terug naar buiten. En aantalkeer = 0 zorgt ervoor dat het goed gaat als je met 0 begint.
Schematisch gezien loopt het programma als volgt:
Neem de code hieronder over en bedenk nog minimaal 3 vermenigvuldigen om te controleren of het klopt.
Zet hiervoor in de klasse Vermenigvuldiging
een paar System.out.println
opdrachten zodat je kunt zien waar het programma langs loopt.
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
Vermenigvuldiging v = new Vermenigvuldiging();
System.out.println("4 * 3 = "+Integer.toString(v.vermenigvuldig(4, 3)));
System.out.println("6 * 5 = "+Integer.toString(v.vermenigvuldig(6, 5)));
}
}
Met dezelfde manier kun je ook een faculteit berekenen (zie ook de bronnen)
Je kunt de code voor de eindopdrachten ophalen op https://github.com/DrentheCollege/A2Eindopdrachten.git met een git clone opdracht.
Er is een video met uitleg over de eindopdrachten:
Maak een recursieve functie die berekeningen kan doen.
De eisen:
Dus bijvoorbeeld:
4 + 3 =7
4 *3 + 2 = 12 + 2 = 14
(3+4)*3 = 7 * 3 = 21
( ( 2 +1) * 4) + (2 * 3) = ( 3 * 4) + (2 * 3) = 12 + 6 = 18
Dat moet je oplossen met een recursieve methode (definitie: public int bereken(String input), en vergeet niet om het resultaat steeds terug te geven (return).
Je kunt dit controleren met bovenstaande sommen (gebruik die bijvoorbeeld in je code), maar bedenk er zelf ook 3 en controleer het resultaat.
In deze opdracht krijg je een stuk code dat niet af is. Bedenk hier een manier om alle niet wenselijke karakters uit de string te halen. Maak een nieuwe klasse die dit gaat doen, en gebruik zoveel mogelijk methodes.
Tekst.replaceAll is niet toegestaan, het is de bedoeling dat je zelf het programma bedenkt en schrijft.