methods parametros de - ¿Es Java "paso por referencia" o "paso por valor"?





15 Answers

Me acabo de dar cuenta de que referenciaste mi artículo

La especificación de Java dice que todo en Java es pasado por valor. No hay tal cosa como "paso por referencia" en Java.

La clave para entender esto es que algo como

Dog myDog;

no es un perro; En realidad es un puntero a un perro.

Lo que eso significa, es cuando tienes

Dog myDog = new Dog("Rover");
foo(myDog);

Básicamente, estás pasando la dirección del objeto Dog creado al método foo .

(Digo esencialmente porque los punteros de Java no son direcciones directas, pero es más fácil pensarlos de esa manera)

Supongamos que el objeto Dog reside en la dirección de memoria 42. Esto significa que pasamos 42 al método.

si el método fuera definido como

public void foo(Dog someDog) {
    someDog.setName("Max");     // AAA
    someDog = new Dog("Fifi");  // BBB
    someDog.setName("Rowlf");   // CCC
}

echemos un vistazo a lo que está pasando.

  • El parámetro someDog se establece en el valor 42
  • en la línea "AAA"
    • someDog le sigue el Dog que apunta (el objeto Dog en la dirección 42)
    • se le pide a ese Dog (el de la dirección 42) que cambie su nombre a Max
  • en la línea "BBB"
    • Se crea un nuevo Dog . Digamos que está en la dirección 74
    • Le asignamos el parámetro someDog a 74
  • en la línea "CCC"
    • A algún perro le sigue el Dog que apunta (el objeto Dog en la dirección 74)
    • a ese Dog (el que está en la dirección 74) se le pide que cambie su nombre a Rowlf
  • luego volvemos

Ahora pensemos en lo que sucede fuera del método:

¿ myDog ?

Ahí está la clave.

Teniendo en cuenta que myDog es un puntero , y no un Dog real, la respuesta es NO. myDog todavía tiene el valor 42; sigue apuntando al Dog original (pero tenga en cuenta que debido a la línea "AAA", su nombre ahora es "Max", sigue siendo el mismo perro; el valor de myDog no ha cambiado).

Es perfectamente válido seguir una dirección y cambiar lo que hay al final; Eso no cambia la variable, sin embargo.

Java funciona exactamente como C. Puede asignar un puntero, pasar el puntero a un método, seguir el puntero en el método y cambiar los datos a los que se apuntó. Sin embargo, no puede cambiar a donde apunta ese puntero.

En C ++, Ada, Pascal y otros idiomas que admiten paso por referencia, realmente puede cambiar la variable que se pasó.

Si Java tuviera una semántica de paso por referencia, el método foo que definimos anteriormente habría cambiado donde myDog estaba apuntando cuando asignó someDog en la línea BBB.

Piense en los parámetros de referencia como si fueran alias para la variable pasada. Cuando se asigna ese alias, también lo es la variable que se pasó.

ejemplo objetos ejemplos

Siempre pensé que Java era paso por referencia .

Sin embargo, he visto un par de publicaciones de blog (por ejemplo, este blog ) que afirman que no lo es.

No creo entender la distinción que están haciendo.

¿Cuál es la explicación?




Esto le dará una idea de cómo funciona realmente Java hasta el punto de que en su próxima discusión sobre el paso de Java por referencia o por valor, simplemente sonreirá :-)

El primer paso borra de tu mente la palabra que comienza con 'p' "_ _ _ _ _ _ _", especialmente si vienes de otros lenguajes de programación. Java y 'p' no se pueden escribir en el mismo libro, foro o incluso txt.

El segundo paso recuerda que cuando pasas un objeto a un método, estás pasando la referencia del objeto y no el objeto en sí.

  • Estudiante : Maestro, ¿significa esto que Java es paso por referencia?
  • Maestro : Saltamontes, No.

Ahora piense en lo que hace / es la referencia / variable de un objeto:

  1. Una variable contiene los bits que le indican a la JVM cómo llegar al Objeto referenciado en la memoria (Heap).
  2. Al pasar argumentos a un método NO ESTÁ pasando la variable de referencia, sino una copia de los bits en la variable de referencia . Algo así: 3bad086a. 3bad086a representa una forma de llegar al objeto pasado.
  3. Así que solo estás pasando 3bad086a que es el valor de la referencia.
  4. Está pasando el valor de la referencia y no la referencia en sí (y no el objeto).
  5. Este valor es en realidad COPIADO y dado al método .

