valor - tipos de variables en java ejemplos




Pasando una cadena por referencia en Java? (9)

Estoy acostumbrado a hacer lo siguiente en C :

void main() {
    String zText = "";
    fillString(zText);
    printf(zText);
}

void fillString(String zText) {
    zText += "foo";
}

Y la salida es:

foo

Sin embargo, en Java, esto no parece funcionar. Supongo que porque el objeto String se copia en lugar de pasar por referencia . Pensé que las cuerdas eran objetos, que siempre pasan por referencia.

¿Que esta pasando aqui?


Aaron Digulla tiene la mejor respuesta hasta ahora. Una variación de su segunda opción es usar el tipo de contenedor o contenedor clase MutableObject de commons lang library versión 3+:

void fillString(MutableObject<String> c) { c.setValue(c.getValue() + "foo"); }

guarda la declaración de la clase de contenedor. El inconveniente es una dependencia de commons lang lib. Pero la lib tiene muchas funciones útiles y casi cualquier proyecto más grande en el que haya trabajado lo usó.


En Java, nada se pasa por referencia . Todo se pasa por valor . Las referencias a objetos se pasan por valor. Además, las cadenas son inmutables . Entonces cuando agregas el String pasado, obtienes un nuevo String. Puede usar un valor de retorno o pasar un StringBuffer en su lugar.


La cadena es inmutable en Java. no puede modificar / cambiar un literal / objeto de cadena existente.

String s = "Hola"; s = s + "hola";

Aquí, la referencia anterior s se reemplaza por la nueva referencia que apunta al valor "HelloHi".

Sin embargo, para llevar mutabilidad tenemos StringBuilder y StringBuffer.

StringBuilder s = new StringBuilder (); s.append ("Hola");

esto agrega el nuevo valor "Hola" a la misma referencia. //


La respuesta es simple. En java, las cadenas son inmutables. Por lo tanto, es como usar el modificador 'final' (o 'const' en C / C ++). Entonces, una vez asignado, no puedes cambiarlo como lo hiciste.

Puede cambiar el valor al que apunta una cadena, pero NO puede cambiar el valor real al que apunta actualmente esta cadena.

Es decir. String s1 = "hey" . Puedes hacer s1 = "woah" , y eso está totalmente bien, pero no puedes cambiar el valor subyacente de la cadena (en este caso: "hey") para que sea otra cosa una vez que se asigne usando plusEquals, etc. . s1 += " whatup != "hey whatup" ).

Para hacer eso, use las clases StringBuilder o StringBuffer u otros contenedores mutables, luego simplemente llame a .toString () para convertir el objeto a una cadena.

Nota: Las cadenas se utilizan a menudo como teclas de almohadilla, por lo que es parte de la razón por la que son inmutables.



Lo que está sucediendo es que la referencia se pasa por valor, es decir, se pasa una copia de la referencia. Nada en Java se pasa por referencia, y como una cadena es inmutable, esa asignación crea un nuevo objeto de cadena al que ahora apunta la copia de la referencia . La referencia original aún apunta a la cadena vacía.

Esto sería lo mismo para cualquier objeto, es decir, establecerlo en un nuevo valor en un método. El siguiente ejemplo simplemente hace que lo que está pasando sea más obvio, pero concatenar una cadena es realmente lo mismo.

void foo( object o )
{
    o = new Object( );  // original reference still points to old value on the heap
}

String es una clase especial en Java. Es Thread Save lo que significa "Una vez que se crea una instancia de String, el contenido de la instancia de String nunca cambiará".

Esto es lo que está pasando para

 zText += "foo";

En primer lugar, el compilador de Java obtendrá el valor de la instancia de zText String y luego creará una nueva instancia de String cuyo valor sea zText y se agregará "foo". Entonces sabes por qué la instancia a la que zText apunta no cambia. Es totalmente una nueva instancia. De hecho, incluso String "foo" es una nueva instancia de String. Por lo tanto, para esta afirmación, Java creará dos instancias String, una es "foo", otra es el valor de zText, agregue "foo". La regla es simple: el valor de la instancia de String nunca cambiará.

Para method fillString, puede usar un StringBuffer como parámetro, o puede cambiarlo así:

String fillString(String zText) {
    return zText += "foo";
}

Tienes tres opciones:

  1. Use un StringBuilder:

    StringBuilder zText = new StringBuilder ();
    void fillString(StringBuilder zText) { zText.append ("foo"); }
    
  2. Cree una clase de contenedor y pase una instancia del contenedor a su método:

    public class Container { public String data; }
    void fillString(Container c) { c.data += "foo"; }
    
  3. Crear una matriz:

    new String[] zText = new String[1];
    zText[0] = "";
    
    void fillString(String[] zText) { zText[0] += "foo"; }
    

Desde el punto de vista del rendimiento, StringBuilder suele ser la mejor opción.


los objetos se pasan por referencia, los primitivos se pasan por valor.

La cadena no es primitiva, es un objeto, y es un caso especial de objeto.

Esto es para fines de ahorro de memoria. En JVM, hay un grupo de cadenas. Para cada cadena creada, JVM intentará ver si existe la misma cadena en el grupo de cadenas, y apuntará a ella si ya hay una.

public class TestString
{
    private static String a = "hello world";
    private static String b = "hello world";
    private static String c = "hello " + "world";
    private static String d = new String("hello world");

    private static Object o1 = new Object();
    private static Object o2 = new Object();

    public static void main(String[] args)
    {
        System.out.println("a==b:"+(a == b));
        System.out.println("a==c:"+(a == c));
        System.out.println("a==d:"+(a == d));
        System.out.println("a.equals(d):"+(a.equals(d)));
        System.out.println("o1==o2:"+(o1 == o2));

        passString(a);
        passString(d);
    }

    public static void passString(String s)
    {
        System.out.println("passString:"+(a == s));
    }
}

/ * OUTPUT * /

a==b:true
a==c:true
a==d:false
a.equals(d):true
o1==o2:false
passString:true
passString:false

el == está buscando la dirección de la memoria (referencia), y el .equals está buscando contenido (valor)







pass-by-value