2012-08-03 8 views
7

Principiante pregunta java, pero no puedo entender cómo Call-by-valor (o de referencia) está trabajando en el siguiente ejemplo -Java - El estado del objeto no cambia después de llamada de método

¿Cómo es que no se modifica el valor de cadena después de que sale del método mientras está mi Objeto String personalizado. ? Lo mismo ocurre con otras clases como .. Fecha

public class StringMadness { 

public static void main(String[] args) { 
    String s = "Native String"; 
    CustomStringObject cs = new CustomStringObject(); 
    System.out.println("Custom String Before: " + cs.str); 
    hello(cs); 
    System.out.println("Custom String After: " + cs.str); 

    System.out.println("Native String Before: " + s); 
    hello(s); 
    System.out.println("Native String After: " + s); 
} 

private static void hello(String t) { 
    t = "hello " + t; 
} 

private static void hello(CustomStringObject o) { 
    o.str = "hello " + o.str; 
    } 
} 

class CustomStringObject { 

String str = "Custom String"; 
} 

Respuesta

16

comparar estos dos métodos:

private static void hello(String t) { 
    t = "hello " + t; 
} 

private static void hello(CustomStringObject o) { 
    o.str = "hello " + o.str; 
} 

En el primer caso, se le asigna una nuevo valor a t. Eso no tendrá ningún efecto en el código de llamada; solo está cambiando el valor de un parámetro, y todos los argumentos se pasan por valor en Java.

En el segundo caso, está asignando un nuevo valor a o.str. Eso está cambiando el valor de un campo dentro del objeto al que se refiere el valor de o. La persona que llama va a ver ese cambio, porque la persona que llama todavía tiene una referencia a ese objeto.

En resumen: Java siempre usa pasar por valor, pero debe recordar que para las clases, el valor de una variable (o de cualquier otra expresión) es una referencia, no un objeto. No es necesario utilizar el paso de parámetros a ver esto:

Foo foo1 = new Foo(); 
Foo foo2 = foo1; 
foo1.someField = "changed"; 
System.out.println(foo2.someField) // "changed" 

La segunda línea aquí copia el valor de foo1 en foo2 - las dos variables se refieren al mismo objeto, por lo que no importa que la variable usar para acceder a ella.

+0

Ahh ... Lo veo. gracias ... Originalmente, mi 'hello (CustomStringObject o)' estaba instanciando una nueva instancia como en 'o = new CustomStringObject()' y noté que fuera del método hello, la instalación nunca tuvo ningún efecto. Esto es lo que provocó la pregunta. –

+0

@Jon Buena explicación. El ejemplo de Foo ayuda. +1 –

+0

Si la persona que llama pasa la referencia nula, entonces he observado que la modificación de llamada no se refleja en la persona que llama. ¿Por qué es así? –

0

t apuntará al nuevo objeto y ámbito es único método, por lo que los cambios no fuera visible.

Segundo caso, el valor que está cambiando se actualizará al objeto, por lo que esos cambios son visibles después de la llamada al método.

+0

No es porque las cadenas sean inmutables. Incluso si esto fuera un StringBuilder, la asignación de un nuevo valor al parámetro no afectaría a la persona que llama ... –

+0

@JonSkeet: De acuerdo. Actualizado mi respuesta. – kosa

4

Hay una diferencia importante entre los dos métodos: el uso de hello(String) que está tratando de cambiar la referencia a la String, y con hello(CustomObject), dada una referencia, que está utilizando la referencia a cambiar un miembro del objeto .

hello(String) toma como referencia String. En la función, intenta cambiar a qué objeto apunta la referencia, pero solo está cambiando la copia de valor porcentual de la referencia. Por lo tanto, sus cambios no se reflejan fuera del método.

hello(CustomObject) se le da una copia de una referencia a un objeto, que luego puede usar para cambiar el objeto real. Piense en esto como cambiar el contenido del objeto. Entonces sus cambios son reflejados en la persona que llama.

Dada una referencia a un objeto, puede cambiar el objeto con que está métodos expuestos/campos

0

Porque para String solo está cambiando la referencia del parámetro local.

0

No funciona porque String es un objeto inmutable

Cuestiones relacionadas