Sunteți pe pagina 1din 39

Pgina 1

141
CAPTULO
7
Programacin general
T
SU
captulo es dedicado en gran parte a los aspectos prcticos de la lengua. discute
el tratamiento de las variables locales, el uso de bibliotecas, el uso de varios tipos de
datos,
y el uso de dos instalaciones extralingsticas: reflexin y mtodos nativos. Por ltimo,
se
discute las convenciones de denominacin y de optimizacin.
Punto 29: Reducir al mnimo el alcance de las variables locales
Este artculo es de naturaleza similar a la del artculo 12, "Minimizar la accesibilidad de
las clases y
miembros ". B y minimizando el alcance de las variables locales, que aumentan la
legibilidad
y capacidad de mantenimiento de su cdigo y reducir la probabilidad de error.
Los mandatos de lenguaje de programacin C. que las variables locales deben ser
objeto de declaracin
a la cabeza de un bloque, y los programadores siguen hacerlo por costumbre; es un
hbito digno de ltima hora. Como recordatorio, el lenguaje de programacin Java que
permite
declarar variables en cualquier lugar una declaracin es legal.
El ms potente tcnica para reducir al mnimo el alcance de una variable local
es declarar que en el que se utiliz por primera vez. Si se declara una variable antes
de ser usado, es
simplemente el desorden-una cosa ms para distraer al lector que est tratando de
averiguar qu
el programa lo hace. Por el momento se utiliza la variable, el lector podra no recordar
tipo de la variable o el valor inicial. Si el programa evoluciona y la variable no est
Ya no se utiliza, es fcil olvidar retirar la declaracin si est muy alejada de
el punto de inicio del consumo.
No slo se puede declarar una variable local prematuramente causar su alcance para
extender
demasiado pronto, pero tambin demasiado tarde. El alcance de una variable local se
extiende desde el punto de
su declaracin hasta el final del bloque que lo contiene. Si se declara una variable fuera
de
el bloque en el que se utiliza, permanece visible despus de que el programa sale de ese
bloque.
Si se utiliza una variable accidentalmente antes o despus de su regin de uso previsto,
la con-
secuencias pueden ser desastrosos.

Pgina 2
CAPTULO 7 PROGRAMACIN GENERAL
142
Casi cada declaracin de variable local debe contener un inicializador. Si
an no tienen suficiente informacin para inicializar una variable con sensatez, que
debiera
posponer la declaracin hasta que lo haga. Una excepcin a esta regla preocupaciones
tratar
-
captura
declaraciones. Si una variable es inicializada por un mtodo que lanza una marcada
excepcin, debe inicializarse dentro de una
tratar
bloquear. Si se debe utilizar el valor
fuera de la
tratar
bloque, entonces debe ser declarada antes de la
tratar
bloque, donde
sin embargo, no puede ser "sensiblemente inicializado." Por ejemplo, ver la pgina
159 .
Bucles presentan una oportunidad especial para minimizar el alcance de las variables.
los
para
bucle le permite declarar variables de bucle, lo que limita su alcance a la exacta
regin donde se necesitan. (Esta regin consiste en el cuerpo del bucle, as
como la inicializacin, prueba y actualizacin anterior del cuerpo.) Por lo tanto
prefieren
para
bucles de
mientras
bucles, suponiendo que el contenido de la variable de bucle (s) no son necesarios
despus de que el bucle termina.
Por ejemplo, aqu es el idioma preferido para la iteracin en una coleccin:
for (i = iterador c.iterator (); i.hasNext ();) {
doSomething (i.next ());
}
Para ver por qu esto
para
bucle es preferible a la ms evidente
mientras
lazo, con-
Sider el siguiente fragmento de cdigo, que contiene dos
mientras
bucles y una bichos:
Iterator i = c.iterator ();
while (i.hasNext ()) {
doSomething (i.next ());
}
...
Iterador i2 = c2.iterator ();
mientras que (i .hasNext ()) {
// ERROR!
doSomethingElse (i2.next ());
}
El segundo bucle contiene un error de cortar y pegar: Se inicia un nuevo bucle
variable,
i2
, Sino que utiliza la antigua,
yo
, Que por desgracia sigue siendo en su alcance. los
resultando cdigo se compila sin error y se ejecuta sin lanzar una excepcin, pero
que hace las cosas mal. En lugar de una iteracin
c2
, El segundo bucle termina
de inmediato, dando la falsa impresin de que
c2
esta vacio. Debido a que el programa de
yerra en silencio, el error puede no ser detectados por un largo tiempo.
Si se cometi el error de cortar y pegar anloga en conjuncin con el pre
preferida
para
modismo bucle, el cdigo resultante no sera ni siquiera compilar. La variable de bucle

Pgina 3
ARTCULO 29: reducir al mximo las variables locales
143
capaz de la primera bucle no sera en su alcance en el punto en el segundo bucle
ocurri:
for (i = iterador c.iterator (); i.hasNext ();) {
doSomething (i.next ());
}
...
// Error en tiempo de compilacin - el smbolo i no puede resolverse
for (Iterator i2 = c2.iterator (); i .hasNext ();) {
doSomething (i2.next ());
}
Por otra parte, si se utiliza el
para
modismo bucle, es mucho menos probable que usted va a hacer
el error de cortar y pegar, ya que no hay incentivo para utilizar un nombre de variable
en diferentes
los dos bucles. Los bucles son completamente independientes, por lo que no hay dao
en reutilizable
ing el nombre de la variable de bucle. De hecho, es elegante para hacerlo.
los
para
idioma bucle tiene otra ventaja sobre la
mientras
modismo bucle, aunque
un menor de edad. los
para
modismo bucle es una lnea ms corta, lo que ayuda a que el que contiene
Mtodo de ajuste en una ventana del editor de tamao fijo, mejorando la legibilidad.
Aqu hay otro lenguaje de bucle para iterar sobre una lista que minimiza el alcance de
variables locales:
// Lenguaje de alto rendimiento para la iteracin en las listas de acceso al azar
for (int i = 0, n = list.size (); i <n; i ++) {
doSomething (list.get (i));
}
Este idioma es til para acceso aleatorio
Lista
implementaciones como
Formacin-
Lista
y
Vector
porque es probable que se ejecute ms rpido que el "idioma preferido" por encima
para dichas listas. Lo importante a notar acerca de este lenguaje es que tiene dos lazos
variables,
yo
y
norte
, Ambos de los cuales tienen exactamente el alcance adecuado. El uso de la seccin
OND variable es esencial para el rendimiento de la expresin. Sin l, el bucle
tendra que llamar a la
tamao
mtodo de una vez por iteracin, lo que invalidara la
ventaja de rendimiento del idioma. El uso de este lenguaje es aceptable cuando ests
de que la lista realmente proporciona acceso aleatorio; de lo contrario, se muestra
cuadrtica
actuacin.
Existen expresiones similares para otras tareas de bucle, por ejemplo,
for (int i = 0, n = expensiveComputation (); i <n; i ++) {
doSomething (i);
}

pgina 4
CAPTULO 7 PROGRAMACIN GENERAL
144
Una vez ms, este idioma utiliza dos variables de bucle, y la segunda variable,
norte
, se usa para
evitar el coste de la realizacin de clculo redundante en cada iteracin. Como una
regla,
usted debe utilizar este idioma si la prueba de bucle implica una invocacin de mtodo
y la
invocacin del mtodo est garantizado para devolver el mismo resultado en cada
iteracin.
Una tcnica final para minimizar el alcance de las variables locales es mantener
mtodos
pequea y enfocada. Si se combinan dos actividades en el mismo mtodo, variable
local,
ables correspondiente a una actividad puede estar en el mbito del cdigo que realiza la
otra
actividad. Para evitar que esto suceda, simplemente separar el mtodo en dos: una
para cada actividad.

