10 Exception handling

Vergelijkbare documenten

public Paneel() { knop = new JButton( Klik ); knop.addactionlistener( new KnopHandler() ); tekstvak = new JTextField(10); add(knop); add(tekstvak);

eerste voorbeelden in Java

Lessen Java: Reeks 3. David Blinder Jan G. Cornelis

voegtoe: eerst methode bevat gebruiken, alleen toevoegen als bevat() false is

Handleiding JCreator. Inhoud. Een Workspace en een eerste project maken

Een stoomcursus door Edgar de Graaf, november 2006

Omschrijf bij ieder onderdeel van de methode de betekenis ervan. Java kent twee groepen van klassen die een GUI kunnen maken: awt en swing.

Modelleren en Programmeren

Programmeren in C# Exceptions. Hoofdstuk 17

Tentamen Inleiding Programmeren (IN1608WI), 2 februari 2012, , Technische Universiteit Delft, Faculteit EWI, Afdeling 2.


Programmeren (1) Examen NAAM:

Opdracht 7a. Applicatiebouw 2014/2015

Vakgroep CW KAHO Sint-Lieven

APPLICATIEBOUW 3E COLLEGE: OBJECT GEORIËNTEERD PROGRAMMEREN, METHODEN, PARAMETERS, SCOPE VAN VARIABELEN. Onderdeel van SmartProducts

Wat is een grafische gebruikersinterface (GUI)?

Een topprogrammeur in het OO programmeren is Graig Larman. Hij bedacht de volgende zin:

Zelftest Programmeren in Java

Java Objectgeoriënteerd ontwerpen en programmeren

IMP Uitwerking week 13

Variabelen en statements in ActionScript

Ingebouwde klassen & methodes

BEGINNER JAVA Inhoudsopgave

In de tweede regel plaatsen we in het gereserveerde stukje geheugen een getal.

Modelleren en Programmeren

PROS1E1 Gestructureerd programmeren in C Dd/Kf/Bd

Kleine cursus PHP5. Auteur: Raymond Moesker

Tentamen Imperatief Programmeren

Tentamen Object Georiënteerd Programmeren TI oktober 2014, Afdeling SCT, Faculteit EWI, TU Delft

Java Les 3 Theorie Herhaal structuren

Tentamen Object Georiënteerd Programmeren TI januari 2013, Afdeling SCT, Faculteit EWI, TU Delft

NAAM: Programmeren 1 Examen 21/01/2011

Een gelinkte lijst in C#

Labo 2 Programmeren II

VBA voor Doe het Zelvers deel 9

sheets Programmeren 2 Java Recursie, de muis en graphics Walter Kosters

Uitleg: In de bovenstaande oefening zie je in het eerste blokje een LEES en een SCHRIJF opdracht. Dit is nog lesstof uit het tweede trimester.

Programmeren in Java. De Java-GUI

Uitwerking Tweede deeltentamen Imperatief programmeren - versie 1 Vrijdag 21 oktober 2016, uur

Derde deeltentamen Imperatief programmeren - versie 1 Vrijdag 7 november 2014, uur

Tentamen Imperatief en Object-georiënteerd programmeren in Java voor CKI

Universiteit van Amsterdam FNWI. Voorbeeld van tussentoets Inleiding programmeren

Derde deeltentamen Imperatief programmeren - versie 1 Vrijdag 6 november 2015, uur

Tentamen Objectgeorienteerd Programmeren IN1205 Voorbeeld

Uitwerkingen Tweede deeltentamen Imperatief programmeren Vrijdag 15 oktober 2010, uur

Zo vind u hierin de volgende documentatie over de klasse Applet: +----java.awt.panel java.applet.applet

NAAM: Programmeren 1 Examen 29/08/2012

Programmeren in Java 3

Kennismaken Greenfoot

Programmeren I. 26 augustus Algemene Richtlijnen. Richtlijnen Programmeren 1

Game of Life in Java

Kwis (3) class X { public void a() { System.out.println("x"); public static void main(string[] args) { X x = new X();

APPLICATIEBOUW 7E COLLEGE: DPU3, OEFENEN TOETS. Onderdeel van SmartProducts

Visual Basic.NET. Visual Basic.NET. M. den Besten 0.3 VB. NET

Modelleren en Programmeren

Inhoud Inhoud. Over dit boek 7. 1 Eclipse IDE (Integrated Development Environment) 9. 2 Functionele specificatie 13

Opgaven. Python Assessment

Tutorial 1, Delphi: Geldspraak

Small Basic Programmeren Text Console 2

Programmeren 1 23 januari 2013 Prof. T. Schrijvers

APPLICATIEBOUW 2E COLLEGE: ONTWERPEN, GEBRUIKERSINTERFACES, VARIABELEN & EXPRESSIES. Onderdeel van SmartProducts

Voorbeeldtentamen Inleiding programmeren (IN1608WI), Oktober 2003, , Technische Universiteit Delft, Faculteit EWI, Afdeling 2.

Objectgericht programmeren 1.

HANDLEIDING PROGRAMMEREN IN PASCAL (LAZARUS)

Een inleiding in de Unified Modeling Language 79

Voor het bepalen van de getalswaarde van een string is een standaardmethode beschikbaar: n = Integer.parseInt(s);

Tentamen Objectgeorienteerd Programmeren TI februari Afdeling ST Faculteit EWI TU Delft

6.3 VBA Syntax Instructie. Wij gaan de Visual Basic Editor opnieuw openen, om de instructie die wij zojuist getypt hebben, nader te bekijken.

6,1. Samenvatting door een scholier 1809 woorden 28 oktober keer beoordeeld. Informatica

Modelleren en Programmeren

Android apps met App Inventor 2 antwoorden

HOOFDSTUK 3. Imperatief programmeren. 3.1 Stapsgewijs programmeren. 3.2 If Then Else. Module 4 Programmeren

Als een PSD selecties bevat, deelt de lijn van het programma zich op met de verschillende antwoorden op het vraagstuk.

[13] Rondjes draaien (loops)

Inhoudsopgave. Hoofdstuk 1.RMI...2

6.2 VBA Syntax. Inleiding Visual Basic

Modelleren en Programmeren

DOMjudge teamhandleiding

Hst 1 Klassen en methoden

Klassen & objecten, overerving, abstracte klassen, debuggen, interfaces, formulieren, polymorfie, statische methoden, event-handlers

Swing.

Formulieren maken met Dreamweaver CS 4/CS 5

Scala. Korte introductie. Sylvia Stuurman

Uitwerking Aanvullend tentamen Imperatief programmeren Woensdag 24 december 2014, uur

Werken op afstand via internet

Een eerste applicatie

AFO 142 Titel Aanwinsten Geschiedenis

recursie Hoofdstuk 5 Studeeraanwijzingen De studielast van deze leereenheid bedraagt circa 6 uur. Terminologie

Verslag. Projectteam: 107 Datum: 16 oktober 2008 Project leden: Lennard Fonteijn Harish Marhe Nicoletta Saba Turgay Saruhan Robin Tummers

Transcriptie:

10.1 Inleiding Onder de term exception handling (afhandelen van uitzonderingen) verstaan we het op een systematische manier verwerken van fouten en andere uitzonderingssituaties die zich tijdens het draaien van een programma kunnen voordoen. Stel dat je een applet maakt die om de invoer van een aantal cijfers vraagt waarvan de applet het gemiddelde uitrekent. Om het gemiddelde uit te kunnen rekenen moet er gedeeld worden. Een simpel voorbeeld van een exceptie die dan kan optreden is delen door nul. Wanneer zoiets plaatsvindt in een Java-applet zal er een foutmelding komen in het zogeheten Java console-venster waarover veel browsers beschikken. Deze melding wordt waarschijnlijk niet door de gebruiker gezien en de applet zal verder gewoon doordraaien of vastlopen. Dat is een nogal primitieve manier om een fout op te lossen. Afhankelijk van de situatie zijn er betere oplossingen denkbaar, zoals bijvoorbeeld een passende mededeling op het scherm zetten en de gebruiker om nieuwe invoer vragen. Weer andere excepties doen zich voor als een programma tevergeefs probeert te schrijven naar een bestand in een directory op een diskette. Er kunnen een heleboel verschillende redenen zijn waarom dit niet lukt: er zit misschien geen diskette in de drive, of de drive is niet gesloten, of de diskette is beveiligd tegen schrijven. Ook kan de diskette stuk of vol zijn, of kan de betreffende directory niet bestaan. Hoe het programma in zulke uitzonderingsgevallen precies moet handelen is in het algemeen moeilijk te zeggen. Het programma onderbreken is het meest vergaand. In veel gevallen is het wenselijk op een of andere manier te proberen de fout te repareren. In de praktijk blijkt heel vaak dat zo n reparatie onmogelijk kan gebeuren op de plaats waar de fout is geconstateerd, maar eventueel wel op een hoger niveau in het programma. Hiervoor bestaat in Java een mechanisme dat gebruik maakt van de woorden try, throw en catch: probeer iets uit, als het mis gaat werp dan een exceptie en vang deze ergens op. 10.2 Het genereren van een exceptie In het volgende voorbeeld wordt gevraagd een geheel getal in te voeren in een tekstvak. Als je dat doet en op Enter drukt wordt de event opgevangen in action- Performed(). Het ingevoerde getal komt als string binnen en wordt met Integer.parseInt() omgezet naar een int-waarde, die vermenigvuldigd met 10 in een uitvoervak op het scherm wordt gezet. Zie project InvoerApplet in de map Voorbeelden\Hoofdstuk 10.

318 OO-PROGRAMMEREN IN JAVA MET BLUEJ // Genereren van een exceptie import java.awt.*; import java.awt.event.*; import javax.swing.*; public class InvoerApplet extends JApplet { public void init() { setcontentpane( new Invoerpaneel() ); public class Invoerpaneel extends JPanel { private JTextField invoervak, uitvoervak; public Invoerpaneel() { setlayout( new GridLayout( 2, 2 ) ); invoervak = new JTextField( 10 ); invoervak.addactionlistener( new VakHandler() ); uitvoervak = new JTextField( 20 ); add( new JLabel( Voer een geheel getal in ) ); add( invoervak ); add( new JLabel( 10-voud ) ); add( uitvoervak ); private class VakHandler implements ActionListener { public void actionperformed( ActionEvent e ) { String invoer = invoervak.gettext(); int getal = 10 * Integer.parseInt( invoer ); uitvoervak.settext( + getal ); Zie de uitvoer in figuur 10.1. Figuur 10.1 Het zwakke punt in dit programma is deze regel: getal = 10 * Integer.parseInt( invoer );

319 Zolang de gebruiker een correct geheel getal invoert gaat alles goed. Maar zodra je iets afwijkends intikt als 5b of hola of in een leeg vak op Enter drukt kan parse- Int() zijn werk niet doen: de omzetting naar een int lukt niet. Wat parseint() dan doet is een exceptie genereren. Een exceptie is een object dat informatie bevat over de fout (of uitzondering) die is opgetreden. Een exceptie-object moet je, net als een event-object, ergens opvangen anders gaat het verloren en, wat erger is, het programma blijft meestal in een ongewisse toestand. In voorbeeld is er geen voorziening om de exceptie op te vangen. Als je de applet runt in bijvoorbeeld JCreator zie je de foutmelding over de exceptie verschijnen in een console-venster. Ook veel browsers hebben een Java consolevenster (dat je aan of uit kunt zetten). 10.3 Het opvangen van een exceptie: try en catch Het opvangen en afhandelen van een exceptie doe je met behulp van een trycatch-blok. Zo n try-catch-blok ziet er in principe zo uit:... mogelijk ontstaan van een exceptie catch( Exception e ) {... afhandeling van de exceptie In het try-blok plaats je de code waar eventueel iets mee mis kan gaan, in dit geval de omzetting van String naar int door parseint(). In het catch-blok plaats je code die zorgt voor de afhandeling van de fout, in dit geval het op het scherm zetten van een passende mededeling. In de volgende broncode (project Try- CatchApplet uit de map Voorbeelden\Hoofdstuk 10) zie je hoe een en ander gaat: // Opvangen van exceptie bij het // niet kunnen omzetten van String naar int import java.awt.*; import java.awt.event.*; import javax.swing.*; public class TryCatchApplet extends JApplet { public void init() { setcontentpane( new TryCatchpaneel() ); public class TryCatchpaneel extends JPanel { private JTextField invoervak, uitvoervak; public TryCatchpaneel() { setlayout( new GridLayout( 2, 2 ) );

320 OO-PROGRAMMEREN IN JAVA MET BLUEJ invoervak = new JTextField( 10 ); invoervak.addactionlistener( new VakHandler() ); uitvoervak = new JTextField( 20 ); add( new JLabel( Voer een geheel getal in ) ); add( invoervak ); add( new JLabel( 10-voud ) ); add( uitvoervak ); private class VakHandler implements ActionListener { public void actionperformed( ActionEvent e ) { String invoer = invoervak.gettext(); int getal = 10 * Integer.parseInt( invoer ); uitvoervak.settext( + getal ); catch( NumberFormatException nfe ) { if( invoer.equals( ) ) invoer = lege invoer ; uitvoervak.settext( Fout getal: + invoer ); De uitvoer van deze applet bij foute invoer is te zien in figuur 10.2 Figuur 10.2 Het verschil tussen het voorbeeld in paragraaf 10.2 en dit voorbeeld zit uitsluitend in actionperformed() waar de omzetting van de string invoer naar een gehele waarde plaatsvindt. public void actionperformed( ActionEvent e ) { String invoer = invoervak.gettext(); int getal = 10 * Integer.parseInt( invoer ); uitvoervak.settext( + getal ); catch( NumberFormatException nfe ) { if( invoer.equals( ) ) invoer = lege invoer ;

321 uitvoervak.settext( Fout getal: + invoer ); In actionperformed() staat nu een try-catch-blok, dat is het vetgedrukte gedeelte vanaf het woord try tot en met de tweede sluitaccolade. Een try-catch-blok omvat altijd een try-blok en een catch-blok. Het catch-blok heet ook wel een exceptionhandler, of kortweg een handler. Er kan meer dan één handler voorkomen in een try-catch-blok. Alle handlers bij elkaar vormen dan een handler-list (zie ook paragraaf 10.5). Er kunnen zich nu twee situaties voordoen: de invoer is correct of de invoer is onjuist. In beide gevallen is het programmaverloop anders. Wat gebeurt er als de invoer onjuist is? Stel dat je als string 325r invoert. Het programma haalt eerst de ingevoerde string uit het tekstvak en loopt vanzelf het try-blok binnen waar de methode parseint() wordt aangeroepen. Omdat deze methode de string niet kan converteren naar een geheel getal werpt parseint() een exceptie. Bij het werpen van de exceptie wordt de uitvoering van de methode parseint() meteen onderbroken en de verdere uitvoering van het try-blok ook. Het laatste statement in het try-blok wordt in dit geval dus niet uitgevoerd. De exceptie die parseint() genereert is een object van het type NumberFormat- Exception, en het Javasysteem geeft dit object door aan het catch-blok, als er tenminste een handler is waarvan het argument overeenkomt met het type van de exceptie. In dit voorbeeld is dat het geval. Het exceptie-object komt het catch-blok binnen via het argument nfe. Dit argument wordt (in dit voorbeeld) verder niet gebruikt. Het programma gaat dan verder met de uitvoering van de opdrachten in de handler, hier zijn dat de opdrachten: if( invoer.equals( ) ) invoer = lege invoer ; uitvoervak.settext( Fout getal: + invoer ); Hiermee is de exceptie afgehandeld. Het programma vervolgt zijn weg met de opdrachten na het catch-blok, in dit geval staan daar geen opdrachten. Wat gebeurt er als de invoer wel juist is? Het programma haalt eerst de ingevoerde string uit het tekstvak en loopt vanzelf het try-blok binnen waar parseint() wordt aangeroepen. Als hierin geen fout optreedt wordt de rest van het try-blok uitgevoerd, het catch-gedeelte wordt in zijn geheel overgeslagen en het programma vervolgt zijn weg met de opdrachten na het catch-blok, waar in dit geval geen opdrachten staan. Kort gezegd: Een statement waarin mogelijk een exceptie kan optreden plaats je in een try-blok. Bij het daadwerkelijk optreden van een exceptie wordt het try-blok onderbroken om het catch-blok uit te voeren. Als er geen exceptie optreedt wordt het try-blok in zijn geheel uitgevoerd en het catch-blok overgeslagen.

322 OO-PROGRAMMEREN IN JAVA MET BLUEJ 10.3.1 Mededeling in een apart venster: JOptionPane Een fraaie afhandeling van het optreden van een uitzondering in een programma kan zijn een apart venster te openen en daarin een mededeling aan de gebruiker te doen. Het volgende voorbeeld is een aangepaste versie van dat uit de vorige paragraaf. In het volgende voorbeeld komt de mededeling over onjuiste invoer in een apart dialoogvenster. Dat venster is van het type JOptionPane, een klasse met een groot aantal voorgedefinieerde vensters. Zie project OptionPaneApplet in de map Voorbeelden\Hoofdstuk 10. // Opvangen van een exceptie // Mededeling in een apart venster import java.awt.*; import java.awt.event.*; import javax.swing.*; public class OptionPaneApplet extends JApplet { public void init() { setcontentpane( new Invoerpaneel() ); public class Invoerpaneel extends JPanel { private JTextField invoervak, uitvoervak; public Invoerpaneel() { setlayout( new GridLayout( 2, 2 ) ); invoervak = new JTextField( 10 ); invoervak.addactionlistener( new VakHandler() ); uitvoervak = new JTextField( 20 ); add( new JLabel( Voer een geheel getal in ) ); add( invoervak ); add( new JLabel( 10-voud ) ); add( uitvoervak ); private class VakHandler implements ActionListener { public void actionperformed( ActionEvent e ) { String invoer = invoervak.gettext(); int getal = 10 * Integer.parseInt( invoer ); uitvoervak.settext( + getal ); catch( NumberFormatException nfe ) { if( invoer.equals( ) ) invoer = lege invoer ; JOptionPane.showMessageDialog( Invoerpaneel.this, Fout getal: + invoer,

323 Fout in invoer, JOptionPane.ERROR_MESSAGE ); finally { // zie volgende paragraaf invoervak.selectall(); In figuur 10.3 zie je het dialoogvenster bij onjuiste invoer. Figuur 10.3 Het dialoogvenster wordt getoond door middel van de volgende opdracht: JOptionPane.showMessageDialog( Invoerpaneel.this, Fout getal: + invoer, Fout in invoer, JOptionPane.ERROR_MESSAGE ); De methode showmessagedialog() is een statische methode, dat wil zeggen dat hij kan worden aangeroepen met de naam van de klasse in plaats van met een object. De methode heeft vier argumenten, het eerste argument is een referentie naar het venster waar het dialoogvenster bij hoort. In dit geval is dat het invoerpaneel. Vanuit de inwendige klasse VakHandler heet deze referentie Invoerpaneel.this. Het tweede argument is de mededeling die in het dialoogvenster komt. Het derde argument is de titel voor het venster en het laatste argument geeft het soort dialoogvenster aan. Het hier getoonde dialoogvenster is maar één van de talloze mogelijkheden. Zie de JDK-documentatie voor uitgebreide informatie over JOptionPane.

324 OO-PROGRAMMEREN IN JAVA MET BLUEJ 10.3.2 Finally Een soms handige voorziening bij een exception handling is een finally-blok. Je hebt de garantie dat een finally-blok wordt uitgevoerd onafhankelijk van het feit of er een exceptie is opgetreden of niet. Een finally-is dus ideaal om afsluitende werkzaamheden te doen, of voorbereidende werkzaamheden voor het verdergaan van het programma. Schematisch ziet het er zo uit: // code die exceptie kan opleveren catch(... ) { // handel exceptie af catch(... ) { // handel andere exceptie af finally { // afsluitende werkzaamheden // code na finally-blok Er kan zich een aantal situaties voordoen waarin het programmaverloop verschillend is: Er treedt geen exceptie op. In dit geval voert het programma eerst het try-blok in zijn geheel uit, daarna het finally-blok en daarna de code na het finally-blok. Er treedt in het try-blok een exceptie op die kan worden opgevangen in een catch-blok. In dit geval voert het programma eerst het try-blok uit tot de plek waar de exceptie optreedt, daarna het catch-blok, dan het finally-blok en tot slot de code na het finally-blok. Er treedt in het try-blok een exceptie op die wordt opgevangen in een catchblok en er treedt in deze handler opnieuw een exceptie op. Dit kan een onverwachte exceptie zijn, het kan ook een rethrow zijn. In elk geval voert het programma eerst het try-blok uit tot aan de exceptie, dan het catchblok tot de plek waar de exceptie optreedt, vervolgens het finally-blok en geeft dan de exceptie door naar de aanroepende methode (de eerstvolgende methode op de call-stack). De code na het finally-blok komt niet aan de beurt. Er treedt in het try-blok een exceptie die niet wordt opgevangen door een van de handlers. In dit geval voert het programma eerst het try-blok uit tot de plek waar de exceptie optreedt, dan het finally-blok en geeft vervolgens de exceptie door naar de aanroepende methode (de eerstvolgende methode op de call-stack). De code na het finally-blok komt niet aan de beurt. In alle gevallen komt het finally-blok aan de beurt.

325 In het voorbeeld in de vorige paragraaf staat zo n finally-blok met de opdracht invoervak.selectall(): finally { invoervak.selectall(); Door de opdracht selectall() wordt de ingevoerde tekst in het tekstvak geselecteerd, zodat de gebruiker meteen een nieuw getal kan intikken zonder de oude invoer eerst te hoeven verwijderen. 10.4 Een exceptie opwerpen: throw In de vorige paragrafen heb je gezien hoe je een exceptie opvangt, maar niet hoe je zelf een exceptie-object maakt. Ik zal dit laatste toelichten aan de hand van een ArithmeticException een exceptie veroorzaakt door een foutieve rekenkundige bewerking, zoals delen door nul. Merkwaardig is dat deze exceptie automatisch door het Java-systeem gegenereerd wordt als je een int-waarde door nul deelt, maar niet als je een double door nul deelt. In dit laatste geval komt er de waarde Infinity (oneindig) uit. In het volgende voorbeeld (project DeelApplet in de map Voorbeelden\Hoofdstuk 10) kun je dat zien. // Delen door 0 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DeelApplet extends JApplet { public void init() { setcontentpane( new Invoerpaneel() ); public class Invoerpaneel extends JPanel { private JTextField invoervaka, invoervakb, uitvoervak; public Invoerpaneel() { setlayout( new GridLayout( 4, 2 ) ); invoervaka = new JTextField( 10 ); invoervakb = new JTextField( 10 ); uitvoervak = new JTextField( 20 ); uitvoervak.seteditable( false ); uitvoervak.setbackground( Color.WHITE ); add( new JLabel( Getal a ) ); add( invoervaka ); add( new JLabel( Getal b ) ); add( invoervakb );

326 OO-PROGRAMMEREN IN JAVA MET BLUEJ add( new JLabel( a gedeeld door b: ) ); add( uitvoervak ); JButton deelknop = new JButton( deel ); deelknop.addactionlistener( new KnopHandler() ); add( new JLabel() ); // leeg label add( deelknop ); private class KnopHandler implements ActionListener { public void actionperformed( ActionEvent e ) { double a = Double.parseDouble( invoervaka.gettext() ); double b = Double.parseDouble( invoervakb.gettext() ); double resultaat = deel( a, b ); uitvoervak.settext( String.format( %.4f, resultaat ) ); double deel( double x, double y ) { return x / y; De uitvoer staat in figuur 10.4 Figuur 10.4 De feitelijke deling vind plaats in de klasse KnopHandler. Ik heb de uitvoering van de deling in een aparte methode gezet, om er later nog wat aan toe te kunnen voegen. De methode deel() is heel simpel: hij deelt zijn argumenten x en y en levert het resultaat als terugkeerwaarde af. Als y de waarde nul heeft is het resultaat van de deling Infinity. Met Infinity is het lastig verder rekenen, daarom kun je de methode deel() zo maken dat hij vóór het uitvoeren van de deling waarschuwt als b de waarde nul heeft. Die waarschuwing komt in de vorm van een exceptie, en dat gaat zo in zijn werk: double deel( double x, double y ) { if( y == 0.0 ) throw new ArithmeticException(); return x / y;

327 De klasse ArithmeticException is een van de vele voorgedefinieerde exceptieklassen. Met new ArithmeticException() maak je een nieuwe instantie van deze exceptie en het woord throw betekent letterlijk dat de exceptie gegooid wordt naar de plek vanwaar de methode is aangeroepen. Als de throw-opdracht wordt uitgevoerd (dus als y gelijk aan nul is) wordt de uitvoering van de rest van de methode afgebroken. Dat betekent dat het statement return x/y niet wordt uitgevoerd en de methode heeft in dat geval geen terugkeerwaarde. Het is dan ook belangrijk dat programmeurs die de methode aanroepen er van op de hoogte zijn of er mogelijk een exceptie kan optreden, en zo ja welke exceptie. Als maker van zo n methode doe je er dan ook goed aan in de kop van de methode aan te geven dat deze methode een exceptie kan genereren. Dat doe je met het woord het woord throws (met een s aan het eind): double deel( double x, double y ) throws ArithmeticException { if( y == 0.0 ) throw new ArithmeticException(); return x / y; De uitdrukking throws ArithmeticException betekent dat deze methode mogelijk een exceptie genereert en de uitdrukking throw new ArithmeticException() betekent dat er daadwerkelijk een exceptie gemaakt en opgeworpen wordt. Alle exceptie-klassen hebben twee constructoren: een constructor zonder argumenten (ofwel een default-constructor) en een constructor met een String-argument. Via dit argument kun je in het exceptie-object bijvoorbeeld een mededeling opbergen over de uitzonderlijke situatie. Deze mededeling kun je weer opvragen met getmessage(). Het volgende stukje code maakt gebruik van de constructor met String-argument: double deel( double a, double b ) throws ArithmeticException { if( y == 0.0 ) throw new ArithmeticException( Deling door nul ); return x / y; Als gebruiker van een methode die een exceptie kan genereren moet je er voor zorgen de exceptie op te vangen, omdat het programma anders in een ongewisse toestand verder gaat, de methode deel() levert immers geen terugkeerwaarde als b gelijk aan nul is. Het opvangen van de exceptie zie je in het volgende voorbeeld (project DeelApplet2 in de map Voorbeelden\Hoofdstuk 10). // Opvangen en verwerken van exeptie delen door 0 import java.awt.*; import java.awt.event.*; import javax.swing.*; public class DeelApplet2 extends JApplet { public void init() {

328 OO-PROGRAMMEREN IN JAVA MET BLUEJ setcontentpane( new Invoerpaneel() ); public class Invoerpaneel extends JPanel { private JTextField invoervaka, invoervakb, uitvoervak; public Invoerpaneel() { setlayout( new GridLayout( 4, 2 ) ); invoervaka = new JTextField( 10 ); invoervakb = new JTextField( 10 ); uitvoervak = new JTextField( 20 ); uitvoervak.seteditable( false ); uitvoervak.setbackground( Color.YELLOW ); add( new JLabel( Getal a ) ); add( invoervaka ); add( new JLabel( Getal b ) ); add( invoervakb ); add( new JLabel( a gedeeld door b: ) ); add( uitvoervak ); JButton deelknop = new JButton( deel ); deelknop.addactionlistener( new KnopHandler() ); add( new JLabel() ); // leeg label add( deelknop ); private class KnopHandler implements ActionListener { public void actionperformed( ActionEvent e ) { double a = Double.parseDouble( invoervaka.gettext() ); double b = Double.parseDouble( invoervakb.gettext() ); double resultaat = deel( a, b ); uitvoervak.settext( String.format( Locale.US, %.4f, resultaat ) ); catch( ArithmeticException ae ) { JOptionPane.showMessageDialog( Invoerpaneel.this, ae.getmessage(), Fout, JOptionPane.ERROR_MESSAGE ); double deel( double x, double y ) throws ArithmeticException {

329 if( y == 0.0 ) throw new ArithmeticException( Deling door nul ); return x / y; Het resultaat bij deling door 0 is te zien in figuur 10.5. Figuur 10.5 10.5 Formatteren van uitvoer naar tekstvak Als je het resultaat van een berekening (een getal) in een tekstvak zet, moet je dat getal omzetten naar een string. De meest eenvoudige manier om dat te doen is door middel van de concatenatie met een al of niet lege string, bijvoorbeeld zo: double resultaat = deel( a, b ); uitvoervak.settext( String.format( + resultaat ) ); Nadeel is dat je vaak nogal veel cijfers achter de komma krijgt. Je kunt getallen formatteren met behulp van de methode format() uit de klasse String. Deze methode levert een String af. Het is een statische methode, dus je roept hem aan met de naam van de klasse. De methode format() werkt met een format string op dezelfde manier als printf()uit hoofdstuk 6. In de beide applets in paragraaf 10.4 vind je een voorbeeld: double resultaat = deel( a, b ); uitvoervak.settext( String.format( %.4f, resultaat ) ); De uitdrukking String.format( %.4f, resultaat ) levert als retourwaarde een String met een geformatteerde getal met 4 cijfers achter de komma.

330 OO-PROGRAMMEREN IN JAVA MET BLUEJ Als je liever geen komma maar een decimale punt wilt, kun je dat aangeven met Locale.US: String.format( Locale.US, %.4f, resultaat ) Zie voor meer mogelijkheden van de format-string de methode printf() in paragraaf 6.6. 10.6 Eén try, twee catches Een try-blok kun je laten volgen door meer dan één catch-blok. In elk van de catch-blokken kun je een andere soort exceptie opvangen en afhandelen. In het programma in de vorige paragraaf kan er niet alleen deling door 0 plaatsvinden, maar ook kan de gebruiker ongeldige getallen invoeren, of helemaal geen getal. De methode parsedouble() levert dan, net als parseint() een NumberFormatException (zie paragraaf 10.3). Het is mogelijk twee afzonderlijke try-catch-blokken te maken die elk een eigen exceptie opvangen en afhandelen. Bijvoorbeeld zo: // Eerste try-catch-blok double a = Double.parseDouble( invoervaka.gettext() ); double b = Double.parseDouble( invoervakb.gettext() ); catch( NumerFormatException nfe ) { // Handel foute invoer af // Tweede try-catch-blok double resultaat = deel( a, b ); uitvoervak.settext( String.format( %.4f, resultaat ) ); catch( ArithmeticException ae ) { // Handel delen door 0 af Het is ook mogelijk een try-blok te laten volgen door twee catch-blokken. Elk catchblok vangt dan een aparte exceptie op, zoals in het voorbeeld hieronder. // Een try, twee catch-blokken import java.awt.*; import java.awt.event.*; import javax.swing.*; public class CatchListApplet extends JApplet { public void init() { setcontentpane( new Invoerpaneel() );

331 public class Invoerpaneel extends JPanel { private JTextField invoervaka, invoervakb, uitvoervak; public Invoerpaneel() { setlayout( new GridLayout( 4, 2 ) ); invoervaka = new JTextField( 10 ); invoervakb = new JTextField( 10 ); uitvoervak = new JTextField( 20 ); uitvoervak.seteditable( false ); uitvoervak.setbackground( Color.YELLOW ); add( new JLabel( Getal a ) ); add( invoervaka ); add( new JLabel( Getal b ) ); add( invoervakb ); add( new JLabel( a gedeeld door b: ) ); add( uitvoervak ); JButton deelknop = new JButton( deel ); deelknop.addactionlistener( new KnopHandler() ); add( new JLabel() ); // leeg label add( deelknop ); private class KnopHandler implements ActionListener { public void actionperformed( ActionEvent e ) { double a = Double.parseDouble( invoervaka.gettext() ); double b = Double.parseDouble( invoervakb.gettext() ); double resultaat = deel( a, b ); uitvoervak.settext( String.format( %.4f, resultaat ) ); catch( NumberFormatException nfe ) { JOptionPane.showMessageDialog( Invoerpaneel.this, Fout getal ingevoerd, Fout, JOptionPane.ERROR_MESSAGE ); catch( ArithmeticException ae ) { JOptionPane.showMessageDialog( Invoerpaneel.this, ae.getmessage(), Fout, JOptionPane.ERROR_MESSAGE );

332 OO-PROGRAMMEREN IN JAVA MET BLUEJ double deel( double x, double y ) throws ArithmeticException { if( y == 0.0 ) throw new ArithmeticException( Deling door nul ); return x / y; In het try-blok staan drie opdrachten die een exceptie kunnen opleveren: double a = Double.parseDouble( invoervaka.gettext() ); double b = Double.parseDouble( invoervakb.gettext() ); double resultaat = deel( a, b );... De eerste twee statements kunnen een NumberFormatException opleveren die opgevangen wordt in het eerste catch-blok: catch( NumberFormatException nfe ) {... Het derde statement kan een ArithmeticException opwerpen die opgevangen wordt in het tweede catch-blok: catch( ArithmeticException ae ) {... Als je meer dan één catch-blok hebt is soms de volgorde van belang, zie paragraaf 10.7.1. 10.7 De exceptie-klassen Java kent een uitgebreide hiërarchie van voorgedefinieerde exceptie-klassen. Veel van deze klassen zijn gedefinieerd in de package java.lang. Dat is een package die je niet hoeft te importeren omdat dat automatisch wordt gedaan: het is een package met standaardvoorzieningen van de taal (language) Java. In figuur 10.6 zie je een stukje van de hiërarchie van deze exceptie-klassen. Het zijn subklassen van Throwable. Al deze klassen worden gebruikt in de Java-bibliotheek, maar je kunt ze desgewenst ook in je eigen klassen gebruiken, dat wil zeggen: je kunt er objecten van maken die je met throw opwerpt. De hiërarchie splitst zich in twee verschillende takken: Error en Exception. Excepties van het type Error of van een van zijn subklassen worden gegenereerd door het Java-systeem en komen zelden voor. Als programmeur hoef je daar geen rekening mee te houden.

333 Throwable checked unchecked Error Exception IOException RuntimeException Figuur 10.6 Van groter belang zijn excepties van het type Exception of van een van zijn subklassen, zie figuur 10.7. Exception ClassNotFoundException CloneNotSupportedException IllegalAccessException InstantiationExcepti IOException IterruptedException NoSuchFieldException NoSuchMethodException RuntimeException ArithmeticException ArrayStoreException ClassCastException IllegalArgumentException IllegalThreadStateException NumberFormatException IllegalMonitorStateException IllegalStateException EOFException FileNotFoundException InterruptedIOException ObjectStreamException InvalidClassException InvalidObjectException NotActiveException NotSerializableException OptionalDataException StreamCorruptedException WriteAbortedException EOFException FileNotFoundException InterruptedIOException IndexOutOfBoundsException ArrayIndexOutOfBoundsException StringIndexOutOfBoundsException NegativeArraySizeException NullPointerException SecurityException UnsupportedOperationException Figuur 10.7

334 OO-PROGRAMMEREN IN JAVA MET BLUEJ Zoals je in figuur 10.7 ziet, zijn Exceptions verdeeld in twee soorten: gecontroleeerde (checked) en ongecontroleerde (unchecked). Bij een gecontroleerde exceptie heb je als programmeur de plicht om: óf de exceptie op te vangen met een try-catch-blok; óf de exceptie met throws te melden in de kop van de methode waarin de exceptie kan optreden. In het laatste geval geeft de methode de exceptie door aan zijn aanroeper, die op zijn beurt de exceptie weer moet opvangen of hem melden in de kop van de methode. De compiler controleert of je programma aan deze eisen voldoet. Voor ongecontroleerde excepties gelden deze eisen niet: je bent niet verplicht ze op te vangen en je bent niet verplicht ze in de kop van de methode te melden. Wat zeker niet wil zeggen dat je het daarom altijd moet laten. Alle excepties van de klasse Exception en de subklassen daarvan zijn gecontroleerde excepties, behalve RuntimeException en zijn subklassen, zie figuur 10.7. Overigens zijn ook excepties van het type Error unchecked. Ongecontroleerde excepties, dat wil zeggen van het type RuntimeException en subklassen, duiden soms op programmeerfouten die niet door exception-handling opgevangen moeten worden, maar door een verbetering aan te brengen in de broncode van het programma. Een goed voorbeeld daarvan is een IndexOutOf- BoundsExceptie die gegenereerd wordt als de index van een array buiten zijn grenzen treedt, zoals in het volgende fragment: int[] leeftijdrij = { 18, 21, 34, 17 ; int som = 0; for( int i = 0; i <= leeftijdrij.length; i++ ) som += leeftijdrij[ i ]; De programmeur heeft hier per ongeluk <= getypt in plaats van <. Het is niet de bedoeling dat je foute stukjes code omgeeft met een try-catch-blok: int[] leeftijdrij = { 18, 21, 34, 17 ; int som = 0; for( int i = 0; i <= leeftijdrij.length; i++ ) som += leeftijrij[ i ]; catch( IndexOutOfBoundsException ) {...Dit is een onzinnig stukje programma Een dergelijke fout moet je verbeteren. Als je zulke fouten maakt is het optreden van de exceptie een hulpmiddel om de fout op te sporen. Een niet opgevangen exceptie wordt immers gemeld in het console-venster van de ontwikkelomgeving die je gebruikt.

335 10.7.1 Over de volgorde van de catch-blokken In principe kun je net zoveel catch-blokken achter elkaar zetten als je wilt. Je moet dan wel rekening houden met de volgorde waarin je de verschillende excepties opvangt. De reden is de volgende: alle excepties zijn subklassen van Exception, zie figuur 10.7, en daarom kan een referentie van het statische type Exception wijzen naar instanties van elk van de subklassen. In principe kun je daarom elke exceptie opvangen met het volgende stukje code: // code die excepties kan leveren catch( Exception e ) { // vang alle mogelijke excepties op Nadeel hiervan is dat je niet weet welke soort exceptie er is opgetreden, zodat het ook lastig is een passende maatregel te nemen. Daarom is het in het algemeen beter de verschillende soorten excepties apart op te vangen in hun eigen blok. Bij het optreden van een exceptie doorzoekt het Java-systeem de diverse catchblokken (als die er zijn) van boven naar beneden en het eerste passende catch-blok dat gevonden wordt mag de exceptie afhandelen. Als catch(exception e) als eerste in de lijst van catch-blokken staat zal deze alle excepties afhandelen, waardoor de andere catch-blokken overbodig zijn. De compiler reageert hier dan ook op met een foutmelding. Een juiste volgorde is bijvoorbeeld: // code die diverse soorten excepties kan leveren catch( NumberFormatException nfe ) { // vang NumberFormatException op catch( ArithmeticException ae ) { // vang ArithmeticException op catch( Exception ex ) { // vang alle overige excepties op Het blok catch(exception ex) staat aan het einde van de lijst, omdat de klasse Exception hoog staat in de hiërarchie van exceptie-klassen. 10.8 Wat gebeurt er als je een exceptie niet opvangt? Gecontroleerde excepties moet je opvangen, als je dat vergeet geeft de compiler daarover een melding. Ongecontroleerde excepties die je niet opvangt leveren een mededeling in het console-venster, ongeveer zoals in figuur 10.9 te zien is. Ontwikkelomgevingen als JCreator of JBuilder hebben hun eigen console-venster.

336 OO-PROGRAMMEREN IN JAVA MET BLUEJ Als je buiten een ontwikkelomgeving een Java-applicatie runt, of een Java-applet in een browser laat uitvoeren, kun je het console-venster openen met de rechter muisknop te klikken op het icoontje met het koffiekopje in de taakbalk, zie figuur 10.8 Figuur 10.8 Het venster dat je in figuur 10.9 ziet is afkomstig van de Java Runtime Environment (JRE) dat onder andere gebruikt wordt door een browser die voorzien is van de Java Plug-in. Figuur 10.9 10.8.1 De call stack Wat stellen de regels in figuur 10.9 precies voor? Wat je ziet is de zogenoemde cal stack, de stapel met informatie over welke methoden zijn aangeroepen voordat de exceptie is opgetreden.

337 Een stack of stapel is een datastructuur waarin je gegevens opbergt door ze als het ware steeds bovenop een stapel te leggen. In figuur 10.10 zie je drie stadia van een stapel die wordt gevuld met achtereenvolgens de gegevens a, b en c. c b b a a a Figuur 10.10 Een stack is zo gemaakt dat je de gegevens alleen van de bovenkant van de stapel kunt afhalen. Als je in figuur 10.10 de gegevens van de stack haalt krijg je eerst c, dan b en tot slot a. De gegevens komen dus in de omgekeerde volgorde uit de stack. Dit principe wordt vaak aangeduid met LIFO: Last In First Out. Elk programma, niet alleen Java-programma s, hebben een call-stack met informatie over de aangeroepen, maar nog niet volledig afgehandelde methoden. Als je vanuit een methode a() methode b() aanroept, en van daaruit c(), moet het programma na afloop van c()verdergaan met de rest van b() en na het beëindigen van b() met de rest van a(). In dit voorbeeld gebeurt het aanroepen van de methoden in de volgorde a, b, c en het beëindigen van de methoden gebeurt in de omgekeerde volgorde c, b, a. Dit is een ideale situatie voor het gebruik van een stack. Een overzicht van de call-stack van een Java-programma kun je op het scherm krijgen met de methode printstacktrace() uit de klasse Throwable. Deze methode wordt door alle subklassen van Throwable, dus door alle exceptie-klassen geërfd. In het volgende schematische programma zie je hoe je zo n stack-trace op het (console-)venster krijgt. Zie project StacktraceApplet in de map Voorbeelden\Hoofdstuk 10. // Laten zien van de call-stack met printstacktrace() import java.awt.*; import java.applet.*; import javax.swing.*; public class StacktraceApplet extends JApplet { public void init() { setcontentpane( new Paneel() ); public class Paneel extends JPanel { public Paneel() { test1(); catch( RuntimeException re ) { System.out.println( Dit is de stack-trace: );

338 OO-PROGRAMMEREN IN JAVA MET BLUEJ re.printstacktrace(); public void paintcomponent( Graphics g ) { super.paintcomponent( g ); g.drawstring( Call-stack staat in console-venster., 20, 20 ); public void test1() { test2(); public void test2() { throw new RuntimeException(); Figuur 10.11 De uitvoer van dit voorbeeld komt in het console-venster, zie figuur 10.11. De stack-trace begint met: java.lang.runtimeexception Deze regel vertelt dat er een RuntimeException is opgetreden. Op de regel daaronder staat waar die exceptie plaatsvond: at Paneel.test2(StacktraceApplet.java:33) Hier staat: in de methode test2() van de klasse Paneel, om precies te zijn in regel 33 van het bestand StacktraceApplet.java. De volgende regel vertelt vanwaar de methode test2() werd aangeroepen: at Paneel.test1(StacktraceApplet.java:29) Namelijk in de methode test1() van de klasse Paneel, op regel 29 van het bestand StacktraceApplet.java.

339 Verder zie je dat deze methode op zijn beurt in regel 15 werd aangeroepen in <init> van Paneel, dat is de constructor. Deze constructor werd aangeroepen in de methode init() van de klasse StacktraceApplet. De laatste twee regels duiden op methoden uit het Java-systeem die nodig zijn om de applet op te starten. Nu je weet wat een call-stack is kan ik de vraag van de titel van paragraaf beantwoorden: wat gebeurt er als je een exceptie niet opvangt? Bekijk het volgende, wat schematische stukje code waarin de exceptie niet wordt opgevangen (zie project ExceptieApplet uit de map Voorbeelden\Hoofdstuk 10). public class ExceptieApplet extends JApplet { public void init() { setcontentpane( new Paneel() ); System.out.println( In init() ); public class Paneel extends JPanel { private int getal = 1; public Paneel() { test1(); System.out.println( In constructor van Paneel ); public void test1() { test2(); System.out.println( In test1 ); public void test2() { if ( getal == 1 ) throw new RuntimeException(); System.out.println( In test2 ); Bij de uitvoering van deze applet gebeurt het volgende: Het Java-systeem roept de methode init() van ExceptieApplet aan. In init() wordt de constructor van Paneel aangeroepen. De constructor van Paneel roept test1() aan. test1() roept test2() aan. In test2() ontstaat de exceptie.

340 OO-PROGRAMMEREN IN JAVA MET BLUEJ De call-stack ziet er dus zo uit: Paneel.test2 Paneel.test1 Paneel.<init> ExceptieApplet.init Javasysteem Bij het optreden van de exceptie in test2() breekt het Java-systeem de uitvoering van de methode onmiddellijk af. Dat betekent bijvoorbeeld dat de eventuele opdrachten in test2() die na de exceptie staan, niet worden uitgevoerd. Dus de mededeling In test2 komt niet op het scherm. Nu gebeurt er het volgende: omdat de exceptie niet in een try-blok is ontstaan en er dus geen passend catch-blok kan zijn, geeft het systeem de exceptie door aan eerstvolgende methode op de call-stack, dat is de methode test1(). De verdere uitvoering van deze methode wordt onderbroken, dus de mededeling In test2 komt niet op het scherm. Het systeem geeft de exceptie door aan de volgende methode op de call-stack, de constructor van Paneel. Ook hier ontbreekt een exception-handler, de uitvoering van de constructor wordt onderbroken, de mededeling In constructor van Paneel komt niet op het scherm en de exceptie wordt doorgegeven aan init() van ExceptieApplet. Ook de uitvoering van deze methode wordt onderbroken, de mededeling In init() komt niet op het scherm en de exceptie komt terecht buiten het programma in het Java-systeem. Het Java-systeem vangt alle niet eerder opgevangen excepties op, maar weet uiteraard niet hoe elke exceptie afgehandeld moet worden. Het systeem reageert daarom alleen met het automatisch aanroepen van printstacktrace(). Afgezien van het tonen van de call-stack hoef je aan een applet niet veel te merken als je een exceptie niet opvangt. De vraag is wel in welke toestand de applet zich bevindt. Uit de zojuist gegeven beschrijving blijkt immers dat een deel van de methoden die aangeroepen werden voor de exceptie plaatsvond, niet worden afgemaakt. In ExceptieApplet zijn dat de methoden test2(), test1(), de constructor van Paneel en init(). Voor elke applet is het essentieel dat init() wel op een normale manier wordt beëindigd. Als dat niet het geval is krijg je de melding: Applet not initialized, en zie je verder niets op het scherm. Als je daarentegen de aanroep test1() van init() naar paintcomponent() van Paneel zou verplaatsen, zou de applet op een betrekkelijk normale manier worden uitgevoerd. Of een applet wel of niet normaal functioneert na een niet opgevangen exceptie hangt af van de plaats van de exceptie en met name van de opdrachten die niet aan bod konden in de methoden van de call-stack doordat de exceptie dat verhinderde. Anders gezegd: als je een exceptie niet opvangt hangt het welslagen

341 van je programma af van het toeval. Het is dus raadzaam de oorzaak van elke exceptie op te sporen en bij het optreden van een RuntimeException (of een van de subklassen) zo mogelijk de oorzaak uit de weg te ruimen, of anders de exceptie op te vangen. Niet alleen voor een applet, maar ook voor het niet opvangen van een exceptie in een grafische applicatie gelden dezelfde overwegingen. Naast grafische applicaties kun je in Java ook niet-grafische applicaties (console-applicaties) maken. Het niet opvangen van een exceptie in een niet-grafische applicatie leidt altijd tot het stoppen van de applicatie. 10.9 Rethrow Een rethrow is het opnieuw genereren van dezelfde exceptie die in een handler is opgevangen. Je kunt vaak een exceptie beter doorgeven aan een hoger niveau, dat wil zeggen aan een methode die eerder op de call-stack is terechtgekomen. Schematisch komt een rethrow op het hierop neer: // code die exceptie kan opleveren catch( Exception e ) { // doe wat afsluitende dingen throw e; // gooi de exceptie opnieuw Eventueel kun je in een finally-blok (zie paragraaf 10.3.2) opdrachten zetten die in alle gevallen uitgevoerd moeten worden, zowel bij het niet optreden van een exceptie als bij een rethrow. 10.10 Samenvatting Een fout of andere uitzonderlijke situatie die optreedt tijdens het draaien van een programma heet een exceptie. In Java is een exceptie een instantie van een van de exceptie-klassen. Het mechanisme van het afhandelen van een exceptie bestaat uit het gooien van een exceptie-object, het opvangen van dat object en het nemen van passende maatregelen. Er zijn in Java twee soorten excepties: checked (gecontroleerde) en unchecked (niet gecontroleerde). Checked excepties moet je altijd opvangen, de compiler controleert of je dat inderdaad doet. Exception handling gebeurt in Java met behulp van een try-catch-blok. Je kunt verschillende soorten excepties die optreden na een try opvangen in verschillende catch-blokken. De volgorde van de catch-blokken is soms van belang: eerst de meest specialistische excepties, daarna de algemenere.

342 OO-PROGRAMMEREN IN JAVA MET BLUEJ Een try-catch-blok kun je afsluiten met een finally-blok waarin code staat die altijd wordt uitgevoerd. 10.11 Vragen 1. Wat is exception-handling? 2. Wat is een try-blok? Een catch-blok? 3. Als je een catch-lijst hebt met meer dan één catch-blok, in welke volgorde moeten deze dan staan? 4. Wat is het verschil tussen een unchecked en een checked exceptie? 5. Moet je een exceptie altijd opvangen? 6. Als je een exceptie niet opvangt wat gebeurt er dan? 7. Wat is een rethrow? 8. Waar dient een finally-blok voor? 9. Waarom is het aanroepen van printstacktrace() bij het opvangen van een exceptie handig? 10.12 Opgaven 1. Schrijf een applicatie die aan de gebruiker een getal vraagt waarvan het programma de wortel bepaalt en op het scherm laat zien. Voor het berekenen van de wortel kun je de methode Math.sqrt() gebruiken. Ga na welke melding je krijgt wanneer je een negatief getal intikt. Pas het programma zodanig aan dat alle situaties netjes afgehandeld worden: voor een positief getal (of 0) wordt de vierkantswortel getoond; voor een negatief getal krijg je de melding dat een vierkantswortel niet gedefinieerd is; wanneer je geen geldig getal intikt moet een aangepaste melding verschijnen. 2. Schrijf een applicatie die er bij de start uitziet als in figuur 10.12. Maak gebruik van een array van knoppen, maar gebruik geen lay-outmanager. Figuur 10.12 Wanneer de gebruiker op een correcte manier zijn keuze bekend maakt door een getal in te tikken en op Enter te drukken, krijg je een resultaat als in figuur 10.13

343 (bedenk dat gebruikers van 1 tot en met 5 tellen, maar de array-indexen van 0 tot en met 4 lopen): Figuur 10.13 Handel de excepties die optreden als de gebruiker een te groot of te klein getal, of een letter of string intikt, op een correcte manier af.