Webbservern.se

Användararea  [inloggning krävs]

Ansökan

Om servern

 Användarnas www-sidor

 Donera

 Loggbok

 Nyhetsbrev

 Om webbservern.se

 Senast ändrade filer

 Webbserverinfo (CV)

 Villkor

Webbapplikationer

 Bildkonvertering

 MD5/Jämför filer

 Kryptera

 PDF-konvertering

 Rättstavning

 Väder

 Webbkamera

 Webmail

Handboken

 Backup
 Bandbredd
 CVS
 Databas (MySQL)
 E-post
 E-postlistor
 Lösenord
 Programmering
 Programvara
 Quota
 SFTP och SCP
 SSH
 VNC
 WWW


sök på webbservern.se

Handboken / Programmering / Java

I denna guide ska jag försöka hålla mig kortfattat eftersom Java är ett så pass stort ämne. Det ska inte bli någon bok och allt kommer inte att gås igenom 100-procentigt. Det blir många exempel eftersom det är ett bra sätt att uttrycka mycket med få ord. Jag tror och hoppas att det ska gå att hänga med bra även om man inte är bekant med programmering sedan tidigare.

Jag har för avsikt att följa detta förslag till svenska Javaterminologi. Om jag misslyckas med detta på något ställe får du gärna upplysa mig om detta.

Ursprung

Java började utvecklas av SUN under ledning av James Gosling runt 1991. Det var tänkt att Java, eller Oak som det först kallades, skulle användas i olika typer av elektronik, till exempel en brödrost.

Vad är Java för typ av språk?

Java är ett objektorienterat, statiskt typat, imperativt, kompilerat (eller semikompilerat) och plattformsoberoende programmeringsspråk.

Objektorienterat

Java är strikt objektorienterat, det är inte påklistrat i efterhand som fallet är med PHP och Perl. Java är från grunden utvecklat i enlighet med det objektorienterade tänkandet.

Statiskt typat och imperativt

Java är liksom C++ statiskt typat och imperativt. Att Java är statiskt typat (jo, det är svengelska) innebär i praktiken att variabler måste deklareras innan de används och att Javatolken kommer att protestera om du försöker associera till exempel ett decimaltal till en heltalsvariabel. Det finns mycket mer att orda om skillnaderna mellan statiskt och dynamiskt typade språk men det gräver vi inte djupare i just nu.

Plattformsoberoende och kompilerat

Java är kompilerat på så vis att din Javakod måste kompileras innan du exekverar programmet. Det kompileras dock inte till maskinkod utan till ett mellansteg, bytekod som i sin tur interpreteras av en Javatolk (JVM, Java Virtual Machine). Detta har den uppenbara fördelen att ditt Javaprogram kan köras i de operativsystem som har en Javatolk portad till sig. Eftersom det finns en JVM portad till alla vanligt förekommande operativsystem kan man möjligen hävda att Java är plattformsoberoende.

Java på webbservern - utvecklingsmiljö och kompilering

För tillfället körs Java 1.4.2 på webbservern. Du kan kontrollera själv vilken version som körs:

Emacs är den rekommenderade utvecklingsmiljön eftersom det lämpar sig väl att köras via SSH över nätverk. Den som vill kan även pröva Eclipse.

Grunderna i Java

Ett komplett program

Innan vi dyker in bland variabler och allt annat tar vi ett komplett, enkelt men framför allt traditionsenligt Javaprogramexempel. Det kan vara bra att känna till strukturen för ett komplett Javaprogram om du vill provköra någon kodsnutt nedan. Byt då bara ut innehållet i main-metoden.

class Hello {
  public static void main(String[] args) {
    System.out.println("Hello World!");
  }
}

Om du skulle vilja provköra exemplet skriver du in de fem raderna i en fil. Sparar den som ren text och ger den filnamnet Hello.java. För att kompilera Hello.java och sedan köra programmet skriver du:

javac Hello.java
java Hello

Variabler och datatyper

Java är som sagt statiskt typat och när du skapar en variabel ska du ange vilken datatyp du vill ha. Det beror förstås på vad för data du vill associera till din variabel. Nedan har du en tabell med vilka du har att välja på:

