Programmeren in Java/Static

Nu dat je instanties van klassen hebt gemaakt, weet je dat iedere instantie verschillende waardes kunnen hebben voor hun velden en dat die waardes een invloed kunnen hebben op het gedrag van de methoden over de verschillende instanties heen. Neem nu volgend voorbeeld van een klasse Circle.

class Circle {
    public int radius;
    public double pi = 3.14;

    public Circle(int radius) {
        this.radius = radius;
    }

    public double getArea() {
        return pi * radius * radius;
    }
}


public class Main {

    public static void main(String[] args) {
        Circle circle1 = new Circle(2);
        Circle circle2 = new Circle(4);

        System.out.println("Oppervlakte van cirkel #1 is " + circle1.getArea());
        System.out.println("Oppervlakte van cirkel #2 is " + circle2.getArea());
    }
}

Dit toont het volgende op het scherm:

Oppervlakte van cirkel #1 is 12.56
Oppervlakte van cirkel #2 is 50.24

Om de oppervlakte te berekenen heb je pi nodig, we hebben in dit voorbeeld 3,14 gebruikt. Pi is echter een oneindig getal en als je een preciezer oppervlakte wilt berekenen moet je een langer getal gebruiken. Je kunt dan eventueel de waarde van pi veranderen in je klasse naar bijvoorbeeld 3,14159, maar wat als je het dynamisch wilt veranderen naar een ander getal wanner je programma draait? Dan moet je de waarde van pi veranderen in ieder object afzonderlijk hoewel pi voor ieder object hetzelfde zou moeten zijn. Zoals bijvoorbeeld als volgt:

public class Main {

    public static void main(String[] args) {
        Circle circle1 = new Circle(2);
        Circle circle2 = new Circle(4);

        System.out.println("Oppervlakte van cirkel #1 is " + circle1.getArea());
        System.out.println("Oppervlakte van cirkel #2 is " + circle2.getArea());

        circle1.pi = 3.14159;
        circle2.pi = 3.14159;

        System.out.println("Oppervlakte van cirkel #1 is " + circle1.getArea());
        System.out.println("Oppervlakte van cirkel #2 is " + circle2.getArea());
    }
}

Met als restultaat:

Oppervlakte van cirkel #1 is 12.56
Oppervlakte van cirkel #2 is 50.24
Oppervlakte van cirkel #1 is 12.56636
Oppervlakte van cirkel #2 is 50.26544

Dit is natuurlijk correct, maar als je programma duizenden van zulke Circle objecten moet aanpassen moet er véél dubbel werk worden gedaan. Want elk Circle object heeft deze aanpassingen nodig.

Statische veldenBewerken

Gelukkig kun je met statische velden dit vereenvoudigen. Een statisch veld is een veld die door alle instanties van een klasse worden gedeeld. Er wordt dus één waarde bijgehouden in dat veld. Om een veld statisch te maken moet je het sleutelwoord static gebruiken.

class Circle {
    public int radius;
    public static double pi = 3.14;

    public Circle(int radius) {
        this.radius = radius;
    }

    public double getArea() {
        return pi * radius * radius;
    }
}


public class Main {

    public static void main(String[] args) {
        Circle circle1 = new Circle(2);
        Circle circle2 = new Circle(4);

        System.out.println("Oppervlakte van cirkel #1 is " + circle1.getArea());
        System.out.println("Oppervlakte van cirkel #2 is " + circle2.getArea());

        Circle.pi = 3.14159;

        System.out.println("Oppervlakte van cirkel #1 is " + circle1.getArea());
        System.out.println("Oppervlakte van cirkel #2 is " + circle2.getArea());
    }
}

Dit zal hetzelfde resultaat geven als vorig voorbeeld. Je ziet hier ook dat het veld pi niet via een object wordt aangepast, maar door middel van de klasse en dat je dit slechts éénmalig hebt moeten doen om effect te hebben op alle objecten van die klasse.

Een statisch veld gebruiken heeft dus volgende voordelen:

  • Je hebt geen object van de klasse nodig, je kunt de aanpassing doen rechtstreeks op de klasse.
  • Doordat je géén object nodig hebt, is het toegankelijk overal in je code waar je de klasse kunt importeren.
  • Er wordt minder geheugen verbruikt, het statisch veld moet slecht één keer bewaard worden voor alle objecten.

Constante statische veldenBewerken

Nu dat je een statisch veld hebt kun je er ook een constante van maken met het sleutelwoord final. Met een constante wordt bedoeld dat je de waarde van het veld niet meer kunt veranderen.

