Programmeren in Java/Generics

Uit Wikibooks
Naar navigatie springen Naar zoeken springen

Generics of genericiteit is een techniek om in een programmeertaal "generiek" te programmeren. Deze zin zegt eigenlijk niet veel over wat generics is. Het is makkelijker om het uit te leggen met een voorbeeld. Stel je wilt een klasse aanmaken die een array met instanties van een bepaald object bevat. Tijdens het ontwikkelen weet je echter nog niet wat voor een object dit gaat zijn, maar je weet wel alvast dat het een object is en geen primitieve datatype. Je kunt dan het volgende doen.

public class ArrayOfObject {
    private Object[] arrayOfObject;

    public ArrayOfObject(Object[] arrayOfObject){
        this.arrayOfObject  = arrayOfObject;
    }

    public Object[] getArrayOfObject() {
        return arrayOfObject;
    }
    
    public Object get(int index){
        return arrayOfObject[index];
    }
    
    // Andere methodes
}

Je hebt dus een klasse gemaakt met een array van Objecten. Na verloop van tijd weet je welke klasse je wilt gebruiken met deze ArrayOfObject, namelijk Person. Dus pas je je klasse aan naar het volgende:

public class ArrayOfPerson {
    private Person[] arrayOfPerson;

    public ArrayOfPerson(Person[] arrayOfPerson){
        this.arrayOfPerson  = arrayOfPerson;
    }

    public Person[] getArrayOfObject() {
        return arrayOfPerson;
    }

    public Person get(int index){
        return arrayOfPerson[index];
    }
    
    // Andere methodes
}

Alle verwijzingen naar Object zijn nu veranderd naar Person en het werkt. Maar nu wil je het ook gebruiken voor andere soorten klasses, bijvoorbeeld Animal, Car, maar ook meer abstrakte zaken zoals File. Je kunt dan twee dingen doen. Je kunt terug gaan naar Object aangezien je met Object alle soorten klasses kunt gebruiken. Of je maakt deze ArrayOf-klasse voor elk type klasse.

Waarom je Object niet zou gebruiken:

  • Als je een Person instantie in een Object steekt, moet je het terug casten naar een Person klasse wanneer je het eruit haalt.
  • Omdat het Object is kunnen er ook instanties van verschillende klasses worden bewaard, waardoor er misschien problemen komen.

Waar je geen ArrayOf-klasse zou schrijven voor iedere klasse:

  • Je schrijft dan eigenlijk dubbele code voor ieder type klasse
  • Als er een fout is in de code moet je dit doen voor alle versies van het "ArrayOf" klasse.

Dit is waar generics van pas kunnen komen. Het is een vorm van abstractie waarbij je éénmaal een klasse kunt schrijven die gebruikt maakt van één of meerdere generics die instaan voor een type klasse. De bedoeling is dat deze klasse, de generische klasse genoemd, dan werkt ongeacht welke klasse uiteindelijk in de plaats van een generic zouden komen.

Basis[bewerken]

Om een generische klasse aan te maken moet er worden gebruik gemaakt van een Type Parameter, die instaat voor de klasse die we later gaan gebruiken. Een Type Parameter vermelden we achter de naam van de klasse tussen punthaakjes(<>).

public class ArrayOf<T> {
    
}

Hier gebruiken we dus T als Type Parameter. Nu kunnen we verderbouwen en de klasse uitbreiden. Je kunt nu namelijk de Type Parameter gebruiken voor het volgende:

  • Voor het datatype te bepalen van een property(eigenschap) van een klasse.
  • Als datatype voor een argument bij zowel een constructor van de klasse als bij een gewone methode.
  • Het datatype van de return van een methode.

Als datatype kun je het dus bijvoorbeeld als volgt gebruiken:

private T t1; // Een property met als datatype T
private T[] ts; // Een array van T objecten

Dit kunnen we toepassen in de ArrayOf-klasse.

public class ArrayOf<T> {
    private T[] ts;

}

Je kunt dus ook de Type Parameter gebruiken als datatype(naast andere datatypes) voor parameters bij constructors en methodes.

public constructor(T t){
    //code
}
public constructor(T[] t, int nietGerelateerdeInt){
    //code
}

public methodeA(T t){
    //code
}

public methodeB(T[] t){
    //code
}

In de ArrayOf klasse wordt het dan ongeveer zo.

public class ArrayOf<T> {
    private T[] ts;

    public ArrayOf(T[] ts){
        this.ts  = ts;
    }
}

Als laatste nog de Type parameter voor de return type, die je onder ander zo kunt gebruiken.

public T getT(int index) {
    //code
}

public T[] getTs() {
    //code
}

Wat uiteindelijk voor de ArrayOf-klasse het volgende geeft.

public class ArrayOf<T> {
    private T[] ts;

    public ArrayOf(T[] ts){
        this.ts  = ts;
    }

    public T[] getArrayOf() {
        return ts;
    }
    
    public T get(int index){
        return ts[index];
    }

    // Andere methodes
}

Een generische klasse gebruiken[bewerken]

Een generische klasse aanmaken doe je net zoals een gewone klasse met het sleutelwoord new. Je moet dan ook een klasse meegeven als type parameter. Bijvoorbeeld als volgt:

public class Main {

    public static void main(String[] args) {
        ArrayOf<Person> persons = new ArrayOf<Person>(new Person[10]);
    }

    public static class ArrayOf<T> {
        private T[] ts;

        public ArrayOf(T[] ts) {
            this.ts = ts;
        }

        public T[] getArrayOf() {
            return ts;
        }

        public T get(int index) {
            return ts[index];
        }

        // Andere methodes
    }

    public class Person {
        // Lege klasse bedoeld als voorbeeld.
    }
}

Je kunt vervolgens andere klasses in de plaats van Person gebruiken.

ArrayOf<String> strings = new ArrayOf<String>(new String[10]);
ArrayOf<Integer> integers = new ArrayOf<Integer>(new Integer[10]);
ArrayOf<ElkeAndereKlasseZolangHetBestaat> elkeAndereKlasseZolangHetBestaats = new ArrayOf<ElkeAndereKlasseZolangHetBestaat>(new ElkeAndereKlasseZolangHetBestaat[10]);

Meerdere Type Parameters[bewerken]

Naamgeving voor Type Parameters[bewerken]

Je kunt in principe elke letter gebruiken als type parameter, maar er is wel een conventie die sterk wordt aangeraden om te gebruiken.

  • T – Type (Het eerste type parameter dat je gebruikt)
  • S, U, V, etc. – (Een tweede, derde, vierde, etc. type parameter)
  • E – Element (wordt gebruikt bij Collections)
  • K – Key (Sleutel, wordt gebruikt bij Dictionaries)
  • V – Value (Waarde, wordt net zoals by Key gebruikt bij Dictionaries)
  • N – Number (een nummer)
Informatie afkomstig van http://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.