sábado, 10 de marzo de 2012

String, StringBuffer y StringBuilder

votar
String, StringBuffer y StringBuilder son de las clases más utilizadas en programación Java, porque representan cadenas de caracteres y es difícil encontrar programas que no usen estas cadenas. En esta entrada vamos a explicar cuáles son las diferencias entre ellas, o más bien entre String y las otras dos, porque entre StringBuffer y StringBuilder sólo existe una diferencia, como veremos luego.

   Comencemos por la clase String. Los objetos de esta clase son inmutables, lo que significa que una vez creados no vas a poder modificarlos. Por ejemplo, si escribes

   String str = new String("Hola mundo"); //que originales que somos

ese "Hola mundo" queda "archivado" con str referenciándolo. Pero entonces, pensarás, si quieres añadirle algo a ese texto, ¿no puedes?. Sí, claro que puedes, pero no estarás modificando ese String, si no creando otro nuevo, por ejemplo

   str += " y parte del extranjero";

o utilizando el método .concat()

   str = str.concat(" y parte del extranjero");

te daría "Hola mundo y parte del extranjero", pero str ya no referenciaría a "Hola mundo", que quedaría "archivado", sin nada que lo referenciase, porque str ahora referenciaría al nuevo String.

   Veamos otro caso:

   String s1 = new String("abc");
   String s2 = new String("abc");

   ¿Cuántos objetos se han creado?. ¿Uno, dos?. En realidad, hay dos objetos de clase String creados por "new", pero un solo literal "abc". Para ahorrar memoria, los literales no se repiten, quedan "archivado" para futuros usos. Así que, aunque s1 y s2 no son iguales, porque son dos objetos distintos, si en lugar de usar new utilizamos sólo literales:

   String s1 = "abc";
   String s2 = "abc";

en este caso s1 == s2 porque referencian al mismo espacio en la memoria.

   Por último, si hacemos

   String s1 = "Hola mundo";
   String s2 = s1;
   s1 = s1.concat(" y parte del extranjero");

¿a qué se está refiriendo ahora s2?. Pues a "Hola mundo", porque s2 = s1 significa que los dos "apuntan" (no os riais los de C) a un mismo lugar en la memoria, y el nuevo s1 referencia ahora a otro lugar, con un nuevo String, pero s2 sigue refiriéndose al viejo, inmutable, "Hola mundo".

   Precisamente para asegurar la inmutabilidad de sus objetos, la clase String está marcada como final: sus métodos no pueden sobreescribirse.

   Llegamos así a la necesidad de las clases StringBuilder y StringBuffer: si tienes que hacer muchas modificaciones en tus objetos String, acabas con un montón de objetos inútiles ocupando espacio en la memoria. En cambio, los objetos de tipo StringBuffer y StringBuilder sí que pueden ser modificados.

   ¿Cuál es la diferencia entre los dos?. Bueno, los métodos de StringBuffer están sincronizados, y los de StringBuilder no. Eso significa que StringBuilder es más rápido, pero que si trabajas con programación multihebra es mejor que uses StringBuffer. Por lo demás son exactamente iguales y tienen la misma API.

   Veamos su diferencia con la clase String con un ejemplo:

   String s = "Hola mundo";
   s.concat(" y parte del extranjero";
   System.out.println(s);

   ¿Cuál será la salida?. ¡Pues "Hola mundo", porque no hemos asignado el nuevo String a s así:

   s = s.concat(" y parte del extranjero");

   Sin embargo, con StringBuffer: 

   StringBuffer sb = new StringBuffer( "Hola mundo");
   sb.append(" y parte del extranjero");//append hace lo mismo que concat
   System.out.println("sb: " + sb);

   La salida es "Hola mundo y parte del extranjero", porque hemos modificado sb.

   A continuación os dejamos un programita para mostrar algunos de los usos y métodos de estas clases. Consiste en averiguar si un String es palíndromo o no, es decir, si se puede leer igual hacia delante que hacia atrás. Para simplificarlo, hemos pasado de las tildes, pero podéis modificarlo a vuestro gusto.
import javax.swing.JOptionPane;
public class Palindromo{
   public static void main(String[] args){
      String s = JOptionPane.showInputDialog("Introduce una frase o palabra: ");
      String output = " ";
      s = s.replace(" ",""); //quitamos los espacios en blanco
      StringBuffer sb = new StringBuffer(s); //pasamos s como argumento a StringBuffer
      sb = sb.reverse(); //invertimos el orden de las letras
      if(s.equalsIgnoreCase(sb.toString())){ //comparamos sin importar si hay mayúsculas
         
         output = "Es un Palíndromo";
      }else{
         
         output = "No es un Palíndromo";
      }
      JOptionPane.showMessageDialog(null, output);
   }
}
   Si deseáis más información sobre estas clases y sus métodos, podéis acudir a los docs de Oracle
   Y como siempre, si tenéis alguna consulta, ya sabéis dónde estamos.; )

3 comentarios: