KVL logo

Java-oversigt del 1

Java er et objekt-orienteret programmeringssprog, en modernisering og forbedring af det udbredte sprog C++. Dette er del 1 af en kort oversigt over dele af Java til brug i kurset Databehandling ved KVL. Oversigten består af følgende afsnit:

Del 1
1. Skelet til en Java applet 9. Komponenter i en applet
2. Et komplet eksempel på en applet 10. Hændelser og metoden action
3. Ordrer 11. Grafik og metoden paint
4. Udtryk og operatorer 12. Musehændelser og tastaturhændelser
5. Erklæringer 13. Konvertering mellem typer
6. Tegnstrenge 14. Læsning af flere tal fra en tegnstreng
7. Tabeller 15. Linievis læsning
8. Navne og nøgleord  
Del 2
16. Avancerede komponenter i en applet 18. Skelet til et Java-program
17. Layout af komponenter 19. Indlæsning fra fil eller tastatur

Der er masser af materiale om Java på nettet, f.eks.

1. Skelet til en Java applet

En Java `applet' er et Java-program der har sit eget vindue på skærmen. En applet kan for eksempel startes af en webside med HTML-mærket APPLET; så vises applettens vindue som en del websiden i browseren (Netscape). En nærmere forklaring findes i HTML-oversigten, del 3.

En Java applet med navnet Klasse defineres i en fil kaldet Klasse.java, som skal indeholde Java-tekst af denne form:

    import java.applet.Applet;
    import java.awt.*;

    public class Klasse extends Applet
    {
      ... erklæringer ... 
      public void init()
      { ... }
      public boolean action( Event e, Object o )
      { ... }
      public void paint( Graphics g )
      { ... }
    }

Som det ses vil appletten normalt indeholde metoder kaldet init, action og paint. Disse metoder spiller en særlig rolle:

Det er programmørens opgave at indsætte erklæringer i klassen og at fylde indmad i metoderne init, action og paint. Det sker ved at skrive erklæringer, ordrer og udtryk:

Af sikkerhedshensyn kan en applet ikke læse og skrive filer på den lokale disk eller diskette, og kan ikke skrive ud på printeren. Til disse formål er man nødt til at bruge et egentligt Java-program.

2. Et komplet eksempel på en applet

Nedenstående Java-applet viser en knap med teksten `Klik her' og et tekstfelt (et lille vindue) når den køres. I tekstfeltet vises et tal. Hver gang man trykker på knappen forøges tallet i tekstfeltet med én.

   import java.applet.Applet;
   import java.awt.*;

   public class Klik0 extends Applet {

     int antalklik;
     Button knap = new Button("Klik her");
     TextField vindue = new TextField(10);

     public void init() {
       add(knap);
       add(vindue);
       antalklik = 0;
     }

     public boolean action(Event e, Object o) {
       if (e.target == knap) {
         antalklik = antalklik + 1;
         vindue.setText(Integer.toString(antalklik));
       }
       return true;
     }
   }

Forklaring: Når appletten startes, oprettes en tæller (variablen antalklik), en knap (variablen knap) og et tekstfelt (variablen vindue). Derefter udføres metoden init, hvor add bevirker at knappen og tekstfeltet vises på skærmen. Tælleren antalklik nulstilles.

Hver gang brugeren trykker på knappen, udføres ordrerne der står i action. Derved forøges tælleren antalklik med 1, og den nye tællerværdi vises i tekstfeltet vindue. Den synlige effekt er at hvert klik forøger værdien i tekstfeltet med én.

