Frage

Mit einem Dritten API beobachtete ich die folgende.

Anstelle von

public static string getString(){
   return "Hello World";
}

verwendet es so etwas wie

public static void getString(String output){

}

und ich erhalte die "Ausgabe" string zugeordnet.

Ich bin neugierig über den Grund diese Funktionalität zu implementieren. Was sind die Vorteile einer solchen Ausgangsparameter mit?

War es hilfreich?

Lösung

Etwas ist nicht richtig in Ihrem Beispiel.

class Foo {

    public static void main(String[] args) {
        String x = "foo";
        getString(x);
        System.out.println(x);
    }

    public static void getString(String output){
        output = "Hello World"
    }
}

In dem obigen Programm der Zeichenfolge "foo" ausgegeben werden, nicht "Hallo Welt".

Einige Arten sind wandelbar, in dem Fall, dass Sie ein Objekt in eine Funktion übergeben ändern können. Für unveränderliche Typen (wie String), würden Sie irgendeine Art von Wrapper-Klasse bauen müssen, die Sie um stattdessen passieren können:

class Holder<T> {
    public Holder(T value) {
        this.value = value;
    }
    public T value;
}

Dann können Sie stattdessen den Halter passieren um:

public static void main(String[] args) {
    String x = "foo";
    Holder<String> h = new Holder(x);
    getString(h);
    System.out.println(h.value);
}

public static void getString(Holder<String> output){
    output.value = "Hello World"
}

Andere Tipps

Ich bin nicht einverstanden mit Jasper: „Meiner Meinung nach ist dies ein wirklich hässlich und schlecht ist mehr als ein Ergebnis zurückzukehren“. In .NET gibt es ein interessantes Konstrukt, das die Ausgabeparameter verwenden:

bool IDictionary.TryGet(key, out value);

Ich finde es sehr nützlich und elegant. Und es ist der bequemste Weg, um aks, wenn ein Artikel in Sammlung und schicken Sie sie zur gleichen Zeit. Mit ihm kann man schreiben:

object obj;
if (myList.TryGet(theKey, out obj))
{
  ... work with the obj;
}

ich meine Entwickler ständig schimpfen, wenn ich im alten Stil Code sehen wie:

if (myList.Contains(theKey))
{
  obj = myList.Get(theKey);
}

Sie sehen, es die Leistung halbiert. In Java gibt es keine Möglichkeit von Nicht-Existenz eines Artikel in einer Karte in einem Aufruf null Wert einen vorhandenen Artikel zu unterscheiden. Manchmal ist dies notwendig.

Dieses Beispiel ist falsch, Java nicht Ausgabeparameter hat.

Eine Sache, die Sie tun können, dieses Verhalten zu emulieren ist:

public void doSomething(String[] output) {
    output[0] = "Hello World!";
}

Aber IMHO saugt diese auf mehreren Ebenen. :)

Wenn Sie eine Methode wollen etwas zurückgeben, machen sie es zurück. Wenn Sie mehrere Objekte zurückgeben müssen, erstellen Sie eine Container-Klasse diese Objekte in und zurück, dass zu setzen.

Diese Funktionalität hat einen großen Nachteil - es funktioniert nicht. Funktionsparameter sind lokal zu funktionieren und sie die Zuordnung hat keine Auswirkungen außerhalb der Funktion.
Auf der anderen Seite

void getString(StringBuilder builder) {
    builder.delete(0, builder.length());
    builder.append("hello world");
}

funktionieren wird, aber ich sehe keine Vorteile, dies zu tun (außer, wenn Sie mehr als einen Wert zurückgeben müssen).

String unveränderlich sind, können Sie nicht von Java Pseudoausgangsparameter mit unveränderlichen Objekten verwenden können.

Auch der Umfang der Ausgang ist auf die getString Methode. Wenn Sie ändern die Ausgang Variable, der Anrufer wird eine Sache nicht sehen.

Was Sie tun können, ist jedoch die ändern Zustand des Parameters. Betrachten Sie das folgende Beispiel:

void handle(Request r) {
    doStuff(r.getContent());
    r.changeState("foobar");
    r.setHandled();
}

Wenn Sie einen Manager ruft mehrere Griffe mit einer einzigen Anfrage haben, können Sie den Zustand der Anfrage ändern Weiterverarbeitung zu ermöglichen (durch andere Handler) auf einem modifizierten Inhalt. Der Manager könnte auch entscheiden Verarbeitung zu beenden.