TypBeskrivning
byteheltal, [-128 - 127]
shortheltal, [-32768 - 32767]
intheltal, [-2147483648 - 2147483647]
longheltal, [-9223372036854775808 - 9223372036854775807]
floatflyttal, [-3.4E38 - 3.4E38]
doubleflyttal, [-1.7E308 - 1.7E308]
booleanboolsk variabel [antingen true eller false]
chartecken (lagras som Unicode, 16 bitar)

Det går även att tilldela variabeln ett värde direkt vid deklareringen. Vi tar några exempel (där det också framgår hur man kommenterar och avslutar satser):

byte fingers; //Antalet fingrar
short result1, result2;
int hair = 120000;
long gatesMoney, distanceToMoonInMillimetres = 384400000000;
float average, height;
boolean isMore = false, isEmpty = true;
char favouriteLetter = 'J', tab = '\t';

Det kan även vara bra att veta att det går att till explicit omvandla en variabels datatyp till en annan. Man skriver på följande vis för att omvandla från en integer till en float:

int a = 10;
float flyttal = (float) a // flyttal = 10.0;

Lite aritmetik

Java är en kraftfull miniräknare och det går att räkna hejvilt. Dessa aritmetiska operatorer finns att tillgå.

OperatorBetydelse
+Addition
-Subtraktion
/Division
*Multiplikation
%Modulus

Det mesta fungerar som man kan förvänta sig och det går bra att använda parenteser för att specificera evalueringsordningen (precedensen med ett fint ord). Exempel är bra.

double average, quantity = 50, total = 547.6;
average = total / quantity;
System.out.println("Per styck: " + average);
// Java skriver ut: Per styck: 10.952

I förbigående passar vi på att notera att utskrifter sker via System.out.println.

Modulusoperatorn kanske du inte stött på tidigare. Den ger dig resten vid en heltalsdivision. Exempelvis är "11 modulus 6" lika med 5.

int a = 11 % 6; // a = 5

Det finns ett gäng operatorer till men de kan du läsa om på annat håll. Lägg även märke till deras inbördes prioritetsordning.

Strängar

Siffror i all ära men strängar, en bunt alfanumeriska tecken alltså, är också bra att kunna hantera. Strängar är inte en vanlig datatyp i Java, det är en instans av String-klassen. Det där med objektorienterad programmering har vi inte kommit till ännu så du har inte missat nåt om "instans" känns som ett främmande ord.

Vi tar ett exempel som vanligt.

String greeting = "Tjena!\n", body, bye = "Hejdå!";
body = "Jag mår bra. Hur mår du?\n";
System.out.println(greeting + body + bye);

Javatolken tittar på satserna ovan och skriver ut följande:

Tjena!
Jag mår bra. Hur mår du?
Hejdå!

Kommentarer

Du bör ta som vana att kommentera allt som inte är uppenbart i din kod. Vad som är uppenbart är individuellt och dynamiskt men hellre en kommentar för mycket än en kommentar för lite.

Om du vill infoga en mindre kommentar används två snedstreck, //, och därefter kommentaren. Det som kommer efter snedstrecken på den raden antas vara en kommentar.

Om du vill infoga en längre kommentar omgärdar du kommentaren med /* och */.

Så här skulle några kommentarer (med något kommenterbart) se ut:

// Beräknar medelvärde
double average = (totalAmount / noOfParticipants);

String command = program + " " + arguments; // Hela kommandot.

/*
Metoden nedan kan starkt ifrågasättas men
i nuläget finns annat som är viktigare att
korrigera.
*/

Det finns även något som kallas dokumentationskommentarer. Om du nyttjar dig av sådana kan du med hjälp av javadoc skapa en separat dokumentation för ditt program.

En dokumentationskommentar börjar med /** och slutar med */. Det finns ett antal nyckelord som man kan använda sig av för att dokumentera metoder och klasser i ett standardformat.

Vi kikar som brukligt är på ett exempel:


/**
 * Krypterar med IDEA-algoritmen och
 * sparar den nya filen under nytt namn.
 * @author Arne Anka
 * @param filename   filnamnet för filen som ska krypteras<
 *        doCompress anger om filen ska krypteras eller ej
 * @return           absoluta sökvägen till den krypterade filen
 */

public String crypt(String inFile, boolean doCompress) {
   // Lite kod som gör det som utlovas.
}

Villkorsstyrning

Naturligtvis finns den (förhoppningsvis) bekanta if...else-konstruktionen implementerad i Java. ─ven om den inte är bekant bör den vara lätt att ta till sig: Om ett villkor är uppfyllt, gör si, i annat fall kan vi testa mot ett annat villkor och göra något annat, om inget av villkoren är uppfyllda kan vi välja att göra ytterligare något annat. Ett exempel (om än småfjantigt) säger mer än tusen ord som vi säger på webbservern.se:

short grade = 3;
if (grade < 3) {
  System.out.println("Nja, inte riktigt bra.");
} else if (grade == 3) {
  System.out.println("Okej, det funkar.");
} else {
  System.out.println("Stabilt! Fortsätt så.");
}

I exemplet ovan används "else if" och "else" för att testa ytterligare villkor men dessa två är inte obligatoriska. Exemplet ovan skulle även kunna implementeras med hjälp av en switch-konstruktion. Så här skulle det kunna se ut:

short grade = 3;
switch(grade) {
  case(1): {
    System.out.println("Nja, inte riktigt bra.");
    break;
  }
  case(2): {
    System.out.println("Nja, inte riktigt bra.");
    break;
  }
  case(3): {
    System.out.println("Okej, det funkar.");
    break;
  }
  case(4): {
    System.out.println("Stabilt! Fortsätt så.");
    break;
  }
  default: {
    if (grade == 5) {
      System.out.println("Stabilt! Fortsätt så.");
    } else {
      System.out.println("Märkligt betyg.");
    }
    break;
  }
}

Loopar

En loop gör att du kan köra en sats eller ett block (ett gäng satser) upprepade gånger. Vi ska titta på tre konstruktioner: for, while samt do while. I alla dessa tre varianter kan break och continue användas. Break hoppar ut ur loopen medan continue hoppar till nästa iteration i loopen.

For

For-loopen är kompakt och praktiskt i många fall. Den används till exempel ofta för att iterera över en listas element. I det enkla exemplet nedan loopar vi runt 10 gånger och skriver ut vilken iteration vi befinner oss på för tillfället.

for (int i = 0; i < 10; i++) {
  System.out.println("Iteration: " + i);
}

While

While-loopen är enkel till sin natur. Den ligger nära vårt vardagliga sätt att tänka: Gör si så länge ett villkor är uppfyllt.

int i = 0;
while (i < 10) {
  System.out.println("Iteration: " + i);
  i++;
}

Do-While

Do-loopen nedan kontrollerar villkoret första gången efter att den har skrivit ut "Iteration: 0". I detta exempel är det oväsentligt men i andra tillämpningar kan det vara en viktigt skillnad.

int i = 0;
do {
  System.out.println("Iteration: " + i);
  i++;
} while (i < 10);

Matriser

Enkelt uttryckt låter matriser dig hantera flera variabler av samma typ via endast ett variabelnamn. Det kanske inte låter så användbart men det är det. Jag tror vi är redo för ett litet exempel där vi även knyter an till avsnittet om for-loopar ovan. Med hjälp av for-loopen kan vi loopa precis så många gånger som det finns element i matrisen (matrisnamn.length).

int[] grades = {3,5,4,3,3}; //Vi fyller matrisen med betygen för våra 5 kurser.
for(int i = 0; i < grades.length; i++) {
  System.out.println("Betyg i kurs " + i + ": " + grades[i]);
}

I exemplet ovan deklareras matrisen grades samtidigt som den initieras med betygen. Varje betyg motsvarar ett element i matrisen och kan kommas åt på formen grades[x] där x är en siffra 0-4.

Det går även bra att göra flerdimensionella matriser samt naturligtvis fylla dem med annat än heltal.

Metoder

