Hat Java etwas wie C # ref und out Keywords?

Etwas wie das Folgende:

Referenzbeispiel:

void changeString(ref String str) { str = "def"; } void main() { String abc = "abc"; changeString(ref abc); System.out.println(abc); //prints "def" } 

Beispiel:

 void setString(out String str) { str = "def"; } void main() { String abc; changeString(out abc); System.out.println(abc); //prints "def" } 

Nein, Java hat nicht so etwas wie C # ‘s ref und out Keywords für die Weitergabe als Referenz.

Sie können nur nach Wert in Java übergeben. Sogar Referenzen werden nach Wert übergeben. Weitere Informationen finden Sie auf der Jon Skeet -Seite zur Parameterübergabe in Java .

Um etwas Ähnliches wie ref oder out , müssten Sie Ihre Parameter in ein anderes Objekt einfügen und diese Objektreferenz als Parameter übergeben.

Direkte Antwort: Nein

Sie können jedoch die Referenz mit Wrappern simulieren.

Und folgendes tun:

 void changeString( _ str ) { str.s("def"); } void testRef() { _ abc = new _("abc"); changeString( abc ); out.println( abc ); // prints def } 

aus

 void setString( _ ref ) { str.s( "def" ); } void testOut(){ _ abc = _(); setString( abc ); out.println(abc); // prints def } 

Und im Grunde jede andere Art wie:

 _ one = new (1); addOneTo( one ); out.println( one ); // May print 2 

Java übergibt Parameter nach Wert und verfügt über keinen Mechanismus, um Pass-by-Reference zuzulassen. Das bedeutet, dass, wenn ein Parameter übergeben wird, sein Wert in den Stack-Frame kopiert wird, der den Aufruf behandelt.

Der Begriff Wert, wie ich ihn hier verwende, bedarf einer kleinen Klärung. In Java haben wir zwei Arten von Variablen – Primitive und Objekte. Ein Wert eines Grundelements ist das Grundelement selbst, und der Wert eines Objekts ist seine Referenz (und nicht der Zustand des Objekts, auf das verwiesen wird). Daher ändert jede Änderung des Werts innerhalb der Methode nur die Kopie des Werts im Stapel und wird vom Aufrufer nicht gesehen. Zum Beispiel gibt es keine Möglichkeit, eine echte Swap-Methode zu implementieren, die zwei Referenzen empfängt und sie tauscht (nicht ihren Inhalt!).

Eigentlich gibt es weder Ref- noch Out- Schlüsselwort in Java , soweit ich weiß. Allerdings habe ich gerade einen C # -Code in Java umgewandelt , der out- Parameter verwendet und berate, was ich gerade getan habe. Sie sollten jedes Objekt in eine Wrapper-class einschließen und die in der Wrapper-Objektinstanz enthaltenen Werte wie folgt übergeben.

Ein einfaches Beispiel für die Verwendung von Wrapper

Hier ist die Wrapper-class ;

 public class Wrapper { public Object ref1; // use this as ref public Object ref2; // use this as out public Wrapper(Object ref1) { this.ref1 = ref1; } } 

Und hier ist der Testcode;

 public class Test { public static void main(String[] args) { String abc = "abc"; changeString(abc); System.out.println("Initial object: " + abc); //wont print "def" Wrapper w = new Wrapper(abc); changeStringWithWrapper(w); System.out.println("Updated object: " + w.ref1); System.out.println("Out object: " + w.ref2); } // This won't work public static void changeString(String str) { str = "def"; } // This will work public static void changeStringWithWrapper(Wrapper w) { w.ref1 = "def"; w.ref2 = "And this should be used as out!"; } } 

Ein reales Beispiel

AC # .NET-Methode, die out-Parameter verwendet

Hier gibt es eine C # .NET- Methode, die out- Schlüsselwort verwendet;

 public bool Contains(T value) { BinaryTreeNode parent; return FindWithParent(value, out parent) != null; } private BinaryTreeNode FindWithParent(T value, out BinaryTreeNode parent) { BinaryTreeNode current = _head; parent = null; while(current != null) { int result = current.CompareTo(value); if (result > 0) { parent = current; current = current.Left; } else if (result < 0) { parent = current; current = current.Right; } else { break; } } return current; } 

Java-Äquivalent des C # -Codes, der den out-Parameter verwendet

Und das Java- Äquivalent dieser Methode mit Hilfe der Wrapper-class ist wie folgt;

 public boolean contains(T value) { BinaryTreeNodeGeneration result = findWithParent(value); return (result != null); } private BinaryTreeNodeGeneration findWithParent(T value) { BinaryTreeNode current = head; BinaryTreeNode parent = null; BinaryTreeNodeGeneration resultGeneration = new BinaryTreeNodeGeneration(); resultGeneration.setParentNode(null); while(current != null) { int result = current.compareTo(value); if(result >0) { parent = current; current = current.left; } else if(result < 0) { parent = current; current = current.right; } else { break; } } resultGeneration.setChildNode(current); resultGeneration.setParentNode(parent); return resultGeneration; } 

Wrapper-class

Und die in diesem Java-Code verwendete Wrapper-class ist wie folgt;

 public class BinaryTreeNodeGeneration> { private BinaryTreeNode parentNode; private BinaryTreeNode childNode; public BinaryTreeNodeGeneration() { this.parentNode = null; this.childNode = null; } public BinaryTreeNode getParentNode() { return parentNode; } public void setParentNode(BinaryTreeNode parentNode) { this.parentNode = parentNode; } public BinaryTreeNode getChildNode() { return childNode; } public void setChildNode(BinaryTreeNode childNode) { this.childNode = childNode; } } 

Wie viele andere musste ich ein C # -Projekt in Java konvertieren. Ich habe im Internet keine vollständige Lösung für die Modifikatoren ” out” und ” ref” gefunden . Aber ich war in der Lage, die Informationen, die ich gefunden habe, zu übernehmen und zu erweitern, um meine eigenen classn zu erstellen, um die Anforderungen zu erfüllen. Ich wollte zwischen Ref- und Out- Parametern für die Code-Klarheit unterscheiden. Mit den folgenden classn ist es möglich. Möge diese Information anderen Zeit und Mühe sparen.

Ein Beispiel ist im folgenden Code enthalten.

 //******************************************************************************************* //XOUT CLASS //******************************************************************************************* public class XOUT { public XOBJ Obj = null; public XOUT(T value) { Obj = new XOBJ(value); } public XOUT() { Obj = new XOBJ(); } public XOUT Out() { return(this); } public XREF Ref() { return(Obj.Ref()); } }; //******************************************************************************************* //XREF CLASS //******************************************************************************************* public class XREF { public XOBJ Obj = null; public XREF(T value) { Obj = new XOBJ(value); } public XREF() { Obj = new XOBJ(); } public XOUT Out() { return(Obj.Out()); } public XREF Ref() { return(this); } }; //******************************************************************************************* //XOBJ CLASS //******************************************************************************************* /** * * @author jsimms */ /* XOBJ is the base object that houses the value. XREF and XOUT are classes that internally use XOBJ. The classes XOBJ, XREF, and XOUT have methods that allow the object to be used as XREF or XOUT parameter; This is important, because objects of these types are interchangeable. See Method: XXX.Ref() XXX.Out() The below example shows how to use XOBJ, XREF, and XOUT; // // Reference parameter example // void AddToTotal(int a, XREF Total) { Total.Obj.Value += a; } // // out parameter example // void Add(int a, int b, XOUT ParmOut) { ParmOut.Obj.Value = a+b; } // // XOBJ example // int XObjTest() { XOBJ Total = new XOBJ<>(0); Add(1, 2, Total.Out()); // Example of using out parameter AddToTotal(1,Total.Ref()); // Example of using ref parameter return(Total.Value); } */ public class XOBJ { public T Value; public XOBJ() { } public XOBJ(T value) { this.Value = value; } // // Method: Ref() // Purpose: returns a Reference Parameter object using the XOBJ value // public XREF Ref() { XREF ref = new XREF(); ref.Obj = this; return(ref); } // // Method: Out() // Purpose: returns an Out Parameter Object using the XOBJ value // public XOUT Out() { XOUT out = new XOUT(); out.Obj = this; return(out); } // // Method get() // Purpose: returns the value // Note: Because this is combersome to edit in the code, // the Value object has been made public // public T get() { return Value; } // // Method get() // Purpose: sets the value // Note: Because this is combersome to edit in the code, // the Value object has been made public // public void set(T anotherValue) { Value = anotherValue; } @Override public String toString() { return Value.toString(); } @Override public boolean equals(Object obj) { return Value.equals(obj); } @Override public int hashCode() { return Value.hashCode(); } } 

Drei nicht ausdrücklich genannte Lösungen:

 ArrayList doThings() { // } void doThings(ArrayList list) { // } Pair doThings() { // } 

Für Pair würde ich empfehlen: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html

Java hat keine Standardmethode. Die meisten Swaps werden in der Liste vorgenommen, die in der class verpackt ist. Aber es gibt einen inoffiziellen Weg, es zu tun:

 package Example; import java.lang.reflect.Field; import java.util.logging.Level; import java.util.logging.Logger; public class Test{ private static  void SetValue(T obj,T value){ try { Field f = obj.getClass().getDeclaredField("value"); f.setAccessible(true); f.set(obj,value); } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException ex) { Logger.getLogger(CautrucjavaCanBan.class.getName()).log(Level.SEVERE, null, ex); } } private static void permutation(Integer a,Integer b){ Integer tmp = new Integer(a); SetValue(a, b); SetValue(b, tmp); } private static void permutation(String a,String b){ char[] tmp = a.toCharArray(); SetValue(a, b.toCharArray()); SetValue(b, tmp); } public static void main(String[] args) { { Integer d = 9; Integer e = 8; HoanVi(d, e); System.out.println(d+" "+ e); } { String d = "tai nguyen"; String e = "Thai nguyen"; permutation(d, e); System.out.println(d+" "+ e); } } }