En lo siguiente (por favor no intente compilar / ejecutar esto ...):

1. Person person;
2. person = new Person("Tom");
3. changeName(person);
4.
5. //I didn't use Person person below as an argument to be nice
6. static void changeName(Person anotherReferenceToTheSamePersonObject) {
7.     anotherReferenceToTheSamePersonObject.setName("Jerry");
8. }

¿Lo que pasa?

  • La persona variable se crea en la línea # 1 y es nula al principio.
  • Se crea un nuevo objeto de persona en la línea # 2, se almacena en la memoria, y la persona variable recibe la referencia al objeto de persona. Es decir, su dirección. Digamos 3bad086a.
  • La persona variable que contiene la dirección del Objeto se pasa a la función en la línea # 3.
  • En la línea # 4 puedes escuchar el sonido del silencio.
  • Compruebe el comentario en la línea # 5
  • Se crea una variable local del método - anotherReferenceToTheSamePersonObject - y luego viene la magia en la línea # 6:
    • La variable / persona de referencia se copia bit a bit y se pasa a otroReferenceToTheSamePersonObject dentro de la función.
    • No se crean nuevas instancias de Person.
    • Tanto " person " como " anotherReferenceToTheSamePersonObject " tienen el mismo valor de 3bad086a.
    • No intente esto, pero la persona == anotherReferenceToTheSamePersonObject sería verdadera.
    • Ambas variables tienen COPIAS IDENTICAS de la referencia y ambas se refieren al mismo Objeto de persona, el MISMO objeto en el montón y NO A UNA COPIA.

Una imagen vale mas que mil palabras:

Tenga en cuenta que las flechas anotherReferenceToTheSamePersonObject se dirigen hacia el objeto y no hacia la persona variable.

Si no lo obtuvo, entonces confíe en mí y recuerde que es mejor decir que Java se pasa por valor . Bueno, pasar por valor de referencia . Oh, bueno, ¡aún mejor es pasar-por-la-copia-del-valor-variable! ;)

Ahora siéntase libre de odiarme, pero tenga en cuenta que dado esto, no hay diferencia entre pasar tipos de datos primitivos y Objetos cuando se habla de argumentos de métodos.

¡Siempre se pasa una copia de los bits del valor de la referencia!

  • Si se trata de un tipo de datos primitivos, estos bits contendrán el valor del tipo de datos primitivos en sí.
  • Si se trata de un objeto, los bits contendrán el valor de la dirección que le indica a la JVM cómo llegar al objeto.

Java es pasado por valor porque dentro de un método puede modificar el Objeto referenciado tanto como quiera, pero no importa cuánto lo intente, nunca podrá modificar la variable pasada que seguirá haciendo referencia (no p _ _ _ _ _ _ _) ¡El mismo Objeto pase lo que pase!

La función de cambio de nombre anterior nunca podrá modificar el contenido real (los valores de bit) de la referencia pasada. En otras palabras, changeName no puede hacer que Person person se refiera a otro Objeto.

¡Por supuesto que puede abreviar y simplemente decir que Java se pasa de valor!




Java pasa referencias por valor.

Así que no puedes cambiar la referencia que se pasa.




Solo para mostrar el contraste, compare los siguientes fragmentos de código C++ y Java :

En C ++: Nota: Código incorrecto - ¡Fugas de memoria! Pero demuestra el punto.

void cppMethod(int val, int &ref, Dog obj, Dog &objRef, Dog *objPtr, Dog *&objPtrRef)
{
    val = 7; // Modifies the copy
    ref = 7; // Modifies the original variable
    obj.SetName("obj"); // Modifies the copy of Dog passed
    objRef.SetName("objRef"); // Modifies the original Dog passed
    objPtr->SetName("objPtr"); // Modifies the original Dog pointed to 
                               // by the copy of the pointer passed.
    objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                   // leaving the original object alone.
    objPtrRef->SetName("objRefPtr"); // Modifies the original Dog pointed to 
                                    // by the original pointer passed. 
    objPtrRef = new Dog("newObjPtrRef"); // Modifies the original pointer passed
}