Det som i många andra programmeringsspråk kallas för funktioner heter i Java metoder. Metoder är bra till mycket, till exempel är det vettigt att lägga en ofta använd kodsnutt i en metod och därefter anropa metoden istället för att duplicera kodsnutten ännu en gång.

Ett exempel får illustrera som så många gånger förr.

public double average (int persons, double totalAmount) {
  return (totalAmount / persons);
}

Det finns flera intressanta iakttagelser vi kan göra. För det första, public är metodens åtkomstmodifierare (fungerar på samma sätt för hela klasser) och definierar vad som ska kunna komma åt denna metod. Vi ska snart titta på vad public innebär och vad det finns för andra alternativ.

Efter åtkomstmodifieraren följer vilken datatyp som metodens returvärde ska ha. Metoden "average" ovan ska returnera ett flyttal, en variabel av datatypen double. Om en metod inte ska returnerar något anges "void".

Inom parenteserna finns metodens parametrar. Om metoden inte tar emot några parametrar skriver man helt enkelt ingenting mellan parenteserna En parameter definierar alltså typen för det värde som kan skickas till metoden samt namnet som kan användas för att referera till den i koden i metoden. En del blandar ihop argument med parameter. Argumentet är det värde som skickas till metoden när den körs och detta värde refereras av parameternamnet under exekvering av metoden.

Vi noterar även att vi returnerar värdet från metoden med return vilket samtidigt gör att vi lämnar metoden. Om en en metod inte har något definierat returvärde kan "return" användas ensamt för att lämna metoden.

┼tkomstmodifierare och paket

I en statisk klassmetod (deklarerad som static) är det möjligt att referera till de andra statiska medlemmarna i samma klass medan en icke-statisk metod kan nå alla medlemmar. (Som medlem i en klass räknas fält och variabler. Ett fält är en variabel som deklarerats i en klass, med andra ord instansvaribler och klassvariabler.)

Utöver ovanstående regler ska vi bekanta oss med åtkomstmodifieraren som talar om hur variabler och metoder inuti en klass är åtkomliga från andra klasser. Detta åskådliggörs enklast i tabellform.

┼tkomstmodifierare┼tkomst
Ingen åtkomstmodifierare angiven Från klasser i samma paket.
public Från alla klasser.
private Ingen åtkomst utanför klassen.
protected Från klasser i samma paket och från alla subklasser.

Vi stötte nu på begreppet paket. Paket är en namngiven samling klasser som används för att gruppera klasserna. Om man inte anger något paket först i filen så kommer filens klasser att tillhöra ett namnlöst paket som är gemensamt för alla filer utan paketdeklaration.

Ett kortill exempel för att visa hur paketdeklarationen kan se ut.

package myPackage; //På första raden i filen

De filer som ska tillhöra paketet "mittPaket" måste sparas i en katalog med samma namn, det vill säga "mittPaket" (utan citationstecken). Det går även att bygga upp en hierarki med paket genom att särskilja paketen med punkter. Ett exempel till.

package allMyPackages.myPackage; //På första raden i filen

I exemplet ovan antas "myPackage" vara en underkatalog till "allMyPackages".

Undantagshantering

Undantag används för att signalera att något har gått på tok. Dessa signaler kan snappas upp så att du har möjlighet att parera misstaget eller helt enkelt "dö graciöst" (ruggig direktöversättning av "die gracefully").

Upplägget är följande:

try {
  Gör det farliga;
}
catch (Undantagsparameter) {
  Hantera felet (undantaget).
}

Vi "försöker" (try) göra något som vi vet kan gå snett. Om det går snett "kastas" (throw) ett undantag. Om vi har varit förutseende kan vi "fånga" (catch) det kastade undantaget.

Det går att ha flera catch-block, nästlade try-block och till och med kasta tillbaka undantag till det anropande programmet. Det är dock inget vi kikar på närmare i detta kapitel. Något vi ska titta lite på innan vi är klara med undantag är finally-blocket.

Finally-blocket körs efter catch-blocken och används när du vill vara säker på att viss kod körs innan en metod avslutas. Du kan rensa upp efter det avbrutna try-blocket, exempelvis stänga öppna filer.

