Mobil: Grunderna om Java

Java och andra språk: C, C++ och C#

Filen Hello.java:
public class Hello {
    public static void main(String[] args) {
	System.out.println("Hello, world!");
    }
} // Hello
Körexempel:
linux> javac Hello.java
linux> java Hello
Hello, world!
linux> 
Java-programmet är inte en vanlig körbar fil ("exe-fil"), utan måste köras av en Java-tolk, den virtuella maskinen (JVM).

Jämför med Microsofts C# ("sii shaarp"), som påminner mycket om Java:

class HelloWorld { 
    public static void Main() { 
        System.Console.WriteLine("Hello, world!"); 
    } 
}
En åsikt är att Microsofts C#, och hela .NET-arkitekturen, är en kopia av Sun:s Java, "as close as legally possible", dvs en så exakt kopia som det går att göra utan att bli stämd.

Vi jämför med C. Filen hello.c:

#include <stdio.h>

int main(int argc, char* argv[]) {
    printf("Hello, world!\n");
    return 0;
} /* main */
Körexempel:
linux> gcc -Wall hello.c -o hello
linux> ./hello
Hello, world!
linux> 
Vi jämför med C++. Filen hello.cpp:
#include <iostream>

int main(int argc, char* argv[]) {
    std::cout << "Hello, world!\n";
} // main
Körexempel:
linux> g++ -Wall hello.cpp -o hello
linux> ./hello
Hello, world!
linux> 

Javafiler

Virtuell maskin

Rektangelprogram

Filen Rektangelkalkylator.java:
// Det finns minst ett fel i det här programmet.

import java.io.*;                                            

class Rektangelkalkylator {
    public static void main(String args[]) {
        int a = 0, b = 0;
        String buf;
        BufferedReader kbd_reader
            = new BufferedReader(new InputStreamReader(System.in));

        try {
            System.out.print("Ge sida a: ");
            buf = kbd_reader.readLine();
            a = Integer.parseInt(buf);
            System.out.print("Ge sida b: ");
            buf = kbd_reader.readLine();
            b = Integer.parseInt(buf);

            System.out.println("Area: " + a * b);
            System.out.println("Omkrets: " + 2*a + 2*b);
        }
        catch (IOException e) {
            System.out.println("Kunde inte läsa!");
        }
    } // main
} // Rektangelkalkylator
Körexempel:
linux> javac Rektangelkalkylator.java
linux> java Rektangelkalkylator
Ge sida a: 5
Ge sida b: 4
Area: 20
Omkrets: 108
linux> 
Fixa felet. Sen:
linux> java Rektangelkalkylator
Ge sida a: Bengt
Exception in thread "main" java.lang.NumberFormatException: For input string: "Bengt"
        at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
        at java.lang.Integer.parseInt(Integer.java:447)
        at java.lang.Integer.parseInt(Integer.java:497)
        at Rektangelkalkylator.main(Rektangelkalkylator.java:15)
linux> 
Jämför med vad som händer i C++. Programmet rektangelkalkylator.cpp:
#include <iostream>
using namespace std;

int main(int argc, char* argv[]) {
  int a = 0, b = 0;

  cout << "Ge sida a: ";
  cin >> a;
  cout << "Ge sida b: ";
  cin >> b;

  cout << "Area: " << a * b << "\n";
  cout << "Omkrets: " << 2*a + 2*b << "\n";
} // main
Körexempel (C++):
linux> make rektangelkalkylator
g++ rektangelkalkylator.cpp -o rektangelkalkylator
linux> ./rektangelkalkylator
Ge sida a: Bengt
Ge sida b: Area: 0
Omkrets: 0
linux> 
Fångar Java alla fel? Nej:
linux> java Rektangelkalkylator
Ge sida a: 1000000
Ge sida b: 1000000
Area: -727379968
Omkrets: 4000000
linux> 

Filhantering i Java