Vorteile:

  • Sie brauchen kein spezielles Objekt mit dem neuen Inhalt und ob die Verarbeitung stoppen sollte zurückzukehren. Das Objekt nur einmal werden würde und die Erstellung der Objektabfall Speicher und Rechenleistung verwendet.
  • Sie müssen nicht ein anderes Request-Objekt erstellen und die Garbage Collector lassen die jetzt obsolet Referenz loszuwerden.
  • In einigen Fällen Sie nicht ein neues Objekt erstellen. Zum Beispiel, weil das Objekt erstellt wurde, eine Fabrik mit, und Sie haben keinen Zugriff darauf, oder weil das Objekt Zuhörer hatte, und Sie wissen nicht, wie die Objekte zu erzählen, die zu dem alten Antrag zuhörten, sie sollten statt hören Sie die neue Anfrage.

Eigentlich ist es unmöglich, Parameter in Java zu haben, aber Sie können eine Arbeit machen um wodurch das Verfahren nimmt auf einer de-Referenz für den unveränderlichen String und Primitiven entweder durch eine generische Klasse zu schreiben, wo die unveränderlichen der Gattungs mit der ist Wert und Setter und Getter oder durch eine Anordnung unter Verwendung von in dem Element 0 (1 in der Länge) der Wert ist, vorausgesetzt, es ist zuerst ist instanziieren, weil es Situationen gibt, in denen man mehr als ein Wert zurückgeben müssen, wo nur eine Klasse schreiben sie zurückzukehren, in dem die Klasse wird nur verwendet, da nur eine Verschwendung von Text und nicht wirklich wiederverwendbar ist.

Nun wird ein C / C ++ und auch .Net (mono oder MS), es drängt mich, dass Java nicht mindestens eine de-Referenz für die Primitiven nicht unterstützt; so, ich greifen stattdessen auf das Array.

Hier ist ein Beispiel. Lassen Sie uns sagen, dass Sie eine Funktion (Methode) zu erstellen, um zu überprüfen, ob der Index in dem Array gültig ist, aber Sie wollen auch die remainding Länge zurückzukehren, nachdem der Index überprüft wird. Sagen wir es in c nennen als 'Bool VALIDATE_INDEX (int index, int arr_len, int & rem)'. Ein Weg, dies in Java zu tun wäre 'Boolean VALIDATE_INDEX (int index, int arr_len, int [] rem1)' sein. REM1 bedeutet nur das Array 1 Element halten.

public static Boolean validate_index(int index, int arr_len, int[] rem1)
{
    if (index < 0 || arr_len <= 0) return false;

    Boolean retVal = (index >= 0 && index < arr_len);

    if (retVal && rem1 != null) rem1[0] = (arr_len - (index + 1));

    return retVal;

}

Nun, wenn wir diese verwenden können wir beide bekommen die Boolesche Rückkehr und den Rest.

 public static void main(String[] args)
 {
    int[] ints = int[]{1, 2, 3, 4, 5, 6};
    int[] aRem = int[]{-1};
    //because we can only scapegoat the de-ref we need to instantiate it first.
    Boolean result = validate_index(3, ints.length, aRem);

    System.out.println("Validation = " + result.toString());
    System.out.println("Remainding elements equals " + aRem[0].toString());

 }

setzt: Validation = True setzt: Elemente gleich 2

Remainding

Array-Elemente immer entweder auf das Objekt auf dem Stack oder die Adresse des Objekts auf dem Heap. So absolut möglich ist, es als de-Referenzen unter Verwendung auch für Arrays durch eine doppelte Anordnung macht es als myArrayPointer = new Klasse instanziieren [1] [] übergeben Sie dann in denn manchmal wissen Sie nicht, was die Länge des Arrays bis der Anruf wie durch einen Algorithmus geht 'Boolean tryToGetArray (Someobject o, T [] [] ppArray)', die die gleichen wie in c / c ++ als 'template bool tryToGetArray (Someobject * p, T ** ppArray)' wäre oder C # 'bool tryToGetArray (Someobject O, ref T [] array)'. Es funktioniert und es funktioniert gut, solange die [] [] oder [] wird im Speicher instanziiert zunächst mit mindestens einem Element.

Manchmal kann dieser Mechanismus Schaffung eines neuen Objekts vermeiden.

Beispiel: Wenn ein geeignetes Objekt ohnehin vorhanden ist, ist es schneller an die Methode zu übergeben und erhalten einig Feld geändert.

Das ist effizienter als ein neues Objekt in der aufgerufenen Methode zu schaffen, und die Rückkehr und seine Referenz (Herstellung von Müll, der irgendwann gesammelt werden muss) zugeordnet wird.

meiner Meinung nach, ist dies nützlich, wenn Sie mehr als ein Ergebnis haben in einer Funktion.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top