try {
  Gör det farliga;
}
catch (Undantagsparameter) {
  // Hantera felet (undantaget).
}
finally {
  // Rensa upp.
}

I nästa stycke om filhantering studerar vi hur undantagshanteringen kan gå till i praktiken.

Läsa/skriva till fil

Det är skillnad på hur text- respektive binärfiler hanteras. Vi behandlar endast fallet med textfiler men om du vill läsa/skriva binära filer går det till på liknande sätt.

Vi börjar med ett exempel där vi läser en textfil och skriver ut dess innehåll till standardutenheten (skärmen i vårt fall). Det blir även ett utmärkt tillfälle att studera undandtagshantering i praktiken.

import java.io.*;

class ReadFile {
  public static void main(String[] args) {
    try {
      FileReader fr = new FileReader("testfil.txt");
      BufferedReader br = new BufferedReader(fr);
      // Läs första raden.
      String stringRead = br.readLine();
      // Läs resten av filen.
      while (stringRead != null) {
        System.out.println(stringRead);
        stringRead = br.readLine();
      }
      br.close();
    }
    catch (FileNotFoundException e) {
      System.out.println("Filen hittades inte!");
      System.exit(0);
    }
    catch (IOException f) {
      System.out.println("IOExecption under läsning av fil.");
    System.exit(0);
    }
  }
}

Först skapas ett FileReader-objekt som upprättar en anslutning till den specificerade filen och Javaprogrammet. Därefter skapas ett BufferedReader-objekt som kan buffra operationer från ett annat Reader-objekt (såsom FileReader). (Klasserna i standardbiblioteket är alla subklasser till den abstrakta superklassen Reader.)

När det väl är ordnat så att vi kan läsa från filen läser vi sträng för sträng tills filen är slut.

Nu tittar vi istället på hur det kan se ut när vi ska skriva till en textfil. Då använder vi några smidiga subklasser till den abstrakta klassen Writer.

import java.io.*;

class WriteFile {
  public static void main(String[] args) {
    try {
      FileWriter fr = new FileWriter("testfil.txt");
      BufferedWriter br = new BufferedWriter(fr);
      br.write("Detta skrivs till filen.\n");
      br.write("Det här med.");
    }
    catch (IOException e) {
      System.out.println("Det gick inte att skriva till filen.");
    System.exit(0);
    }
  }
}

I exemplet ovan skapas en ny fil med filnamnet "testfil.txt" om denna inte redan finns, i så fall skrivs den över. För att lägga till text i "testfil.txt" istället för att skriva över skapar du FileWriter-objektet enligt följande:

FileWriter fr = new FileWriter("testfil.txt", true);

─ven i detta fall skapas "testfil.txt" om den inte redan finns.

Klasser och objekt

Nu är det dags att förstå sig på det här med objektorienterad programmering (OOP). Lite grand i alla fall. Det finns, som om allt annat i den här guiden, mycket att säga om OOP och bara OOP erbjuder material för ett rejäl bok. Om du tyckte att det ovanstående var klurigt och inte riktigt tagit in det ännu kan det vara klokt att vänta med objektorienteringen tills det andra känns mer greppbart.

Vi ska gå igenom klasser och objekt genom en liknelse. Min erfarenhet är att OOP bäst förstås genom ett exempel som relaterar till verkligheten. Det fina i kråksången är nämligen att OOP är en tydlig analogi till verkligheten.

Tänk dig begreppet bil. Vad utmärker en bil? Vi kanske kan enas kring fyra hjul, motor, färg, växellåda, ratt samt ett eller flera säten. Denna prototyp av "bil" kallar vi för en klass (även om vi senare ska se att det mer liknar en abstrakt klass). Det är den allmänna bilen som bara finns i våra hjärnor (jmfr Platons idévärld). De bilar vi ser ute på vägarna är objekt som är instanser av klassen bil.

En gång till med andra ord: en klass är en specifikation för en samling objekt med gemensamma egenskaper. Det är en mall uttryckt i programkod som definierar vad en viss typ av objekt består av.

Ordet instans är detsamma som ett objekt av en viss klass. När du skapar ett objekt utifrån en klass säger man att klassen instansieras.