BufferedReader? InputStreamReader? Vilket krångel! Och jag som bara ville kunna mata ett heltal från tangentbordet.

Tips: IOStreamDemo.java ur Bruce Eckels Thinking in Java, 3d Ed, visar upp typiska användningar av Java-I/O. Det finns förklaringar i online-boken.

Härnäst

Samma problem med andra lösningar:

Rektangelklass

Filen Rektangel.java:
public class Rektangel {
    public Rektangel(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int omkrets() {
        return 2 * this.a + 2 * this.b;
    }
    public int area() {
        return a * b;
    }
    private int a = 0, b = 0;
} // Rektangel
Filen Main.java:
import java.io.*;

public class Main {
    public static void main(String args[]) {
        BufferedReader kbd_reader
            = new BufferedReader(new InputStreamReader(System.in));
        int a, b;
        String buf;
        try {
            System.out.print("Ge sida a: ");
            buf = kbd_reader.readLine();
            a = Integer.parseInt(buf);
            System.out.print("Ge sida b: ");
            buf = kbd_reader.readLine();
            b = Integer.parseInt(buf);

            Rektangel rektangel = new Rektangel(a, b);

            System.out.println("Area: " + rektangel.area());
            System.out.println("Omkrets: " + rektangel.omkrets());
        }
        catch (IOException e) {
            System.out.println("Kunde inte läsa!");
        }
    } // main
} // Main
Körexempel:
linux> javac Rektangel.java
linux> javac Main.java
linux> java Rektangel
Exception in thread "main" java.lang.NoSuchMethodError: main
linux> java Main
Ge sida a: 5
Ge sida b: 4
Area: 20
Omkrets: 18
linux> 

Main i rektangelklassen

Onödigt med en särskild klass bara för att ha någonstans att lägga main-metoden. Ett vanligt trick är att lägga main i den klass man jobbar med.

Filen Rektangel.java:

import java.io.*;

class Rektangel {
    public Rektangel(int a, int b) {
        this.a = a;
        this.b = b;
    }
    public int omkrets() {
        return 2 * this.a + 2 * this.b;
    }
    public int area() {
        return a * b;
    }
    private int a = 0, b = 0;

