javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen

7 Lokale, objekt- og klassevariabler

Indhold:

Forudsættes ikke i resten af bogen.

Forudsætter kapitel Fejl: Henvisningskilde ikke fundet, Fejl: Henvisningskilde ikke fundet.

De variabler, vi er stødt på indtil nu, har enten været lokale variabler eller felter.

Felter kaldes også objektvariabler, fordi de bliver oprettet for hvert objekt.

Der findes også variabler, der eksisterer "i klassen", uafhængigt af om der bliver oprettet objekter. Disse kaldes klassevariabler og erklæres med nøgleordet static (derfor kaldes de ofte også for "statiske variabler").

7.1 Klassevariabler og -metoder

Herunder ses et eksempel på en klassevariabel og en klassemetode (antalBokse).

Klassevariabler og -metoder vises med understregning i UML-notationen (diagrammet til højre).

public class Boks4 
{
  private double længde;              // objektvariabel
  private double bredde;              // objektvariabel
  private double højde;               // objektvariabel
  private static int antalBokse;      // klassevariabel

  public Boks4(double lgd, double b, double h)
  {
    // lgd, b og h er lokale variabler
    længde = lgd;
    bredde = b;
    højde  = h;
    antalBokse = antalBokse + 1;
  }

  public static int læsAntalBokse()   // klassemetode
  {
    return antalBokse;
  }

  public double volumen()
  {
    // vol er en lokal variabel
    double vol;
    vol = længde*bredde*højde;
    return vol; 
  }
}

Variablen antalBokse er en klassevariabel, fordi den er erklæret med nøgleordet static. Dette betyder, at variablen er tilknyttet klassen og at alle Boks-objekter deler den samme variabel. Der vil eksistere én og kun én antalBokse-variabel, uanset om der oprettes 0, 1, 2 eller 100 Boks-objekter.

Ligeledes er metoden læsAntalBokse() en klassemetode, da den er erklæret med nøgleordet static. Den arbejder på klasseniveau (uafhængigt af om der er skabt nogen objekter) og kan derfor ikke anvende metoder og variabler i klassen, der eksisterer på objektnivau. Det er f.eks. forbudt at bruge variablerne længde, bredde eller højde inde fra læsAntalBokse().

Inde fra objektet kan klassevariabler (og -metoder) bruges ligesom almindelige variabler og -metoder. Det ses f.eks. i konstruktøren:

    antalBokse = antalBokse + 1;

Og for fuldstændighedens skyld: Variablerne længde, bredde og højde er "normale" felter/objektvariabler, så hvert Boks-objekt har tilknyttet én af hver. Variablen vol er en lokal variabel, fordi den er erklæret lokalt i volumen-metoden og altså kun eksisterer, når volumen-metoden udføres. Ligeledes med lgd, b og h: De eksisterer kun i Boks' konstruktør.

Vi kan afprøve Boks4 med:

public class BenytBoks4
{
  public static void main(String[] arg)
  {
    System.out.println("Antal bokse: "+ Boks4.læsAntalBokse());

    Boks4 boksen;
    boksen = new Boks4(2,5,10);

    System.out.println("Antal bokse: "+ Boks4.læsAntalBokse());

    Boks4 enAndenBoks, enTredjeBoks;
    enAndenBoks = new Boks4(5,5,10);
    enTredjeBoks = new Boks4(7,5,10);

    System.out.println("Antal bokse: "+ Boks4.læsAntalBokse());
  }
}

Antal bokse: 0
Antal bokse: 1
Antal bokse: 3

Det ses, at vi udefra kan kalde klassemetoder ved bare at angive klassenavnet og metodenavnet som i Boks4.læsAntalBokse(). Havde antalBokse været tilgængelig udefra (f.eks. erklæret public i stedet for private), kunne vi få fat i den udefra med: Boks4.antalBokse.

Vær opmærksom på, at det normalt frarådes at definere mange klassevariabler og -metoder i ens program, da det kan gøre programmet svært at gennemskue og øger de enkelte klassers afhængighed af hinanden (høj kobling). Endelig kan det friste folk til at springe "alt det besværlige med objekter" over og dermed ikke få lært eller udnyttet mulighederne i objektorienteret programmering.

7.1.1 Eksempler på klassevariabler

Du har, måske uden at vide det, allerede brugt en del klassevariabler og -metoder.

Der er mange klassevariabler i Javas standardbibliotek. Af de oftest brugte kan nævnes

Klassevariabler er nyttige til variabler, der skal være tilgængelige overalt i programmet. Det er det nærmeste, man kommer globale variabler, som det kendes fra andre programmeringssprog.

7.1.2 Eksempler på klassemetoder

Af nyttige klassemetoder i standardbiblioteket kan nævnes

Det vigtigste eksempel på en klassemetode er main()-metoden, som du selv erklærer, når du skriver et program, f.eks. BenytBoks.main(). Når et program startes, er det altid main(), der kaldes. På dette tidspunkt eksisterer der endnu ingen objekter og derfor skal main() være en klassemetode. Der skal jo aldrig oprettes nogen BenytBoks-objekter!

Klassemetoder er nyttige til "subrutiner", der skal regne et eller andet ud (ud fra parametrene) og returnere resultatet. Et eksempel er vist i afsnit Fejl: Henvisningskilde ikke fundet, Fejl: Henvisningskilde ikke fundet.

7.2 Lokale variabler og parametre

Når en metode kaldes, opretter systemet en "omgivelse" for det metodekald. I denne omgivelse oprettes parametervariablerne og de lokale variabler.

En lokal variabel er kendt fra dens erklæring og ned til slutningen af den blok, der omslutter den
Dette kaldes variablens virkefelt

Den lidt indviklede formulering skyldes, at man kan lave variabler, der er lokale for en hvilken som helst blok – ikke kun en metode-krop. Man kan altså skrive noget som:

  ...
  int a = 10;
  while (a > 0)
  {
    double b; // b erklæres lokalt i while-blokken
    b = Math.random();
    ...
    System.out.println(b);
    a--;
  }
  System.out.println(a);
  System.out.println(b); // fejl: b eksisterer ikke, da vi er uden for blokken.
...

Vi har desuden allerede set, at man i for-løkker kan erklære en variabel, der er lokal for løkkens krop:

  for (int i=0; i<10; i++) 
    System.out.print(i);

  System.out.print(i); // fejl: i eksisterer ikke uden for løkken.

7.2.1 Parametervariabler

Parametervariabler får tildelt en kopi af den værdi, de blev kaldt med og opfører sig i øvrigt fuldstændigt som lokale variabler. Man kan f.eks. godt tildele dem nye værdier:

  // metode, der udskriver et bestemt antal stjerner på skærmen.
  public void udskrivStjerner(int antal)
  {
    while (antal>0)
    {
      System.out.print(”*”);
      antal = antal-1; // Det kan man godt (men det er dårlig stil)
    }
    System.out.println();
  }

    ....
    int stj = 10;
    udskrivStjerner(stj); // kald af udskrivStjerner
    // stj er stadig 10.

Kalderen mærker intet til, at parametervariablen antal har fået en ny værdi, fordi kalderens værdi netop blev kopieret over i parametervariablen.

Her skal man være opmærksom på forskellen mellem variabler af simple typer og variabler af objekt-typer. Da det sidste er referencer (adresser på objekter), peger parametervariablen på samme objekt som kalderen, når den bliver kopieret. Ændrer man i objektet, slår ændringen også igennem hos kalderen.

Derfor kan flyt1() herunder godt ændre x og y i kalderens punkt-objekt:

import java.awt.Point;
public class Parametervariabler
{
  public static void flyt1(Point p, int dx, int dy)
  {
    p.x = p.x+dx;  // OK, vi ændrer på kalderens objekt
    p.y = p.y+dy;
  }

  public static void flyt2(Point p, int dx, int dy)
  {
    // hmm... vi smider kalderens objekt væk... men det opdager han ikke!
    p = new Point(p.x+dx, p.y+dy);
  }

  public static void main(String[] arg)
  {
    Point p1 = new Point(10,10);
    flyt1(p1,13,14);
    System.out.println("Nu er p1="+p1);

    Point p2 = new Point(10,10);
    flyt2(p2,13,14);
    System.out.println("Nu er p2="+p2);
  }
}

Nu er p1=java.awt.Point[x=23,y=24]
Nu er p2=java.awt.Point[x=10,y=10]

Vi kan ikke ændre på kalderens reference, som vi forsøger på i flyt2(): En lokal variabel oprettes, når man går ind i blokken, hvor den er defineret og nedlægges igen, når blokken forlades. Der bliver oprettet en ny variabel, hver gang programudførelsen går ind i blokken.

Når en metode kaldes, bliver der oprettet et nyt sæt lokale variabler (incl. parametervariabler) uafhængigt af, hvilke metoder, der i øvrigt kaldes eller er i gang med at blive kaldt

Hvis en metode bliver kaldt to gange, eksisterer der altså to versioner af den lokale variabel – én i hver deres omgivelse. Det behøver man som regel ikke at tænke på, men det er rart at have vished for, at en anden metode ikke bare kan ændre ens lokale variabler.

Rekursion er en teknik, der udnytter, at der bliver oprettet en ny omgivelse med nye lokale variabler, hver gang en metode kaldes. Nogle problemer kan løses meget elegant med rekursion. I Avanceret-afsnittet i slutningen af kapitlet vises nogle eksempler på rekursion.

7.3 Test dig selv

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.4 Resumé

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.4.1 Tilknytning

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.4.2 Adgang til variabler og metoder

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.4.3 Adgang fra metoder

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.5 Avanceret

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.5.1 Introduktion til rekursive algoritmer

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.5.2 Rekursion: Beregning af formel

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.5.3 Rekursion: Listning af filer

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.

7.5.4 Rekursion: Tegning af fraktaler

Dette afsnit er ikke omfattet af Åben Dokumentslicens.
Du skal købe bogen for at måtte læse dette afsnit.
Jeg erklærer, at jeg allerede har købt bogen
Jeg lover at anskaffe den i nær fremtid.
javabog.dk  |  << forrige  |  indhold  |  næste >>  |  programeksempler  |  om bogen
http://javabog.dk/ - Forord af Jacob Nordfalk.
Licens og kopiering under Åben Dokumentlicens (ÅDL) hvor intet andet er nævnt (79% af værket).

Ønsker du at se de sidste 21% af dette værk (267325 tegn) skal du købe bogen. Så får du pæne figurer og layout, stikordsregister og en trykt bog med i købet.