Vi lämnar bilarna ett tag och tar ett enkel exempel med rektanglar. Vi återkommer till bilarna snart.

public class Rectangle {
  //Klassvaribel
  static final int noOfSides = 4;

  //Instansvariabler
  double height;
  double width;

  double area() {
    return (this.height * this.width);
  }
}

De objekt som skapas från klassen Rectangle kommer att dela på klassvariabeln "noOfSides" som dessutom är definierad som en konstant (final). De skapade objekten kommer dock att få varsin kopia av instansvariablerna "height" och "width" som talar om hur hög och bred rektangeln är. Vi kan även notera att instansmetoden (area) har en variabel this som refererar till det aktuella objektet för vilken metoden anropas.

Vi kan nu skapa rektangelobjekt på detta sätt:


Rectangle myRectangle = new Rectangle();

//Bestämmer rektangelns storlek
myRectangle.height = 10.5;
myRectangle.width = 6.5;

System.out.println("Rektangelns area: " + myRectangle.area() + " areaenheter.");

Konstruktorer

I exemplet ovan bestäms höjden och bredden på den skapade rektangeln efter att rektangeln skapats. Det går naturligtvis att göra så att den skapade rektangeln redan vid dess skapelse tilldelas en höjd och en bredd. Med hjälp av två konstruktorer kan vi hantera både fallet när en höjd och bredd har angivits vid skapelsen och när höjd och bredd saknas.

public class Rectangle {
  //Klassvaribel
  static final int noOfSides = 4;

  //Instansvariabler
  double height;
  double width;

  //Konstruktor som tar hand om fallet när höjd och bredd är angiven.
  Rectangle (double height, double width) {
    this.height = height;
    this.width = width;
  }

  //Konstruktor som tar hand om fallet när höjd och bredd inte är angiven.
  Rectangle() {
    this.height = 10;
    this.width = 5;
  }

  double area() {
    return (this.height * this.width);
  }
}

Abstrakta klasser

Som det nämndes tidigare finns det något som heter abstrakta klasser. Bilklassen som diskuterades i exemplet ovan skulle behöva implementeras som en abstrakt klass eftersom bilarna skiljer sig åt på en del punkter, Car-klassen svarar inte mot något objekt i verkligheten. Exempelvis finns det bilar med manuell respektive automatisk växellåda och det vore då lämpligt att inte specificera exakt hur det går till när man växlar. Det är upp till subklasserna som ärver från den abstrakta klassen att definiera dessa funktioner. Lugn bara lugn så ska vi snart räta ut eventuella frågetecken.

Vi ska nu titta på hur bilklassen kan se ut i ett exempel där vi även stöter på en del andra nyheter.

public abstract class Car {
  static final int wheels = 4; //Klassvariabel med ett fast värde.

  //Instansvariabler
  String engine;
  String gearbox;
  String colour;
  int seats;

  //Instansmetoder
  void horn() {
    System.out.println("Tut tut!");
  }

  void gas() {
    System.out.println("Wrooom!");
  }
  //Instansmetoder som deklareras men inte definieras
  abstract void steer (double degree);
  abstract void changeGear (int gear);
}

Vi noterar att den definierade klassen är abstrakt, den börjar med "public abstract class...". Den är abstrakt eftersom det finns två abstrakta metoder, steer() och changeGear(), som är deklarerade men inte definierade. Det går inte att skapa objekt direkt från denna abstrakta klass. Istället måste subklasserna ärva från superklassen "Car".

Vi tittar på ett exempel där vi skapar två subklasser varav en (V70) inte är abstrakt.

public abstract class Volvo extends Car {
  static final String brand = "Volvo";
}

class V70 extends Volvo {
  static final String model = "V70";
  boolean manualGearBox = true;
  //Konstruktor
  V70 (String colour) {
    this.colour = colour;
    System.out.println("Tjena V70:n här, jag är " + this.colour + ".");
  }

  void steer (double degree) {
    //Ställ in hjulens vinklar.
  }
  void changeGear (int gear) {
    //Växla
  }
}