    public static void main(String args[]) {
        BufferedReader kbd_reader
            = new BufferedReader(new InputStreamReader(System.in));
        int a, b;
        String buf;
        try {
            System.out.print("Ge sida a: ");
            buf = kbd_reader.readLine();
            a = Integer.parseInt(buf);
            System.out.print("Ge sida b: ");
            buf = kbd_reader.readLine();
            b = Integer.parseInt(buf);

            Rektangel rektangel = new Rektangel(a, b);

            System.out.println("Area: " + rektangel.area());
            System.out.println("Omkrets: " + rektangel.omkrets());
        }
        catch (IOException e) {
            System.out.println("Kunde inte läsa!");
        }
    } // main
} // Rektangel
Körexempel:
linux> javac Rektangel.java
linux> java Rektangel
Ge sida a: 45
Ge sida b: 34
Area: 1530
Omkrets: 158
linux> 
Man kan ha en main-funktion i varje klass. Bra för testning!

Programtyper

Syntaxen påminner starkt om C# och C++

Kanske mest förvånande skillnaden mot C++: Man måste inte ha semikolon efter en klassdefinition.

Kommentarer

// Sträcker sig över resten av raden
/* Kan sträcka sig
      över flera
          rader */

Datatyper

Primitiva typer - storlek

boolean   1 bit      false eller true
char     16 bitar    Unicode-tecken
byte      8 bitar   -128 .. 127
short    16 bitar   -32768 .. 32767
int      32 bitar   -2147483648 .. 2147483647
long     64 bitar   -9223372036854775808 ..
                    9223372036854775807
float    32 bitar   3.40282347E+38 ..
                    1.40239846E-45
double   64 bitar   1.79769313486231570E+308 ..
                    4.94065645841246544E-324

Variabeldeklarationer

Arrayer

Java har flera olika "behållar"-typer, som kan innehålla andra objekt, till exempel listor, mängder och mappningar.

Det finns flera olika sorters arrayer! Ingen av dem fungerar som i C och C++.

De inbyggda arrayerna kan lagra både primitiva typer och objekt. Man måste (oftast) göra new.

Exempel:

int[] intarray = new int[10];
int intarray[] = new int[10];
String[] fruits = { "Äpplen", "Päron", "Apelsiner" };
int intarray[10]; // Ger kompileringsfel!

Tilldelning och likhetsjämförelse

Som i C och C++: = är tilldelning och == är jämförelse

Räkneoperationer

Som i C och C++: +, -, *, /, ++, --, +=, /= med flera.

Notera att bitskiftningsoperatorerna << och >>, som i C++ överlagrats för in- och utmatning, bara är bitskiftningsoperatorer i Java.

Kontrollflöden

(Nästan) precis som i C++: if, while, do ... while, for, switch, break, continue.

Några skillnader gentemot C++

Objektorientering

Läs en introduktion här: http://www.databasteknik.se/webbkursen/oo-grunder/

Klasser och arv: djur, fiskar och fåglar

Basklassen Djur med subklasserna Fågel och Fisk

Ett djur har ett namn (variabeln name) och en vikt (variabeln weight), och det kan äta (metoden eat):

class Animal {
    protected String name;
    private int weight;
    public Animal(String n, int w) {
        name = n;
        weight = w;
    }
    public void eat(String food) {
        System.out.println(name + " eats some " + food + ".");
        weight += 0.5;
    }
} // class Animal
(Jag använder engelska namn, men det hade funkat bra med svenska, inklusive ÅÄÖ!)

En fisk är ett djur. Den har alla egenskaper som ett djur har (nämligen namn och vikt) och den kan allt som ett djur kan (nämligen äta). Men dessutom har den en största djup som den kan simma på, och den kan simma:

class Fish extends Animal {
    private int maxDepth;
    public Fish(String n, int w, int d) {
        super(n, w);
        maxDepth = d;
    }
    public void swim() {
        System.out.println(name + " swims.");
    }
} // class Fish
En fågel är också ett djur. Den har alla egenskaper som ett djur har (nämligen namn och vikt) och den kan allt som ett djur kan (nämligen äta). Men dessutom har den en högsta flyghöjd, och den kan flyga. Dessutom beter den sig lite speciellt när den äter: först fladdrar den med vingarna av lycka över att ha fått matm och därefter äter den precis som ett vanligt djur.
class Bird extends Animal {
    private int maxAltitude;
    public Bird(String n, int w, int a) {
        super(n, w);
        maxAltitude = a;
    }
    public void fly() {
        System.out.println(name + " flies.");
    }
    public void eat(String food) {
        System.out.println(name + " flutters its wings.");
        super.eat(food);
    }
} // class Bird
Vi provkör klasserna med hjälp av klassen Zoo och dess main-metod:
class Zoo {
    public static void main(String[] args) {
        Bird tweety = new Bird("Tweety", 3, 1000);
        tweety.eat("corn");
        tweety.fly();

        Fish b = new Fish("Bubbles", 13, 100);
        b.eat("fish food");
        b.swim();

        Animal w = new Fish("Willy", 4000, 1000);
        w.eat("tourists");
        // w.swim(); -- Doesn't work. See below.
    }
} // class Zoo
Utmatning:
Tweety flutters its wings.
Tweety eats some corn.
Tweety flies.
Bubbles eats some fish food.
Bubbles swims.
Willy eats some tourists.
Kommentarer:

Lägg märke till att klassen Bird har en egen metod som heter eat. Det finns en i Animal också, men den nya ersätter eller "döljer" (engelska: overrides) den gamla, och kommer att användas i alla Bird-objekt. Om man har en metod i en subklass med samma namn (och argument) som en metod i superklassen, så döljer metoden i subklassen metoden i superklassen. Om man trots det vill anropa metoden i superklassen kan man använda super, som är objektet men "tolkat som om det enbart hörde till superklassen". Det är vad vi gör i metoden eat: efter att ha fladdrat med vingarna så ska fågeln faktiskt äta, och det görs med ett anrop till super.eat.

Angående w.swim(): Variabelb w är av typen Animal, och Animal har ingen metod som heter swim. Variabeln w innehåller Willy, som är en Fish, och Fish har ju en swim-metod, så den skulle ha kunnat anropas när programmet körs. Men kompilatorn måste vara säker på att det aldrig kan uppstå ett typfel! Därför kontrollerar den vid kompileringstillfället att anropet aldrig kan misslyckas. Det betyder att varje objekt som kan lagras i variabeln w måste vara av en klass som har en swim-metod.

Programmet finns som filen Zoo.java.

Polymorfism: figurer

Världen består av figurer, och en figur kan antingen vara en rektangel eller en cirkel:

Basklassen Figur med subklasserna Rektangel och Cirkel

En Figur har en mittpunkt, som anges med koordinaterna x_center och y_center. Man kan räkna ut dess area och omkrets, och den högsta x-koordinat och y-koordinat som täcks av figuren.

Men! Hur figuren ser ut, och hur man räknar ut area och omkrets, beror ju helt på vilken figur det är! Därför kan de metoderna inte implementeras i klassen Figur, utan "lämnas" till subklasserna. Det kallas att metoderna är abstrakta. Eftersom det finns abstrakta metoder i klassen, kan man inte skapa objekt av den typen, så hela klassen blir abstrakt.

public abstract class Figur {
    public Figur(int x, int y) {
        this.x_center = x;
        this.y_center = y;
    } // Figur