int main()
{
    int a = 0;
    int b = 0;
    Dog d0 = Dog("d0");
    Dog d1 = Dog("d1");
    Dog *d2 = new Dog("d2");
    Dog *d3 = new Dog("d3");
    cppMethod(a, b, d0, d1, d2, d3);
    // a is still set to 0
    // b is now set to 7
    // d0 still have name "d0"
    // d1 now has name "objRef"
    // d2 now has name "objPtr"
    // d3 now has name "newObjPtrRef"
}

En java

public static void javaMethod(int val, Dog objPtr)
{
   val = 7; // Modifies the copy
   objPtr.SetName("objPtr") // Modifies the original Dog pointed to 
                            // by the copy of the pointer passed.
   objPtr = new Dog("newObjPtr");  // Modifies the copy of the pointer, 
                                  // leaving the original object alone.
}

public static void main()
{
    int a = 0;
    Dog d0 = new Dog("d0");
    javaMethod(a, d0);
    // a is still set to 0
    // d0 now has name "objPtr"
}

Java solo tiene los dos tipos de transferencia: por valor para los tipos incorporados y por valor del puntero para los tipos de objeto.




Básicamente, la reasignación de parámetros de Objeto no afecta el argumento, por ejemplo,

private void foo(Object bar) {
    bar = null;
}

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

imprimirá "Hah!" en lugar de null La razón por la que esto funciona es porque bar es una copia del valor de baz , que es solo una referencia a "Hah!" .Si se tratara de la referencia actual, foose habría redefinido baza null.




El quid de la cuestión es que la palabra referencia en la expresión "pasar por referencia" significa algo completamente diferente del significado habitual de la palabra referencia en Java.

Por lo general, en referencia de Java significa una referencia a un objeto . Pero los términos técnicos que pasan por referencia / valor de la teoría del lenguaje de programación están hablando de una referencia a la celda de memoria que contiene la variable , que es algo completamente diferente.




Una referencia siempre es un valor cuando se representa, independientemente del idioma que utilice.

Al obtener una vista externa de la caja, veamos Ensamblado o alguna administración de memoria de bajo nivel. En el nivel de la CPU, una referencia a cualquier cosa se convierte inmediatamente en un valor si se escribe en la memoria o en uno de los registros de la CPU. (Es por eso que el puntero es una buena definición. Es un valor, que tiene un propósito al mismo tiempo).

Los datos en la memoria tienen una ubicación y en esa ubicación hay un valor (byte, palabra, lo que sea). En Ensamblaje tenemos una solución conveniente para dar un Nombre a cierta Ubicación (también conocida como variable), pero al compilar el código, el ensamblador simplemente reemplaza Nombre por la ubicación designada al igual que su navegador reemplaza los nombres de dominio con direcciones IP.

Básicamente, es técnicamente imposible pasar una referencia a cualquier cosa en cualquier idioma sin representarlo (cuando se convierte de inmediato en un valor).

Digamos que tenemos una variable Foo, su ubicación está en el byte 47 en la memoria y su valor es 5. Tenemos otra variable Ref2Foo que está en el 223er byte en la memoria, y su valor será 47. Este Ref2Foo podría ser una variable técnica , no creado explícitamente por el programa. Si solo observa 5 y 47 sin ninguna otra información, verá solo dos valores . Si los usas como referencias entonces para llegar a ellos 5tenemos que viajar:

(Name)[Location] -> [Value at the Location]
---------------------
(Ref2Foo)[223]  -> 47
(Foo)[47]       -> 5

Así es como funcionan las tablas de salto.

Si queremos llamar a un método / función / procedimiento con el valor de Foo, hay algunas formas posibles de pasar la variable al método, dependiendo del idioma y sus varios modos de invocación de método:

  1. 5 se copia en uno de los registros de la CPU (es decir, EAX).
  2. 5 obtiene PUSHd a la pila.
  3. 47 se copia en uno de los registros de la CPU
  4. 47 PUSHd a la pila.
  5. 223 se copia en uno de los registros de la CPU.
  6. 223 obtiene PUSHd a la pila.

En todos los casos por encima de un valor, se ha creado una copia de un valor existente, ahora depende del método de recepción para manejarlo. Cuando se escribe "Foo" dentro del método, se lee en EAX, o se elimina la referencia automáticamente o se hace doble referencia, el proceso depende de cómo funciona el idioma y / o de lo que dicta el tipo de Foo. Esto se oculta al desarrollador hasta que ella elude el proceso de desreferenciación. Por lo tanto, una referencia es un valor cuando se representa, porque una referencia es un valor que debe procesarse (a nivel de idioma).

