martes, 18 de mayo de 2010

operador +, cadenas, cadenas constante y el compilador en Java

"Mucho ayuda el que no estorba"

El uso de cadenas, en un sistema es casi inevitable, pues las personas en general leen y escriben cadenas, independientemente de que estas representen fechas, numeros, palabras, etc.

La generacion de estas cadenas, repercute negativamente en el desempeño de una aplicacion o sistema, sobre todo, cuando se generan y utilizan de manera incorrecta o excesiva.

Un ejemplo es el operador + en el lenguaje de programacion, que cuando es correctamente empleado, puede no ser una carga excesiva, pero cuando se emplea incorrectamete o se mal interpreta su utilizacion, puede provocar que se trabaje de manera excesiva, consumiendo tiempo de procesamiento y memoria indiscriminadamente.

La mayoria de los lenguajes compilados, como Java, particularmente, los que no soportan sobrecarga de operadores por programacion, convierten las instrucciones que tienen el operador + cuando estan operando con cadenas, en objetos y/o funciones. Sin embargo, el compilador, puede tener la capacidad de manipular el codigo resultante, para minimizar el uso de los recursos (memoria y procesador)

En el siguiente codigo, se hace uso del operador +.




01: package test;
02: 
03: public class StringTest {
04:         public static void main(String[] args) {
05:                 String a = "cadena1";
06:                 String b = "cadena2";
07:                 String c = a + b;
08:                 System.out.println(c);
09:         }
10: }
11: 

Posteriormente ejecutamos los siguientes comandos:

   javac test\StringBuilderTest.java

   javap -c -classpath . test.StringTest

Obteniendo el siguiente codigo:

Compiled from "StringTest.java"
   public class test.StringTest extends java.lang.Object{
   public test.StringTest();
   Code:
   0: aload_0
   1: invokespecial #8; //Method java/lang/Object."<init>":()V
   4: return

   public static void main(java.lang.String[]);
   Code:
   0: ldc #16; //String cadena1
   2: astore_1
   3: ldc #18; //String cadena2
   5: astore_2
   6: new #20; //class java/lang/StringBuilder
   9: dup
   10: aload_1
   11: invokestatic #22; //Method java/lang/String.valueOf:(Ljava/lang/Object;)Ljava/lang/String;
   14: invokespecial #28; //Method java/lang/StringBuilder."<init>":(Ljava/lang/String;)V
   17: aload_2
   18: invokevirtual #31; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
   21: invokevirtual #35; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
   24: astore_3
   25: getstatic #39; //Field java/lang/System.out:Ljava/io/PrintStream;
   28: aload_3
   29: invokevirtual #45; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   32: return
   }

Como se puede observar, el compilador, tradujo la sentencia con el operador + en el uso de la funcion valueOf, la creacion de un objeto StringBuilder, el uso de la funcion append y finalmente toString, es decir algo como esto:



01: package test;
02: 
03: public class StringTest2 {
04:         public static void main(String[] args) {
05:                 String a = "cadena1";
06:                 String b = "cadena2";
07:                 String c = new StringBuilder(String.valueOf(a)).append(b).toString();
08:                 System.out.println(c);
09:         }
10: }
11: 

Nosotros conocemos que se estan empleando constantes, por lo que podemos substituir la variable por el valor.


1: package test;
2: 
3: public class StringTest3 {
4:         public static void main(String[] args) {
5:                 String c = "cadena1" + "cadena2";
6:                 System.out.println(c);
7:         }
8: }
9: 

Ejecutamos la compilacion (javac) y de compilacion (javap), obteniendo lo siguiente:

Compiled from "StringTest3.java"
   public class test.StringTest3 extends java.lang.Object{
   public test.StringTest3();
   Code:
   0: aload_0
   1: invokespecial #8; //Method java/lang/Object."<init>":()V
   4: return

   public static void main(java.lang.String[]);
   Code:
   0: ldc #16; //String cadena1cadena2
   2: astore_1
   3: getstatic #18; //Field java/lang/System.out:Ljava/io/PrintStream;
   6: aload_1
   7: invokevirtual #24; //Method java/io/PrintStream.println:(Ljava/lang/String;)V
   10: return
   }

Este es el codigo equivalente, el cual genera el mismo codigo compilado, que el codigo anterior.



1: package test;
2: 
3: public class StringTest4 {
4:         public static void main(String[] args) {
5:                 String c = "cadena1cadena2";
6:                 System.out.println(c);
7:         }
8: }
9: 

Como se puede notar, cuando se utilizan constantes, el operador + y el compilador, pueden optimizar el codigo, siempre y cuando la constante este "inline". De ahi, la frase inicial "mucho ayuda el que no estorba", en ocasiones hay que dejar que el compilador haga su trabajo.

No hay comentarios.:

Publicar un comentario