Nu har vi skapat en klass, V70, som går att instansiera. Vi ska titta på hur detta går fill.

//Skapar en ny V70.
V70 minVolvoV70 = new V70("röd");
System.out.println("Jag är en " + minV70.brand + ".");
minV70.gas();
minV70.horn();

Java-tolken svarar:
Tjena! V70:n här, jag är röd.
Jag är en Volvo.
Wrooom!
Tut tut!

Exemplet ovan gör inte anspråk på att vara det bästa upplägget när man ska modellera bilar i allmänhet och Volvo V70 i synnerhet men förhoppningsvis illustrerar det något av kraftfullheten med OOP.

Grafiska gränssnitt

I vissa sammanhang krävs ett grafiskt gränssnitt. Javakodens komplexitet ökar naturligtvis men vi ska ändå titta på några exempel för att få ett hum om hur det fungerar.

Vi ska använda oss av Swing vilket är ett klassbibliotek för att skapa grafiska gränssnitt som bygger föregångaren AWT (Abstract Windowing Toolkit).

Ett enkelt fönster

Vi börjar med att skapa ett fönster helt enkelt.

import javax.swing.*;

public class SimpleFrame extends JFrame {
  public SimpleFrame() {
    // Top-Level Container, en JFrame
    JFrame myFrame = new JFrame ("Ett fönster");
    myFrame.setSize (400, 300);
    myFrame.setVisible (true);
  }

  public static void main (String args[]) {
    new SimpleFrame();
  }
}

Programmet ovan är inte bra till mycket annat än att visa hur man skapar ett fönster. Vi ser att en JFrame skapas och döps till myFrame. Denna JFrame är en så kallad Top-Level Container. En Top-Level Container kan även bestå av en JDialog eller JApplet.

I exemplet bestämmer vi fönstrets storlek och säger att det ska visas. Som standard kommer fönstret då att hamna längst upp till vänster vilket motsvarar koordinaterna (0,0). Positionen kan bestämmas genom setLocation (x, y). Som vanligt symboliserar x koordinaten i sidled och y koordinaten i höjdled.

Vi utvidgar nu exemplet något ger det lite mer funktionalitet.

import javax.swing.*;

public class SimpleFrame extends JFrame {
  public SimpleFrame() {
    // Top-Level Container, en JFrame
    JFrame myFrame = new JFrame ("Ett fönster");

    // Gör så att det går att stänga fönstret på vanligt vis
    myFrame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    myFrame.setSize (400, 300);
    myFrame.setLocation (200, 100);
    myFrame.setVisible (true);
  }

  public static void main (String args[]) {
    new SimpleFrame();
  }
}

I exemplet ovan gjorde vi det möjligt att stänga fönstret på vanligt sätt genom användandet av setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE).

Ett fönster med innehåll

Det finns en del att hålla reda på nu när vi tar ytterligare ett steg och det är förstås nödvändigt att ha lite grundläggande koll på detta om resultatet ska bli lyckat.

Att skapa tomma fönster kan vara kul men de är som sagt inte så användbara alla gånger. Nu ska vi lägga in några komponenter (typ knappar, menyer, textinmatningsrutor och etiketter). Komponenter som ska visas måste placeras i en container. JFrame, som vi redan använt, är en container (till och med Top-Level Container som du minns) och i Swing är även en komponent en container.

Varje container har en layout manager som bestämmer hur komponenternas ska placeras ut i containern. Det finns ett antal olika layout managers men vi nöjer oss med den som är standard för en JFrame, nämligen Border Layout.

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

public class SimpleFrame extends JFrame {
  public SimpleFrame() {
    // Skapar en knapp.
    JButton myButton = new JButton("Klicka på mig!");

    // Ger knappen ett kortkommando, Alt-K
    myButton.setMnemonic(KeyEvent.VK_K);

    // Skapar en JPanel att ha knappen i.
    JPanel myPane = new JPanel();

    // Lägger till knappen i panelen.
    myPane.add(myButton);

    // Top-Level Container, en JFrame
    JFrame myFrame = new JFrame ("Ett fönster");

    // Gör så att det går att stänga fönstret på vanligt vis
    myFrame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    myFrame.setContentPane(myPane);
    myFrame.setSize (400, 300);
    myFrame.setLocation (200, 100);
    myFrame.setVisible (true);
  }
  public static void main (String args[]) {
    new SimpleFrame();
  }
}

I exemplet ovan kopplade vi ett kortkommando till knappen och för att göra det var vi tvungna att importera från klassbiblioteket AWT som du ser på näst översta raden. I övrigt hoppas jag att kommentarerna i koden räcker för att förstå vad som händer.

Hantera händelser

Vi har skapat ett fönster med en knapp men det är ingen funktionalitet kopplad till knappen. Inte så bra kan man tycka. För att snappa upp klicket på knappen måste vi koppla ett lyssnarobjekt till komponenten. Lyssnaren ligger och lyssnar efter klick på knappen. När den tror sig höra ett klick kan vi reagera på användarens knappklickande och göra något passande.

I exemplet nedan ska vi göra så att man bara kan klicka på knappen en gång. Lyssnaren rapporterar det första klicket och sen är det klippt.

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

public class SimpleFrame extends JFrame {
  private JButton myButton = null;
  private JPanel myPane = null;
  private JFrame myFrame = null;

  public SimpleFrame() {
    // Skapar en knapp.
    myButton = new JButton("Klicka på mig!");

    // Ger knappen ett kortkommando, Alt-K
    myButton.setMnemonic(KeyEvent.VK_K);

    // Skapar en lyssnare
    myButton.addActionListener(new ButtonListener());

    // Skapar en JPanel att ha knappen i.
    JPanel myPane = new JPanel();

    // Lägger till knappen i panelen.
    myPane.add(myButton);

    // Top-Level Container, en JFrame
    JFrame myFrame = new JFrame ("Ett fönster");

    // Gör så att det går att stänga fönstret på vanligt vis
    myFrame.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);

    myFrame.setContentPane(myPane);
    myFrame.setSize (400, 300);
    myFrame.setLocation (200, 100);
    myFrame.setVisible (true);
  }

  // Knappens händelsehanterare
  public class ButtonListener implements ActionListener {
    public void actionPerformed(ActionEvent e) {
      // Inaktivera knappen
      myButton.setEnabled(false);
    }
  }

  public static void main (String args[]) {
    new SimpleFrame();
  }
}

För att låta klassen ButtonListener komma åt knappen har vi lyft ut deklarationen av "myButton" utanför metoden main.

För att göra ett grafiskt Javaprogram med lite mer vettig funktionalitet blir det raskt mycket kod. Eventuellt fyller jag på med ett lite större exempelprogram senare.

Applets och JAR-arkiv

Applets har uppmärksammats en hel del, även utanför programmerarkretsar, och är Java-program som körs i en webbläsare. Det medför att de är lite begränsade till sin natur men vi låter oss inte nedslås av det utan kikar på ett simpelt applet.

import javax.swing.*;

public class SimpleAppletill extends JApplet {
  public void init() {
    getContentPane().add(new JLabel("Webbservern.se introducerar applets."));
  }
}

Det är klokt att paketera appleten i ett JAR-arkiv för att effektivisera både nedladdningen och exekveringen av appleten. I vårt fall har vi vara en .class-fil men vi gör ett JAR-arkiv ändå:

jar cf SimpleApplet.jar SimpleApplet.class

Det går alltså bra att paketera flera .class-filer i ett JAR-arkiv, byt helt enkelt ut "SimpleApplet.class" till "*.class" eller något annat passande.

För att bädda in appleten i en webbsida när JAR-arkivet ligger i samma katalog som webbsidan skriver du så här:

<head><title>SimpleApplet</title></head>
<body>
<applet code=SimpleApplet.class
archive=SimpleApplet.jar
width=400 height=100>
</applet>
</body>

Servlets

För en introduktion till servlets rekommenderas Java-servlets-kapitlet.

Läs mer på annat håll

--------------
Den här filen ändrades senast Saturday, 19-Mar-2016 09:02:39 CET.
Respons i någon form mailas till webmaster at webbservern.se