Ahora hemos pasado Foo al método:

  • en el caso 1. y 2. si cambia Foo ( Foo = 9), solo afecta el alcance local ya que tiene una copia del Valor. Desde dentro del método, ni siquiera podemos determinar dónde se ubicó el Foo original en la memoria.
  • en el caso 3. y 4. si usa construcciones de idioma predeterminadas y cambia Foo ( Foo = 11), podría cambiar Foo globalmente (depende del idioma, es decir, Java o como la procedure findMin(x, y, z: integer; var m de Pascal : integer);). Sin embargo, si el lenguaje le permite eludir el proceso de desreferencia, puede cambiar 47, digamos a 49. En ese punto, parece que Foo ha cambiado si lo lees, porque le has cambiado el puntero local . Y si tuviera que modificar este Foo dentro del método ( Foo = 12) probablemente FUBARÁ la ejecución del programa (también conocido como segfault) porque escribirá en una memoria diferente a la esperada, incluso puede modificar un área que está destinada a contener ejecutables El programa y la escritura en él modificarán el código en ejecución (Foo ahora no está en 47). PERO el valor de Foo de47No cambió globalmente, solo el que estaba dentro del método, porque 47también era una copia del método.
  • en el caso 5. y 6. si modifica 223dentro del método, crea el mismo caos que en 3. o 4. (un puntero, que apunta a un valor ahora malo, que se usa nuevamente como un puntero) pero esto sigue siendo un local Problema, ya que se copió el 223 . Sin embargo, si puede desreferenciar Ref2Foo(es decir 223), alcanzar y modificar el valor señalado 47, digamos, 49afectará a Foo globalmente , porque en este caso los métodos obtuvieron una copia 223pero la referencia 47solo existe una vez, y cambiarla que 49conducirá cada Ref2Foodoble desreferencia a un valor incorrecto.

Al optar por detalles insignificantes, incluso los idiomas que pasan por referencia pasarán valores a las funciones, pero esas funciones saben que tienen que usarlo para fines de desreferenciación. Este paso-la-referencia-como-valor está oculto para el programador porque es prácticamente inútil y la terminología es solo paso por referencia .

El paso por valor estricto también es inútil, significaría que una matriz de 100 Mbyte debería copiarse cada vez que llamamos a un método con la matriz como argumento, por lo tanto, Java no puede ser estrictamente pasado por valor. Cada idioma pasaría una referencia a esta gran matriz (como un valor) y empleará un mecanismo de copia en escritura si esa matriz puede cambiarse localmente dentro del método o permite que el método (como lo hace Java) modifique la matriz globalmente (desde la vista de la persona que llama) y algunos idiomas permiten modificar el valor de la referencia en sí.

Entonces, en resumen y en la terminología propia de Java, Java es el valor por donde el valor puede ser: un valor real o un valor que es una representación de una referencia .




Por lo que sé, Java solo sabe llamada por valor. Esto significa que para los tipos de datos primitivos trabajará con una copia y para los objetos trabajará con una copia de la referencia a los objetos. Sin embargo creo que hay algunos escollos; por ejemplo, esto no funcionará:

public static void swap(StringBuffer s1, StringBuffer s2) {
    StringBuffer temp = s1;
    s1 = s2;
    s2 = temp;
}


public static void main(String[] args) {
    StringBuffer s1 = new StringBuffer("Hello");
    StringBuffer s2 = new StringBuffer("World");
    swap(s1, s2);
    System.out.println(s1);
    System.out.println(s2);
}

Esto llenará Hello World y no World Hello porque en la función de intercambio usas copys que no tienen impacto en las referencias en la página principal. Pero si tus objetos no son inmutables, puedes cambiarlos, por ejemplo:

public static void appendWorld(StringBuffer s1) {
    s1.append(" World");
}

public static void main(String[] args) {
    StringBuffer s = new StringBuffer("Hello");
    appendWorld(s);
    System.out.println(s);
}

Esto llenará Hello World en la línea de comando. Si cambias StringBuffer en String, solo se producirá Hello, porque String es inmutable. Por ejemplo:

public static void appendWorld(String s){
    s = s+" World";
}

