Java Generics Void / Void-Typen

78

Ich implementiere a ResponseHandler für das Apache HttpClient-Paket wie folgt:

new ResponseHandler<int>() {
    public int handleResponse(...) {
        // ... code ...
        return 0;
    }
}

aber ich möchte, dass die handleResponseFunktion nichts zurückgibt, dh void. Ist das möglich? Folgendes wird seitdem nicht kompiliertvoid es sich nicht um einen gültigen Java-Typ handelt:

new ResponseHandler<void>() {
        public void handleResponse(...) {
            // ... code ...
        }
}

Ich nehme an, ich ersetzen könnte voidmit Voidzurück ein VoidObjekt, aber das ist nicht wirklich das, was ich will. Frage : Ist es möglich , diesen Rückruf Situation derart zu organisieren , dass ich zurückkehren kann voidaus handleResponse?

Travis Webb
quelle

Antworten:

64

Generics behandelt nur Objektklassen. Leere und primitive Typen werden von Generics nicht unterstützt und können nicht als parametrisierter Typ verwendet werden. Sie müssen stattdessen Void verwenden.

Können Sie sagen, warum Sie nicht verwenden möchten Void?

Peter Lawrey
quelle
8
Ich würde es einfach vorziehen, keine returnAnweisung in eine Funktion aufnehmen zu müssen, in der ich nichts zurückgebe, hauptsächlich aus Gründen der Sauberkeit.
Travis Webb
8
Sie könnten einen abstrakten Wrapper erstellen, der Ihre voidMethode aufruft und zurückkehrt null, um diese Hässlichkeit zu verbergen.
Peter Lawrey
47
+1, um mich daran zu erinnern, dass "jedes Problem in der Informatik durch Hinzufügen einer Indirektionsebene gelöst werden kann"
Travis Webb
@TravisWebb Wenn Sie sich Ihre spezifischen Bedürfnisse ansehen, verwenden Sie überhaupt keine Generika und geben Sie den ObjectTyp zurück, wenn es funktioniert
Chaitanya,
87

Der VoidTyp wurde genau für diese Situation erstellt: um eine Methode mit einem generischen Rückgabetyp zu erstellen, bei dem ein Subtyp "void" sein kann. Voidwurde so konzipiert, dass möglicherweise keine Objekte dieses Typs erstellt werden können. Daher wird eine Methode vom Typ Voidimmer zurückkehren null(oder abnormal abgeschlossen werden), was so nahe an nichts liegt, wie Sie es bekommen werden. Du musst setzenreturn null die Methode eingeben, dies sollte jedoch nur eine geringfügige Unannehmlichkeit sein.

Kurzum: Verwenden Sie Void.

ILMTitan
quelle
Arrgh - der Schmerz der Generika ist das Problem, wenn wir beispielsweise einen Rückgabetyp von "Void" definieren, müssen Sie einen "return (null)" eingeben. Der Hauptgrund für die Deklaration des Rückgabetyps void ist, dass Sie keine return-Anweisung benötigen und eine vorhandene "void" -Methode verwenden können :) Ein Teil des Problems mit Java Generics ist die Verschmelzung der Laufzeit-Typprüfung mit der Notwendigkeit der Generierung des Kompilierungszeitcodes und der Unterstützung beim "Bookeeping". Man braucht "Makros" und "Vorlagen", die das Schreiben von Code auf der Sprachseite erleichtern.
Peterk
6
+1 Zur Verdeutlichung gibt es Void seit JDK1.1. Es wurde ursprünglich für die Verwendung mit Reflection erstellt, spielt jedoch bei Generika eine ähnliche Rolle.
John McCarthy
@ILMTitan Könnten Sie bitte Verweise auf die Dokumentation zur Anweisung "return null" in Methoden angeben, die für die Rückgabe von Void definiert wurden?
Andriy Simonov
@ andriy-simonov Methoden mit einem Rückgabetyp von voidmüssen keinen Wert zurückgeben. Methoden mit einem Rückgabetyp Objectoder einer beliebigen Unterklasse, z. B. Voidmüssen einen Wert zurückgeben (oder sind normalerweise nicht vollständig). Der einzige Wert, der Voideiner VoidMethode zugewiesen und von dieser zurückgegeben werden kann, ist null.
ILMTitan
8

Wenn Sie zurückkehren müssen, kehren Sie java.lang.Voideinfach zurück null.

Ken Chu
quelle
1

Leider ist es nicht möglich. Sie können den Code so einstellen, dass er Voidwie gesagt zurückgibt, Sie können jedoch niemals a instanziierenVoid sodass Sie keine Funktion schreiben können, die dieser Spezifikation entspricht.

Stellen Sie sich das so vor: Die generische Funktion sagt "Diese Funktion gibt etwas vom Typ X zurück", und Sie können X angeben, aber Sie können den Satz nicht in "Diese Funktion gibt nichts zurück" ändern. (Ich bin nicht sicher, ob ich mit dieser Semantik einverstanden bin, aber so sind sie.)

In diesem Fall mache ich immer nur die Funktion return type Objectund tatsächlich immer return null.

Adrian Smith
quelle
1
Da der Compiler bei einem Rückgabetyp von Object nicht garantieren kann, dass nur null zurückgegeben wird. Versuchen Sie static Void v() { return null; } static Void n() { return "NotAllowed"; } static Object o() { return "Allowed"; }
Nathan Niesen
1

Sie können keine Primitiven in Generika haben, also intist das eigentlich eine Integer. Das Objekt Voidist analog zum Schlüsselwort voidfür Generika.

mark-cs
quelle
4
voidist kein Grundelement, sondern lediglich ein Java-Schlüsselwort. Es hat keinen "Typ"
Travis Webb
und es ist sicher nicht auch! void(Kleinbuchstaben) - Schlüsselwort, nichts zurückgegeben; Void(Großbuchstaben) - eine (nicht instabilisierbare) Klasse , wobei eine Instanz dieser Klasse zurückgegeben wird (kann nur nullseitdem nicht instabilisierbar sein)
user85421
@ Carlos Heuberger analog noch besser für dich?
Mark-Cs
0

Diese Implementierung von java.lang.Void in Java spricht für sich. Außerdem habe ich einen Artikel geschrieben, der dies mit Generika verbindet. Es dauerte ein bisschen, bis ich anfing, dies zu verstehen: http://www.siteconsortium.com/h/D00006.php . Beachten Sie TYPE = Class.getPrimitiveClass ("void");

Paket java.lang;

public final class Void {

    public static final Class<Void> TYPE = Class.getPrimitiveClass("void");

    private Void() {}
}
Jon
quelle