HOOFDSTUK 6 METHODEN 6.1 Inleiding Tot nu toe: kleine, eenvoudige programma’s • applicatie: methode main() • applet: methode paint() en eventueel init() Vanaf hoofdstuk 6: complexere, grotere programma’s (= realiteit) Gevolg: programma verdelen in kleine stukjes, modules genoemd = verdeel en heers methode 1 6.2 Programmamodules in JAVA Modules in Java: • methoden • klassen Java API voorziet meerdere modules Programmeurs kunnen zelf ook modules ontwerpen, nl. programmer-defined modules JAVA-programma = combinatie van nieuwe methoden en klassen, die de programmeur schrijft, met methodes en klassen die beschikbaar zijn in de Java API! VERMIJD HET HERUITVINDEN VAN HET WIEL! 2 6.2 Programmamodules in JAVA (vervolg) Methoden • om specifieke taken te definiëren Voorbeeld: invoer van een positief geheel getal + test • kan meerdere keren in een programma gebruikt worden! • aanroepen via een method call; specifieert de naam van de methode en de data, die de methode nodig heeft om de taak uit te voeren = argumenten • kan een resultaat teruggeven aan de calling method (caller) 3 6.2 Programmamodules in JAVA (vervolg) Methoden • Te vergelijken met de baas (caller), die zijn werknemer vraagt (called method) een taak te volbrengen en de resultaten te rapporteren. • De baas moet niet weten hoe de werker zijn taak volbrengt. Een werker kan ook beroep doen op andere werkers, zonder dat de baas dit weet! 4 baas werkman1 werkman4 werkman2 werkman3 werkman5 Fig. 6.1 Hierarchische baas-methode/werkman-methode relatie. 5 6.3 Klassemethoden van de klasse Math class java.lang.Math • voorziet gebruikelijke mathematische bewerkingen • Voorbeeld: de vierkantswortel van 900.0 double x = Math.sqrt(900.0); • De methode sqrt behoort tot de klasse Math en is static, zoals alle methoden in deze klasse! aanroep: klassenaam.methodenaam(argumenten) 6 6.3 Klassemethoden van de klasse Math (vervolg) class java.lang.Math • na de methodenaam volgen de argumenten tussen ronde haakjes; nul, één of meerdere gescheiden door komma’s • Argumenten kunnen constanten zijn: double x = Math.sqrt(50); variabelen zijn: double y = 14, x = Math.sqrt(y); expressies zijn: double z = 70.5; System.out.println( Math.sqrt(z+7)); 7 Methode abs( x ) ceil( x ) cos( x ) exp( x ) Omschrijving Absolute waarde van x (eveneens versies voor float, int en long waarden) Rond x af naar de kleinste integer die niet kleiner is dan x Trigonometrische cosinus van x (x is in radialen) Exponentiele methode ex Voorbeeld abs( 23.7 ) is 23.7 abs( 0.0 ) is 0.0 abs( -23.7 ) is 23.7 ceil( 9.2 ) is 10.0 ceil( -9.8 ) is -9.0 cos( 0.0 ) is 1.0 exp( 1.0 ) is 2.71828 exp( 2.0 ) is 7.38906 floor( x ) Rond x af naar de grootste integer niet groter floor( 9.2 ) is 9.0 floor( -9.8 ) is -10.0 dan x log( x ) log( 2.718282 ) is 1.0 natuurlijk logarithme van x (basis e) log( 7.389056 ) is 2.0 max( x, y Grootste waarde van x en y max( 2.3, 12.7 ) is 12.7 ) max( -2.3, -12.7 ) is -2.3 (eveneens versies voor float, int en long waarden) min( x, y Grootste waarde van x en y min( 2.3, 12.7 ) is 2.3 ) min( -2.3, -12.7 ) is -12.7 (eveneens versies voor float, int en long waarden) pow( x, y x verheven tot de macht y (xy) pow( 2.0, 7.0 ) is 128.0 ) pow( 9.0, .5 ) is 3.0 sin( x ) sin( 0.0 ) is 0.0 Trigonometrische cosinus van x (x is in radialen) sqrt( x ) Vierkantswortel uit x sqrt( 900.0 ) is 30.0 sqrt( 9.0 ) is 3.0 tan( x ) tan( 0.0 ) is 0.0 Trigonometrische tangens van x (x is in radialen) Fig. 6.2 Math klasse methoden. 8 Oef 1. Wat is de waarde van x na evaluatie ? a) b) c) d) e) f) g) x = Math.abs(7.5); x = Math.floor(7.5); x = Math.abs(0.0); x = Math.ceil(0.0); x = Math.abs(-6.4); x = Math.ceil(-6.4); x = Math.ceil(-Math.abs(-8 + Math.floor(5.5))); 9 6.4 Methoden definitie. Methoden • laten modularisatie van een programma toe Voordelen: maakt programmaontwikkeling eenvoudiger software kan opnieuw gebruikt worden vermijd herhalende code 10 6.4 Methoden definitie (vervolg). Methoden • gebruiken lokale variabelen • enkel de methode kent de lokale variabelen • lokale variabelen bestaan enkel vanaf de declaratie tot aan de sluitaccolade van de body waarin ze gedeclareerd zijn 11 6.4 Methoden definitie (vervolg). Methoden • hebben meestal een lijst van parameters • parameters voorzien uitwisseling van informatie tussen methoden via de methode oproep (method call) • een parameter is eveneens een lokale variabele voor de methode Voorbeelden: public static void main (String[] args) -> args public void paint (Graphics g) -> g public double square (double x) -> x 12 6.4 Methoden definitie (vervolg). Programmeurs kunnen hun eigen methoden schrijven, naast het gebruikmaken van methoden uit de Java API. Voorbeeld 1: SquareIntegers.java • een applet, dat de kwadraten van de gehele getallen van 1 t.e.m. 10 bepaalt en weergeeft op het scherm • Hierbij wordt een for-herhalingsstructuur en een zelfgedefinieerde methode square gebruikt. • De functie square bepaalt het kwadraat van een willekeurig geheel getal. 13 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // Fig. 6.3: SquareIntegers.java // Met zelfgedefinieerde square methode // Java core packages import java.awt.Container; // Java extension packages import javax.swing.*; public class SquareIntegers extends JApplet { // opzetten van GUI en berekenen van kwadraten van 1 tot 10 public void init() { // JTextArea om resultaten weer te geven JTextArea outputArea = new JTextArea(); // een referentie naar de applets content pane Container container = getContentPane(); // outputArea vasthechten aan container container.add( outputArea ); int result; // resultaat van methode-aanroep square String output = ""; // String die resultaten bevat 14 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 } // lus 10 keer for ( int counter = 1; counter <= 10; counter++ ) { // berekenen kwadraat van counter en in result stoppen result = square( counter ); // result toevoegen aan String output output += "The square of " + counter + " is " + result + "\n"; } // einde for-lus outputArea.setText( output ); } // zet resultaten in JTextArea // einde methode init // square methode definitie public int square( int y ) { return y * y; // return square of y } // einde methode square // einde klasse SquareIntegers 15 16 12 13 14 15 16 17 18 19 20 21 22 // opzetten van GUI en berekenen van kwadraten van 1 tot 10 public void init() { // JTextArea om resultaten weer te geven JTextArea outputArea = new JTextArea(); // een referentie naar de applets content pane Container container = getContentPane(); // outputArea vasthechten aan container container.add( outputArea ); Lijn 19 : Elk weergavescherm van een applet heeft een “content pane”, waaraan GUI componenten kunnen worden gekoppeld. De “content pane” is een object van de klasse Container (java.awt). getContentPane() geeft een referentie terug naar het “content pane” van de applet; deze functie erven we van de klasse JApplet Lijn 22 : outputArea GUI-component wordt aan “content pane” gekoppeld en neemt het volledige grafische scherm van de applet in beslag 17 26 27 28 29 30 31 32 33 34 35 36 37 // lus 10 keer for ( int counter = 1; counter <= 10; counter++ ) { // berekenen kwadraat van counter en in result stoppen result = square( counter ); // result toevoegen aan String output output += "The square of " + counter + " is " + result + "\n"; } // einde for-lus Lijn 31 Aanroep van de methode square Methode square levert een int (returns), die in result wordt opgeslagen. Deze terugkeerwaarde is het kwadraat van counter. 18 43 44 45 46 47 48 49 50 } // square methode definitie public int square( int y ) { return y * y; } // return square of y // einde methode square // einde klasse SquareIntegers Lijn 44 tot 48 Zelfgedefinieerde methode square Terugkeerwaarde = int Methodenaam = square Parameterlijst = 1 integer, nl. y Return = y*y 19 6.4 Methoden definitie (vervolg). Algemeen formaat van een methode: terugkeerwaarde-type methodenaam( parameterlijst ) { declaraties en statements } • De methodenaam moet een geldige , betekenisvolle identifier zijn! • Het terugkeerwaardetype is het type van het resultaat dat de methode teruggeeft aan de caller. void (leeg): er is geen terugkeerwaarde int: de methode geeft een geheel getal terug • Een methode kan tenhoogste één waarde teruggeven! 20 6.4 Methoden definitie (vervolg). • De parameterlijst = lijst van elke parameternaam en –type, gescheiden door komma’s. • Voor elke parameter MOET er een argument zijn in de aanroep van de methode én het type moet compatibel zijn! Voorbeeld: public double square (double y) y kan één van de volgende waarden ontvangen: 7.35, 22, -0.034 y kan de string “Hello” niet ontvangen! • Een parameterlijst kan leeg zijn! Voorbeeld: public void init() { } 21 6.4 Methoden definitie (vervolg). • Er zijn drie verschillende mogelijkheden om terug te keren naar de caller: als er geen terugkeerwaarde is, keren we terug wanneer * de sluitaccolade van de methode bereikt is OF * het statement return; wordt uitgevoerd als er wel een terugkeerwaarde is, keren we terug wanneer het statement return expression; wordt uitgevoerd; de expressie wordt geëvalueerd en de resulterende waarde wordt teruggegeven aan de caller 22 6.4 Methoden definitie (vervolg). • Methode-body = block met declaraties van lokale variabelen statements • Een methode kan NIET gedefinieerd zijn binnen een andere methode! • Een methode kan wel caller zijn van zichzelf = recursieve methode (zie $ 6.12) 23 6.4 Methoden definitie (vervolg). • Er zijn drie verschillende manieren om methoden aan te roepen: via een referentie naar een object, gevolgd door de puntoperator: g.drawLine(x1,y1,x2,y2); via een klassenaam, gevolgd door de puntoperator: int i = Integer.parseInt(stringToConvert); (enkel voor static-methoden van een klasse!) gewoon de naam van de methode en de argumenten int result = square(counter); Dit kan enkel door een caller uit dezelfde klasse! 24 VOORBEELD 2 Maximum.java • Een applet, die het maximum van drie reële getallen bepaalt. • Er wordt een zelfgedefinieerde methode maximum uitgewerkt, die op haar beurt een voorgedefinieerde methode Math.max() gebruikt. 25 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 // Fig. 6.4: Maximum.java // Het maximum vinden van drie doubles // Java core packages import java.awt.Container; // Java extension packages import javax.swing.*; public class Maximum extends JApplet { // initialiseer applet door gebruikersinput en maken van GUI public void init() { // vraag gebruikersinput String s1 = JOptionPane.showInputDialog( "Enter first floating-point value" ); String s2 = JOptionPane.showInputDialog( "Enter second floating-point value" ); String s3 = JOptionPane.showInputDialog( "Enter third floating-point value" ); // converteer gebruikersinput naar double double number1 = Double.parseDouble( s1 ); double number2 = Double.parseDouble( s2 ); double number3 = Double.parseDouble( s3 ); 26 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 } // methode-aanroep maximum om grootste waarde te bepalen double max = maximum( number1, number2, number3 ); // maak JTextArea om resultaten weer te geven JTextArea outputArea = new JTextArea(); outputArea.setText( "number1: " + number1 + "\nnumber2: " + number2 + "\nnumber3: " + number3 + "\nmaximum is: " + max ); // referentie naar de applets GUI component display area Container container = getContentPane(); // outputArea vasthechten aan Container c container.add( outputArea ); } // einde methode init // maximum methode gebruikt Math klasse methode max om // de maximum waarde te bepalen public double maximum( double x, double y, double z ) { return Math.max( x, Math.max( y, z ) ); } // einde methode maximum // einde klasse Maximum 27 Maximum.java 28 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // initialiseer applet door gebruikersinput en maken van GUI public void init() { // vraag gebruikersinput String s1 = JOptionPane.showInputDialog( "Enter first floating-point value" ); String s2 = JOptionPane.showInputDialog( "Enter second floating-point value" ); String s3 = JOptionPane.showInputDialog( "Enter third floating-point value" ); // converteer gebruikersinput naar double double number1 = Double.parseDouble( s1 ); double number2 = Double.parseDouble( s2 ); double number3 = Double.parseDouble( s3 ); // methode-aanroep maximum om grootste waarde te bepalen double max = maximum( number1, number2, number3 ); Lijn 29 Aanroep van de methode maximum. Deze methode geeft een double terug, die het grootste getal van de drie meegegeven argumenten voorstelt. Dit resultaat komt in max.29 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 // maak JTextArea om resultaten weer te geven JTextArea outputArea = new JTextArea(); outputArea.setText( "number1: " + number1 + "\nnumber2: " + number2 + "\nnumber3: " + number3 + "\nmaximum is: " + max ); // referentie naar de applets GUI component display area Container container = getContentPane(); // outputArea vasthechten aan Container c container.add( outputArea ); } // einde methode init Lijn 40 tot 43 getContentPane() geeft een referentie terug naar het “content pane” van de applet outputArea GUI-component wordt aan “content pane” gekoppeld 30 47 48 49 50 51 52 53 54 55 } // maximum methode gebruikt Math klasse methode max om // de maximum waarde te bepalen public double maximum( double x, double y, double z ) { return Math.max( x, Math.max( y, z ) ); } // einde methode maximum // einde klasse Maximum Lijn 49 tot 53 Zelfgedefinieerde methode maximum : Terugkeerwaarde = double Methodenaam = maximum Parameterlijst = 3 doubles x,y en z Return = maximum van de 3 doubles, gebruikmakend van de voorgedefinieerde methode max uit de klasse Math, die van 2 getallen het grootste kan bepalen. 31 Oef 2. Schrijf een methode getTemperatuurStatus. int intTemp = Integer.parseInt(JOptionPane.showInputDialog(null, “geef de temperatuur”)); String temp = getTemperatuurStatus(intTemp); In temp komt de “koud” bij x < 10 of “lauw” bij x tussen [10 en 20] of “warm” bij x > 20 Met x de ingegeven temperatuur. 32 Oef 3. Wijzig de methode getTemperatuurStatus. • Maak de methode getTemperatuurStatus meer algemeen bruikbaar. De temperatuur moet zowel in graden Celcius (oorspronkelijke versie) als in Fahrenheit doorgegeven kunnen worden. Het eindresultaat blijft uiteraard hetzelfde. de formule F = 32 + (C * 9)/5 . 33 6.5 Argumentpromotie Typeconversie (Coercion) van argumenten • Forceert argumenten naar het gepaste type om door te geven aan de methode • bv. sqrt() verwacht een double: System.out.println( Math.sqrt( 4 ) ); – Evalueert Math.sqrt( 4.) – Evalueert dan System.out.println(2.) Promotieregels • Specifiëren hoe types converteren naar andere types zonder gegevensverlies • Het type van een argument kan steeds gepromoveerd worden naar een “hoger” type (zie tabel) 34 Type Toegelaten promoties double float Geen Double long float of double int long, float of double int, long, float of double char short byte int, long, float of double short, int, long, float of double boolean Geen (boolean waarden zijn geen getallen in Java) Fig. 6.5 Toegelaten promoties voor primitieve data types. Deze regels worden eveneens toegepast bij een gemengde expressie! Voorbeeld: int a = 10; double b = 0; b += a; Om de methode square(int y) aan te roepen met een double (x = 3.5), gebruiken we de volgende aanroep: double res= square((int)x); 35 6.6 Java API Packages Packages • Klassen gegroepeerd in categorieën van gerelateerde klassen. • Promoot software hergebruik (reuse). • import statements specifiëren de nodige klassen in het Java programma om te compileren • bv. import javax.swing.JApplet; 36 Package Beschrijving java.applet Het Java Applet package. Dit package bevat de Applet klasse en verscheidene interfaces die de creatievan applets toelaten, interactie van applets met de browser en afspelen van audioclips. In Java 2, definieert de klasse javax.swing.JApplet een applet die de Swing GUI components gebruikt. java.awt Het Java Abstract Windowing Toolkit Package. Dit package bevat de klassen en interfaces vereist om graphical user interfaces (GUI’s) te creëren en manipuleren in Java 1.0 en 1.1. In Java 2 kunnen deze klassen nog steeds gebruikt worden, maar de Swing GUI components van javax.swing packages worden meestal in de plaats gebruikt. java.awt.event Het Java Abstract Windowing Toolkit Event Package. Dit package bevat klassen en interfaces die instaan voor event handling voor GUI componenten zowel in java.awt als javax.swing packages. java.io Het Java Input/Output Package. Dit package bevat klassen voor invoer en uitvoer van data (zie hoofstuk 16, Files en Streams). java.lang Het Java Language Package. Dit package bevat klassen en interfaces die in veel Java programma’s vereist zijn, en wordt automatisch geïmporteerd in alle Java programma’s. Fig. 6.6 Packages van Java API (Deel 1 van 2). 37 Package java.net java.text java.util javax.swing javax.swing.event Fig. 6.6 Description Het Java Networking Package. Dit package bevat klassen om programma’s te laten communiceren via networks (zie hoofdstuk 18, Networking). Het Java Text Package. Dit package bevat klassen en interfaces die voor manipulatie van getallen, data, karakters en strings. Bevat ook veel voor Java’s internationale ondersteuning, vb: een applet kan strings tonen in verschillende talen, fahankelijk van het land van de gebruiker. Het Java Utilities Package. Dit package bevat utility klassen en interfaces zoals: datum en tijd manipulaties, random getallen (Random), opslag en verwerking van grote hoeveeelheden data, strings opsplitsen in tokens (StringTokenizer) (zie hoofdstuk 20, Data Structures, hoofdstuk 21, Java Utilities Package and Bit Manipulation, en hoofdstukr 22, The Collections API). Het Java Swing GUI Components Package. Dit package bevat klassen en interfaces die Java’s Swing GUI componenten voorziet voor overdraagbare GUIs. Het Java Swing Event Package. Dit package bevat klassen en interfaces voor event handling van GUI components in het javax.swing package. Packages van het Java API (Deel 2 van 2). 38 6.7 Generatie van willekeurige getallen Java kan willekeurige getallen (random-numbers) genereren via een methode uit de klasse Math: • Math.random() double randomValue = Math.random(); 1.0 > randomValue >= 0.0 Het zijn pseudo-random getallen, want ze worden bepaald door een complexe wiskundige berekening, die gebruik maakt van de actuele tijd. Het interval van waarden dat geproduceerd wordt door deze methode, is meestal verschillend van het gewenste interval! Voorbeelden: kop (0) of munt (1); gooien van een dobbelsteen (1, 2, ..., 6);.... 39 6.7 Generatie van willekeurige getallen (vervolg) Om een geheel getal tussen 1 en 6 (beide inbegrepen) te verkrijgen, gebruiken we de volgende expressie: (int) (Math.random() * 6) We brengen het interval van waarden op schaal en het cijfer 6 noemen we de schaalfactor! Door vervolgens één op te tellen bij ons vorig resultaat, verkrijgen we het gewenste resultaat: (int) (Math.random() * 6) + 1 Algemeen: int n = a + (int)(Math.random() * b); a = shiftwaarde, b = schaalfactor 40 VOORBEELD 3 RandomIntegers.java • een applicatie, die 20 willekeurige getallen genereert met een waarde tussen 1 en 6. • gebruikt een for-herhalingsstructuur en de voorgedefinieerde methode Math.random(). 41 1 // Fig. 6.7: RandomIntegers.java 2 // Willekeurige geschaalde integers. 3 4 // Java extension packages 5 import javax.swing.JOptionPane; 6 7 public class RandomIntegers 8 { 9 // main methode begint uitvoering van Java applicatie 10 public static void main( String args[] ) 11 { 12 int value; 13 String output = ""; 14 15 // lus 20 keer 16 for ( int counter = 1; counter <= 20; counter++ ) { 17 18 // kies willekeurige integer tussen 1 en 6 19 value = 1 + ( int ) ( Math.random() * 6 ); 20 21 output += value + " "; // value toevoegen aan output 22 23 // als counter deelbaar is door 5, 24 // voeg newline toe aan String output 25 if ( counter % 5 == 0 ) 26 output += "\n"; 27 28 } // end for structuur 42 29 30 31 32 33 34 35 36 37 38 } JOptionPane.showMessageDialog( null, output, "20 Random Numbers from 1 to 6", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); } // beëindigt de applicatie // einde methode main // einde klasse RandomIntegers 43 15 16 17 18 19 20 21 22 23 24 25 26 27 28 // lus 20 keer for ( int counter = 1; counter <= 20; counter++ ) { // kies willekeurige integer tussen 1 en 6 value = 1 + ( int ) ( Math.random() * 6 ); output += value + " "; // value toevoegen aan output // als counter deelbaar is door 5, // voeg newline toe aan String output if ( counter % 5 == 0 ) output += "\n"; } // end for structuur Lijn 19 Genereert integers in het bereik 1- 6 Math.random levert een double, die >= 0.0 en <1.0. We converteren (casten) de double naar een int 44 VOORBEELD 4 RollDie.java • Applicatie, die een simulatie doet van 6000 teerlingworpen, om te bewijzen dat elk getal (1,..,6) bijna evenveel kans heeft om voor te komen. • Deze gebruikt een for-herhalingsstructuur en een switch-case. 45 1 // Fig. 6.8: RollDie.java 2 // Werp een dobbelsteen 6000 keer. 3 4 // Java extension packages 5 import javax.swing.*; 6 7 public class RollDie 8 { 9 // main methode begint uitvoering van Java applicatie 10 public static void main( String args[] ) 11 { 12 int frequency1 = 0, frequency2 = 0, frequency3 = 0, 13 frequency4 = 0, frequency5 = 0, frequency6 = 0, face; 14 15 // resultaten samenvatten 16 for ( int roll = 1; roll <= 6000; roll++ ) { 17 face = 1 + ( int ) ( Math.random() * 6 ); 18 46 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 // bepaal waarde teerlingworp en verhoog gepaste teller switch ( face ) { case 1: RollDie.java ++frequency1; break; case 2: ++frequency2; break; case 3: ++frequency3; break; case 4: ++frequency4; break; case 5: ++frequency5; break; case 6: ++frequency6; break; } // einde switch structuur 47 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 } } // einde for structuur JTextArea outputArea = new JTextArea(); RollDie.java outputArea.setText( "Face\tFrequency" + "\n1\t" + frequency1 + "\n2\t" + frequency2 + "\n3\t" + frequency3 + "\n4\t" + frequency4 + "\n5\t" + frequency5 + "\n6\t" + frequency6 ); JOptionPane.showMessageDialog( null, outputArea, "Rolling a Die 6000 Times", JOptionPane.INFORMATION_MESSAGE ); System.exit( 0 ); } // beëindigt applicatie // einde methode main // einde klasse RollDie 48 RollDie.java 49 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 // Fig. 6.8: RollDie.java // Werp een dobbelsteen 6000 keer. // Java extension packages import javax.swing.*; public class RollDie { // main methode begint uitvoering van Java applicatie public static void main( String args[] ) { int frequency1 = 0, frequency2 = 0, frequency3 = 0, frequency4 = 0, frequency5 = 0, frequency6 = 0, face; // resultaten samenvatten for ( int roll = 1; roll <= 6000; roll++ ) { face = 1 + ( int ) ( Math.random() * 6 ); Lijn 12-13 Tellers die frequentie gegooide ogen, bijhouden Lijn 16-17 Genereert integers in het bereik 1- 6, voor 6000 worpen 50 // bepaal waarde teerlingworp en verhoog gepaste teller switch ( face ) 19 20 21 22 23 24 25 26 { case 1: ++frequency1; break; RollDie.java case 2: . . 41 42 43 44 45 46 47 48 49 case 6: ++frequency6; break; } } // einde switch structuur // end for structure Lijn 20-46 voor elke worp wordt de juiste frequentie-teller aangepast 51 6.8 VOORBEELD 5: Een kansspel Craps simulatie • Gooi de teerlingen een eerste keer Als de som gelijk is aan 7 of 11, de speler wint Als de som gelijk is aan 2, 3 of 12, de speler verliest Elke andere som (4, 5, 6, 8, 9, 10) is de spelers point • Blijf teerlingen gooien totdat … de som overeenkomt met de spelers point speler wint de som komt overeen met 7 of 11 speler verliest 52 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // Fig. 6.9: Craps.java // Craps // Java core packages import java.awt.*; import java.awt.event.*; Craps.java // Java extension packages import javax.swing.*; public class Craps extends JApplet implements ActionListener { // constanten voor status van het spel weer te geven private final int WON = 0, LOST = 1, CONTINUE = 2; // andere gebruikte variabelen private boolean firstRoll = true; private int sumOfDice = 0; private int myPoint = 0; // niet private int gameStatus = CONTINUE; // true bij eerste worp // som van teerling gewonnen op eerste worp // spel nog niet over // GUI componenten private JLabel die1Label, die2Label, sumLabel, pointLabel; private JTextField die1Field, die2Field, sumField, pointField; private JButton rollButton; 53 1 2 3 4 5 6 7 8 9 10 11 12 13 // Fig. 6.9: Craps.java // Craps // Java core packages import java.awt.*; import java.awt.event.*; Craps.java // Java extension packages import javax.swing.*; public class Craps extends JApplet implements ActionListener { Lijn 11 We maken een klasse Craps die ActionListener implementeert. Een ActionListener is letterlijk een klasse die ‘luistert’ of er een Actionevent plaatsvindt, bv. de gebruiker drukt op een button. Lijn 6 : import van het pakket java.awt.event, waar de klasse ActionListener deel van uitmaakt. 54 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 // opzetten van GUI componenten public void init() { Craps.java // haal referentie naar content pane en verander de layout // naar die van een FlowLayout Container container = getContentPane(); container.setLayout( new FlowLayout() ); // maak label en tekstveld voor eerste teerling die1Label = new JLabel( "Die 1" ); container.add( die1Label ); die1Field = new JTextField( 10 ); die1Field.setEditable( false ); container.add( die1Field ); // maak label en tekstveld voor tweede teerling die2Label = new JLabel( "Die 2" ); container.add( die2Label ); die2Field = new JTextField( 10 ); die2Field.setEditable( false ); container.add( die2Field ); Lijn 35-47 voor uitvoer van teerling 1 en teerling 2 55 // maak label en tekstveld voor som sumLabel = new JLabel( "Sum is" ); container.add( sumLabel ); sumField = new JTextField( 10 ); sumField.setEditable( false ); container.add( sumField ); 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 // maak label en tekstveld voor punten pointLabel = new JLabel( "Point is" ); container.add( pointLabel ); pointField = new JTextField( 10 ); pointField.setEditable( false ); container.add( pointField ); // maak knop voor gebruikers om teerling te werpen //registreer rolButton als component waarop de event zal 64 65 66 67 68 //plaatsgrijpen rollButton = new JButton( "Roll Dice" ); rollButton.addActionListener( this ); container.add( rollButton ); } Lijn 49-54 :voor uitvoer van de som van de worpen Lijn 56-61 : voor uitvoer van de speler zijn ‘point’ Lijn 63-66 : knop om teerlingen te werpen 56 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 // proces van een teerlingworp public void actionPerformed( ActionEvent actionEvent ) { // eerste teerlingworp Indien eerste worp activeer rollDice if ( firstRoll ) { sumOfDice = rollDice(); // werp teerling switch ( sumOfDice ) { // winnen op eerste worp case 7: case 11: gameStatus = WON; pointField.setText( "" ); break; // verliezen op eerste worp case 2: case 3: case 12: gameStatus = LOST; pointField.setText( "" ); break; Indien de som 7 of 11 is, speler wint // leeg pointveld Indien de som is 2, 3 of 12 is, speler verliest // leeg pointveld Lijn 70 : Methode wordt automatisch geactiveerd als Jbutton wordt ingedrukt om de event af te handelen. 57 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 Bij een van som 4, 5, 6, 8, 9 of 10 // Onthoud punt default: wordt dit de point gameStatus = CONTINUE; myPoint = sumOfDice; pointField.setText( Integer.toString( myPoint ) ); firstRoll = false; break; } } // einde switch structuur // einde body if structuur // aansluitende teerlingworp else { sumOfDice = rollDice(); // werp teerling // bepaal status van het spel if ( sumOfDice == myPoint ) // winnen door maken punt gameStatus = WON; Als de som gelijk is aan point, else speler wint; Als som 7 is, if ( sumOfDice == 7 ) // verliezen speler doorverliest 7 te werpen gameStatus = LOST; } // toon boodschap die status spel weergeeft displayMessage(); } // end method actionPerformed 58 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 // werp teerling, bereken som en toon resultaten public int rollDice() { int die1, die2, sum; // kies willekeurige waarden teerlingworpen die1 = 1 + ( int ) ( Math.random() * 6 ); die2 = 1 + ( int ) ( Math.random() * 6 ); sum = die1 + die2; // som van de teerlingogen // toon resultaten die1Field.setText( Integer.toString( die1 ) ); die2Field.setText( Integer.toString( die2 ) ); sumField.setText( Integer.toString( sum ) ); return sum; } // geef som van worpen terug // einde methode rollDice Lijn 125-126 : Methode rollDice() gebruikt Math.random() om twee teerlingen te simuleren en geeft de som ervan terug. 59 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 } // bepaal spel status en geef de gepaste boodschap weer // in de statusbalk public void displayMessage() { // spel mag doorgaan if ( gameStatus == CONTINUE ) showStatus( "Roll again." ); // spel gewonnen of verloren else { if ( gameStatus == WON ) showStatus( "Player wins. " + "Click Roll Dice to play again." ); else showStatus( "Player loses. " + "Click Roll Dice to play again." ); // volgende worp is eerste van een nieuw spel firstRoll = true; } } // eind methode displayMessage // einde klasse Craps Lijn 151 : Methode showStatus toont een string in de applet zijn containers 60 statusbalk. Craps.java 61 6.9 Levensduur van identifiers Identifier levensduur • Levensduur Periode dat de identifier bestaat in het geheugen • Automatic levensduur Lokale variabelen Bestaan van zodra het declaratiestatement wordt uitgevoerd, totdat de programmacontrole het betreffende blok verlaat. 62 6.9 Levensduur van identifiers (vervolg) Identifier levensduur • Static levensduur static klasse attributen (class variabele/ class reference) Bestaan van zodra de klasse die ze definieert is geladen, tot het einde van het programma. Kunnen echter niet noodzakelijk overal in het programma gebruikt worden! Identifier scope • Definieert waar de identifier kan worden gebruikt. 63 6.10 Scope regels Scope van een identifier • is het deel binnen de broncod e waarin naar de identifier kan gerefereerd worden. • Klasse scope Begint bij de openingsaccolade ({) en eindigt bij de sluitingsaccolade (}) van de klasse bv. object-variabelen en methoden • Blok scope Begint bij de identifierdeclaratie en eindigt bij de sluitingsaccolade (}) van de blok bv. lokale variabelen en methodeparameters 64 VOORBEELD 6 Scoping.java • een object-variabele x en twee lokale variabelen, ook met als naam x worden gedeclareerd in een applet • deze applet zal, voor de eerste keer, de methode start() (her)definiëren met de vaste hoofding public void start() {....} 65 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 // Fig. 6.10: Scoping.java // A scoping example. // Java core packages import java.awt.Container; Scoping.java // Java extension packages import javax.swing.*; public class Scoping extends JApplet { private JTextArea outputArea; // object-variabele x private int x = 1; // initialiseert de applet: GUI toekennen aan de applet public void init() { outputArea = new JTextArea(); Container container = getContentPane(); container.add( outputArea ); } // einde methode init // methode start wordt opgeroepen nadat de methode init werd uitgevoerd; De methode // start roept de methodes useLocal en useInstance op. public void start() { int x = 5; // lokale variabele x van de methode start outputArea.append( "local x in start is " + x ); useLocal(); useInstance(); // useLocal bevat een lokale variabele x // useInstance gebruikt de object-variabele x 66 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 } useLocal(); useInstance(); // useLocal herinitialiseert zijn lokale variabele x // object-variable x heeft zijn vorige waarde behouden outputArea.append( "\n\nlocal x in start is " + x ); } // einde methode start // useLocal herinitialiseert de lokale variable x telkens deze methode wordt opgeroepen public void useLocal() { int x = 25; // initialisatie van de lokale variabele x outputArea.append( "\n\nlocal " after entering useLocal" ++x; outputArea.append( "\nlocal x " before exiting useLocal" } x in useLocal is " + x + ); in useLocal is " + x + ); // einde methode useLocal // useInstance wijzigt de object-variabele x telkens deze methode wordt opgeroepen public void useInstance() { outputArea.append( "\n\ninstance variable x is " + x + " on entering useInstance" ); x *= 10; outputArea.append( "\ninstance variable x is " + x + " on exiting useInstance" ); } // einde methode useInstance // einde klasse Scoping 67 1 2 3 4 5 6 7 8 9 10 11 12 13 14 // Fig. 6.10: Scoping.java // A scoping example. // Java core packages import java.awt.Container; Scoping.java // Java extension packages import javax.swing.*; public class Scoping extends JApplet { private JTextArea outputArea; // object-variabele x private int x = 1; Lijn 14 • Object-variabele x heeft klasse scope. M.a.w. x kan gebruikt worden in alle methoden en in alle inwendige klassen van de klasse Scoping. 68 16 17 18 19 20 21 22 23 // initialiseert de applet: GUI toekennen aan de applet public void init() { Scoping.java outputArea = new JTextArea(); Container container = getContentPane(); container.add( outputArea ); } // einde methode init Lijn 21 • In een container kan je componenten stoppen, zoals het GUI-component JTextArea. • Met de methode add kan je een component (een knop, een tekstvak, een panel) toevoegen aan een container-object. 69 25 // start wordt opgeroepen nadat de methode init werd uitgevoerd. 26 // De methode start roept de methodes useLocal en useInstance op. 27 public void start() Scoping.java 28 { 29 int x = 5; // lokale variabele x van de methode start 30 31 outputArea.append( "local x in start is " + x ); 32 33 useLocal(); // useLocal bevat een lokale variabele x 34 useInstance();// useInstance gebruikt de object-variabele x 35 useLocal(); // useLocal herinitialiseert zijn lokale variabele useInstance();//object-variable x heeft zijn vorige waarde behouden 38 outputArea.append( "\n\nlocal x in start is " + x ); 39 40 } // einde methode start Lijn 29 • Lokale variabele x heeft blok scope. M.a.w. x kan uitsluitend gebruikt worden vanaf de plaats waar hij is gedefinieerd (lijn 29) tot aan de sluitingsaccolade van het blok waarin de declaratie staat (lijn 40). 70 41 42 43 44 45 46 47 48 49 50 51 52 53 // useLocal herinitialiseert de lokale variable x // telkens deze methode wordt opgeroepen public void useLocal() { int x = 25; // initialisatie van de lokale variabele x outputArea.append( "\n\nlocal " after entering useLocal" ++x; outputArea.append( "\nlocal x " before exiting useLocal" } x in useLocal is " + x + ); in useLocal is " + x + ); // einde methode useLocal Lijn 45 : Lokale variabele x heeft blok scope. Deze variabele heeft een andere scope als de lokale variabele x (lijn 29), dus het zijn twee verschillende variabelen en ze zitten elkaar niet in de weg! 27 public void start() 28 { 29 int x = 5; // lokale variabele x van de methode start … 40 } // einde methode start 71 54 55 56 57 58 59 60 61 62 63 64 65 66 } // useInstance wijzigt de object-variabele x // telkens deze methode wordt opgeroepen public void useInstance() { outputArea.append( "\n\ninstance variable x is " + x + " on entering useInstance" ); x *= 10; outputArea.append( "\ninstance variable x is " + x + " on exiting useInstance" ); } // einde methode useInstance // einde klasse Scoping Lijn 60 • Object-variabele x heeft klasse scope, dus kan x gebruikt worden in de methode useInstance. De objectvariabele x wordt met 10 vermenigvuldigd. 72 Scoping.java 73 6.11 Methode Overloading Methode overloading • Meerdere methoden met dezelfde naam in één programma. • NOODZAAK : een verschillende argumentenset voor elke methode Het aantal argumenten moet verschillend zijn EN/OF De argumenttypen moeten verschillend zijn 74 VOORBEELD 7: MethodOverload.java • voorbeeld van methode overloading: het programma bevat de methode square met argument int en de methode square met argument double. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // Fig. 6.16: MethodOverload.java // methode overloading // Java core packages import java.awt.Container; // Java extension packages import javax.swing.*; public class MethodOverload extends JApplet { // roept verschillende versies van methode square op. public void init() { JTextArea outputArea = new JTextArea(); Container container = getContentPane(); container.add( outputArea ); 75 19 outputArea.setText( 20 "The square of integer 7 is " + square( 7 ) + 21 "\nThe square of double 7.5 is " + square( 7.5 ) ); 22 } //einde methode init Lijn 20 • de methode square wordt opgeroepen. Als argument geven we het geheel getal 7 door. Lijn 21 • de methode square wordt opgeroepen. Als argument geven we het decimaal getal 7.5 door. 76 24 25 26 27 28 29 30 31 32 // methode square met argument int public int square( int intValue ) { System.out.println( "Called square with int argument: " + intValue ); return intValue * intValue; } // einde methode square met argument int Lijn 25 • Methode square ontvangt int als argument en geeft dus ook een int terug! 77 34 // square methode met argument double 35 public double square( double doubleValue ) 36 { 37 System.out.println( 38 "Called square with double argument: " + doubleValue ); 39 40 return doubleValue * doubleValue; 41 42 } // einde methode square met argument double 43 44 } // einde klasse MethodOverload Lijn 35 • Overloaded methode square ontvangt double als argument en geeft een double terug. 78 VOORBEELD 8 : MethodOverload.java • aantonen dat een compiler geen onderscheid kan maken tussen methoden met identieke namen, die dezelfde argumentenset bevatten; nochtans hebben ze een verschillend return type. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // Fig. 6.17: MethodOverload.java // Twee methodes met dezelfde naam en hetzelfde argument // maar met een andere return type. // Java extension packages import javax.swing.JApplet; public class MethodOverload extends JApplet { // eerste definitie van de methode square met argument double public int square( double x ) { return x * x; } // tweede definitie van de methode square met argument double // veroorzaakt een ‘syntax error’ public double square( double y ) { return y * y; } } // einde klasse MethodOverload 79 10 11 12 13 14 15 16 17 18 19 20 21 22 // eerste definitie van de methode square met argument double public int square( double x ) { return x * x; } // tweede definitie van de methode square met argument double // veroorzaakt een ‘syntax error’ public double square( double y ) { return y * y; } MethodOverload.java:18: square(double) is already defined in MethodOverload public double square( double y ) ^ MethodOverload.java:13: possible loss of precision found : double required: int return x * x; ^ 2 errors Compiler error messages tengevolge van gelijke argumentenlijst en enkel verschillende return types. 80 6.12 Recursie Recursieve methode • Roept zichzelf op (direct of indirect via een andere methode) • De methode kan enkel de basis case(s) oplossen, m.a.w. roepen we de methode aan met de basis case(s), dan geeft deze een resultaat terug. • Als de methode wordt aangeroepen met een complexer probleem, dan wordt het probleem verdeelt in Basis case Eenvoudiger probleem De methode verdeelt nu dit eenvoudiger probleem, totdat het opgelost is. 81 6.12 Recursie (vervolg) Recursieve methode • Bevat een recursieve oproep (call): Het nieuwe, eenvoudiger probleem lijkt op het originele probleem, dus roept de methode zichzelf terug aan om het eenvoudiger probleem op te lossen = recursieve doorloop (step). De recursieve stap bevat normaal ook het keyword return, vermits het resultaat van deze aanroep moet gecombineerd worden met het resultaat van het gedeelte dat de methode wel kan oplossen om uiteindelijk een eindresultaat aan de originele caller te kunnen teruggeven! 82 VOORBEELD : De faculteit berekenen van het getal 5 5! = 5 * 4 * 3 * 2 * 1 5! = 5 * (4 * 3 * 2 * 1) 5! = 5 * 4! De recursieve methode verdeelt het probleem in een eenvoudiger probleem: 5! = 5 * 4! De recursieve methode verdeelt het probleem in een eenvoudiger probleem: 4! = 4 * 3! De recursieve methode verdeelt het probleem in een eenvoudiger probleem: 3! = 3 * 2! De recursieve methode verdeelt het probleem in een eenvoudiger probleem: 2! = 2 * 1! De recursieve methode verdeelt het probleem in een basis case: 1! = 1 83 Finale waarde = 120 5! 5! 5 * 4! 5 * 4! 4 * 3! 5! = 5 * 24 = 120 is returned 4 * 3! 3 * 2! 4! = 4 * 6 = 24 is returned 3 * 2! 2 * 1! 1 (a) Verwerking van de recursieve calls. 3! = 3 * 2 = 6 is returned 2 * 1! 1 2! = 2 * 1 = 2 is returned 1 returned (b) Waarde returned bij iedere recursieve call. Fig. 6.11 Recursieve evaluatie van 5!. 84 VOORBEELD 9 FactorialTest.java • De faculteit van de getallen 0 t.e.m. 10 worden berekend. 1 2 3 4 5 6 7 8 9 10 11 12 // Fig. 6.12: FactorialTest.java // Programma bevat de recursieve methode factorial // Java core packages import java.awt.*; // Java extension packages import javax.swing.*; public class FactorialTest extends JApplet { private JTextArea outputArea; 85 13 14 15 16 17 18 19 20 21 22 23 24 25 26 // initialisatie applet public void init() { outputArea = new JTextArea(); Container container = getContentPane(); container.add( outputArea ); // het faculteit berekenen van 0 tot en met 10 for ( long counter = 0; counter <= 10; counter++ ) outputArea.append( counter + "! = " + factorial( counter ) + "\n" ); } // einde methode init Lijn 24 • De methode factorial wordt 10 keer opgeroepen. 86 28 29 30 31 32 33 34 35 36 37 38 39 40 41 } // Recursieve methode factorial public long factorial( long number ) { // basis case if ( number <= 1 ) return 1; // recursive step else return number * factorial( number - 1 ); } // einde methode factorial // einde klasse FactorialTest Lijn 32-33 • De recursieve methode verdeelt het probleem in de basis cases: 1! = 1 en 0!= 1 EN Lijn 32-33 • in een eenvoudiger probleem fac(n) = n * fac(n-1) 87 88 6.13 Voorbeeld met Recursie: De Fibonacci Reeks Fibonacci reeks • Elk getal in de reeks is de som van de twee voorgaande getallen • vb. 0, 1, 1, 2, 3, 5, 8, 13, 21… fibonacci(0) = 0 fibonacci(1) = 1 fibonacci(n) = fibonacci(n - 1) + fibonacci( n – 2 ) • fibonacci(0) en fibonacci(1) zijn basis cases • Gulden snede 89 f( 3 ) return return f( 1 ) return 1 + f( 2 ) + f( 0 ) f( 1 ) return 1 return 0 Fig. 6.14 Verzameling recursive calls naar methode fibonacci (f in dit diagram). 90 VOORBEELD 10 FibonacciTest.java • de fibonacci-waarde van een ingegeven getal wordt berekend in deze applet 91 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 // Fig. 6.13: FibonacciTest.java // Programma bevat de recursieve methode fibonacci // Java core packages import java.awt.*; import java.awt.event.*; // Java extension packages import javax.swing.*; public class FibonacciTest extends JApplet implements ActionListener { private JLabel numberLabel, resultLabel; private JTextField numberField, resultField; // initialiseert de applet: GUI toekennen aan de applet public void init() { // "get content pane" en ken zijn layout toe aan FlowLayout Container container = getContentPane(); container.setLayout( new FlowLayout() ); // creëer numberLabel en ken het toe aan “content pane” numberLabel = new JLabel( "Enter an integer and press Enter" ); container.add( numberLabel ); // creëer numberField en ken het toe aan “content pane” numberField = new JTextField( 10 ); container.add( numberField ); // bewaar deze applet als “numberField’s ActionListener” numberField.addActionListener( this ); 92 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 // creëer resultLabel en ken het toe aan “content pane” resultLabel = new JLabel( "Fibonacci value is" ); container.add( resultLabel ); // creëer resultField, maak het “uneditable” // en ken het toe aan “content pane” resultField = new JTextField( 15 ); resultField.setEditable( false ); container.add( resultField ); } // einde methode init // input wordt aan de gebruiker gevraagd en de methode fibonacci wordt opgeroepen public void actionPerformed( ActionEvent e ) { long number, fibonacciValue; // de input van de gebruiker wordt omgezet naar long number = Long.parseLong( numberField.getText() ); showStatus( "Calculating ..." ); // bereken de fibonacci van het ingegeven getal fibonacciValue = fibonacci( number ); // het resultaat (fibonacci van het ingegeven getal) weergeven showStatus( "Done." ); resultField.setText( Long.toString( fibonacciValue ) ); } // einde methode actionPerformed 93 67 68 69 70 71 72 73 74 75 76 77 78 79 80 } // recursieve methode fibonacci public long fibonacci( long n ) { // basis case if ( n == 0 || n == 1 ) return n; // recursieve stap else return fibonacci( n - 1 ) + fibonacci( n - 2 ); } // einde methode fibonacci // einde klasse FibonacciTest 94 95 96 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // Fig. 6.13: FibonacciTest.java // Programma bevat de recursieve methode fibonacci // Java core packages import java.awt.*; import java.awt.event.*; FibonacciTest.ja va // Java extension packages import javax.swing.*; public class FibonacciTest extends JApplet implements ActionListener { private JLabel numberLabel, resultLabel; private JTextField numberField, resultField; Lijn 11-12 • We maken een klasse FibonacciTest die ActionListener implementeert. Een ActionListener is letterlijk een klasse die ‘luistert’ of er een Actionevent plaatsvindt, bv. de gebruiker drukt op enter. 97 17 18 19 20 21 22 23 // initialiseert de applet: GUI toekennen aan de applet public void init() { FibonacciTest.ja // "get content pane" en ken zijn layout toe aan FlowLayout va Container container = getContentPane(); container.setLayout( new FlowLayout() ); Lijn 22 • De eenvoudigste layout-manager is de FlowLayout. De FlowLayout zet de componenten, in de volgorde waarin ze in de container gestopt worden, van links naar rechts gecentreerd op een rij. Als de rij vol is komen de volgende componenten gecentreerd op de rij eronder. • methode setLayout stelt de layout, voor de container, in op de eenvoudige FlowLayout, VOOR de componenten toegevoegd worden aan de container. 98 24 25 26 27 28 29 30 31 // creëer numberLabel en ken het toe aan “content pane” numberLabel = new JLabel( "Enter an integer and press Enter" ); FibonacciTest.ja container.add( numberLabel ); va // creëer numberField en ken het toe aan “content pane” numberField = new JTextField( 10 ); container.add( numberField ); Lijn 27, 31 • In de volgorde waarin je de componenten met de methode add aan de applet toevoegt, komen ze ook op het scherm. numberLabel numberField 99 33 zal 34 35 36 37 38 39 40 41 42 43 44 45 46 //registreer numberField als component waarop de event //plaatsgrijpen numberField.addActionListener( this ); // creëer resultLabel en ken het toe aan “content pane” resultLabel = new JLabel( "Fibonacci value is" ); container.add( resultLabel ); // creëer resultField, maak het “uneditable” // en ken het toe aan “content pane” resultField = new JTextField( 15 ); resultField.setEditable( false ); container.add( resultField ); } // einde methode init Lijn 34 : We vertellen aan numberfield dat “this applet” de event zal afhandelen. Lijn 43 : De component resultField dient enkel als output. resultLabel resultField 100 48 // input wordt aan de gebruiker gevraagd en de methode fibonacci wordt opgeroepen 49 public void actionPerformed( ActionEvent e ) 50 { 51 long number, fibonacciValue; 52 53 // de input van de gebruiker wordt omgezet naar long 54 number = Long.parseLong( numberField.getText() ); 55 56 showStatus( "Calculating ..." ); 57 58 // bereken de fibonacci van het ingegeven getal 59 fibonacciValue = fibonacci( number ); 60 61 // het resultaat (fibonacci van het ingegeven getal) weergeven 62 showStatus( "Done." ); 63 resultField.setText( Long.toString( fibonacciValue ) ); 64 65 } // einde methode actionPerformed Lijn 49: methode actionPerformed wordt AUTOMATISCH geactiveerd als de gebruiker op Enter drukt. Lijn 51: we gebruiken long, omdat Fibonacci getallen snel groot worden. Lijn 59: De input van de gebruiker wordt doorgegeven aan de methode fibonacci 101 67 68 69 70 71 72 73 74 75 76 77 78 79 80 } // recursieve methode fibonacci public long fibonacci( long n ) { // basis case if ( n == 0 || n == 1 ) return n; // recursieve stap else return fibonacci( n - 1 ) + fibonacci( n - 2 ); } // einde methode fibonacci // einde klasse FibonacciTest Lijn 71-72 • De recursieve methode verdeelt het probleem in een basis case: fibonacci(0) = 0 en fibonacci(1) = 1 Lijn 76 • De recursieve methode verdeelt het probleem in een eenvoudiger probleem: fibonacci(n) = fibonacci(n - 1) + fibonacci( n – 2 ) 102 Oef 4. Wat doet de volgende methode? // parameter b moet een positief integer zijn // om oneindige recursie te vermijden public int mysterie (int a, int b) { if (b == 1) return a; else return a + mysterie ( a, b – 1); } 103 6.14 Recursie vs. Iteratie Iteratie • Gebruikt herhalingstructuur (for, while of dowhile) • Herhaling door expliciet gebruik van een herhalingsstructuur • Eindigt als lusvoorwaarde false evalueert Recursie • • • • Gebruikt selectiestructuur (if, if-else of switch) Herhaling door herhaalde methode calls Eindigt als de basis case voldaan is Controleert herhaling door het probleem in eenvoudigere te delen 104 6.14 Recursie vs. Iteratie (verv.) Recursie • Meer overhead dan bij iteratie. M.a.w. elke recursieve call maakt een kopie van de argumenten van de methode. • Geheugenintensiever dan bij een iteratie. • Kan ook iteratief opgelost worden (maar soms met vele lijnen code). • Kan dikwijls geïmplementeerd worden met slechts enkele lijnen code. 105 Chapter 6 7 11 20 Recursion examples and exercises Factorial method Fibonacci method Greatest common divisor Sum of two integers Multiply two integers Raising an integer to an integer power Towers of Hanoi Visualizing recursion Sum the elements of an array Print an array Print an array backward Check if a string is a palindrome Minimum value in an array Selection sort Eight Queens Linear search Binary search Quicksort Maze traversal Printing a string input at the keyboard backward Linked-list insert Linked-list delete Search a linked list Print a linked list backward Binary-tree insert Preorder traversal of a binary tree Inorder traversal of a binary tree Postorder traversal of a binary tree Fig. 6.15 Samenvatting van recursie voorbeelden en oefeningen in het boek. 106 6.15 Methoden van Klasse JApplet Java API definieert meerdere JApplet methoden • De applet container (= viewer of browser) roept de methoden init, start, paint, stop en destroy, gedurende de uitvoering van de applet, op. • We overschrijven enkel de methode(s) die we nodig hebben. M.a.w. we “overriden” de methode(s) die we nodig hebben. 107 a Methode public void init() Wanneer de methode wordt opgeroepen en het doel van de methode Deze methode wordt slechts eenmaal geactiveerd door de appletviewer of browser wanneer de applet wordt geladen voor executie. Ze verzorgt de initialisatie van de applet. Typische acties zijn initializatie van instance variabelen en GUI componenten van de applet, het laden van geluiden om te spelen of beelden om te tonen (zie hfdst. 19, Multimedia) en de creatie van threads (zie hfdst. 16, Multithreading). public void Wordt geactiveerd nadat de init methode is uitgevoerd en telkens als de gebruiker van start() de browser terugkeert naar de HTML pagina waarin de applet huist (na het bekijken van een andere HTML pagina). Deze methode voert taken uit die moeten volbracht worden als de applet voor de eerste keer wordt geladen in de browser en telkens opnieuw als de pagina wordt herbezocht. Typische acties zijn het startenvan een animation (zie hfdst. 18, Multimedia) en het starten van andere threads (zie hfdst. 16, Multithreading). public void Deze methode wordt voor het eerst opgeroepen na de start methode en telkens weer paint( Graphics g opnieuw als het nodig is om de applet output te hertekenen. Bv. De paint methode wordt ) opgeroepen als de gebruiker de applet overdekt met een ander venster en dan het venster weer weg doet. Typische acties zijn het tekenen met het Graphics object g dat automatisch als argument met paint wordt meegegeven. public void Deze methode wordt geactiveerd als de applet moet eindigen—normaal wanneer de stop() gebruiker van de browser de HTML pagina verlaat. Deze methode voert de vereiste taken uit om de applet’s executie te schorsen. Typische actions zijn het stoppen van de uitvoering van een animatie en threads. public void Deze methode wordt geactiveerd als de applet uit het geheugen wordt verwijderd — destroy() normaal als de gebruiker van de browser de sessie beëindigt. Deze methode voert taken uit die vereist zijn om resources vrij te geven die door de applet werden gereserveerd. Fig. 6.18 JApplet methoden die de applet container oproept gedurende de applet’s executie. 108 JApplet methode die de appletcontainer oproept gedurende de applet’s executie public void init() • Deze methode wordt slechts eenmaal geactiveerd door de appletviewer of browser wanneer de applet wordt geladen voor executie. Ze verzorgt de initialisatie van de applet. Typische acties zijn initialisatie van object-variabelen en GUI-componenten van de applet, het laden van geluiden om af te spelen of beelden om te tonen (zie hfdst. 19, Multimedia) en de creatie van threads (zie hfdst. 16, Multithreading). 109 JApplet methode die de applet container oproept gedurende de applet’s executie public void start() • Wordt geactiveerd nadat de init methode is uitgevoerd en telkens als de gebruiker van de browser terugkeert naar de HTML pagina waarin de applet huist (na het bekijken van een andere HTML pagina). Deze methode voert taken uit die moeten volbracht worden als de applet voor de eerste keer wordt geladen in de browser en telkens opnieuw als de pagina wordt herbezocht. Typische acties zijn het starten van een animatie (zie hfdst. 19, Multimedia) en het starten van andere threads (zie hfdst. 16, Multithreading). 110 JApplet methode die de applet container oproept gedurende de applet’s executie public void paint( Graphics g ) • Deze methode wordt voor het eerst opgeroepen na de start methode en telkens weer opnieuw als het nodig is om de applet output te hertekenen (expliciet via de methode repaint()). Bv. de paint methode wordt opgeroepen als de gebruiker de applet overdekt met een ander venster en dan het venster weer weg doet. Typische acties zijn het tekenen met het Graphics object g, dat automatisch als argument met paint wordt meegegeven. 111 JApplet methode die de applet container oproept gedurende de applet’s executie public void stop() • Deze methode wordt geactiveerd als de applet moet eindigen—normaal wanneer de gebruiker van de browser de HTML pagina verlaat. Deze methode voert de vereiste taken uit om de applet’s executie te schorsen. Typische acties zijn het stoppen van de uitvoering van een animatie en threads. 112 JApplet methode die de applet container oproept gedurende de applet’s executie public void destroy() • Deze methode wordt geactiveerd als de applet uit het geheugen wordt verwijderd —normaal als de gebruiker van de browser de sessie beëindigt. Deze methode voert taken uit die vereist zijn om resources vrij te geven die door de applet werden gereserveerd. 113 Oef 5. Schrijf een applet die … Vraag de zijde voor een ‘vierkant’ en karakter om dat vierkant af te drukken. Druk het vierkant af met dat vulteken. **** **** **** **** Gebruik hiervoor een methode maakvierkant die het volledige vierkant afdrukt. 114 Oef 6. Schrijf een applicatie die … Nagaat welke gehele getallen perfect zijn uit de reeks natuurlijke getallen waarvan de kleinste en grootste waarde door de gebruiker worden ingevoerd. Een getal is perfect als het gelijk is aan de som van zijn delers, bv: 6 = 1 + 2 + 3. Schrijf hiervoor een methode perfect die nagaat of zijn argument een perfect getal is. De methode perfect zelf gebruikt de methode somvandelers die je ook uitwerkt en die de som van de delers van zijn argument aflevert. 115