public static void main(String[] args) {
    String s = new String("Hello");
    appendWorld(s);
    System.out.println(s);
}

Sin embargo, podrías hacer una envoltura para String como esta que lo haría capaz de usarlo con Strings:

class StringWrapper {
    public String value;

    public StringWrapper(String value) {
        this.value = value;
    }
}

public static void appendWorld(StringWrapper s){
    s.value = s.value +" World";
}

public static void main(String[] args) {
    StringWrapper s = new StringWrapper("Hello");
    appendWorld(s);
    System.out.println(s.value);
}

edit: creo que esta es también la razón para usar StringBuffer cuando se trata de "agregar" dos Strings porque puedes modificar el objeto original que no puedes con objetos inmutables como es String.




Permítame tratar de explicar mi comprensión con la ayuda de cuatro ejemplos. Java es paso por valor, y no paso por referencia

/ **

Pasar por valor

En Java, todos los parámetros se pasan por valor, es decir, la asignación de un argumento de método no es visible para la persona que llama.

* /

Ejemplo 1:

public class PassByValueString {
    public static void main(String[] args) {
        new PassByValueString().caller();
    }

    public void caller() {
        String value = "Nikhil";
        boolean valueflag = false;
        String output = method(value, valueflag);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'value' and 'valueflag'
         */
        System.out.println("output : " + output);
        System.out.println("value : " + value);
        System.out.println("valueflag : " + valueflag);

    }

    public String method(String value, boolean valueflag) {
        value = "Anand";
        valueflag = true;
        return "output";
    }
}

Resultado

output : output
value : Nikhil
valueflag : false

Ejemplo 2:

/ ** * * Pasar por valor * * /

public class PassByValueNewString {
    public static void main(String[] args) {
        new PassByValueNewString().caller();
    }

    public void caller() {
        String value = new String("Nikhil");
        boolean valueflag = false;
        String output = method(value, valueflag);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'value' and 'valueflag'
         */
        System.out.println("output : " + output);
        System.out.println("value : " + value);
        System.out.println("valueflag : " + valueflag);

    }

    public String method(String value, boolean valueflag) {
        value = "Anand";
        valueflag = true;
        return "output";
    }
}

Resultado

output : output
value : Nikhil
valueflag : false

Ejemplo 3:

/ ** Este 'Pasar por valor tiene la sensación de' Pasar por referencia '

Algunas personas dicen que los tipos primitivos y 'Cadena' son 'pasar por valor' y los objetos son 'pasar por referencia'.

Pero a partir de este ejemplo, podemos entender que se trata de pasar de hecho solo por valor, teniendo en cuenta que aquí estamos pasando la referencia como valor. Es decir: la referencia se pasa por valor. Es por eso que son capaces de cambiar y aún se mantiene vigente después del alcance local. Pero no podemos cambiar la referencia real fuera del alcance original. lo que eso significa se demuestra en el siguiente ejemplo de PassByValueObjectCase2.

* /

public class PassByValueObjectCase1 {

    private class Student {
        int id;
        String name;
        public Student() {
        }
        public Student(int id, String name) {
            super();
            this.id = id;
            this.name = name;
        }
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        @Override
        public String toString() {
            return "Student [id=" + id + ", name=" + name + "]";
        }
    }

    public static void main(String[] args) {
        new PassByValueObjectCase1().caller();
    }

    public void caller() {
        Student student = new Student(10, "Nikhil");
        String output = method(student);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'student'
         */
        System.out.println("output : " + output);
        System.out.println("student : " + student);
    }

    public String method(Student student) {
        student.setName("Anand");
        return "output";
    }
}

Resultado

output : output
student : Student [id=10, name=Anand]

Ejemplo 4:

/ **

Además de lo que se mencionó en el Ejemplo 3 (PassByValueObjectCase1.java), no podemos cambiar la referencia real fuera del alcance original ".

Nota: No estoy pegando el código para private class Student. La definición de clase para Studentes igual que en Ejemplo3.

* /

public class PassByValueObjectCase2 {

    public static void main(String[] args) {
        new PassByValueObjectCase2().caller();
    }

    public void caller() {
        // student has the actual reference to a Student object created
        // can we change this actual reference outside the local scope? Let's see
        Student student = new Student(10, "Nikhil");
        String output = method(student);
        /*
         * 'output' is insignificant in this example. we are more interested in
         * 'student'
         */
        System.out.println("output : " + output);
        System.out.println("student : " + student); // Will it print Nikhil or Anand?
    }

    public String method(Student student) {
        student = new Student(20, "Anand");
        return "output";
    }

}

Resultado

output : output
student : Student [id=10, name=Nikhil]



Java es una llamada por valor.

Cómo funciona

  • ¡Siempre se pasa una copia de los bits del valor de la referencia!

  • Si se trata de un tipo de datos primitivos, estos bits contienen el valor del tipo de datos primitivos en sí, por eso, si cambiamos el valor de encabezado dentro del método, entonces no refleja los cambios externos.

  • Si se trata de un tipo de datos de objeto como Foo foo = new Foo () , en este caso, la copia de la dirección del objeto pasa como acceso directo al archivo, supongamos que tenemos un archivo de texto abc.txt en C: \ desktop y supongamos que hacemos un acceso directo de el mismo archivo y colóquelo dentro de C: \ desktop \ abc-shortcut para que cuando acceda al archivo desde C: \ desktop \ abc.txt y escriba '' y cierre el archivo y nuevamente abra el archivo desde el acceso directo. write 'es la comunidad en línea más grande para que aprendan los programadores', luego el cambio total de archivos será ' es la comunidad en línea más grande para que aprendan los programadores'lo que significa que no importa desde donde abra el archivo, cada vez que accedemos al mismo archivo, aquí podemos asumir que Foo es un archivo y supongamos que foo está almacenado en 123hd7h (dirección original como C: \ desktop \ abc.txt ) dirección y 234jdid (dirección copiada como C: \ desktop \ abc-shortcut que en realidad contiene la dirección original del archivo). Así que para una mejor comprensión, haga un archivo de acceso directo y sienta ...




La distinción, o tal vez la forma en que recuerdo que solía tener la misma impresión que el póster original es la siguiente: Java siempre se pasa por valor. Todos los objetos (en Java, cualquier cosa excepto los primitivos) en Java son referencias. Estas referencias se pasan por valor.




Java solo tiene pase por valor. Un ejemplo muy simple para validar esto.

public void test() {
    MyClass obj = null;
    init(obj);
    //After calling init method, obj still points to null
    //this is because obj is passed as value and not as reference.
}
private void init(MyClass objVar) {
    objVar = new MyClass();
}



Siempre lo veo como "pasar por copia". Es una copia del valor ya sea primitivo o de referencia. Si es una primitiva, es una copia de los bits que son el valor y si es un Objeto, es una copia de la referencia.

public class PassByCopy{
    public static void changeName(Dog d){
        d.name = "Fido";
    }
    public static void main(String[] args){
        Dog d = new Dog("Maxx");
        System.out.println("name= "+ d.name);
        changeName(d);
        System.out.println("name= "+ d.name);
    }
}
class Dog{
    public String name;
    public Dog(String s){
        this.name = s;
    }
}

Salida de Java PassByCopy:

nombre = Maxx
nombre = Fido

Las clases de contenedor primitivo y las cadenas son inmutables, por lo que cualquier ejemplo que use esos tipos no funcionará igual que otros tipos / objetos.




Algunas correcciones a algunos posts.

C no admite el paso por referencia. SIEMPRE se pasa por valor. C ++ admite el paso por referencia, pero no es el valor predeterminado y es bastante peligroso.

No importa cuál sea el valor en Java: primitivo o dirección (aproximadamente) del objeto, SIEMPRE se pasa por valor.

Si un objeto Java "se comporta" como si se pasara por referencia, eso es una propiedad de mutabilidad y no tiene absolutamente nada que ver con los mecanismos de paso.

No estoy seguro de por qué esto es tan confuso, quizás porque muchos "programadores" de Java no están formalmente entrenados y, por lo tanto, no entienden lo que realmente está pasando en la memoria




Java pasa los parámetros por VALOR, y por valor SOLAMENTE .

Para acortar el cuento largo:

Para aquellos que vienen de C #: NO HAY NINGÚN parámetro "out".

Para aquellos que vienen de PASCAL: NO HAY "var" parámetro .

Esto significa que no puede cambiar la referencia desde el objeto en sí, pero siempre puede cambiar las propiedades del objeto.

Una solución es utilizar el StringBuilderparámetro en su lugar String. ¡Y siempre puedes usar arreglos!




Related