    public abstract int max_x();
    public abstract int max_y();
    public abstract int area();
    public abstract int omkrets();

    protected int x_center, y_center;
} // class Figur
Se filen Figur.java.

En Rektangel är en sorts Figur, och den innehåller förstås ett sätt att räkna ut omkretsen och ett sätt att räkna ut arean. Klassen Rektangel är inte abstrakt, utan man kan skapa Rektangel-objekt. En Rektangel har inte bara en mittpunkt, utan dessutom två sidor. Vi skriver en konstruktor med de extra parametrarna.

public class Rektangel extends Figur {
    public Rektangel(int x, int y, int sida, int hojd) {
        super(x, y);
        this.sida = sida;
        this.hojd = hojd;
    } // Rektangel

    public int max_x() {
        return super.x_center + this.sida / 2;
    } // max_x

    public int max_y() {
        return super.x_center + this.hojd / 2;
    } // max_y

    public int area() {
        return this.sida * this.hojd;
    } // area

    public int omkrets() {
        return 2*this.sida + 2*this.hojd;
    } // omkrets

    private int sida, hojd;
} // class Rektangel
Se filen Rektangel.java.

En Cirkel är en annan sorts Figur:

public class Cirkel extends Figur {
    public Cirkel(int x, int y, int radie) {
        super( x, y );
        this.radie = radie;
    } // Cirkel

    public int max_x() {
        return super.x_center + this.radie;
    } // max_x

    public int max_y() {
        return super.y_center + this.radie;
    } // max_y

    public int area() {
        return (int)(Math.PI * this.radie * this.radie);
    } // area

    public int omkrets() {
        return (int)(2*Math.PI * this.radie);
    } // omkrets

    public int diameter() {
        return this.radie + this.radie;
    } // diameter

