2011-04-29 14 views
16

El siguiente segmento de código Java es de un examen de práctica de AP Computer Science.Configuración de la variable Java String: ¿referencia o valor?

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

La salida de este código es "abc ab" en BlueJ. Sin embargo, una de las posibles opciones de respuesta es "abc abc". La respuesta puede ser dependiendo de si Java establece la referencia de cadena como tipos primitivos (por valor) o como Objetos (por referencia).

Para ilustrar mejor esto, veamos un ejemplo con tipos primitivos:

int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 

Pero, decir que tuvimos CuentaBancaria objetos que mantienen saldos.

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1.setBalance(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 0" 

No estoy seguro de cuál es el caso de Strings. Técnicamente son objetos, pero mi compilador parece tratarlos como tipos primitivos al establecer variables entre sí.

Si Java pasa variables String como tipo primitivo, la respuesta es "abc ab". Sin embargo, si Java trata las variables String como referencias a cualquier otro objeto, la respuesta sería "abc abc"

¿Cuál crees que es la respuesta correcta?

+0

¿Has visto la documentación de String? ¿Dice si es una clase o un primitivo? – DJClayworth

+0

Es posible que desee leer el [javadoc] (http://download.oracle.com/javase/6/docs/api/java/lang/String.html) mientras responde sus preguntas. –

+4

'System.out.println (s1 +" "+ s2); // imprime "1 42" 'no es verdadero ... imprime' "42 1" ' – whytheq

Respuesta

27

java Las cadenas son inmutables, por lo que su reasignación hace que la variable apunte a una nueva instancia de Cadena en lugar de cambiar el valor de la Cadena.

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2); 

en la línea 2, s1 == s2 AND s1.equals (s2). Después de su concatenación en la línea 3, s1 ahora hace referencia a una instancia diferente con el valor inmutable de "abc", por lo que ni s1 == s2 ni s1.equals (s2).

+1

Lo es y lo hace, pero eso en realidad no responde la pregunta más fundamental del OP. –

+5

Claro que sí. Explica implícitamente que su comparación del caso String con la Cuenta bancaria no es la misma. Uno está asignando una nueva instancia, mientras que el otro simplemente está modificando uno existente. Para mayor claridad s1 = s1 + "c" básicamente equivale a b = new StringBuilder (s1); b.append ('c'); s1 = b.toString(); – Robin

2

java.lang.String es un objeto, no una primitiva.

lo que el código lo hizo en el primer ejemplo es:

  1. Definir s1 como "ab"
  2. conjunto S2 igual a un mismo objeto subyacente como S1
  3. juego S1 igual a una nueva cadena que es la combinación del antiguo valor de s1 y "c"

Pero para responder a su pregunta sobre la referencia o el valor, es por referencia.

6

En Java, String los objetos se asignan y pasan alrededor de por referencia; a este respecto se comportan exactamente como cualquier otro objeto.

Sin embargo, String s son inmutables : no es una operación que modifica el valor de una cadena existente en el lugar, sin necesidad de crear un nuevo objeto. Por ejemplo, esto significa que s1 = s1 + "c" crea un nuevo objeto y reemplaza la referencia almacenada en s1 con una referencia a este nuevo objeto.

9

No es relevante si String se trata como una primitiva o como un objeto.

En el ejemplo String, la concatenación de dos cadenas produce una nueva instancia String, que luego se asigna a s1. La variable s2 aún hace referencia a la antigua (sin) instancia de Cadena.

Suponiendo que el CuentaBancaria tenían un método para establecer el equilibrio, lo que devuelve una nueva CuentaBancaria, su ejemplo podría tener este aspecto:

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = b1.createNewAccountWithBalance(0); // create and reference a new object 
System.out.println(b1.getBalance() + " " + b2.getBalance()); // prints "0 500" 
13

La diferencia entre su CuentaBancaria y una cadena es que una cadena es inmutable. No existe tal cosa como 'setValue()' o 'setContent()'. El ejemplo equivalente, con su cuenta bancaria sería:

BankAccount b1 = new BankAccount(500); // 500 is initial balance parameter 
BankAccount b2 = b1; // reference to the same object 
b1 = new BankAccount(0); 
System.out.println(b1.getBalance() + " " + s2.getBalance()); // prints "0 500" 

Así que si usted piensa que de esta manera (en realidad no lo hace el compilador, pero funcionalmente equivalente) el escenario de la concatenación de cadenas es:

String s1 = "ab"; 
String s2 = s1; 
s1 = new String("abc"); 
System.out.println(s1 + " " + s2); //prints "abc ab" 
9

De hecho, String es una clase y se asigna/pasa por referencia. Pero lo que es confuso es la declaración:

String s = "abc"; 

lo que sugiere que es una cadena primitve (como 'int x = 10;'); Pero eso es solo un atajo, la frase 'String s = "abc";' en realidad está compilado como 'String s = new String("abc");' Al igual que 'Integer x = 10;' se compila como 'Integer x = new Integer(10);'

Este mecanismo se llama 'boxeo'.

Y más confuso es: hay una clase 'Integer' y una primitiva 'int', pero cadena no tiene un equivalente primitiva (acabase char[] se acerca)

Sije de Haan

0
int s1 = 1; 
int s2 = s1; // copies value, not reference 
s1 = 42; 

System.out.println(s1 + " " + s2); // prints "1 42" 

No imprime "1 42" pero "42 1". Tenga en cuenta cada línea discreta.Primero s1 asigna 1, luego s2 asigna s1, que es 1 hasta ahora (suponga que java no vio la tercera línea aún). Entonces Java ve el tercera línea e inmediatamente c cambia s1 a 42. Después de eso se le dijo a java que imprima lo que sabe hasta ahora, y eso es s1 es 42 y s2 es 1 (el antiguo s1).

En cuanto a la cadena, sucede lo mismo.

String s1 = "ab"; 
String s2 = s1; 
s1 = s1 + "c"; 
System.out.println(s1 + " " + s2);// prints "abc ab". 

Fort cadena no necesariamente cambia s1 s1, sino más bien se refiere ahora a un nuevo objeto String en la memoria del montón, pero el objeto antiguo "ab" sigue ahí, con una nueva referencia de s2!

0

La afirmación

si Java trata a variables de cadena como referencias a cualquier otro objeto, la respuesta sería "abc abc"

es incorrecto. Java trata las variables de cadena como referencias a cualquier otro objeto. Strings son Objetos pero la respuesta es "abc ab" sin embargo.

El problema no es lo que hace el operador de asignación. El operador de asignación asigna una referencia a un objeto String en todos los casos en su ejemplo.

El problema es lo que hace el operador de concatenación ('+'). Crea un nuevo objeto String. Como otros han dicho, esto es necesario porque un objeto String es inmutable pero es un problema de comportamiento del operador y no simplemente porque String es inmutable. El operador de concatenación podría devolver un nuevo objeto incluso si un objeto String fuera mutable.

Por el contrario, en su segundo ejemplo, b1.setBalance (0) no crea un objeto nuevo, sino que modifica el objeto existente.

Cuestiones relacionadas