class Circle {
    public int radius;
    public final static double PI = 3.14;

    public Circle(int radius) {
        this.radius = radius;
    }

    public double getArea() {
        return PI * radius * radius;
    }
}


public class Main {

    public static void main(String[] args) {
        System.out.println("Het getal pi" + Circle.PI);
    }
}

Je ziet dat de naam van de variabele pi aangepast is, dit komt omdat het nu een constante is en er is een andere conventie voor geven van een naam aan en constante. De naam moet bij een constante in hoofdletters worden geschreven met een underscore tussen woorden. Dus pi wordt PI en de naam voor een veld voor een voornaam zou FIRST_NAME zijn als het een constante is.

Statische methodenBewerken

Ook methodes kunnen statisch zijn, deze kunnen dan net zoals statische velden worden gebruikt zonder dat je een instantie van de klasse nodig hebt. We kunnen bijvoorbeeld ons Circle klasse aanpassen zodat we een getArea methode hebben om een oppervlakte te berekenen van een cirkel zonder een object.

class Circle {
    public int radius;
    public final static double PI = 3.14;

    public Circle(int radius) {
        this.radius = radius;
    }

    public double getArea() {
        return PI * radius * radius;
    }

    public static double getArea(int radius) {
        return PI * radius * radius;
    }
}


public class Main {

    public static void main(String[] args) {
        System.out.println("De oppervlakte van een cirkel met een straal van 4 is " + Circle.getArea(4));
    }
}

Met als resultaat:

De oppervlakte van een cirkel met een straal van 4 is 50.24

Wat je echter niet kunt doen binnen een statische methode is rechtstreeks de waarde van een veld aanspreken die niet statisch is. Onthoud dat niet statische velden, velden zijn van een object. Wat je wel kunt doen is een statische methode oproepen vanuit een niet statische methode. Je kunt bijvoorbeeld Circle dan ook als volgt aanpassen.

class Circle {
    public int radius;
    public final static double PI = 3.14;

    public Circle(int radius) {
        this.radius = radius;
    }

    public double getArea() {
        return getArea(this.radius);
    }

    public static double getArea(int radius) {
        return PI * radius * radius;
    }
}

Statische klassenBewerken

Er zijn ook zogenaamde statische klassen, deze bevatten enkel statische methodes en statische velden. Deze worden vaak utility classes of hulpklassen genoemd. Deze hulpkassen worden gebruikt om velden en methoden te bundelen die logisch gezien bij elkaar horen. Je zou bijvoorbeeld een hulpklasse kunnen maken om allerlei wiskundige bewerkingen in verband met cirkels kunnen bundelen in een zo'n hulpklasse.

Java bevat verscheidene van die ingebouwde hulpklassen en zijn terug te vinden in de package java.util. Waaronder de Arrays klasse, deze bevat allerlei methodes om bewerkingen uit te voeren op arrays. Deze kunnen ontwikkelaars gebruiken en moeten ze daardoor niet zelf deze functionaliteiten in hun code schrijven.

Statische initialisatie blokkenBewerken

Als laatste zijn er ook nog wat ze statische initialisatie blokken noemen. Dit zijn statische blokken die één keer worden uitgevoerd wanneer de statische klasse voor de eerste keer wordt gebruikt. Ze worden gebruikt om de klasse waar ze in staan te initialiseren of klaar te maken voor gebruik.

class myClass {
    static int counter;
    static {
        System.out.println("Initialisatie van de teller.");
        counter = 0;
    }

    // Mogelijke methodes.
}

public class Main {

    public static void main(String[] args) {
        System.out.println("Regel voor de initialisatie.");
        myClass.counter++;
        System.out.println("Regel na de initialisatie.");
        System.out.println("Waarde van de teller: " + myClass.counter);
    }
}

Met als resultaat:

Regel voor de initialisatie.
Initialisatie van de teller.
Regel na de initialisatie.
Waarde van de teller: 1

In dit voorbeeld wordt het statisch veld counter geïnitialiseerd en krijgt het de waarde nul. Dit gebeurt echter pas wanneer de klasse voor de eerste keer wordt gebruikt. Je ziet dat de eerste println van de main als eerste wordt uitgevoerd. Dit is een simpel voorbeeld en er is hier geen duidelijk voordeel met het gebruik van een statische initialisatie blokken. Het is echter handig voor wanneer je veel complexere gegevens moet initialiseren, bijvoorbeeld een array of collectie van objecten die je moet aanmaken.

Informatie afkomstig van http://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.