pgina 5
ARTCULO 30: Conocer y utilizar las bibliotecas
145
Punto 30: Conocer y utilizar las bibliotecas
Supongamos que se desea generar nmeros aleatorios entre 0 y alguna cota superior.
Frente a esta tarea comn, muchos programadores escribir un pequeo mtodo que
es como la siguiente:
rnd aleatorio esttica = new Random ();
// Comn pero impreciso!
static int aleatorio (int n) {
volver Math.abs (rnd.nextInt ())% n;
}
Este mtodo no es malo, pero no es perfecto, ya sea-que tiene tres defectos. El primero
defecto es que si
norte
es una pequea potencia de dos, la secuencia de nmeros aleatorios de TI generacin
Ates se repetir despus de un perodo bastante corto. El segundo error es que si
norte
no es un
potencia de dos, algunos nmeros, en promedio, se devolver con ms frecuencia que
otros. Si
norte
es grande, este defecto puede ser bastante pronunciada. Esto es demostrado
grficamente
trado por el siguiente programa, que genera un milln de nmeros aleatorios en una
cuidadosamente elegido gama y luego imprime cuntos de los nmeros cayeron en el
la mitad inferior de la gama:
principales argumentos (String []) {public static void
int n = 2 * (Integer.MAX_VALUE / 3);
bajas = INT 0;
for (int i = 0; i <1000000; i ++)
si (al azar (n) <n / 2)
bajo ++;
System.out.println (bajo);
}
Si el
aleatorio
mtodo ha funcionado correctamente, el programa imprimir un nmero
cerca de medio milln, pero si lo ejecuta, usted encontrar que se imprime un nmero
cercano a
666,666. Dos tercios de los nmeros generados por el
aleatorio
cada en el mtodo
la mitad inferior de su gama!
El tercer defecto en el
aleatorio
mtodo es que puede, en raras ocasiones, fallar cata-
strophically, devolviendo un nmero fuera del rango especificado. Esto es as porque la
mtodo intenta asignar el valor devuelto por
rnd.nextInt ()
en un no negativo
con nmero entero
Math.abs
. Si
nextInt ()
devoluciones
Integer.MIN_VALUE
,
Math.abs
ser
tambin volver
Integer.MIN_VALUE
, Y el operador resto (
%
) Devolver un gativo

Pgina 6
CAPTULO 7 PROGRAMACIN GENERAL
146
nmero ativa, asumiendo
norte
no es una potencia de dos. Esto es casi seguro que causar
el programa falle, y el fracaso puede ser difcil de reproducir.
Para escribir una versin de
aleatorio
que corrige estos tres defectos, que tendra que
saber bastante sobre los generadores de nmeros pseudoaleatorios de congruencia
lineal,
la teora de nmeros y la aritmtica de complemento a dos. Afortunadamente, usted no
tiene que hacer
esto-que ya se ha hecho para usted. Se llama
Random.nextInt (int)
, y eso fue
aadido al paquete de biblioteca estndar
java.util
en la versin 1.2.
Usted no tiene que preocuparse por los detalles de cmo
nextInt (int)
hace su trabajo (aunque se puede estudiar la documentacin o el cdigo fuente si
eres mrbida curiosidad). Un ingeniero senior con experiencia en algoritmos
pasado una buena cantidad de tiempo en el diseo, implementacin y pruebas de este
mtodo y
a continuacin, se lo mostr a expertos en el campo para asegurarse de que estaba bien.
A continuacin, la biblioteca
fue probado la beta, lanzado y utilizado ampliamente por miles de programadores de
Varios aos. Sin defectos se han encontrado todava en el mtodo, pero si un defecto
fuese
descubierto, que se arreglara en la prxima versin. Mediante el uso de una
biblioteca estndar,
tomar ventaja de los conocimientos de los expertos que lo escribi y el
experiencia de los que lo utiliz antes.
Una segunda ventaja de la utilizacin de las bibliotecas es que usted no tiene que perder
su
tiempo escribiendo soluciones ad hoc a los problemas slo marginalmente relacionados
con su trabajo. Si
usted es como la mayora de los programadores, prefiere pasar su tiempo a trabajar en
su
aplicacin que en la instalacin de caeras subyacente.
Una tercera ventaja del uso de bibliotecas estndar es que su rendimiento tiende a
mejorar con el tiempo, sin ningn esfuerzo de su parte. Debido a que muchas personas
los utilizan
y porque estn acostumbrados en los puntos de referencia estndar de la industria, las
organizaciones que
suministrar estas bibliotecas tienen un fuerte incentivo para que funcionen ms rpido.
por
ejemplo, la biblioteca multiprecision aritmtica estndar,
java.math
, Fue reescrito
en la versin 1.3, lo que resulta en mejoras de rendimiento.
Las bibliotecas tambin tienden a ganar una nueva funcionalidad con el tiempo. Si una
clase de biblioteca es
faltan algunas funciones importantes, la comunidad de desarrolladores har que este
deficiencia conocida. La plataforma Java siempre ha sido desarrollado con sustancial
TIAL de entrada de esta comunidad. Anteriormente, el proceso fue informal; ahora
hay
un proceso formal en el lugar llamado el Java Community Process (JCP). De cualquier
manera,
caractersticas que faltan tienden a ser aadido con el tiempo.
Una ltima ventaja de la utilizacin de las bibliotecas estndar es que colocar el cdigo
en
la corriente principal. Dicho cdigo es ms fcil de leer, fcil de mantener y
reutilizable por
la multitud de desarrolladores.
Teniendo en cuenta todas estas ventajas, parece lgico utilizar en instalaciones de la
biblioteca
preferencia a las implementaciones especiales, sin embargo, una fraccin significativa
de los programadores

pgina 7
ARTCULO 30: Conocer y utilizar las bibliotecas
147
no lo hacen. Por qu? Tal vez no saben que existen las instalaciones de la biblioteca.
Numerosos
caractersticas se aaden a las bibliotecas en cada versin principal, y vale la pena
mantener
al corriente de estas adiciones. Usted puede leer la documentacin en lnea o leer
acerca de las bibliotecas en cualquier nmero de libros [J2SE-API, Chan00,
Flanagan99,
Chan98]. Las bibliotecas son demasiado grandes para estudiar toda la documentacin,
pero cada PRO-
gramtica debe estar familiarizado con el contenido de
java.lang
,
java.util,
y,
en un grado menor,
java.io
. El conocimiento de otras bibliotecas se puede adquirir en una
segn sea necesario.
Est ms all del alcance de este artculo para resumir todas las instalaciones en el
bibliotecario
IES, pero algunos llevan una mencin especial. En la versin 1.2, un marco de las
colecciones
se aadi a la
java.util
paquete. Debe ser parte de cada programador de
kit de herramientas bsicas. El marco de las colecciones es una arquitectura unificada
para representar
y la manipulacin de colecciones, lo que les permite ser manipulado de forma
independiente de
los detalles de su representacin. Reduce esfuerzo de programacin al tiempo que
aumenta
actuacin. Se permite la interoperabilidad entre los AIP no relacionados, reduce el
esfuerzo
en el diseo y el aprendizaje de nuevas API, y fomenta la reutilizacin del software.
El marco se basa en seis interfaces de la coleccin (
Coleccin
,
Conjunto
,
Lista
,
Mapa
,
SortedList
y
SortedMap
). Incluye implementaciones de estas interfaces
y algoritmos para manipularlos. Las clases de coleccin legado,
Vector
y
Tabla de picadillo
, Fueron adaptados a participar en el marco, por lo que no tiene que
abandonarlos para aprovechar el marco.
El marco de las colecciones reduce sustancialmente la cantidad de cdigo sario
sario para hacer muchas tareas mundanas. Por ejemplo, suponga que tiene un vector de
cuerdas, y que desea ordenar por orden alfabtico. Esta sola lnea hace el trabajo:
Collections.sort (v);
Si usted quiere hacer lo mismo haciendo caso omiso de las distinciones de casos,
utilizar lo siguiente:
Collections.sort (v, String.CASE_INSENSITIVE_ORDER);
Supongamos que desea imprimir todos los elementos de una matriz. muchos
programa-
meros utilizan una
para
lazo, pero no es necesario si se utiliza el siguiente lenguaje:
System.out.println (Arrays.asList (a));
Por ltimo, supongamos que desea conocer todas las claves de los cuales dos
Tabla de picadillo
instancias,
h1
y
h2
, Contienen las mismas asignaciones. Antes de las Colecciones

pgina 8
CAPTULO 7 PROGRAMACIN GENERAL
148
Se aadi marco, esto habra requerido una buena cantidad de cdigo, pero ahora
tiene tres lneas:
Mapa tmp = new HashMap (h1);
. tmp.entrySet () retainAll (h2.entrySet ());
Conjunto de resultados = tmp.keySet ();
Los anteriores ejemplos apenas araan la superficie de lo que puede hacer con
el marco de las colecciones. Si quiere saber ms, consulte la documentacin
El sitio Web de Sun [ Colecciones] o leer el tutorial [Bloch99].
Una biblioteca de terceros digno de mencin es Doug Lea de
util.concurrent
[Lea01], que proporciona servicios pblicos de concurrencia de alto nivel para
simplificar la tarea de
la programacin multihilo.
Hay muchas adiciones a las bibliotecas en la liberacin 1.4. adiciones notables
Incluya lo siguiente:

java.util.regex
-A Instalacin de expresin en toda regla como las de Perl regular.

java.util.prefs
-A Las instalaciones para el almacenamiento persistente de las preferencias del usuario
y datos de configuracin de programa.

java.nio
-Un Alto rendimiento de E / S instalaciones, incluyendo escalable de E / S (similar a
Unix
encuesta
llamada) y E / S mapeada en memoria (similar a la de Unix
mmap
llamada).

java.util.LinkedHashSet
,
LinkedHashMap
,
IdentityHashMap
colaboracin -New
implementaciones lection.
De vez en cuando, una planta de la biblioteca puede fallar para satisfacer sus
necesidades. Cuanto ms especializado
zado sus necesidades, lo ms probable es que suceda esto. Mientras que su primer
impulso debe
ser el uso de las bibliotecas, si has visto lo que tienen que ofrecer en algn rea y
no se ajusta a sus necesidades, utilizar una implementacin alternativa. Siempre estara
agujeros en la funcionalidad proporcionada por cualquier conjunto finito de bibliotecas.
Si la funcionalidad
que necesita no se encuentra, es posible que tenga ms remedio que aplicar por s
mismo.
Para resumir, no reinventar la rueda. Si tiene que hacer algo que
Parece bastante comn, puede haber ya una clase en las bibliotecas que lo hace
Lo que quieras. Si existe, lo utilizan; Si usted no sabe, el registro. Generalmente
hablando,
cdigo de la biblioteca es probable que sea mejor que el cdigo que iba a escribir usted
mismo y es probable
mejorando con el tiempo. Esto no es un reflejo de sus habilidades como programador;
economas de escala que dictan cdigo de la biblioteca recibe mucha ms atencin que
la
desarrollador promedio podra permitirse el lujo de dedicar a la misma funcionalidad.

pgina 9
ARTCULO 31: EVITAR float y double SI SE REQUIERE respuestas exactas
149
Tema 31: Evitar
flotador
y
doble
si se requieren respuestas exactas
los
flotador
y
doble
tipos estn diseados principalmente para los cientficos e ingenieros
clculos. Llevan a cabo la aritmtica de punto flotante binario, que fue
cuidadosamente
diseado para proporcionar aproximaciones precisas rpidamente sobre una amplia
gama de mag-
tudes. No lo hacen, sin embargo, proporcionan resultados exactos y no deben ser
utilizados cuando
se requieren resultados exactos. La
flotador
y
doble
tipos son particularmente mal adaptado
para los clculos monetarios, ya que es imposible de representar 0,1 (o cualquier otro
potencia negativa de diez) como una
flotador
o
doble
exactamente.
Por ejemplo, suponga que tiene $ 1,03 en el bolsillo, y pasar 42 .
Cunto dinero le queda? He aqu un fragmento de programa que ingenua
los intentos de responder a esta pregunta:
System.out.println (1.03 - .42);
Por desgracia, imprime ,6100000000000001. Este no es un caso aislado.
Suponga que tiene un dlar en el bolsillo, y de comprar nueve arandelas a un precio de
diez
centavos cada una. Cunto cambio se puede conseguir?
System.out.println (1,00 - 0,10 9 *);
De acuerdo con este fragmento de programa, se obtiene $ ,09999999999999995. T
podra pensar que el problema podra resolverse simplemente redondeando los
resultados antes de la
impresin, pero por desgracia esto no siempre funciona. Por ejemplo, supongamos
tener un dlar en el bolsillo, y ves un estante con una fila de deliciosos dulces
a un precio de 10 , 20 , 30 , y as sucesivamente, hasta un dlar. Usted compra una
de cada dulce,
comenzando con el que cuesta 10 , hasta que no puede permitirse el lujo de comprar el
caramelo en la prxima
el estante. Cuntos caramelos se debe comprar, y cunto cambio se puede conseguir?
He aqu un programa ingenua diseado para resolver este problema:
// Broken - utiliza coma flotante para el clculo monetario!
principales argumentos (String []) {public static void
los fondos dobles = 1,00;
int itemsBought = 0;
para (doble precio = 0,10; fondos de> = precio, precio + = .10) {
fondos - = precio;
itemsBought ++;
}
System.out.println (itemsBought + "los artculos comprados.");
System.out.println ( "Cambio: $" + fondos);
}

pgina 10
CAPTULO 7 PROGRAMACIN GENERAL
150
Si ejecuta el programa, usted encontrar que usted puede permitirse tres piezas de
dulces,
y usted tiene $ ,3999999999999999 izquierda. Esta es la respuesta equivocada! El
derecho
manera de resolver este problema es utilizar
BigDecimal
,
int
o
largo
para monetaria
clculos. He aqu una simple transformacin del programa anterior para
utilizar el
BigDecimal
tipo en el lugar de
doble
:
principales argumentos (String []) {public static void
ltima BigDecimal TEN_CENTS = new BigDecimal ( "10");
int itemsBought = 0;
Fondos BigDecimal = new BigDecimal ( "1.00");
para BigDecimal (= precio TEN_CENTS;
funds.compareTo (precio)> = 0;
precio = price.add (TEN_CENTS)) {
itemsBought ++;
los fondos = funds.subtract (precio);
}
System.out.println (itemsBought + "los artculos comprados.");
System.out.println ( "dinero de sobra: $" + fondos);
}
Si ejecuta el programa revisado, usted encontrar que usted puede permitirse cuatro
piezas de
caramelo, con $ 0,00 sobra. Esta es la respuesta correcta. Hay, sin embargo, dos
desventajas en el uso
BigDecimal
: Es menos conveniente que usar una primitiva
tipo aritmtico, y su lento. Este ltimo inconveniente es irrelevante si ests solv-
ing un solo problema a corto, pero el primero que puede molestar.
Una alternativa al uso
BigDecimal
es utilizar
int
o
largo
, dependiendo de
cuanta de las operaciones, y para realizar un seguimiento del punto decimal apuntar a
s mismo. En este ejem-
plo, el enfoque obvio es hacer todo el clculo en centavos en lugar de dlares.
He aqu una simple transformacin del programa se acaba de mostrar que lleva este
enfoque:
principales argumentos (String []) {public static void
int itemsBought = 0;
fondos int = 100;
for (int precio = 10; los fondos> = precio, precio + = 10) {
itemsBought ++;
fondos - = precio;
}
System.out.println (itemsBought + "los artculos comprados.");
System.out.println ( "dinero de sobra:" + + fondos "centavos");
}

pgina 11
ARTCULO 31: EVITAR float y double SI SE REQUIERE respuestas exactas
151
En resumen, no utilice
flotador
o
doble
para todos los clculos que requieren una
respuesta exacta. Utilizar
BigDecimal
si desea que el sistema para realizar un seguimiento del punto decimal
apuntar y no le importa el inconveniente de no usar un tipo primitivo. Utilizando
BigDecimal
tiene la ventaja aadida de que se le da un control total sobre el redondeo,
lo que le permite seleccionar entre ocho modos de redondeo siempre que una operacin
que conlleva
redondeo se realiza. Esto viene muy bien el negocio si usted est realizando
clculos con el comportamiento de redondeo por mandato legal. Si el rendimiento es
del
Esencialmente, si no te importa no perder de vista el punto decimal a s mismo, y si el
cantidades no son demasiado grandes, el uso
int
o
largo
. Si las cantidades no excedan de nueve
dgitos decimales, se puede utilizar
int
; si no superen dieciocho dgitos, puede utilizar
largo
. Si las cantidades superen el diez y ocho dgitos, debe utilizar
BigDecimal
.