    private int radie;
} // class Cirkel
Se filen Cirkel.java.

Klassen FigurMain innehåller metoden main:

Kod:
public class FigurMain {
    public static void main(String args[]) {
        Figur[] figurer = new Figur[4];

        figurer[0] = new Rektangel(
                                   10,   // x
                                   10,   // y
                                   10,   // sida
                                   10 ); // hojd

        figurer[1] = new Cirkel(
                                10,   // x
                                10,   // y
                                10 ); // radie

        figurer[2] = new Rektangel(
                                   20,   // x
                                   20,   // y
                                   20,   // sida
                                   20 ); // hojd

        figurer[3] = new Cirkel(
                                20,   // x
                                20,   // y
                                20 ); // radie

        for (int index = 0; index < figurer.length; index++) {
            if (figurer[index] instanceof Cirkel) {
                System.out.println("Cirkel:");
                System.out.println("  Diameter: " +
                                   ((Cirkel)figurer[index]).diameter() );
            }
            else {
                System.out.println("Rektangel:");
            } // if

            System.out.println("  Högsta x: " + figurer[index].max_x());
            System.out.println("  Högsta y: " + figurer[index].max_y());
            System.out.println("  Area: " + figurer[index].area() );
            System.out.println("  Omkrets: " + figurer[index].omkrets());
        } // for
    } // main
} // class FigurMain
Se filen FigurMain.java.

Körexempel:

Rektangel:
  Högsta x: 15
  Högsta y: 15
  Area: 100
  Omkrets: 40
Cirkel:
  Diameter: 20
  Högsta x: 20
  Högsta y: 20
  Area: 314
  Omkrets: 62
Rektangel:
  Högsta x: 30
  Högsta y: 30
  Area: 400
  Omkrets: 80
Cirkel:
  Diameter: 40
  Högsta x: 40
  Högsta y: 40
  Area: 1256
  Omkrets: 125

Vad är en klass?

Vad är ett objekt?

Ett objekt är en instans av en klass. Exempel:
Cirkel cirkel; // får värdet null
cirkel = new Cirkel( 10, 10, 10 );
Nu har vi en instans av Cirkel. Variabeln cirkel refererar till den cirkeln. (Ungerfär som pekare i C.)
Cirkel cirkel2; // får värdet null
cirkel2 = cirkel;
Nu refererar både cirkel och cirkel2 till samma objekt!

C++:s delete finns inte i Java, och behövs inte. Java har automatisk skräpsamling (engelska: garbage collection).

Syntax

<modifier> 
class 
<name>
 [ extends <baseclassname> ]
 [ implements <interfacename> ]
  {
    . . .
    <variable definitions>
    . . .
    <function definitions>
    . . .
  }

Anrop av instansmetod

Cirkel cirkel = new Cirkel( 10, 10, 10 );
System.out.println("Area: " + cirkel.area());
Anrop av area-metoden i Cirkel. Inuti metoden refererar variabeln this till objektet, dvs cirkeln cirkel.

Peta på data i ett objekt

Gör radie allmänt åtkomlig (public) i Cirkel:
public int radie;
Nu kan man peta på den utifrån:
Cirkel cirkel = new Cirkel( 10, 10, 10 );
cirkel.radie = 27; // som en struct i C

Överlagring av metoder

Flera funktioner med samma namn, men med olika typer på parametrar, olika antal parametrar, olika returtyper. Exempel från klassen Cirkel:
  public void rita(int skala) { /* ... */ }
  public void rita(int x, int y) { /* ... */ }

Konstruktor

Flera konstruktorer

Överlagring även här. Exempel från klassen Figur:
public Figur(int x, int y) { /* ... */ }
public Figur() { /* ... */ }

Destruktor: metoden finalize

Men Java har automatisk skräpsamling! Inte som i C++, där destruktorn måste städa upp allt som ett objekt allokerat.

Lita inte på finalize, till exempel för att stänga filer och ta bort fönster. Man har ingen aning om när den körs.

Knappar

Hittills har vi sett program som arbetar med in-och utmatning i form av text, i ett textfönster, men det allra vanligatse är att man jobbar med grafiska gränssnitt: fönster, knappar och så vidare.

Filen TwoButtons.java:

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;

class TwoButtonWindow extends JFrame {
    private JButton button1 = new JButton("Bing");
    private JButton button2 = new JButton("Bong");
    private JTextField textfield = new JTextField(10);
        
