Sie sind auf Seite 1von 7

Item 51: Beware the performance of string concatenation

El operador de concatenacin de cadenas (+) es una forma conveniente de combinar


un par de cuerdas en uno. Est bien para generar una sola lnea de produccin o para
la construccin de la cadena representacin de una pequea, objeto de tamao fijo,
pero no escala. El uso de la cadena de operador de concatenacin varias veces para
concatenar cadenas n requiere tiempo cuadrtica Posada. Es una consecuencia
desafortunada del hecho de que las cadenas son inmutables (Artculo 15). Cuando se
concatenan dos cadenas, el contenido de ambas se copian.

Por ejemplo, considere el siguiente mtodo que construye una representacin de


cadena de un estado de cuenta concatenando varias veces una lnea para cada
elemento:

Este mtodo realiza abismalmente si el nmero de elementos es grande. Conseguir un


rendimiento aceptable, utilizar un StringBuilder en lugar de una cadena para
almacenar la declaracin en construccin. (La clase StringBuilder, aadido en la
versin 1.5, es un reemplazo desincronizado durante StringBuffer, que ahora es
obsoleto.)
La diferencia de rendimiento es dramtico. Si nmArtculos devuelve 100 y lineForItem
devuelve una cadena de 80 caracteres constante, el segundo mtodo es ochenta y
cinco veces ms rpido que el primero en mi mquina. Debido a que el primer mtodo
es cuadrtica en el nmero de artculos y el segundo es lineal, el rendimiento la
diferencia es an ms dramtico para un mayor nmero de artculos. Tenga en cuenta
que la segunda Mtodo preasigna un StringBuilder suficientemente grande para
contener el resultado. Incluso si es desafinado utilizar un StringBuilder de tamao
predeterminado, todava es cincuenta veces ms rpido. La moraleja es simple: no
utilice el operador de concatenacin de cadenas para combinar ms de unas pocas
cadenas a no ser que el rendimiento es irrelevante. El uso de StringBuilder anexar
mtodo en su lugar. Como alternativa, utilice una matriz de caracteres, o procesar las
cuerdas uno a la vez en lugar de la combinacin de ellos.

EJEMPLO

public class MyClass {


public static void main(String[] args) {

int count = 1000;


String str="";
long startTime = System.nanoTime();
for (int i = 0; i < count; i++)
{
str = str + "core"; // String concatenation
}
long estimatedTime = System.nanoTime() - startTime;
System.out.println("+ operator:" + estimatedTime);

startTime = System.nanoTime();
for (int i = 0; i < count; i++)
{
str = str.concat("core");
}
estimatedTime = System.nanoTime() - startTime;
System.out.println("concat method:" + estimatedTime);

StringBuilder sb = new StringBuilder();


startTime = System.nanoTime();
for (int i = 0; i < count; i++)
{
sb.append("core");
}
str=sb.toString();
estimatedTime = System.nanoTime() - startTime;
System.out.println("StringBuilder:" + estimatedTime);

StringBuffer sbuf = new StringBuffer();


startTime = System.nanoTime();
for (int i = 0; i < count; i++)
{
sbuf.append("core");

}
str=sbuf.toString();
estimatedTime = System.nanoTime() - startTime;
System.out.println("StringBuffer:" + estimatedTime);
}
}

Item 52: Refer to objects by their interfaces


Tema 40 contiene los consejos que usted debe utilizar interfaces ms que clases como
tipos de parmetros. De manera ms general, se debe favorecer el uso de las
interfaces en lugar de clases para referirse a objetos. Si existen tipos de interfaces
apropiadas, a continuacin, los parmetros, Los valores de retorno, variables y
campos de todo deben ser declaradas usando la interfaz tipos. La nica vez que
realmente necesita para hacer referencia a la clase de un objeto es cuando ests crear
con un constructor. Para hacer este concreto, consideremos el caso de Vector, que es
una implementacin de la interfaz de lista. Adquiera el hbito de escribir esto:

En lugar de esto:

Si usted entra en el hbito de usar interfaces son tipos, su programa ser mucho ms
flexible. Si decide que desea cambiar implementaciones, todos usted tiene que hacer
es cambiar el nombre de la clase en el constructor (o utilizar una esttica diferente
fbrica). Por ejemplo, la primera declaracin podra ser cambiado para leer

y todo el cdigo que rodea seguir trabajando. El cdigo de los alrededores era
desconocen el tipo antiguo de aplicacin, por lo que sera ajeno al cambio. Hay una
advertencia: si la aplicacin original ofreca algunas funciones especiales no es
requerido por el contrato general de la interfaz y el cdigo dependa de que la
funcionalidad, entonces es fundamental que la nueva implementacin proporcionar la
misma funcionalidad. Por ejemplo, si el cdigo que rodea a la primera declaracin
dependido de la poltica de la sincronizacin del vector, entonces sera incorrecto
ArrayList sustituto del vector en la declaracin. Si depende de ningn dao especial
propiedades de una aplicacin, documentan las mismas cuando se declaran la
variable.

Entonces, por qu quieres cambiar las implementaciones? Debido a que la nueva


implementacin ofrece un mejor rendimiento o porque ofrece una funcionalidad
adicional deseable. Un ejemplo del mundo real se refiere a la clase ThreadLocal.
Internamente, esta clase utiliza un campo del mapa paquete-privada en Tema a
asociar valores por hilo con
ThreadLocal casos. En la versin 1.3, este campo se inicializa a un HashMap ejemplo.
En la versin 1.4, una implementacin mapa nuevo, de uso especial, llamado
IdentityHashMap, se aadi a la plataforma. Al cambiar una sola lnea de cdigo para
inicializar el campo a un IdentityHashMap en lugar de un HashMap, la ThreadLocal
instalacin se hizo ms rpido. ya que la aplicacin ha evolucionado ThreadLocal
dirigirse a un estudio altamente optimizado que no implementa la interfaz del mapa,
pero esto no hace nada para disminuir el punto.
El campo haba sido declarado como un HashMap en lugar de un mapa, no hay
garanta que un cambio de una sola lnea habra sido suficiente. Si el cdigo de cliente
tena HashMap operaciones usadas que no estaban presentes en la interfaz de mapa
o hayan superado la asignar a un mtodo que exiga un HashMap, el cdigo sera si
no pudiera compilar el campo se cambiaron a un IdentityHashMap. Declarando el
campo con la interfaz Tipo "mantiene honesto."
Es totalmente apropiado para referirse a un objeto por una clase en lugar de una
interconectarse si no existe una interfaz apropiada. Por ejemplo, considere el valor
clases, como String y BigInteger. clases de valores rara vez se escriben con mltiples
implementaciones en mente. Ellos son a menudo final y rara vez tienen sus
correspondientes interfaces. Es perfectamente apropiado utilizar una clase, tales como
un valor parmetros, variables, campo o tipo de retorno. Ms en general, si una clase
concreta no tiene interfaz asociada, entonces no tiene ms remedio que referirse a ella
por su clase si es o no representa un valor. La clase Random entra en esta categora.
Un segundo caso en el que no hay ningn tipo de interfaz adecuada es la de los
objetos perteneciente a un marco cuyos tipos fundamentales son clases en lugar de
interfaces. Si un objeto pertenece a un marco basado en clases, es preferible se
refieren a ella por la clase de base pertinente, que es tpicamente abstracta, ms que
por su clase de implementacin. La clase java.util.TimerTask entra en esta categora.
Un ltimo caso en el que no hay ningn tipo de interfaz apropiado es el de clases que
implementan una interfaz pero proporcionan mtodos adicionales que no se
encuentran en el interface- por ejemplo, LinkedHashMap. una clase de este tipo debe
ser utilizado para referirse a sus instancias slo si el programa se basa en los mtodos
adicionales. Rara vez se debe utilizar como una tipo de parmetro (artculo 40).
Estos casos no estn destinados a ser exhaustiva, sino simplemente para transmitir el
sabor de situaciones en las que es apropiado hacer referencia a un objeto por su
clase. En la prctica, debe ser evidente si un objeto dado tiene una interfaz adecuada.
Si lo hace, su programa ser ms flexible si se utiliza la interfaz para referirse al
objeto; Si No, slo tiene que utilizar la clase menos especfico en la jerarqua de clases
que proporciona la necesaria funcionalidad.

Item 53: Prefer interfaces to reflection


La facilidad de la base de reflexin, java.lang.reflect, ofrece acceso mediante
programacin a informacin acerca de las clases cargadas. Dado un objeto de la
clase, se puede obtener Constructor, Mtodo y campo instancias que representan a
los constructores, mtodos y campos de la clase representada por la instancia de la
clase. Estos objetos proporcionan programtica acceso a los nombres de la clase de
miembro, tipos de campo, firmas de mtodo, y as sucesivamente. Por otra parte, las
instancias del constructor, mtodo y de campo permiten manipular sus homlogos
subyacentes reflexivamente: se puede construir casos, invocan mtodos y campos de
acceso de la clase subyacente por mtodos que invocan en el Constructor, mtodo y
campo instancias. Por ejemplo, permite Method.invoke se invoca un mtodo en
cualquier objeto de cualquier clase (sujeto a la seguridad habitual restricciones).
Reflexin permite una clase que se utiliza otra, incluso si la ltima clase hizo no existe
cuando el primero fue compilado. Este poder, sin embargo, tiene un precio:
Se pierde todos los beneficios de la comprobacin de tipos en tiempo de compilacin,
incluida la excepcin comprobacin. Si un programa intenta invocar un mtodo
inexistente o inaccesible reflexivamente, se producir un error en tiempo de ejecucin,
a menos que haya tomado precauciones especiales. El cdigo necesario para
realizar el acceso reflectante es torpe y prolijo. Es tedioso de escribir y difcil de leer.
El rendimiento se resiente. Reflectante invocacin del mtodo es mucho ms lento que
invocacin del mtodo normal. Exactamente cunto ms lenta es difcil de decir,
porque hay tantos factores en juego. En mi mquina, la diferencia de velocidad puede
ser tan pequeo como un factor de dos o tan grande como un factor de cincuenta. La
facilidad de la base de reflexin fue diseado originalmente para el basadas
componente la herramienta de desarrollo. Estas herramientas generalmente cargan
las clases de la demanda y el uso reflexin para saber qu mtodos y constructores
que apoyan. Las herramientas permiten sus usuarios construyen de forma interactiva
aplicaciones que acceden a estas clases, pero la aplicaciones generadas acceder a
las clases normalmente, no reflexiva. La reflexin es utiliza slo en tiempo de diseo.
Por regla general, los objetos no se debera acceder reflexivamente en aplicaciones
normales en tiempo de ejecucin. Hay algunas aplicaciones sofisticadas que requieren
reflexin. Ejemplos incluir los navegadores de clase, los inspectores de objetos,
herramientas de anlisis de cdigo, y interpretativo sistemas embebidos. La reflexin
tambin es apropiado para su uso en llamada a procedimiento remoto sistemas (RPC)
para eliminar la necesidad de que los compiladores de cdigo auxiliar. Si tiene
cualquier duda si su solicitud corresponde a una de estas categoras, es probable que
no lo hace.
Puede obtener muchos de los beneficios de la reflexin, mientras que incurrir en
algunos de sus costos mediante el uso de slo en una forma muy limitada. Para
muchos programas que deben utilizar una clase que no est disponible en tiempo de
compilacin, existe en tiempo de compilacin de una interfaz o superclase apropiados
que permitan refieren a la clase (artculo 52). Si esto es el caso, puede crear instancias
reflexivamente y acceder a ellos normalmente a travs de su interfaz o superclase. Si
el constructor adecuado no tiene parmetros, a continuacin, usted ni siquiera
necesita usar java.lang.reflect; la Class.newInstance mtodo proporciona la
funcionalidad requerida. Por ejemplo, aqu hay un programa que crea un conjunto

<String> instancia cuyo clase es especificado por el primer argumento de lnea de


comandos. El programa inserta la restante argumentos de lnea de comandos en el
conjunto y lo imprime. A pesar de primer argumento, el programa imprime el resto de
argumentos con los duplicados eliminados. El orden en que se imprimen estos
argumentos, sin embargo, depende de la clase especificada en el primer argumento.
Si especifica java.util.HashSet, son impresa con el fin aparentemente aleatoria; si
especifica java.util.TreeSet, son impreso en orden alfabtico, como los elementos de
una TreeSet se clasifican:

Si bien este programa es slo un juguete, la tcnica que demuestra es muy potente. El
programa de juguete puede ser fcilmente convertido en un probador conjunto
genrico que valida la implementacin conjunto especificado mediante la manipulacin
de uno o ms agresiva instancias y la comprobacin de que obedecen el contrato Set.
Del mismo modo, podra ser convertido en una herramienta de anlisis de rendimiento
conjunto genrico. De hecho, la tcnica es suficientemente poderosa para poner en
prctica un marco proveedor de servicios en toda regla (artculo 1). La mayora de las
veces, esta tcnica es todo lo que necesita en el camino de la reflexin. Este ejemplo
demuestra dos desventajas de la reflexin. En primer lugar, el ejemplo puede generar
tres errores de ejecucin, todos los cuales habran sido en tiempo de compilacin
errores si no se utiliza la instanciacin de reflexin. En segundo lugar, se necesita
veinte lneas de cdigo tedioso para generar una instancia de la clase de su nombre,
mientras que un constructor invocacin encajara perfectamente en una sola lnea.
Estas desventajas son, sin embargo, restringida a la parte del programa que crea una
instancia del objeto. Una vez instancia, es indistinguible de cualquier otra instancia
asignadas. En un programa real, la gran mayora del cdigo es por lo tanto no

afectada por este uso limitado de la reflexin. Si intenta compilar el programa, recibir
el mensaje de error siguiente:

Esta advertencia se refiere a el uso del programa de tipos genricos, pero no indica un
problema real. Para aprender la mejor manera de suprimir la advertencia, vase el
artculo 24. Otra cuestin que merece nota tangencial es el uso de este programa de
sistema. salida. Rara vez es apropiado llamar a este mtodo, que finaliza la totalidad
VM. Es, sin embargo, adecuada para la terminacin anormal de una utilidad de lnea
de comandos. Una legtima, si es poco frecuente, el uso de la reflexin es la gestin
de las dependencias de una clase de otras clases, mtodos o campos que pueden
estar ausentes en tiempo de ejecucin. Esto puede ser til si est escribiendo un
paquete que debe ejecutarse para mltiples versiones de alguna otra paquete. La
tcnica consiste en compilar el paquete contra el entorno mnimo necesario para
soportarla, por lo general la versin ms antigua, y para acceder a cualquier nueva
clases o mtodos reflexivamente. Para que esto funcione, usted tiene que tomar su
caso accin, si no existe una nueva clase o mtodo que est intentando tener acceso
en tiempo de ejecucin. La accin apropiada podra consistir en el uso de algn medio
alternativo para lograr el mismo objetivo o usar la funcionalidad reducida. En resumen,
la reflexin es un potente instalacin que se requiere para cierta sofisticado tareas de
programacin del sistema, pero tiene muchas desventajas. Si est escribiendo un
programa que tiene que trabajar con las clases desconocidas en tiempo de
compilacin, lo que debe, si es posible, el uso de la reflexin slo para crear instancias
de objetos, y acceder a los objetos usando alguna de las interfaces o superclase que
se conoce en tiempo de compilacin.

Das könnte Ihnen auch gefallen