pgina 12
CAPTULO 7 PROGRAMACIN GENERAL
152
Cuestin 32: Evitar cuerdas donde otros tipos son ms apropiadas
Las cadenas estn diseadas para representar texto, y hacen un buen trabajo de ella.
Debido a que las cadenas
son tan comunes y tan bien con el apoyo de la lengua, hay una tendencia natural a
utilizar cadenas para fines distintos de aquellos para los que fueron diseados. ste
tem
discute algunas cosas que no se debe hacer con las cadenas.
Las cadenas son pobres sustitutos de otros tipos de valores. Cuando una pieza de
datos
entra en un programa de un archivo, desde la red, o desde la entrada de teclado, que es
a menudo en forma de cadena. Hay una tendencia natural a dejarlo as, pero esta
tensin
dencia slo se justifica si realmente es textual en la naturaleza. Si es numrico, debe
ser
traducido en el tipo numrico apropiado, tal como
int
,
flotador
o
BigInteger
.
Si se trata de la respuesta a un s-o-no, debera traducirse en una
booleano
.
Ms en general, si hay un tipo de valor adecuado, ya sea primitiva o un objeto
referencia, se debe utilizar; si no hay, debe escribir uno. Si bien este consejo
puede parecer obvio, a menudo se viol.
Las cadenas son pobres sustitutos de los tipos enumerados. Como se discuti en la
partida 21 ,
ambas enumeraciones y typesafe
int
valores hacen constantes de tipo mucho mejor enumerados
que los cordajes.
Las cadenas son pobres sustitutos de tipos de agregados. Si una entidad tiene
mltiples
componentes, por lo general es una mala idea para representarla como una sola cadena.
Por ejemplo,
he aqu una lnea de cdigo que viene de un verdadero sistema de identificador de
nombres han sido
cambiados para proteger a los culpables:
// El uso inapropiado de la cadena como tipo de agregado
Cadena compoundKey = className + "#" + i.next ();
Este enfoque tiene muchas desventajas. Si el carcter utilizado para separar los campos
se produce en uno de los campos, el caos puede resultar. Para acceder a los campos
individuales, usted tiene
para analizar la cadena, que es lento, tedioso y propenso a errores. No se puede dar
es igual
,
Encadenar
o
comparar con
mtodos pero se ven obligados a aceptar el comportamiento
ese
Cuerda
proporciona. Un mejor enfoque es simplemente escribir una clase para representar el
agregado, a menudo un miembro de la clase esttica privada ( artculo 18) .
Las cadenas son pobres sustitutos de capacidades. De vez en cuando, se utilizan
cuerdas
para conceder acceso a algunas funciones. Por ejemplo, considere el diseo de una
local de subprocesos instalacin variable. Una instalacin de este tipo proporciona
variables para cada uno de los cuales
hilo tiene su propio valor. Cuando se enfrentan con el diseo de una instalacin de este
tipo varios

pgina 13
ARTCULO 32: EVITAR CUERDAS DONDE OTROS TIPOS son ms apropiados
153
Hace aos, varias personas llegaron de forma independiente con el mismo diseo en el
que
claves de cadena provista por el cliente permiten el acceso al contenido de una variable
local de subprocesos:
// Broken - uso inadecuado de cuerdas como la capacidad!
public class {ThreadLocal
ThreadLocal privada () {} // no instanciables
// Establece el valor del hilo actual para la variable llamada.
conjunto public void (String key, Object value);
// Devuelve el valor del hilo actual para la variable llamada.
Get public static Object (String key);
}
El problema con este enfoque es que las teclas representan una compartida global
espacio de nombres. Si dos clientes independientes del paquete deciden utilizar el
mismo nombre
por su variable de subproceso local, que sin querer compartir la variable, que se
en general, causar tanto a los clientes a fallar. Adems, la seguridad es deficiente; un
cliente malicioso
podan usar la misma clave que otro cliente para obtener acceso ilcito a la
datos de otros clientes.
Esta API se puede solucionar mediante la sustitucin de la cadena con una clave
infalsificable (alguien
veces llamado una capacidad):
public class {ThreadLocal
ThreadLocal privada () {} // no instanciables
Clave de clase public static {
Llave() { }
}
// Genera una clave nica, infalsificable
getKey clave static () {
volver nueva clave ();
}
conjunto public void (clave Key, del valor del objeto);
Get public static Object (clave Key);
}
Aunque esto resuelve los dos problemas con la API basado en cadena, que puede hacer
mejor. Usted realmente no necesita los mtodos estticos ms. En su lugar, puede
convertido en los mtodos de instancia en la tecla, momento en el que la clave ya no es
una clave: se
es una variable local de subprocesos. En este punto, la clase de nivel superior no
instanciable no es

pgina 14
CAPTULO 7 PROGRAMACIN GENERAL
154
hacer nada ms para usted, por lo que tambin podra deshacerse de l y cambiar el
nombre
clase anidada de
ThreadLocal
:
public class {ThreadLocal
ThreadLocal pblica () {}
conjunto public void (Object value);
Get public Object ();
}
Esto es, a grandes rasgos, la API que
java.util.ThreadLocal
proporciona. En
Adems de resolver los problemas con la API basado en cadena, es ms rpido y ms
elegante que cualquiera de las API basadas en clave.
En resumen, evitar la tendencia natural para representar los objetos como cuerdas
cuando
existen mejores tipos de datos o pueden ser escritos. Utilizados de manera inapropiada,
las cadenas son ms
engorroso, menos flexible, ms lento y ms propenso a errores que otros tipos. tipos
para los que las cadenas son mal utilizados comnmente incluyen tipos primitivos,
enumerados
tipos y tipos de agregados.

pgina 15
ARTCULO 33: CUIDADO CON EL RENDIMIENTO DE concatenacin de cadenas
155
Tema 33: Cuidado con el rendimiento de la concatenacin de cadenas
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 cali-
cuadrtico n. Es una desafortunada consecuencia del hecho de que las cadenas son
inmutables
( Punto 13) . Cuando se concatenan dos cadenas, el contenido de ambas se copian.
Por ejemplo, considere el siguiente mtodo que construye una cadena de representacin
tacin de un estado de cuenta concatenando varias veces una lnea para cada elemento:
// El uso inapropiado de la concatenacin de cadenas - Realiza horrible!
declaracin public String () {
String s = "";
for (int i = 0; i <nmArtculos (); i ++)
s + = lineForItem (i); // La concatenacin de cadenas
devoluciones;
}
Este mtodo realiza abismalmente si el nmero de elementos es grande. Para lograr
rendimiento aceptable, utilice una
StringBuffer
en lugar de un
Cuerda
para almacenar la
declaracin en construccin:
declaracin public String () {
StringBuffer s = new StringBuffer (nmArtculos () * line_width);
for (int i = 0; i <nmArtculos (); i ++)
s.append (lineForItem (i));
s.toString volver ();
}
La diferencia de rendimiento es dramtico. Si
nmArtculos
devuelve 100 y
lineForItem
devuelve una cadena de 80 caracteres constante, el segundo mtodo es noventa
veces ms rpido en mi mquina que el primero. Debido a que el primer mtodo es
cuadrtica en
el nmero de elementos y el segundo es lineal, la diferencia de rendimiento es an
ms dramtica para un mayor nmero de elementos. Tenga en cuenta que el segundo
mtodo
preasigna una
StringBuffer
suficientemente grande para contener el resultado. Incluso si es desafinada
utilizar un tamao predeterminado,
StringBuffer
, Todava es cuarenta y cinco veces ms rpido que el primero.
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. Utilizar
StringBuffer
's
adjuntar
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.

