Heim  >  Artikel  >  Java  >  Java-Generika: Generische Klassen, generische Schnittstellen und generische Methoden

Java-Generika: Generische Klassen, generische Schnittstellen und generische Methoden

高洛峰
高洛峰Original
2016-12-19 15:03:191313Durchsuche

Generische Klasse

Containerklasse sollte als eine der am häufigsten wiederverwendbaren Klassenbibliotheken angesehen werden. Schauen wir uns zunächst an, wie man eine Containerklasse ohne Generika definiert:

public class Container {
    private String key;
    private String value;

    public Container(String k, String v) {
        key = k;
        value = v;
    }
    
    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

Die Containerklasse speichert ein Schlüssel-Wert-Paar, aber der Typ ist fest, das heißt, wenn ich möchte Um ein Schlüssel-Wert-Paar vom Typ String-Integer zu erstellen, ist dies mit diesem Container derzeit nicht möglich und muss angepasst werden. Dann hat dies offensichtlich eine sehr geringe Wiederverwendbarkeit.

Natürlich kann ich Object anstelle von String verwenden, und vor Java SE5 war dies nur möglich. Da Object die Basisklasse aller Typen ist, kann es direkt konvertiert werden. Diese Flexibilität reicht jedoch immer noch nicht aus, da der Typ immer noch angegeben ist, aber diesmal befindet sich der angegebene Typ auf einer höheren Ebene. Ist es möglich, den Typ nicht anzugeben? Ist es möglich, zur Laufzeit zu wissen, um welchen spezifischen Typ es sich handelt?

Also erschienen Generika.

public class Container<K, V> {
    private K key;
    private V value;

    public Container(K k, V v) {
        key = k;
        value = v;
    }

    public K getKey() {
        return key;
    }

    public void setKey(K key) {
        this.key = key;
    }

    public V getValue() {
        return value;
    }

    public void setValue(V value) {
        this.value = value;
    }
}

Zur Kompilierungszeit ist es unmöglich, die spezifischen Typen von K und V zu kennen. Erst zur Laufzeit wird der Speicher tatsächlich basierend auf dem Typ erstellt und zugewiesen. Sie können einen Blick auf die aktuelle Unterstützung verschiedener Typen durch die Container-Klasse werfen:

public class Main {

    public static void main(String[] args) {
        Container<String, String> c1 = new Container<String, String>("name", "findingsea");
        Container<String, Integer> c2 = new Container<String, Integer>("age", 24);
        Container<Double, Double> c3 = new Container<Double, Double>(1.1, 2.2);
        System.out.println(c1.getKey() + " : " + c1.getValue());
        System.out.println(c2.getKey() + " : " + c2.getValue());
        System.out.println(c3.getKey() + " : " + c3.getValue());
    }
}

Ausgabe:

name : findingsea
age : 24
1.1 : 2.2

Generische Schnittstelle

In der generischen Schnittstelle der Generator Schauen Sie sich für ein gutes Verständnis die folgende Definition der Generatorschnittstelle an:

public interface Generator<T> {
    public T next();
}

Definieren Sie dann eine Generatorklasse, um diese Schnittstelle zu implementieren:

public class FruitGenerator implements Generator<String> {

    private String[] fruits = new String[]{"Apple", "Banana", "Pear"};

    @Override
    public String next() {
        Random rand = new Random();
        return fruits[rand.nextInt(3)];
    }
}

Aufruf:

public class Main {

    public static void main(String[] args) {
        FruitGenerator generator = new FruitGenerator();
        System.out.println(generator.next());
        System.out.println(generator.next());
        System.out.println(generator.next());
        System.out.println(generator.next());
    }
}

Ausgabe:

Banana
Banana
Pear
Banana

Generische Methoden

Ein Grundprinzip ist: Wann immer Sie können, sollten Sie versuchen, generische Methoden zu verwenden. Das heißt, wenn die Verwendung generischer Methoden die Generalisierung der gesamten Klasse ersetzen kann, sollte die Verwendung generischer Methoden eingeschränkt werden. Schauen wir uns die Definition einer einfachen generischen Methode an:

public class Main {

    public static <T> void out(T t) {
        System.out.println(t);
    }

    public static void main(String[] args) {
        out("findingsea");
        out(123);
        out(11.11);
        out(true);
    }
}

Sie können sehen, dass die Parameter der Methode vollständig verallgemeinert sind. Dieser Prozess umfasst die Typableitung und automatische Verpackung des Compilers, was bedeutet, dass er ursprünglich benötigt wurde Der Compiler übernimmt nun die Beurteilung und Verarbeitung der Typen für uns. Auf diese Weise müssen Sie beim Definieren einer Methode nicht berücksichtigen, welche Parametertypen in Zukunft verarbeitet werden müssen, was die Flexibilität der Programmierung erheblich erhöht.

Sehen Sie sich ein weiteres Beispiel für generische Methoden und variable Parameter an:

public class Main {

    public static <T> void out(T... args) {
        for (T t : args) {
            System.out.println(t);
        }
    }

    public static void main(String[] args) {
        out("findingsea", 123, 11.11, true);
    }
}

Die Ausgabe ist die gleiche wie im vorherigen Code. Sie können sehen, dass Generika perfekt mit variablen Parametern kombiniert werden können.



Weitere Artikel zu Java-Generika: generische Klassen, generische Schnittstellen und generische Methoden finden Sie auf der chinesischen PHP-Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn