¿Tiene Java algo como las palabras clave ref y out de C #?

Algo como lo siguiente:

ref ejemplo:

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

ejemplo:

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

No, Java no tiene algo como out palabras clave ref y out C # para pasar por referencia.

Solo puede pasar por valor en Java. Incluso las referencias se pasan por valor. Vea la página de Jon Skeet sobre el paso de parámetros en Java para más detalles.

Para hacer algo similar a ref o out tendrías que ajustar tus parámetros dentro de otro objeto y pasar esa referencia de objeto como un parámetro.

Respuesta directa: no

Pero puedes simular referencia con envoltorios .

Y haz lo siguiente:

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

Fuera

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

Y básicamente cualquier otro tipo como:

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

Java pasa los parámetros por valor y no tiene ningún mecanismo para permitir el paso por referencia. Eso significa que cada vez que se pasa un parámetro, su valor se copia en el marco de la stack que maneja la llamada.

El término valor tal como lo uso aquí necesita una pequeña aclaración. En Java tenemos dos tipos de variables: primitivas y objetos. Un valor de una primitiva es la primitiva misma, y ​​el valor de un objeto es su referencia (y no el estado del objeto al que se hace referencia). Por lo tanto, cualquier cambio en el valor dentro del método solo cambiará la copia del valor en la stack y no será visto por la persona que llama. Por ejemplo, no hay ninguna forma de implementar un método de intercambio real, que recibe dos referencias y las intercambia (¡no su contenido!).

En realidad, hasta donde yo sé, no hay ni ref ni out equivalentes de palabra clave en el lenguaje Java . Sin embargo, acabo de transformar un código C # en Java que usa el parámetro out y le aconsejo lo que acabo de hacer. Debería envolver cualquier objeto en una clase contenedora y pasar los valores envueltos en la instancia del objeto contenedor de la siguiente manera;

Un ejemplo simple para usar Wrapper

Aquí está la clase Wrapper ;

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

Y aquí está el código de prueba;

 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!"; } } 

Un ejemplo del mundo real

Método AC # .NET utilizando el parámetro out

Aquí hay un método C # .NET que está usando la palabra clave out ;

 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; } 

Equivalente Java del código C # que está utilizando el parámetro out

Y el equivalente de Java de este método con la ayuda de la clase contenedora es el siguiente;

 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; } 

Clase de envoltura

Y la clase contenedora utilizada en este código Java es la siguiente;

 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; } } 

Como muchos otros, necesitaba convertir un proyecto de C # a Java. No encontré una solución completa en la web con respecto a los modificadores de out y ref . Pero, pude tomar la información que encontré y ampliarla para crear mis propias clases para cumplir con los requisitos. Quería hacer una distinción entre los parámetros ref y out para la claridad del código. Con las siguientes clases, es posible. Que esta información le ahorre a otros tiempo y esfuerzo.

Un ejemplo está incluido en el código a continuación.

 //******************************************************************************************* //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(); } } 

Tres soluciones no oficialmente, explícitamente mencionadas:

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

Para Pair, recomendaría: https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html

java no tiene una forma estándar de hacerlo. La mayoría de los intercambios se realizarán en la lista que está empaquetada en la clase. pero hay una manera no oficial de hacerlo:

 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); } } }