Du kan prøvekøre ovenstående eksempel ved at klikke her og trykke på knappen `Oversæt og kør'.

3. Ordrer

Her er nogle eksempler på de vigtigste ordrer i Java. Semikolon (;) bruges til at afslutte simple ordrer. Krølleparenteser { ... } bruges til at gruppere ordrer. Man behøver ikke lave indrykning af linierne, men det fremmer overblikket.

Ordre, eksempelBetydning
ambi = indk * 0.07 ; Tildeling: udregn udtryk og gem resultatet
saldo += indskud ; Addition og tildeling: forøg saldo med indskud.
Samme virkning som saldo = saldo + indskud ;
saldo -= gebyr ; Subtraktion og tildeling: formindsk saldo med gebyr.
Samme virkning som saldo = saldo - gebyr ;
saldo *= 1 + 0.01 * rentefod ; Multiplikation og tildeling: forøg saldo med rentefod %.
Samme virkning som
saldo = saldo * (1 + 0.01 * rentefod);
if (indk > 134500)
    { skat = skat + 0.05 * indk ; }
Valg uden alternativ
if (vaegt < 1000)
    { porto = 19 ; }
else
    { uddata.setText("For tung") ; }
Valg med alternativ
switch (ugedag) {
case 1: case 2: case 3: case 4: case 5:
   dag = "hverdag"; break;
case 6:
   dag = "lørdag"; break;
case 7:
   dag = "søndag"; break;
default:
   dag = "ukendt"; break;
}
Multivalg: vælg den første gren (case) der passer.
Husk break sidst i hver gren.
for ( int i = 1 ; i <= 100 ; i++ )
    { sum = sum + i ; }
Gentagelse: summér tallene i = 1, 2, ..., 100
while (saldo < 10000)
    { saldo = saldo * 1.06;
      termin++ ;
    }
Gentagelse: udfør løkken (nul eller flere gange) så længe saldo < 10000
udskriv(termin, saldo) ; Metodekald: udregn argumenter og kald metoden
// Programkommentar Kommentar: resten af linien ignoreres
/* Programkommentar ... */ Kommentar: alt mellem /* og */ ignoreres

4. Udtryk og operatorer

UdtrykBetydning
x Variabel x
Aritmetiske operatorer
termin++ Forøg termin med 1; returnér startværdien
++termin Forøg termin med 1; returnér slutværdien
termin-- Formindsk termin med 1; returnér startværdien
--termin Formindsk termin med 1; returnér slutværdien
- x Fortegnsvending
x * y Multiplikation
x / y Division. Hvis x og y har heltalstype, så afkortes resultatet til et heltal. Dvs. 8/3 er 2.
dagnr % 7 Heltalsrest ved division med 7
x + y Addition af tal, eller sammensætning af tegnstrenge
x - y Subtraktion
Sammenligningsoperatorer
x < y x er mindre end y
x <= y x er mindre end eller lig med y
x > y x er større end y
x >= y x større end eller lig med y
x == y x er lig med y
x != y x er forskellig fra y
Logiske operatorer
! (i == 2) Logisk negation: i er ikke lig 2
(0 < i) && (i < 100) Logisk konjunktion: i er større end nul og mindre end hundrede
(i == 2) || (i > 10) Logisk disjunktion: i er lig 2 eller større end 10
Metodekald
Math.pow(x, n+1) Metodekald, her potensopløftning: udregn argumentudtrykkene og kald metoden. Metodens resultat er udtrykkets værdi

5. Erklæringer

En erklæring indfører en ny variabel, og fortæller hvilken type værdier variablen kan indeholde. I erklæringen skrives typen eller klassen først, fulgt af en liste af variable som alle får den pågældende type.

En variabel kan kun bruges hvor den er synlig. Variablens synlighed bestemmes af hvor den er erklæret:

Man bør erklære variable så de er så lidt synlige som muligt. Hvis variablen kun bruges i action, så erklær den i action. Hvis variablen kun bruges som tællevariabel i en for-løkke, så erklær den i for-løkkens hoved.

ErklæringBetydningEksempler på værdier
int a, b, c; a, b og c kan indeholde heltal -12, 67, 129836122
double x, y, z; x, y og z kan indeholde kommatal -1.2, 67.9, 3.1415926, 3E8, 1E-34
boolean fundet, slut; fundet og slut kan indeholde logiske værdier true, false
char c1, c2; c1 og c2 kan indeholde tegn 'A', 'Z', '7'
String s1, s2, s3; s1, s2 og s3 kan indeholde tegnstrenge "Hello", "kartoffel"
int[] dage; dage er en tabel af heltal  
String[] navne; navne er en tabel af tegnstrenge  
int a = 117; erklær a og initialiser med 117  
int[] dage = new int[12]; erklær og opret tabellen dage med 12 heltal  
String[] navne = new String[7]; erklær og opret tabellen navne med 7 strenge  

Erklæringen int[] dage siger blot at hvis dage henviser til noget, så er det en tabel af heltal. For at lave en tabel af heltal skal man bruge operatoren new.

Med tildelingen dage = new int[12] kan man oprette en tabel med plads til 12 heltal, og binde den til variablen dage.

De tre sidste eksempler ovenfor viser at erklæring kan kombineres med initialisering, hvorved variablene får en værdi med det samme. Denne værdi kan oprettes med new om nødvendigt.

6. Tegnstrenge

En tegnstreng (engelsk: string) er en tekst, for eksempel "abc 67lyx" eller "Hello, world".

ProgramtekstBetydning
s1 = new String("Hello, world"); Opret teksten "Hello, world" og gem i s1
s1.length() Længden af s1, dvs. antal tegn i s1
s2 + s3 Konkatenering (sammensætning) af s2 og s3
s1.charAt(0) Det første tegn i s1
s1.equals(s2) Er s1 og s2 ens?
s1.equalsIgnoreCase(s2) Er s1 og s2 ens pånær store/små bogstaver?
s1.compareTo(s2) Giver negativt resultat hvis s1 er mindre end s2, nul hvis s1 lig med s2, positivt hvis s1 større end s2

Sammensætningsoperatoren + på strenge er speciel: hvis et af argumenterne er en streng, så vil det andet argument blive konverteret til en streng inden konkateneringen foretages. Man kan altså skrive "abc" + 112 og få strengen "abc112", hvor tallet 112 er blevet konverteret til strengen "112" inden de to strenge sættes sammen.

Bemærk at ("abc" + 100 + 12) giver "abc10012", ikke "abc112". Tallene 100 og 12 konverteres til "100" og "12" hver for sig inden strengene sættes sammen.

Se også afsnittet om konvertering mellem typer.

7. Tabeller

En tabel (engelsk: array) er en samling nummererede værdier. Nummereringen starter altid 0, 1, ...

ProgramtekstBetydning
dage = new int[12] ; Opret tabel med plads til 12 heltal
dage[0] = 31 ; Sæt første element i tabellen til 31
dage[0] Find indholdet af det første element
dage.length Find tabellens størrelse
for ( int i = 0 ; i < dage.length ; i++ )
    uddata.appendText(dage[i] + " ");
Gennemløb tabellen nedefra og op
for ( int i = dage.length - 1 ; 0 <= i ; i-- )
    uddata.appendText(dage[i] + " ");
Gennemløb tabellen oppefra og ned

8. Navne og nøgleord

Et navn kan betegne en variabel eller en metode. En navn skal begynde med et bogstav eller $ eller _ og fortsætte med nul eller flere cifre eller bogstaver eller $ eller _. Der skelnes mellem små og store bogstaver.

Variabelnavne kan vælges frit; det er altså ligegyldigt for computeren om en variabel hedder antalklik eller bare n. Variabelnavne må dog ikke være sammenfaldende med nøgleord, som har en speciel betydning. Nøgleordene er:

abstract boolean break byte case catch char class const continue default do double else extends final finally float for goto if implements import instanceof int interface long native new package private protected public return short static super switch synchronized this throw throws transient try void volatile while

Alle nøgleord skrives med små bogstaver. I disse noter vises nøgleordene med fede typer for nemmere at skelne dem fra andre navne.

9. Komponenter der kan vises i en applet

En komponent vises som et separat grafisk objekt i applettens vindue. En komponent kan være Label, Button, TextField, TextArea, Choice, Checkbox, eller List. De tre sidstnævnte er omtalt i Java-oversigt del 2.

ProgramtekstBetydningAnvendelse
Etiket (Label)
Label etiket1; Erklær en etiketerklæring
etiket1 = new Label("Etikettens tekst"); Opret etiket med given tekstinit
add(etiket1); Tilføj den til appletteninit
etiket1.setText("Ny tekst til etiketten"); Udskift etikettens tekst 
Knap (Button)
Button knap1; Erklær en knaperklæring
knap1 = new Button("Knappens tekst"); Opret knap med given tekstinit
add(knap1); Tilføj knap til appletinit
Tekstlinie (TextField)
TextField uddata1, inddata1; Erklær to tekstliniererklæring
uddata1 = new TextField("Tekstliniens tekst"); Opret tekstlinie med given tekstinit
inddata1 = new TextField(25); Opret tom tekstlinie med plads til 25 tegninit
add(uddata1);
add(inddata1);
Tilføj de to tekstlinier til appletinit
uddata1.setEditable(false); Teksten kan ikke redigeres 
uddata1.setText("Ny tekst"); Udskift tekstindholdet 
inddata1.getText(); Tekstindholdet som streng 
Tekstområde (TextArea)
TextArea uddata2, inddata2; Erklær to tekstområdererklæring
uddata2 = new TextArea("Tekst", 5, 40); Opret tekstområde, viser 5 linier à 40 tegninit
inddata2 = new TextArea(5, 40); Opret tomt tekstområde, viser 5 linier à 40 tegninit
add(uddata2); add(inddata2); Tilføj de to tekstområder til appletinit
uddata2.setEditable(false); Teksten kan ikke redigeres 
uddata2.setText("Ny tekst til tekstområdet"); Udskift tekstindholdet 
uddata2.appendText("Mere tekst"); Tilføj til tekstindholdet 
uddata2.appendText("\n"); Tilføj linieskift i tekstindholdet 
inddata2.getText(); Tekstindholdet som streng 
inddata2.getSelectedText() Valgt tekst (som tegnstreng) 

10. Hændelser og metoden action

Når brugeren gør noget ved applettens vindue, f.eks. indtaster tekst, flytter musen eller klikker på en musetast, så sker der en hændelse (engelsk: event). Når der sker en hændelse kaldes applettens metode action så appletten kan reagere på hændelsen.

Lad metoden action være erklæret således:

   public boolean action( Event e, Object o )
   {
      ... reaktion på hændelse ...

      return true;
   }

Når der sker en hændelse (f.eks. et museklik) kaldes action, idet parameteren e overføres som en beskrivelse af hændelsen. Denne parameter giver forskellige slags information:

Ordren return true signalerer at hændelsen er blevet håndteret af metoden action.

11. Grafik og metoden paint

Man kan tegne i en applet ved at benytte grafik-objektet g, der overføres til metoden paint når appletten startes, og hver gang man kalder repaint(). Nedenstående metoder skal altså benyttes i paint. Alle koordinater og størrelser angives i pixels, dvs. skærmpunkter.

ProgramtekstBetydning
g.drawString("Tekst", 100, 200) Skriv teksten "Tekst" med nederste venstre hjørne ved (100, 200)
g.setColor(Color.red) Vælg farve. Mulige farvenavne er orange, pink, cyan, magenta, yellow, black, white, gray, lightGray, darkGray, red, green, blue
g.setColor(new Color(255, 0, 255)) Vælg farve; farvekoderne skal være 0-255
g.setFont(new Font("TimesRoman", Font.BOLD, 14)) Vælg skriftsnit Times, fed, 14 punkt. Andre muligheder: Font.ITALIC og Font.PLAIN
g.drawLine(10, 20, 110, 120) Tegn linie fra (10, 20) til (110, 120)
g.drawRect(10, 20, 100, 50) Tegn rektangel; øverst venstre er (10, 20), bredde er 100 og højde er 50
g.fillRect(10, 20, 110, 120) Udfyld rektangel
g.clearRect(10, 20, 110, 120) Tegn rektangel med baggrundsfarven
g.drawOval(10, 20, 100, 200) Tegn oval; øverste venstre er (10, 20), bredde er 100 og højde er 200
g.fillOval(10, 20, 100, 200) Udfyld oval.
g.drawArc(10, 20, 100, 200, -45, 90) Tegn buen (ovalperiferien) fra -45 til 90 grader
g.fillArc(10, 20, 100, 200, -45, 90) Tegn udfyldt bue (ovalsektor) fra -45 til 90 grader
g.drawPolygon(xPoints, yPoints, 7) Tegn polygon (mangekant) med 7 hjørner; xPoints og yPoints er tabeller af heltal med hjørnernes (x, y)-koordinater
g.fillPolygon(xPoints, yPoints, 7) Udfyld polygon
g.copyArea(10, 20, 50, 100, 120, 130) Kopier området med øverste venstre (10, 20), bredde 50 og højde 100; kopien forskydes 120 til højre og 130 ned

12. Musehændelser og tastaturhændelser

Svarende til metoden action, som kan håndtere hændelser der vedrører knapper og tekstfelter, er der nogle metoder som kan håndtere hændelser der vedrører musen og tastaturet. Disse metoder bør ligesom action returnere true.

public boolean mouseDown( Event e, int x, int y ) Kaldes når museknappen trykkes ned; (x, y) angiver hvor musen pegede.
public boolean mouseUp( Event e, int x, int y ) Kaldes når museknappen slippes; (x, y) angiver hvor musen pegede.
public boolean mouseMove( Event e, int x, int y ) Kaldes når musen flyttes uden at en museknap er trykket; (x, y) angiver hvor musen peger.
public boolean mouseDrag( Event e, int x, int y ) Kaldes når musen flyttes mens en museknap er trykket; (x, y) angiver hvor musen peger.
public boolean keyDown( Event e, int key ) Kaldes når en tast trykkes; key er tegnkoden for den tast der trykkes.
public boolean keyUp( Event e, int key ) Kaldes når en tast slippes; key er tegnkoden for den tast der slippes.

For et eksempel på brugen af disse metoder, se Life2.java.

13. Konvertering mellem typer

FraTilUdtrykBemærkning
 
int iStringInteger.toString(i) 
String sintInteger.parseInt(s) 
String sintnew Integer(s).intValue()Alternativ til ovenstående
int idouble(double)(i) 
 
double dStringDouble.toString(d) 
String sdoublenew Double(s).doubleValue() 
double dint(int)(d)Afrund mod nul
 
boolean bStringBoolean.toString(b) 
String sbooleanBoolean.getBoolean(s) 
String sbooleannew Boolean(s).booleanValue()Alternativ til ovenstående

Hvis strengsammensætningsoperatoren + anvendes på et argument, der ikke er en streng, konverteres dette automatisk til en streng; se afsnittet om tegnstrenge. For eksempel vil udtrykket ("abc" + 112) have samme værdi som ("abc" + Integer.toString(112)), nemlig strengen "abc112".

14. Læsning af flere tal fra en tegnstreng

Kaldet Integer.parseInt(s) kan bruges til at læse ét heltal fra tegnstrengen s. Når man skal læse mere end ét tal fra en tegnstreng bør man i stedet benytte StreamTokenizer. Dette kan bruges til at læse vilkårlig mange tal fra TextField, TextArea eller en tekstfil.

Eksempel Sumtal.java. Denne programstump indlæser en række tal fra et TextArea kaldet inddata og udregner deres sum:

   String s = inddata.getText();                            // 1
   InputStream istroem = new StringBufferInputStream(s);    // 2
   StreamTokenizer tstroem = new StreamTokenizer(istroem);  // 3
   tstroem.parseNumbers();                                  // 4
   double sum = 0;                                          // 5
   int brik = tstroem.nextToken();                          // 6
   while (brik == StreamTokenizer.TT_NUMBER) {              // 7
     sum += tstroem.nval;                                   // 8
     brik = tstroem.nextToken();                            // 9
   }

Forklaring:

  1. Indholdet af TextArea inddata gemmes i tegnstrengen s.
  2. Tegnstrengen s konverteres til en indstrøm kaldet istroem.
  3. Indstrømmen istroem konverteres til en strøm af brikker (engelsk: tokens), her kaldet tstroem. En brik er et tal (TT_NUMBER) eller et ord (TT_WORD) eller linieskift (TT_EOL) eller slut-på-strømmen (TT_EOF).
  4. Vi vil gerne læse tal fra tstroem.
  5. Foreløbig er summen 0: der er jo endnu ikke læst nogen tal.
  6. Læs den første brik fra tstroem.
  7. Hvis den senest læste brik er et tal, så udføres løkkekroppen i linie 8 og 9, ellers standser løkken (og variablen sum vil da indeholde summen af alle de læste tal).
  8. Det netop læste tal fås som tstroem.nval, som lægges til den foreløbige sum. (Den læste tegnstreng kan fås ved at skrive sval i stedet for nval).
  9. Der læses endnu en brik fra tstroem, og løkken fortsætter ved linie 7.

Bemærk: Når man bruger StreamTokenizer skal man:

I et egentligt Java-program kan man indlæse fra tekstfiler og fra tastaturet på helt tilsvarende måde.

15. Linievis læsning

Hvis man vil beregne talsummerne linie for linie, så skal man bruge to while-løkker. Den ydre kører en omgang for hver linie, og den indre en gang for hvert tal på linien.

Eksempel Liniesum.java. Beregn summen for hver linie, og gem alle summerne i en tegnstreng summer. Dette gøres ved at erstatte linie 5-9 i eksemplet ovenfor med nedenstående; linie 1-4 er uændret:

   String s = inddata.getText();                            // 1
   InputStream istroem = new StringBufferInputStream(s);    // 2
   StreamTokenizer tstroem = new StreamTokenizer(istroem);  // 3
   tstroem.parseNumbers();                                  // 4
   tstroem.eolIsSignificant(true);                          // A
   int brik = tstroem.nextToken();                          // B
   while (brik != StreamTokenizer.TT_EOF) {                 // C
     double sum = 0;                                        // D
     while (brik == StreamTokenizer.TT_NUMBER) {            // E
       sum += tstroem.nval;                                 // F
       brik = tstroem.nextToken();                          // G
     }
     summer += sum + " ";                                   // H
     brik = tstroem.nextToken();                            // I
   }

Forklaring:

  1. Vi vil gerne holde øje med linieskift (eol = end-of-line) i tstroem.
  2. Læs den første brik fra tstroem.
  3. Hvis den senest læste brik ikke er slut-på-strøm (eof = end-of-file), så udføres løkkekroppen i linie D-I, ellers standser løkken.
  4. Foreløbig er liniens sum 0: der er jo ikke læst nogen tal endnu.
  5. Hvis den senest læste brik er et tal, så udføres den indre løkkekrop i linie F og G, ellers standser løkken.
  6. Det netop læste tal, tstroem.nval, lægges til liniens foreløbige sum.
  7. Der læses endnu en brik fra tstroem, og den indre løkke fortsætter ved linie E.
  8. Når den indre løkke standser, nås linie H, og sum er summen af liniens tal, som føjes til de andre liniesummer.
  9. Der læses endnu en brik fra tstroem, og den ydre løkke fortsætter ved linie C.

Dette dokument er
http://www.dina.kvl.dk/~sestoft/databehandling/java1.html

Tilbage til Databehandlings hjemmeside

Peter Sestoft, Databehandling 1999, 1997-04-30, 1998-04-02, 1999-04-16