Föreläsning 18 - Felhantering, avlusning, särfall

Goda råd vid större program

Nedanstående råd underlättar vid skrivandet av större program. Punkterna är tagna ur dokumentet "Programmeringsstrategi".

Ett lampexempel

Hur programmerar man det här trevliga spelet?

Varför inte börja med en prototyp enligt nedan och sedan utveckla den? Det slutliga programmet finns här.
import java.awt.*;
import java.applet.*;

public class Lampor extends Applet {
    static final int ANTAL_RADER = 3;
    static final int ANTAL_KOLUMNER = 4;

    int antalTryckningar = 0;
    
    Label rubrik = new Label("Alla rum ska lysa!");
    Panel plan = new Panel();
    Label antal = new Label("Antal: " + antalTryckningar);
    Button omstart = new Button("Omstart");
    
    public void init() {
	add(rubrik);

	plan.setLayout(new GridLayout(ANTAL_RADER, ANTAL_KOLUMNER));
	for(int r = 1; r <= ANTAL_RADER; ++r) {
	    for(int k = 1; k <= ANTAL_KOLUMNER; ++k) {
		plan.add(new Button());
	    }
	}
	add(plan);

	add(antal);
        add(omstart);
    }
}

Debugging - avlusning

Redan på femtiotalet kallades programfel för löss (eng. bug) eftersom man brukade skylla ifrån sej på småkryp som tagit sej in i komponenterna (som ju då var reläer). Det finns två sätt att avlusa programmet.
  1. Om man arbetar i en Javamiljö som Visual J++ eller Symantec Cafe kan man stega sej fram sats för sats och samtidigt se hur variabelvärdena ändras.
  2. Utan javamiljö stoppar man in hjälputskrifter i programmet, helst av typen
        if (debug)
            System.out.println("x = " + x);
    
    där man har deklarerat en global variabel
        static boolean debug = false;
    
    Ett elegant sätt att debugga utan omkompilering är att låta det styras av extraord på kommandoraden, alltså till exempel
        java Swahili DEBUG
    
    Det är bara att låta main() börja så här:
        public static void main(String[] args) {
            if (args.length > 0 && args[0].equals("DEBUG"))
                debug = true;
            // ...
    

Exception - särfall

Ibland kraschar en körning med ett felmeddelande enligt
Exception in thread "main" java.lang.NullPointerException
        at Dum.main(Dum.java:6)
Kollar man i metoden main() (rad 6 i filen Dum.java) ser man att man försökt använda ett objekt som är null. Strängen svar har aldrig blivit tilldelat ett referensvärde och därmed finns det inget Sträng-objekt att använda metoden length() på:
public class Dum {
    static String svar;
    
    public static void main(String[] args) {
	System.out.println("Och antalet bokstäver i svaret är...");
	System.out.println("..." + svar.length() + "!");
    }
}

Andra saker som kan få ett program att krascha är division med noll, felaktigt index i en vektor, oväntade tecken vid läsning av tal och oväntat filslut. Så här kan man förhindra felavbrott vid felaktigt vektorindex.
public class Farsson {
    public static void main(String[] args) {
	try {
	    System.out.print("Din son ska heta ");
	    System.out.println(args[0]+"sson");
	}
	catch(ArrayIndexOutOfBoundsException e) {
	    System.out.println("... vad heter du själv?");
	}
    }
}

Det som egentligen händer när konstigheten inträffar är att programflödet bryts, ett informationsobjekt av klassen Exception (sve. särfall) skapas och kastas iväg neråt i programkoden. Om ingen fångar särfallet bryts körningen och och fångas upp av java som skriver ut informationen på skärmen.
Om en metod upåptäcker ett fel kan man låta metoden kasta tillbaka det till anroparen:
public class Dumkvot {
    public static void main(String[] args) {
	try {
	    System.out.println("5/2 = " + kvot(5, 2));
	    System.out.println("3/0 = " + kvot(3, 0));
	    System.out.println("6/3 = " + kvot(6, 3));
	}
	catch(Exception e) {
	    System.out.println(e.getMessage());
	}
    }

    static int kvot(int x, int y) throws Exception {
	if(y == 0) 
	    throw (new Exception("Division med noll!"));
	return x/y;
    }
}


^ Upp till kurssidan.


Sidansvarig: <vahid@nada.kth.se>
Senast ändrad 30 september 2003
Tekniskt stöd: <webmaster@nada.kth.se>