    private class ButtonPressListener implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            String name = ((JButton)e.getSource()).getText();
            textfield.setText(name);
        }
    } // ButtonPressListener

    private ButtonPressListener listener = new ButtonPressListener();

    public TwoButtonWindow() { 
        Container cp = getContentPane();
        cp.setLayout(new FlowLayout());
        cp.add(button1);
        cp.add(button2);
        cp.add(textfield);;

        button1.addActionListener(listener);
        button2.addActionListener(listener);

        setSize(400, 100);
        setVisible(true);
    }
} // TwoButtonWindow

public class TwoButtons {
    public static void main(String[] args) {
        TwoButtonWindow window = new TwoButtonWindow();
    } // main
} // class Buttons
Utseende:

Programmet TwoButtons

Tre olika sorters Java

  1. Java ME ("Micro Edition"), för "små datorer", som mobiltelefoner (gå en kurs?)
  2. Java SE ("Standard Edition"), för vanliga datorer (skrivbords-, bärbara, även servrar)
  3. Java EE ("Enterprise Edition"), för servertillämpningar, t ex webbservrar

Dålig felhantering i C

Felhanteringen i C, och i ganska stor utsträckning C++, bygger på att programmeraren skriver kod som kontrollerar returvärden.

Vad kan gå fel i följande C-program, unsafe-hello.c?

#include <stdio.h>

int main(int argc, char* argv[]) {
    printf("Hello, world!\n");
    return 0;
} /* main */

En säkrare version, safe-hello.c:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char* argv[]) {
    if (printf("Hello, world!\n") != 14) {
        fprintf(stderr,
		"Kunde inte skriva hela texten!\n");
        return EXIT_FAILURE;
    }
    if (fclose(stdout) != 0) {
        fprintf(stderr,
		"Kunde inte skriva till filen!\n");
        return EXIT_FAILURE;
    }
    return 0;
} /* main */

Bra felhantering i Java: Undantag ("exceptions")

Java "kastar ett undantag" ("throws an exception") när något blir fel. Programmet kan "fånga" ett undantag, kanske på ett helt annat ställe än där det kastades.

Liknelse: När man använder sig av ett subsystem (till exempel att man anropar metoden tvätta i objektet t av klassen Tvättmaskin) ska man inte behöva stå och kontrollera att den verkligen tvättar. I stället låter man den tvätta bäst den vill, och om något går fel kommer det ett undantagsobjekt flygande och träffar en i huvudet.

Livet blir lättare med undantag

I många program består huvuddelen av programkoden av felhantering. Med felhantering med hjälp av undantag kan man både samla ihop felhanteringskoden, i stället för att ha den utspridd i hela programmet, och minska mängden felhanteringskod.

En bra sak med undantag är att de kan kastas "genom" en metod. Även om den metoden inte gör någon felhantering alls, kan det kastade undantaget skickas vidare till anroparen. Studera detta utdrag ur ett Java-program som inte innehåller någon felhantering (dinner-1/Dinner.java):

    private void drinkCoffee() {
        // Drick kaffe
    }

    private void eatDinner() {
        eatAppetizer();
        eatMainCourse();
        eatDessert();
        drinkCoffee();
    }

    public static void main(String[] args) {
        Dinner d = new Dinner();
        d.eatDinner();
        System.out.println("Ätandet klart.");
        System.out.println("(Kanske i alla fall.)");
    } // main
Vad händer om det uppstår ett fel någonstans, till exempel i drinkCoffee? Vi måste lägga till felhantering. Vi kan till exempel låta metoderna returnera true om allt gick bra, och false om något gick fel. Utdrag ur dinner-2/Dinner.java:
    private boolean drinkCoffee() {
        if (coffeePot == null)
            return false;
        else {
            // Drick kaffe. Det gick bra:
            return true;
        }
    }

    private boolean eatDinner() {
        if (eatAppetizer() == false)
            return false;
        if (eatMainCourse() == false)
            return false;
        if (eatDessert() == false)
            return false;
        if (drinkCoffee() == false)
            return false;
        return true;
    }

    public static void main(String[] args) {
        Dinner d = new Dinner();
        if (d.eatDinner() == false)
            System.out.println("Ätandet misslyckades!");
    } // main
Notera hur mycket jobb det blev i eatDinner, och hur det programmet egentligen ska göra nästan försvinner bland all felhanteringen.

Bättre med undantag! Utdrag ur dinner-3/Dinner.java:

    private void drinkCoffee() throws NoCoffeePotException {
        if (coffeePot == null)
            throw new NoCoffeePotException();
        else {
            // Drick kaffe
        }
    }

    private void eatDinner() throws NoCoffeePotException {
        eatAppetizer();
        eatMainCourse();
        eatDessert();
        drinkCoffee();
    }

    public static void main(String[] args) {
        Dinner d = new Dinner();
        try {
            d.eatDinner();
        }
        catch (NoCoffeePotException e) {
            System.out.println("Ingen kaffepanna!");
        }
        catch (Exception e) {
            System.out.println("Något annat gick snett.");
        }
    } // main
Så här ser NoCoffeePotException ut:
class NoCoffeePotException extends Exception {

} // class NoCoffeePotException

Inbyggda undantag

Det här har de fått jobba länge på för att få så krångligt! (Designen har utvecklats i flera steg, i stället för på en gång.)

Klasshierarki över undantagsklasserna

Checked exceptions ("kontrollerade undantag") måste fångas med try och catch, eller deklareras med throws. Unchecked exceptions ("okontrollerade undantag") behöver inte.

Normalt bygger man vidare på Exception.

Exempel på program med undantag: DivZeroException

Programmet Number.java:
import java.io.BufferedReader;
import java.io.InputStreamReader;

// Att kastas vid division med noll
class DivZeroException extends Exception {

} // class DivZeroException

class Number {
    public Number(int tal) {
        this.num = tal;
    } // Number

    public void addera(int tal) {
        this.num = this.num + tal;
    } // addera

    public void dividera(int tal)
      throws DivZeroException {
        if (tal == 0)
            throw new DivZeroException();
        this.num = this.num / tal;
    } // dividera

    public int varde() {
        return this.num;
    }

    private int num = 0;

    public static void main(String[] args) {
      BufferedReader kbd_reader =
          new BufferedReader(
                 new InputStreamReader(System.in));
      int tal = 1;
      String buf;
      Number num = new Number(14);

      System.out.println("Startar med: " + num.varde());
      System.out.println("Adderar udda tal.");
      System.out.println("Dividerar jämna tal." );

      try {
        while (tal != 99) {
            System.out.print("Ge ett tal (99 avslutar): ");
            buf = kbd_reader.readLine();
            tal = Integer.parseInt(buf);
            if (tal % 2 == 1)
                num.addera(tal);
            else
                try {
                    num.dividera(tal);
                }
                catch (DivZeroException e) {
                    System.out.println("Ojdå! Division med 0.");
                }

            System.out.println("Nu är talet: " + num.varde());
        } // while
      } // try
      catch (Exception e) {
          System.out.println("Fel inmatning / tangentbordsfel");
      } // catch
    } // main
} // class Number
Körexempel:
pc105-246.oru.se DivZeroException > javac Number.java
pc105-246.oru.se DivZeroException > java Number
Startar med: 14
Adderar udda tal.
Dividerar jämna tal.
Ge ett tal (99 avslutar): 13
Nu är talet: 27
Ge ett tal (99 avslutar): 4
Nu är talet: 6
Ge ett tal (99 avslutar): Bengt
Fel inmatning / tangentbordsfel
pc105-246.oru.se DivZeroException > 


Thomas Padron-McCarthy (Thomas.Padron-McCarthy@oru.se), 11 januari 2009