pgina 16
CAPTULO 7 PROGRAMACIN GENERAL
156
Tema 34: referirse a los objetos por sus interfaces
Punto 25 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 interfaz apropiada, parmetros,
valores de retorno, variables y campos de todo deben ser declaradas usando tipos
de interfaz.
La nica vez que realmente necesita para hacer referencia a la clase de un objeto es
cuando se est creando.
Para hacer este concreto, consideremos el caso de
Vector
, Que es una implementacin de
el
Lista
interfaz. Adquiera el hbito de escribir esto:
// Bueno - utiliza como tipo de interfaz
Suscriptores de la lista = new Vector ();
en lugar de esto:
// Bad - utiliza la clase de tipo!
Vector abonados = new Vector ();
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
Suscriptores de la lista = new ArrayList ();
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 alguna funcin especial
cionalidad no exigir el contrato general de la interfaz y el cdigo
dependa de que la funcionalidad, entonces es fundamental que la nueva aplicacin pro-
cionar la misma funcionalidad. Por ejemplo, si el cdigo que rodea a la primera
declaracin
la dependa del hecho de que
Vector
est sincronizado, entonces sera incorrecto
sustituir
Lista de arreglo
para
Vector
en la declaracin.
Entonces, por qu quieres cambiar las implementaciones? Debido a que la nueva cin
mentacin ofrece un mejor rendimiento o deseable, ya que ofrece funcionalidad
adicional
dad. Un ejemplo del mundo real se refiere a la
ThreadLocal
clase. Internamente, esta clase
utiliza un paquete-privada
Mapa
campo en
Hilo
para asociar valores por hilo con
ThreadLocal
instancias. En la versin 1.3, este campo se inicializa a un
HashMap
ejemplo. En la versin 1.4, una nueva, de uso especial
Mapa
aplicacin, llamado

pgina 17
ARTCULO 34: se refieren a objetos POR SUS INTERFACES
157
IdentityHashMap
, Se aadi a la plataforma. Al cambiar una sola lnea de cdigo
para inicializar el campo a una
IdentityHashMap
en lugar de un
HashMap
, el
ThreadLo-
California
instalacin se hizo ms rpido.
Haba sido declarado el campo como una
HashMap
en lugar de un
Mapa
, No hay ga-
camiseta que un cambio de una sola lnea habra sido suficiente. Si el cdigo de cliente
tena
usado
HashMap
operaciones fuera de la
Mapa
interfaz o se pasa el mapa para una
mtodo que exige una
HashMap
, El cdigo ya no compilar si el campo
se cambiaron a una
IdentityHashMap
. Declarando el campo con el tipo de interfaz
"Mantiene honesto."
Es totalmente apropiado para referirse a un objeto por una clase en lugar de una
si no existe ninguna interfaz de interfaz adecuada. Por ejemplo, considere el valor
clases, tales como
Cuerda
y
BigInteger
. Clases de valores rara vez se escriben con
mltiples implementaciones en mente. Ellos son a menudo final y rara vez tienen
pondiente
las interfaces corres-. Es perfectamente apropiado utilizar una clase de valor como un
parmetro,
la variable, campo o tipo de retorno. Ms en general, si hay una clase concreta ha
asociado
interfaz, entonces no tiene ms remedio que referirse a ella por su clase si es o no
representa un valor. los
Aleatorio
clase 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. los
java.util.TimerTask
clase 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,
Lista enlazada
. Tal clase debe ser utilizado slo para referirse a su
casos si el programa se basa en los mtodos adicionales: nunca se debe utilizar como
una
tipo de parmetro ( punto 25) .
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 ms alta de la jerarqua de clases que proporciona la
necesaria
funcionalidad.

pgina 18
CAPTULO 7 PROGRAMACIN GENERAL
158
Tema 35: Prefiero interfaces para la reflexin
La instalacin de la reflexin,
java.lang.reflect
, Ofrece un acceso programtico a la infor-
macin sobre las clases cargadas. Dado un
Clase
ejemplo, se puede obtener
Constructor
,
Mtodo
y
Campo
instancias que representan a los constructores, mtodos y campos de
la clase representada por la
Clase
ejemplo. Estos objetos proporcionan programtica
acceso a los nombres de la clase de miembro, tipos de campo, firmas de mtodo, y as
sucesivamente.
Adems,
Constructor
,
Mtodo
y
Campo
instancias permiten manipular
sus homlogos subyacentes reflexivamente : Se pueden construir casos, invocan
mtodos y campos de acceso de la clase subyacente por mtodos que invocan en el
Constructor
,
Campo
y
Mtodo
instancias. Por ejemplo,
Method.invoke
deja
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.
rendimiento se resiente . A partir de la versin 1.3, la invocacin de mtodos de
reflexin era
cuarenta veces ms lento en mi mquina que la invocacin de mtodos normales.
Reflexin
fue rearchitected en la liberacin de 1.4 para un rendimiento mejorado en gran medida,
pero sigue siendo
dos veces ms lento, ya que el acceso normal, y es poco probable que reducir la brecha.
La instalacin de la reflexin fue diseado originalmente para aplicacin basada en
componentes
herramientas de desarrollo cin. Estas herramientas generalmente cargan clases sobre la
demanda y el uso de reflexin
para averiguar qu mtodos y constructores que apoyan. Las herramientas permiten a
sus usuarios
interactivamente construir aplicaciones que acceden a estas clases, pero el generado
aplicaciones acceder a las clases normalmente, no reflexiva. Reflexin se utiliza slo
en tiempo de diseo . Por regla general, los objetos no deben acceder reflexivamente
en condiciones normales
aplicaciones en tiempo de ejecucin.
Hay algunas aplicaciones sofisticadas que exigen el uso de la reflexin.
Los ejemplos incluyen los navegadores de clase, los inspectores de objetos,
herramientas de anlisis de cdigo, y inter-
sistemas embebidos interpretativos. Reflexin es tambin apropiado para su uso en
sistemas de RPC
para eliminar la necesidad de los compiladores de cdigo auxiliar. Si usted tiene alguna
duda en cuanto a si
su aplicacin cae en una de estas categoras, es probable que no lo hace.

pgina 19
ARTCULO 35: Prefiero INTERFACES a la reflexin
159
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 disponible en tiempo de compilacin, existe en tiempo de compilacin
de una adecuada
interfaz o superclase por el que se refieren a la clase (I TEM 34). Si este es el caso,
se puede crear instancias reflexivamente y acceder a ellos a travs de su interaccin
con normalidad
cara o superclase . Si el constructor adecuado no tiene parmetros, como es habitual
el caso, entonces usted no necesita ni siquiera utilizar el
java.lang.reflect
paquete; el
Class.newInstance
mtodo proporciona la funcionalidad requerida.
Por ejemplo, aqu hay un programa que crea una
Conjunto
instancia cuya clase es espec-
ified por el primer argumento de la lnea de comandos. El programa inserta la
composicin restante
argumentos de lnea de comando en el conjunto y lo imprime. Independientemente del
primer argumento, el
programa imprime el resto de argumentos con los duplicados eliminados. El orden en el
los que estos argumentos se imprimen depende de la clase especificada en el primer
argumento
ambiente. Si especifica "
java.util.HashSet
, "Que estn impresos en la aparentemente aleatoria
orden; si especifica "
java.util.TreeSet
", Que se imprimen en orden alfabtico,
como los elementos de una
TreeSet
se clasifican:
// Creacin de instancias de reflexin con acceso a la interfaz
principales argumentos (String []) {public static void
// Traducir el nombre de la clase en un objeto de clase
Clase CL = null;
tratar {
cl = Class.forName (args [0]);
} Catch (ClassNotFoundException e) {
System.err.println ( "Clase no encontrada.");
System.exit (1);
}
// Instancia de la clase
Set s = null;
tratar {
s = (Set) cl.newInstance ();
} Catch (IllegalAccessException e) {
System.err.println ( "Clase no es accesible.");
System.exit (1);
} Catch (InstantiationException e) {
System.err.println ( "Clase no instanciable.");
System.exit (1);
}
// Ejercer el conjunto
s.addAll (Arrays.asList (args) .subList (1, args.length-1));
System.out.println (s);
}

pgina 20
CAPTULO 7 PROGRAMACIN GENERAL
160
Si bien este programa es slo un juguete, la tcnica que demuestra es muy
poderoso. El programa de juguete puede ser fcilmente convertido en un probador
conjunto genrico que valo-
idates el especificado
Conjunto
aplicacin mediante la manipulacin de uno o ms agresivamente
instancias y la comprobacin de que obedecen a la
Conjunto
contrato. Del mismo modo, podra ser
convertido en una herramienta de anlisis de rendimiento conjunto genrico. De hecho,
la tcnica que se
demuestra que es suficiente para poner en prctica un verdadero marco de proveedor de
servicios
( Artculo 1) . La mayora de las veces, esta tcnica es todo lo que necesita en el camino
de reflexin
cin.
Se puede ver dos desventajas de la reflexin en el ejemplo. En primer lugar, el ejemplo
es capaz de generar tres errores de ejecucin, todos los cuales habra sido com-
errores en tiempo de pila si no se utiliza de instancias de reflexin. En segundo lugar, se
necesita veinte
lneas de cdigo tedioso para generar una instancia de la clase de su nombre, mientras
que una
La invocacin del constructor podra encajar perfectamente en una sola lnea. Estas
desventajas son,
sin embargo, restringida a la parte del programa que crea una instancia del objeto. Una
vez
instanciado, es indistinguible de cualquier otra
Conjunto
ejemplo. En un programa real,
la gran mayora del cdigo es por lo tanto no afectada por este uso limitado de la
reflexin.
Una legtima, si es poco frecuente, el uso de la reflexin es romper 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 medio mnimo
Ment 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 poderoso instrumento que se requiere para cierta sofisti-
ticada tareas de programacin del sistema, pero tiene muchas desventajas. Si no est
escrito
ing un programa que tiene que trabajar con las clases desconocidas en tiempo de
compilacin 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.

pgina 21
ARTCULO 36: USO DEL NATIVO MTODOS juiciosamente
161
Tema 36: Usar mtodos nativos juiciosamente
El Java Native Interface (JNI) permite a las aplicaciones Java para llamar a los mtodos
nativos ,
los cuales son mtodos especiales escritas en lenguajes de programacin nativos tales
como C o
C ++. Los mtodos nativos pueden realizar el clculo arbitrario en lenguas nativas antes
volviendo al lenguaje de programacin Java.
Histricamente, los mtodos nativos han tenido tres usos principales. Ellos
proporcionan el acceso
a las instalaciones especficas de la plataforma, tales como los registros y los bloqueos
de archivo. Ellos proveen
el acceso a las bibliotecas de cdigo heredado, que a su vez podra facilitar el acceso a
la herencia
datos. Por ltimo, se utilizaron mtodos nativos para escribir piezas de rendimiento
crtico de
aplicaciones en las lenguas nativas para mejorar el rendimiento.
Es legtimo utilizar mtodos nativos para acceder a las instalaciones especficas de la
plataforma, pero
como la plataforma Java madura, se ofrece ms y ms caractersticas que anteriormente
se encontraban
slo en plataformas de acogida. Por ejemplo, el
java.util.prefs
paquete, aadido en
release 1.4, ofrece la funcionalidad de un registro. Tambin es legtimo usar nativa
mtodos para acceder a cdigo heredado, pero hay mejores maneras de acceder a alguna
herencia
cdigo. Por ejemplo, la API JDBC proporciona acceso a bases de datos heredadas.
A partir de la versin 1.3, rara vez es aconsejable el uso de mtodos nativos para
mejorar la
el rendimiento. En las primeras versiones, a menudo era necesario, pero las
implementaciones de JVM
han vuelto mucho ms rpido. Para la mayora de las tareas, ahora es posible obtener
comparable
rendimiento sin recurrir a mtodos nativos. A modo de ejemplo, cuando
java.math
se aadi a la plataforma en la versin 1.1,
BigInteger
fue en prctica
mentado encima de una rpida multiprecision biblioteca aritmtica escrita en C. En el
momento, esta
era necesaria para el desempeo adecuado. En la versin 1.3,
BigInteger
fue rewrit-
diez completamente en Java y cuidadosamente afinado. La nueva versin es ms rpida
que la original
en todas las implementaciones de JVM 1.3 de Sun para la mayora de las operaciones y
tamaos de operando.
El uso de mtodos nativos tiene serias desventajas. Debido a gua nativa
guas no son seguros ( artculo 24) , las aplicaciones que utilizan mtodos nativos ya no
estn
inmune a los errores de corrupcin de memoria. Porque las lenguas nativas son la
plataforma
dependientes, las aplicaciones que utilizan mtodos nativos ya no son de libre porttil.
Nativo
cdigo debe volver a compilar para cada plataforma de destino y puede requerir la
modificacin como
bien. Hay un alto costo fijo asociado con la que entran y salen de cdigo nativo,
por lo mtodos nativos pueden disminuir el rendimiento si lo hacen slo una pequea
cantidad de
trabajo. Por ltimo, los mtodos nativos son tedioso de escribir y difcil de leer.
En resumen, pensar dos veces antes de usar mtodos nativos. Rara vez, o nunca, los
utilizan
para mejorar el rendimiento. Si tiene que usar mtodos nativos de acceso de bajo nivel
recursos o bibliotecas existentes, usar la menor cantidad de cdigo nativo como sea
posible y probarlo Thor-
a fondo. Un solo error en el cdigo nativo puede corromper toda su aplicacin.

pgina 22
CAPTULO 7 PROGRAMACIN GENERAL
162
Punto 37: Optimizar juiciosamente
Hay tres aforismos relativas a la optimizacin de que todo el mundo debe saber.
Ellos quizs estn empezando a sufrir de la sobreexposicin, pero en caso de que an no
estn
familiarizados con ellos, aqu estn:
Ms pecados de computacin se cometen en nombre de la eficiencia (sin sario
riamente lograrlo) que por cualquier otra razn sola ciega estupidez-incluidos.
William A. Wulf [Wulf72]
Nosotros deberamos olvidarnos de las pequeas eficiencias, digamos alrededor del
97% del tiempo: prema-
optimizacin tura es la raz de todos los males.
-donald E. Knuth [Knuth74]
Seguimos dos normas en materia de optimizacin:
Regla 1. No lo haga.
Regla 2 (slo para expertos). No hacerlo todava, es decir, no hasta que tenga una
perfectamente claro y sin optimizar solucin.
-MA Jackson [ Jackson75]
Todos estos aforismos son anteriores al lenguaje de programacin Java por dos
dcadas. Cuentan una profunda verdad sobre la optimizacin: Es fcil de hacer ms
dao que
bueno, especialmente si optimiza de forma prematura. En el proceso, puede producir
software que no es ni rpido ni correcta y no puede ser fcilmente fijado.
No sacrificar principios de la arquitectura de sonido para el rendimiento. Se esfuerzan
para escribir
buenos programas en lugar de los rpidos . Si un buen programa no es lo
suficientemente rpido, su
arquitectura permitir que ser optimizada. Los buenos programas incorporan el
principio de
ocultacin de la informacin : Cuando sea posible, se localizan dentro de las decisiones
de diseo indivi-
UAL mdulos, por lo que las decisiones individuales pueden ser cambiados sin afectar a
los restantes
der del sistema ( punto 12 ).
Esto no quiere decir que se pueden ignorar los problemas de rendimiento hasta que sus
pro-
gramo es completa. Los problemas de aplicacin puede ser fijado por la optimizacin
ms tarde,
pero los defectos generalizados arquitectnicos que limitan el rendimiento puede ser
casi imposible
para fijar sin reescribir el sistema. El cambio de un aspecto fundamental de su diseo
despus del hecho puede resultar en un sistema de mal estructurado que es difcil de
mantener y
evolucionar. Por lo tanto usted debe pensar en el rendimiento durante el proceso de
diseo.
Tratar de evitar las decisiones de diseo que limitan el rendimiento . Los
componentes
de un diseo que son ms difciles de cambiar despus de los hechos son los que
especifican
interacciones entre mdulos y con el mundo exterior. El principal de ellos

pgina 23
ARTCULO 37: OPTIMIZAR juiciosamente
163
componentes de diseo son las API, los protocolos de nivel de alambre, y los formatos
de datos persistentes.
No slo son estos componentes de diseo difciles o imposibles de cambiar despus de
la
de hecho, pero todos ellos pueden poner limitaciones significativas en el rendimiento
que una
sistema nunca puede alcanzar.
Tenga en cuenta las consecuencias de rendimiento de sus decisiones de diseo de la
API .
Haciendo un tipo mutable pblica puede requerir una gran cantidad de copia defensiva
innecesaria
( Artculo 24) . Del mismo modo, el uso de la herencia en una clase pblica en la
composicin hara
han sido los lazos apropiados a la clase siempre para su superclase, que se puede colocar
arti-
lmites ficiales sobre el rendimiento de la subclase (punto 14 ). Como ejemplo final,
el uso de un tipo de aplicacin en lugar de una interfaz en un API de vnculos a una
espe-
aplicacin espe-, a pesar de que las implementaciones ms rpidas pueden ser escritos
en el
futuro ( artculo 34 ).
Los efectos del diseo del API en el rendimiento son muy reales. Considera el
getSize
mtodo en el
java.awt.Component
clase. La decisin de que este Rendimiento-
mtodo crtico era para devolver una
Dimensin
ejemplo, junto con la decisin de que
Dimensin
casos son mutables, obliga a cualquier aplicacin de este mtodo para
asignar una nueva
Dimensin
instancia en cada llamada. A pesar de que, a partir de la liberacin
1.3, la asignacin de objetos pequeos es relativamente barato, la asignacin de
millones de
objetos innecesariamente puede hacer dao real para el rendimiento.
En este caso, existen varias alternativas. Idealmente,
Dimensin
debera haber sido
inmutable (I TEM 13); alternativamente, la
getSize
mtodo podra haber sido reemplazado
por dos mtodos devolucin de los componentes individuales de un primitivos
Dimensin
objeto. De hecho, se aadieron dos de tales mtodos para la
Componente
API en el 1,2
liberar por razones de rendimiento. Preexistentes cdigo de cliente, sin embargo, sigue
utilizando la
getSize
mtodo y todava sufre las consecuencias de rendimiento del original
API de decisiones de diseo.
Afortunadamente, es generalmente el caso que un buen diseo API es compatible con
las buenas
el rendimiento. Es una muy mala idea para deformar una API para lograr una
buena Perfor-
Mance . El problema de rendimiento que le hizo deformar la API puede desaparecer en
una
futuras versiones de la plataforma u otro software subyacente, pero la API deformado
y los dolores de cabeza de apoyo que causa estarn con usted para la vida.
Una vez que haya diseado cuidadosamente su programa y produjo una clara, concisa,
y la aplicacin bien estructurada, a continuacin, puede ser hora de considerar la
optimizacin,
suponiendo que no se encuentra satisfecho con el rendimiento del programa. Recordar
que dos reglas de Jackson de optimizacin fueron "No lo hagas", y "(para expertos
solamente). . No lo haga todava "Podra haber aadido una ms: Medir el desempeo
antes y despus de cada intento de optimizacin.

pgina 24
CAPTULO 7 PROGRAMACIN GENERAL
164
Usted puede ser sorprendido por lo que se encuentra. A menudo, los intentos de
optimizaciones tienen
ningn efecto medible en el rendimiento; A veces lo hacen peor. El principal
la razn es que es difcil de adivinar donde su programa est gastando su tiempo. los
parte del programa que usted piensa que es lento puede no estar en falta, en el que caso
de que le
perdiendo el tiempo tratando de optimizarlo. El sentido comn revela que pro-
gramos gastan el 80 por ciento de su tiempo en un 20 por ciento de su cdigo.
Herramienta bsica pueden ayudar a decidir dnde enfocar sus esfuerzos de
optimizacin.
Estas herramientas le dan informacin en tiempo de ejecucin, tal como
aproximadamente la cantidad de tiempo que cada
mtodo est consumiendo y cuntas veces se invoca. Adems de centrarse
sus esfuerzos de ajuste, esto le puede alertar de la necesidad de cambios algortmicos. Si
un cali-
cuadrtico (o peor) algoritmo se esconde dentro de su programa, ninguna cantidad de
sintonizacin se
arreglar el problema. Debe reemplazar el algoritmo con una que sea ms eficiente.
El cdigo ms en el sistema, el ms importante es el uso de un generador de perfiles. Es
como
buscar una aguja en un pajar: Cuanto ms grande sea el pajar, ms til que es
tener un detector de metales. El SDK de Java 2 viene con un generador de perfiles
simple, y varios
ms sofisticadas herramientas de perfilado estn disponibles comercialmente.
La necesidad de medir los efectos de la optimizacin es an mayor en el Java
plataforma que en las plataformas ms tradicionales, como el lenguaje de programacin
Java
no tiene un fuerte modelo de rendimiento . Los costos relativos de los distintos cebado
sitivos operaciones no estn bien definidos. La "brecha semntica" entre lo que el pro-
Grammer escribe y lo que la CPU ejecuta es mucho mayor que en el tradicional
lenguajes compilados lo que hace muy difcil predecir con fiabilidad el Perfor-
Mance consecuencias de cualquier optimizacin. Hay un montn de mitos de
rendimiento
flotando alrededor que resultan ser verdades a medias o mentiras completas.
No slo est mal definido el modelo de rendimiento, pero vara de JVM en prctica
mentacin a la implementacin JVM y de una versin a. Si va a RUN
nir su programa en mltiples implementaciones de JVM, es importante que usted
medir los efectos de la optimizacin de cada uno. De vez en cuando puede ser forzado
para hacer compensaciones entre el desempeo en diferentes implementaciones de
JVM.
En resumen, no se esfuerzan para escribir programas de esforzarse para escribir buenos
rpidos;
la velocidad seguir. No pensar en los problemas de rendimiento, mientras que usted
est diseando ma
sistemas y APIs especialmente mientras se est diseando, protocolos a nivel de cable, y
persistente
formatos de datos de la tienda. Cuando haya terminado la construccin del sistema,
medir su
actuacin. Si es lo suficientemente rpido, ya est hecho. Si no es as, localizar la
fuente de la probabilidad
blemas con la ayuda de un generador de perfiles, e ir a trabajar optimizando las partes
pertinentes de la
sistema. El primer paso es examinar el tipo de algoritmos: Ninguna cantidad de bajas
optimizacin nivel puede compensar una mala eleccin del algoritmo. Repita este
proceso
si es necesario, la medicin del rendimiento despus de cada cambio, hasta que est
satisfecho.

pgina 25
ARTCULO 38: Se adhieren a las convenciones de nombres generalmente aceptados
165
Punto 38: Se adhieren a las convenciones de nombres generalmente aceptados
La plataforma Java tiene un conjunto bien establecido de las convenciones de nombres ,
muchos de los cuales
estn contenidas en la Especificacin del lenguaje Java [JLS, 6.8]. Hablar libremente,
convenciones de nomenclatura se clasifican en dos categoras: tipogrficos y
gramaticales.
Hay slo un puado de convenciones de nomenclatura tipogrficos, que cubre
paquetes, clases, interfaces, mtodos y campos. Rara vez Debera violarlos
y nunca sin una muy buena razn. Si una API viola estas convenciones, puede
ser difcil de usar. Si una implementacin de los viola, puede ser difcil de mante-
Tain. En ambos casos, violacines tienen el potencial para confundir e irritar a otros
pro-
programadores que trabajan con el cdigo y pueden causar falsas suposiciones que
conducen a
errores. Los instrumentos se resumen en este artculo.
Los nombres de paquetes deben ser jerrquica con las partes separadas por puntos.
Las piezas deben contener caracteres alfabticos en minscula y, rara vez, los dgitos.
los
el nombre de cualquier paquete que ser utilizada fuera de su organizacin debe
comenzar
con el nombre de dominio de Internet de su organizacin con el dominio de nivel
superior en primer lugar, por
ejemplo,
edu.cmu
,
com.sun
,
gov.nsa
. Las bibliotecas estndar y paquete opcional
edades, cuyos nombres comienzan con
Java
y
javax
, Son excepciones a esta regla. usuarios
no debe crear paquetes cuyos nombres comienzan con
Java
o
javax
. Las modalidades
para la conversin de nombres de dominio de Internet para empaquetar prefijos de
nombre se puede encontrar en
La especificacin del lenguaje Java [JLS, 7.7].
El resto de un nombre de paquete debe consistir en una o ms partes describiendo
ing el paquete. Las piezas deben ser cortos, generalmente ocho o menos caracteres.
Media-
abreviaturas sig- se les anima, por ejemplo,
util
ms bien que
utilidades
.
Acrnimos son aceptables, por ejemplo,
AWT
. Piezas general deben consistir en una
sola palabra o abreviatura.
Muchos paquetes tienen nombres con slo una parte, adems de internet
nombre de dominio. Las piezas adicionales son apropiados para grandes instalaciones
cuyo tamao
exige que se pueden dividir en una jerarqua informal. Por ejemplo, el
javax.swing
paquete tiene una rica jerarqua de paquetes con nombres como
javax.swing.plaf.metal
. Tales paquetes se denominan a menudo subpaquetes,
a pesar de que son sub-paquetes por nica convencin; no hay apoyo lingstico
para las jerarquas de paquetes.
Los nombres de clase y de interfaz deben consistir en una o ms palabras, con la
primera
letra de cada palabra en mayscula, por ejemplo,
Minutero
o
TimerTask
. abreviaturas
deben ser evitados, a excepcin de los acrnimos y abreviaturas comunes como ciertos
max
y
min
. Hay poco consenso sobre si acrnimos deben ser maysculas o
slo tengan su primera letra en mayscula. Aunque es ms comn en maysculas, un
fuerte

pgina 26
CAPTULO 7 PROGRAMACIN GENERAL
166
Se puede argumentar a favor de capitalizar slo la primera letra. Incluso si mltiples
acrnimos se producen de back-to-back, todava se puede distinguir dnde comienza la
palabra y la siguiente
palabra termina. Qu clase de nombre prefieres ver,
HTTPUrl
o
HTTPUrl
?
Los nombres de mtodo y de campo siguen las mismas convenciones tipogrficas como
la clase
y los nombres de interfaces, excepto que la primera letra del nombre de un mtodo o
campo debe
estar en minsculas, por ejemplo,
retirar
,
ensureCapacity
. Si se produce un acrnimo como el
primera palabra de un nombre de mtodo o campo, debe ser minscula.
La nica excepcin a la regla anterior se refiere a "campos constantes", cuyo
nombres deben constar de una o ms palabras en maysculas separadas por el carcter
de subrayado
carcter, por ejemplo,
VALORES
o
NEGATIVE_INFINITY
. Un campo constante es una esttica
campo final cuyo valor es inmutable. Si un campo static final tiene un tipo primitivo o
un tipo de referencia inmutable (Se em 13), entonces es un campo constante. Si el tipo
es
potencialmente mutable, todava puede ser un campo constante si el objeto referenciado
es inmu-
mesa. Por ejemplo, una enumeracin typesafe puede exportar su universo de
enumeracin con-
stants en una inmutable
Lista
constante ( pgina 107) . Tenga en cuenta que los campos de constantes
constituyen la nica uso recomendado de subrayados.
nombres de variables locales tienen convenciones de nombres similares a tipogrfico
miembros
ber nombres, excepto que se permiten las abreviaturas, como son los caracteres
individuales
y secuencias cortas de caracteres cuyo significado depende del contexto en el cual
la variable local se produce, por ejemplo,
yo
,
xref
,
nmero de casa
.
Para tener una referencia rpida, Tabla 7. 1 muestra ejemplos de convenciones
tipogrficas.
Las convenciones de nombres gramaticales son ms flexibles y ms controvertido
sial que las convenciones tipogrficas. No hay nomenclatura gramatical con-
intervenciones para hablar de paquetes. Las clases se nombran generalmente con un
sustantivo o
sintagma nominal, por ejemplo,
Minutero
o
BufferedWriter
. Las interfaces se nombran como
Tabla 7.1: Ejemplos de Convenciones tipogrficas
identificador de Tipo
Ejemplos
Paquete
com.sun.medialib
,
com.sun.jdi.event
Clase o Interfaz
Minutero
,
TimerTask
,
KeyFactorySpi
,
HttpServlet
Mtodo o campo
retirar
,
ensureCapacity
,
getCrc
El campo constante
VALORES
,
NEGATIVE_INFINITY
Variable local
yo
,
xref
,
nmero de casa

pgina 27
ARTCULO 38: Se adhieren a las convenciones de nombres generalmente aceptados
167
clases, por ejemplo,
Coleccin
o
comparador
, O con un adjetivo que termina en
"-able" O "-ible", por ejemplo,
ejecutable
o
Accesible
.
Mtodos que realizan algn tipo de accin se nombran generalmente con un verbo o un
verbo
frase, por ejemplo,
adjuntar
o
drawImage
. Los mtodos que devuelven un
booleano
valor
por lo general tienen nombres que comienzan con la palabra "es", seguido de un
sustantivo, un sustantivo
frase o una palabra o frase que funciona como un adjetivo, por ejemplo,
isdigit
,
isProbablePrime
,
esta vacio
,
est habilitado
,
Esta corriendo
.
Mtodos que devuelven una funcin nonboolean o atributo del objeto sobre el cual
que estn invocadas por lo general se nombran con un sustantivo, un sintagma nominal
o un sintagma verbal
comenzando con el verbo "tener", por ejemplo,
tamao
,
cdigo hash
o
consigue tiempo
. Ahi esta
un contingente vocal que afirma slo la tercera forma (comenzando con "get") es
aceptable, pero no hay ninguna base para esta afirmacin. Las dos primeras formas por
lo general conducen a
cdigo sea ms legible, por ejemplo,
si (car.speed ()> 2 * SPEED_LIMIT)
generateAudibleAlert ( "Cuidado con los policas!");
El formulario que comienza con "get" es obligatoria si la clase que contiene el mtodo
es una
Frijol [JavaBeans], y es recomendable si usted est pensando en convertir la clase en
una
Bean en un momento posterior. Adems, hay un fuerte precedente de esta forma si la
clase contiene
un mtodo para configurar el mismo atributo. En este caso, los dos mtodos se deben
nombrar
obtener
atributo y
conjunto
Caractersticas del producto .
Unos pocos nombres de los mtodos merecen una mencin especial. Mtodos que
convierten el tipo
de un objeto, de devolver un objeto independiente de un tipo diferente, a menudo
llamado
a
Tipo , por ejemplo,
,
toArray
. Los mtodos que devuelven un punto de vista ( artculo 4 )
cuyo tipo es diferente de la del objeto de recibir, a menudo se llama
como
Tipo , por
ejemplo,
asList
. Mtodos que devuelven una primitiva con el mismo valor que la
objeto sobre el que estn invocan a menudo son llamados tipo
Valor
, por ejemplo,
intValue
. Los nombres comunes de las fbricas son estticos
y
obtener Instancia
(Artculo 1, pgina 9 ).
convenciones gramaticales para los nombres de campo no estn tan bien establecidas y
menos
importantes que los de clases, interfaces, y los nombres de mtodos, como bien
diseado
API contienen pocos o ningn campos expuestos. Los campos de tipo
booleano
son tpicamente
nombrado como
booleano
mtodos de acceso con la inicial "es" omiten, por ejemplo,
inicializado
,
compuesto
. Los campos de otros tipos se denominan por lo general con los nombres o
frases nominales, tales como
altura
,
dgitos
o
tipo de cuerpo
. convenciones gramaticales
para las variables locales son similares a las de los campos, pero son an ms dbiles.

pgina 28
CAPTULO 7 PROGRAMACIN GENERAL
168
Para resumir, internalizar las convenciones de nomenclatura estndar y aprender a
utilizar
como una segunda naturaleza. Las convenciones tipogrficas son sencillos y
en gran medida sin ambigedades; las convenciones gramaticales son ms complejos y
ms flojo.
Citando Los Especificacin del lenguaje Java [JLS, 6,8], "Estas convenciones
no debe ser seguido servilmente si el uso convencional de larga data dicta otro-
sabia. "Use el sentido comn.

S-ar putea să vă placă și