Frage

Java ist ein ‚Pass von Wert‘ Sprache, was bedeutet, dass in einem Verfahren in einer Variablen zu senden, zeigt die Variable auf ein neues Objekt, hat keinen Einfluss auf die äußere Variable.

public void one() {

String s = "one";
two(s);
System.out.println(s);

}

public void two( String s ) {
s = "two";
}

schreiben würde "Eins".

Gibt es eine Möglichkeit, dies zu verhindern? Oder was ist die häufigste Lösung oder Muster tatsächlich ändern s auf „zwei“ in der Methode?

War es hilfreich?

Lösung

Sie können nicht pass-by-reference - zumindest nicht die Variable selbst. Alle Parameter werden von Wert übergeben. Allerdings Objekte enthalten Referenzen - und werden als Referenzen selbst vertreten. Sie können jederzeit das Innere des Objekts ändern, und die Änderungen Stick haben. So ein Array schicken, oder eine Wrapper-Klasse erstellen oder eigene Referenzobjekt machen:

class Ref<T> {
  T obj;
  public Ref(T value) {
    this.obj = value;
  }
  public void set(T value) {
    obj = value;
  }
  public T get() {
    return obj;
  }
}

Wie die anderen gesagt haben, ist String nicht wandelbar sowieso, also bist du nicht wirklich die Zeichenfolge hier ändern sich, aber die Herstellung der variablen Punkt in die andere Richtung, so dass es nicht wirklich so viel Sinn machen, nicht einfach die neue Rück String.

Andere Tipps

Ist das nicht möglich, es zu verhindern.

Sie können es emulieren mit einem generischen Wrapper wie folgt aus:

class _<T>{
    public T _;
    public _(T t ) {
        _ = t;
    }
    public String toString(){ return _.toString(); }
}

Und dann verwenden Sie es, wie Sie beabsichtigten.

class GeneriWrapperDemo {
    public static void main(String [] args ) {
        _<String> one = new _<String>("One");
        two( one );
        System.out.println( one );
    }
    public static void two( _<String> s ) {
        s._ = "two";
    }
}

Aber sieht hässlich aus. Ich denke, das Beste wäre, den Verweis ändern es sich von selbst:

public String two( String a ) {
     return "two";
}

Und es verwendet,

 String one = "one";
 one = two( one );

:)

Wenn s ein veränderbares Objekt waren, könnte man seinen Wert ändern (das heißt der Wert seiner Datenelemente). Und kann das Element auch eine String sein. Das funktioniert nicht mit einem String Parameter direkt, wie es unveränderlich ist, so dass der einzige Weg, um „Veränderung“ sie den Verweis auf ein anderes Objekt zu richten ist.

Erstellen Sie ein Objekt, das die Zeichenfolge enthält, dann passieren, dass in dem Verfahren.

public class StringHolder {
    public String s;

    public StringHolder(String s) {
        this.s = s;
    }
}

Dann würde der Code wie folgt aussehen:

public void two(StringHolder sh) {
    sh.s = "two";
}

StringHolder sh = new StringHolder("one");
two(sh);
System.out.println(sh.s);

Obwohl für das obige Beispiel, könnten Sie nur zurück den gewünschten Wert:

public String two(String s) {
    return "two";
}

String s = "one";
s = two(s);
System.out.println(s);

Für Strings, können Sie immer verwenden StringBuffer, die wandelbar ist:

public void two(StringBuffer buf) {
    buf.setLength(0);
    buf.append("two");
}

Sie können nicht verhindern Java von wert vorbei; Das ist die Sprache Semantik.

Sie können, eine oder andere Weise, herumkommen es, je nachdem, was Sie tun möchten.

Sie können einen neuen Wert basierend auf dem Parameter return, die vergangen ist:

static String scramble(String s) {
    return s.replaceAll("(.*) (.*)", "$2, $1");
}

// then later...
String s = "james bond";
s = scramble(s);
System.out.println(s); // prints "bond, james"

Sie können auch etwas übergeben, die wandelbar ist:

static void scramble(StringBuilder sb) {
    int p = sb.indexOf(" ");
    sb.append(", ").append(sb.substring(0, p)).delete(0, p+1);
}

// then later...
StringBuilder sb = new StringBuilder("james bond");
scramble(sb);
System.out.println(sb); // prints "bond, james"

Strings sind unveränderlich ... anders, aber alles, was Sie zu tun haben würde, ist eine Methode aufrufen, auf das gleiche Objekt zu betreiben und haben das irgendwie den String-Wert ändern.

Ich bin sicher, dass es eine Reihe von Java-Klassen, die die Arbeit für Sie tun, aber man könnte auch Ihre eigene Rolle einfach durch eine einkapselnde Klasse mit dem Erstellen von entweder einem öffentlichen Bereich oder einem Setter / Getter. Ein Beispiel für ersteres ist so etwas wie folgt aus:

public class EncapsulatedString
{
    public String str;

    public EncapsulatedString(String s)
    {
        str = s;
    }
}

Erstellen Sie einen Wrapper, der das Objekt und ändert Inhalt der Verpackung enthält:

public class StringWrapper {
    private String str;    
    public String getString() {
       return str;
    }
    public String setString(String str){
        this.str = str;
    }
    public String toString() {
        return str;
    }
}

public void one() {
    StringWrapper s = new StringWrapper();
    s.setString("one");
    two(w);
    // This will print "two"
    System.out.println(s);
}
public void two( StringWrapper  s ) {
    s.setString("two");
}

Eine hässliche Lösung, die mir in den Sinn kommt, ist ein String-Array der Länge passieren um 1. Es ist nicht etwas, was ich ermutigen würde, aber wenn Sie das Gefühl, dass Sie es tun wollen ...

  1  public class One {
  2 
  3     public static void main( String[] _ ) {
  4         String[] s = {"one"};
  5         two(s);
  6         System.out.println(s[0]);
  7     }
  8 
  9     public static void two( String[] s ) {
 10         s[0] = "two";
 11     }
 12 }

1-Array mit der Länge ist ein bisschen hässlich, aber perfekt funktionierende Lösung. Keine Notwendigkeit Überschuss Wrapper-Klassen zu erstellen:

public void one() {
    String[] s = new String[]{"one"};
    two(s);
    System.out.println(s[0]);
}

public void two(String[] s) {
    s[0] = "two";
}

Dieses Muster ist besonders nützlich, wenn alten übersetzen (zum Beispiel C) Code, in dem Durchgang durch das Bezug extensiv angewandt wurde.

Das heißt, ein neuer, frischer Wert zurückgegeben wird immer weniger verwirrend als die „Eingabe“ Wert mutiert.

Verwenden String oder Stringbuilder, die wandelbar sind.

Java ist nicht eine Pass-by-Wert Sprache. Im Gegenteil - es ist eine Pass-by-reference Sprache. (Vorbei an-by-reference bedeutet nicht, dass Sie das Original „Zeiger“ ändern kann an anderer Stelle wie C ++ Punkt erlaubt). Die einzigen Dinge, die von Wert übergeben werden, sind Primitiven (int, long, char etc.)
Objektreferenzen werden immer als Referenz übergeben - also, wenn Ihr Objekt, um seinen Inhalt zu Unterstützung Änderung der Lage ist, (beispielsweise über Getter und Setter-Methoden) - es verändert werden kann.

String spezifisch ist unveränderlich - was bedeutet, dass ihr Inhalt darf nie geändert werden. Also für Ihre Frage, wenn Sie die Zeichenfolge wollen, auf die sich die lokale Variable ‚s‘ Sie es mit einem Verweis auf eine neue Instanz eines String Objekt schaffen, ändern müssen.

Beispiel:

public void one()  
{
    String s = "one";
    s = two(); // Here your local variable will point to a new instance of a String with the value "two"
    System.out.println(s);
}

public String two() 
{
  return "two";
}

Wenn Sie andere Objekte als String -. Sie Setter-Methoden auf sie definieren können, die ihren Inhalt für Sie aktualisieren

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