Generikus típusok Javában

Kategória: Standard Java.

A Java-ban a generikus típusok az 5-ös verzióban jelentek meg. Ez lehetővé teszi azt, hogy olyan osztályokat és függvényeket készítsünk, amelyeknél nem adjuk meg a típust, így többféle típussal létrehozhatjuk ill. lefuttathatjuk. A generikus típust csúcsos zárójelek (< és >) közé kell tennünk, pl. így: <T>. Lássunk egy példát!

// GenericsExample.java
public class GenericsExample<T> {
    T object;
 
    public GenericsExample(T object) {
        this.object = object;
    }
 
    public void fancyPrint() {
        System.out.println("> " + object + " <");
    }
}
 
// Main.java
public class Main {
    public static <E extends Comparable<E>> E getMaxElement(E[] inputArray) {
        if (inputArray.length == 0) {
            return null;
        }
        E max = inputArray[0];
        for (E element : inputArray) {
            if (element.compareTo(max) > 0) {
                max = element;
            }
        }
        return max;
    }
 
    public static void main(String[] args) {
        GenericsExample<Integer> geInt = new GenericsExample<Integer>(15);
        geInt.fancyPrint();
 
        GenericsExample<String> geString = new GenericsExample<String>("apple");
        geString.fancyPrint();
 
        Integer[] intArray = {4, 8, 2};
        Double[] doubleArray = {4.89, -5.2, 1.0};
        Character[] charArray = {'a', 'p', 'p', 'l', 'e'};
        System.out.println(getMaxElement(intArray));
        System.out.println(getMaxElement(doubleArray));
        System.out.println(getMaxElement(charArray));
    }
}

A példában a Comparable egy olyan interfész, amely maga is generikus, és egy metódust definiál: int compareTo(o); ha az adott objektum a nagyobb, akkor a visszatérési érték pozitív, ha a másik (azaz a paraméterül átadott o), akkor negatív, és ha egyenlőek, akkor 0.

Az egész értelme leginkább a Collections esetén van, amit lejjebb látunk majd részletesebben.

A GenericsExample osztály egy osztály szintű generikus típust tartalmaz, amit T-vel jelölünk. Az osztályban létrehozott fancyPrint() metódus csúcsos zárójelek közé helyezve kiírja a generikus típusú attribútumot. Ezt a főprogramból kétféleképpen hívjuk meg: először egész számmal (Integer), másodszor szöveges típussal (String).

A második példa a főosztályba került. Ez egy generikus függvény, a generikus típus tehát itt függvény szinten van megadva, nem osztály szinten. A típusnév (E) után találunk egy extends kulcsszót; ezzel azt jelöljük, hogy a konkrét típus nem lehet akármilyen, hanem csak olyan, amely megvalósítja a Comparable interfészt. A függvény maga, kihasználva azt, hogy meghívhatja a compareTo() függvényt, meghatározza a maximális elemet.

Összefoglalva és kiegészítve:

  • A generikus típust csúcsos zárójelbe tesszük, így: <T>
  • A típust általában egy nagybetűs karakterrel adjuk meg. Néhány konvenció:
    • T: általános típus. Ha szükség van továbbiakra: S, U, V stb.
    • K és V: kulcs (key) és érték (value).
    • E: elem (element) különböző adatszerkezetek esetén.
    • N: szám (number).
  • Léteznek generikus osztályok és generikus függvények; a generikus típus jelölést mindkét esetben a név elé kell tenni.
  • Az extends kulcsszóval adhatjuk meg az, hogy a generikus típus csak egy adott interfész megvalósítása vagy adott osztály leszármazottja lehet, pl. <N extends Number>.
  • A generikus típusra az öröklődés nem vonatkozik, pl. az Integer a Number osztályból öröklődik, de a GenericsExample<Number> nem őse a GenericsExample<Integer>-nek, azaz az előbbinek nem adhatjuk utóbbit értékül. (Emlékeztetőül: egy Number típusnak értékül adhatunk Integer-t).
  • Egyszerre megadhatunk több megszorítást is & jellel elválasztva (melyek közül értelemszerűen legfeljebb egy lehet osztály), pl. <T extends Comparable & Serializable>.
  • Paraméterek, mezők, lokális változók és visszatérési értékek esetén használhatjuk a dzsóker paramétert, ami a kérdőjel (<?>). Ennek adhatunk alsó korlátot (pl. ? extends Number) vagy felső korlátot (pl. ? super Integer).
Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License