"Claro que quisiera tener este libro hace diez años. Algunos podrían pensar que yo no necesito ningún libro de Java, pero necesito esta. "
-James Gosling, colega y vicepresidente de Sun Microsystems, Inc., y inventor del lenguaje de programación Java
"Un excelente libro, repleto de buenos consejos sobre cómo utilizar el programa de Java-idioma ming y la programación orientada a objetos en general. "
-Gilad Bracha, distinguido ingeniero, Cadence Design Systems, y coautor de El Java ™ Especificación del lenguaje, Tercera Edición (Addison-Wesley, 2005)
"10/10-anyone aspiran a escribir buen código Java que otros apreciarán
la lectura y el mantenimiento deben estar obligados a poseer una copia de este libro. Este es uno de esos libros raros en los que la información no se volverá obsoleto con
las versiones posteriores de la biblioteca JDK ".
-Peter Tran, camarero, JavaRanch.com
"El mejor libro que se haya escrito en Java .... Realmente genial; muy legible y eminentemente útil. No puedo decir suficientes cosas buenas sobre este libro. En JavaOne 2001,
James Gosling dijo: 'Ve a comprar este libro! "Me alegro de haberlo hecho, y yo no podía estar de acuerdo
más ".
-Keith Edwards, miembro de alto rango del personal de investigación, Computer Science Lab en el Centro de Investigación de Palo Alto (PARC), y autor de Core JINI (Prentice Hall, 2000)
"Este es un verdaderamente excelente libro hecho por el hombre que diseñó varios de los mejores APIs de la plataforma Java recientes (incluyendo el API Collections). "
"Gran contenido. Análogo al clásico de Scott Meyers Efectiva de C + +. Si conoces los conceptos básicos de Java, este tiene que ser su próximo libro ".
-Gary K. Evans, OO mentor y consultor, Evanetics, Inc.
"Josh Bloch da una gran comprensión de las mejores prácticas que en realidad sólo pueden ser
descu-Ered después de años de estudio y experiencia. "
-Mark Mascolino, ingeniero de software
"Este es un libro extraordinario. Cubre con claridad muchas de las sutilezas lenguaje / plataforma y el engaño que necesita para aprender a convertirse en un verdadero maestro de Java ".
-Victor Wiewiorowski, desarrollo vicepresidente y gerente de calidad de código, ValueCommerce Co., Tokio, Japón
"Me gustan los libros que prometer menos en sus títulos y el exceso de entregar en sus contenidos. Este libro consta de 57 artículos de consejos de programación que están bien elegidos. Cada ítem revela un claro y profundo conocimiento de la lengua,. Cada uno ilustra en estilo sencillo y práctico términos de los límites de la programación de la intuición por sí sola, o tomar el camino más directo a una solución sin entender completamente lo que ofrece el lenguaje ".
-Michael Ernest, Inkling Research, Inc.
"Yo no encuentro muchos libros de programación que me hacen querer leer cada página-este es uno de ellos. "
-Matt Tucker, director técnico, Jive Software
"Gran how-to de recursos para el desarrollador experimentado."
-John Zukowski, autor de numerosos libros de Java
"Elegí este libro hasta hace dos semanas y puedo decir con seguridad que aprendí más sobre la Lenguaje Java en tres días de la lectura de lo que hice en tres meses de estudio! Un
excelente libro y una adición bienvenida a mi biblioteca Java ".
El ™ Serie Java
Ken Arnold, James Gosling, David Holmes
El lenguaje de programación Java ™, Cuarta Edición Joshua Bloch
Effective Java Programming Language Guide ™ Joshua Bloch
Effective Java ™, Segunda Edición
Stephanie Bodoff, Dale Green, Kim Haase, Eric Jendrock El Tutorial J2EE ™, segunda edición
María Campione, Kathy Walrath, Alison Huml
El Tutorial de Java ™, tercera edición: Un Curso Corto en los conceptos básicos
María Campione, Kathy Walrath, Alison Huml, La Equipo Tutorial
El Tutorial de Java ™ Continúa: El Resto del JDK ™ Patrick Chan
El Java ™ Desarrolladores Almanaque 1,4, Volumen 1 Patrick Chan
El Java ™ Desarrolladores Almanaque 1,4, Volumen 2 Patrick Chan, Rosanna Lee
Las bibliotecas de clases de Java ™, segunda edición, volumen 2: java.applet, java.awt, java.beans
Patrick Chan, Rosanna Lee, Doug Kramer
Las bibliotecas de clases de Java, Second Edition, Volume 1: Suplemento para la Java ™ 2 Platform, Standard Edition, v1.2
™
Eric Jendrock, Jennifer Bola
El Java™EE 5 Tutorial, tercera edición Jonni Kanerva
El FAQ de Java ™ Jonathan Knudsen
Kicking Butt con MIDP y MSA: Creando Gran Aplicaciones Móviles
David Lambert
Venta inteligente: Estrategias de Venta Consultiva para satisfacer Necesidades del comprador Cada Hora
Doug Lea
Programación Concurrente en Java ™, segunda edición: Principios y patrones de diseño
Rosanna Lee, Scott Seligman
JNDI API Tutorial y Referencia: Edificio Directorio-Aplicaciones Java ™ activado
Sheng Liang
La interfaz nativa de Java ™: Guía del programador y Especificación
Tim Lindholm, Frank Yellin
El Java ™ Virtual Machine Especificación, segunda edición Roger Riggs, Antero Taivalsaari, Jim Van Peursem, Jyri Huopaniemi, Mark Patel, Aleksi Uotila
Programación de los dispositivos inalámbricos con la Java ™ 2 Platform, Micro Edition, Second Edition
Rahul Sharma, Beth Stearns Tony Ng J2EE Connector Architecture ™ y Empresa Integración de Aplicaciones
Inderjeet Singh, Beth Stearns, Mark Johnson, Enterprise Equipo
El diseño de aplicaciones empresariales con J2EE ™ Plataforma, segunda edición
Inderjeet Singh, Sean Brydon, Greg Murray, Vijay Ramachandran, Thierry Violleau, Beth Stearns Diseño de Servicios Web con J2EE ™ 1.4 Plataforma: JAX-RPC, SOAP y XML Tecnologías
Kathy Walrath, Mary Campione, Alison Huml, Sharon Zakhour
El Tutorial JFC Swing, Segunda edición: Una guía para La construcción de interfaces gráficas de usuario Steve Wilson, Jeff Kesselman
Plataforma Java ™ Rendimiento: Estrategias y Tácticas Sharon Zakhour, Scott Hommel, Jacob Royal,
Isaac Rabinovitch, Tom Risser, Mark Hoeber El Java™Tutorial, cuarta edición: Un Curso Corto sobre los Fundamentos
Kirk Chen, Li Gong
Programación Abierta Servicio Gateways con Java ™ Embedded Server
Zhiqun Chen
Tecnología Java Card ™ para tarjetas inteligentes: Arquitectura y la Guía del Programador
Maydene Fisher, Jon Ellis, Jonathan Bruce
JDBC ™ Tutorial API y Referencia, Tercera Edición Eric Freeman, Susanne Hupfer, Ken Arnold JavaSpaces Principios ™, Patterns, and Practice Li Gong, Gary Ellison, Mary DAGEFÖRDE
Dentro de Java ™ 2 Platform Seguridad, segunda edición: Arquitectura, Diseño API e implementación
James Gosling, Bill Joy, Guy Steele, Gilad Bracha El Java ™ Language Specification, Tercera edición Chet Haase, Romain individuo
Clientes Filthy Rich: Desarrollo y animación gráfica Efectos para aplicaciones de escritorio Java ™ Marcos Hapner, Rich Burridge, Rahul Sharma, Joseph Fialli, Kim Haase
Segunda edición
Joshua Bloch
Muchas de las denominaciones utilizadas por los fabricantes y vendedores para distinguir sus productos se consideran marcas comerciales. Donde estas designaciones aparecen en este libro, y el editor fue consciente de una reclamación de la marca, las designaciones han sido
impreso con letra inicial mayúscula o en todas las capitales.
Sun Microsystems, Inc. tiene derechos de propiedad intelectual relacionados con las implementaciones de la tecnología que se describen en este pub-cación. En concreto, y sin limitación alguna, estos derechos de propiedad intelectual pueden incluir una o más patentes de Estados Unidos, por-Eign patentes o aplicaciones pendientes.
Sun, Sun Microsystems, el logotipo de Sun, J2ME, J2EE, Java Card, y todas las marcas comerciales y logotipos basados en Sun y Java son el
comercio-marcas comerciales o comercio-marcas comerciales registradas de Sun Microsystems, Inc., en los Estados Unidos y otros países. UNIX es una marca registrada marca registrada en los Estados Unidos y otros países, bajo licencia exclusiva de X / Open Company, Ltd. esta publicación
CIÓN SE PROPORCIONA "TAL CUAL" SIN GARANTÍA DE NINGÚN TIPO, YA SEA EXPRESA O IMPLÍCITA, INCLUYENDO ING, PERO NO LIMITADO A, LAS GARANTÍAS DE COMERCIALIZACIÓN, IDONEIDAD PARA UN
PROPÓSITO PARTICULAR O NO INFRACCIÓN. ESTA PUBLICACIÓN CONTENGA TÉCNICA INEXACTITUDES O ERRORES TIPOGRÁFICOS. CAMBIOS PERIODICOS PARA LA INFORMA-CIÓN AQUÍ; Estos cambios se incorporarán en nuevas ediciones de la publicación. SOL
MICROSYSTEMS, INC PUEDEN EFECTUAR MEJORAS Y / O CAMBIOS EN EL PRODUCTO (S) Y / O EL PROGRAMA (S) DESCRITO EN ESTA PUBLICACIÓN EN CUALQUIER MOMENTO.
El autor y el editor han cuidado en la preparación de este libro, pero hacer ninguna garantía expresa o implícita de ningún
tipo y no asumimos ninguna responsabilidad por errores u omisiones. No se asume responsabilidad por daños incidentales o consecuentes en conexión con o que surjan de la utilización de la información o programas contenidos en el presente documento.
El editor ofrece excelentes descuentos en este libro cuando se pide una cantidad para compras al por mayor o ventas especiales, que
puede incluir las versiones electrónicas y / o cubiertas personalizadas y contenido concreto a su negocio, los objetivos de formación, comercialización enfocar, y los intereses de la marca. Para obtener más información, póngase en contacto con:
EE.UU. corporativos y gubernamentales de ventas (800) 382-3419
Para las ventas fuera de los Estados Unidos, por favor póngase en contacto con:
Ventas Internacionales [email protected]
Visítenos en la Web: informit.com / aw
Biblioteca del Congreso Número de control: 2008926278 Copyright © 2008 Sun Microsystems, Inc.
4150 Red Circle,
Santa Clara, California 95054 U.S.A
Todos los derechos reservados. Impreso en los Estados Unidos de América. Esta publicación está protegida por derechos de autor, y permis-sión se debe obtener de la editorial antes de cualquier reproducción prohibida, el almacenamiento en sistemas de recuperación o trans-misión en cualquier forma o por cualquier medio, de fotocopia electrónico, mecánico, de grabación, o así mismo. Para información con respecto a los permisos, escriba a:
Pearson Education, Inc. Derechos y Contratos 501 Boylston Street, Suite 900 Boston, MA 02116
Fax: (617) 671-3447 -13 ISBN: 978-0-321-35668-0 ISBN-10: los 0-321-35668-3
Esta página ha sido dejada en blanco intencionalmente
Contenido
Prólogo. . . xiii
Prefacio. . . Xv
Agradecimientos. . . xix
1 Introducción. . . 0.1
2 Creación y destrucción de objetos. . . 0.5
Tema 1: Considere métodos de generador estáticos en lugar de constructores. . . 5 Tema 2: Considere un constructor cuando se enfrentan a muchos constructor parámetros. . . 11
Tema 3: Hacer cumplir la propiedad singleton con un privado
constructor o un tipo de enumeración. . . 17 Tema 4: Hacer cumplir noninstantiability con un constructor privado. . . . 19 Tema 5: Evitar la creación de objetos innecesarios. . . 20 Tema 6: Eliminar las referencias a objetos en desuso. . . 24 Tema 7: Evite los finalizadores. . . 27
3 métodos comunes a todos los objetos. . . 0.33
Tema 8: Respete el contrato general, cuando se reemplace es igual a . . . Tema 9: Siempre override hashCode cuando
anular es igual a . . . Artículo 10: Siempre override toString . . . Tema 11: Anulación clon juiciosamente. . . Tema 12: Considerar la implementación de Comparable . . .
33 45 51 54 62
x CONTENIDOS
4 clases e interfaces. . . 67
Tema 13: Minimizar la accesibilidad de clases y miembros. . . 67
Artículo 14: En las clases públicas, utilizar métodos de acceso, campos no públicos. . . 71
Tema 15: Minimizar mutabilidad. . . 73
Artículo 16: Composición de la Merced sobre la herencia. . . 81
Tema 17: Diseño y documentación de la herencia o de lo prohíban. . 87
Artículo 18: Prefiero interfaces para las clases abstractas. . . 93
Tema 19: Use las interfaces sólo para definir tipos. . . 98
Artículo 20: Prefiero las jerarquías de clase para las clases marcadas. . . 100
Tema 21: Utilizar la función de objetos para representar las estrategias. . . 103
Artículo 22: Favorecer clases miembro estáticas sobre no estático. . . 106
5 Los genéricos. . . 109
Artículo 23: No utilice tipos primas en el nuevo código. . . 109
Artículo 24: Eliminar las advertencias sin marcar. . . 116
Artículo 25: Prefiero listas de matrices. . . 119
Artículo 26: Favorecer tipos genéricos. . . 124
Artículo 27: Favorecer métodos genéricos. . . 129
Artículo 28: Uso limitado comodines para aumentar la flexibilidad de la API. . . 134
Artículo 29: Considere typesafe contenedores heterogéneos. . . 142
6 Las enumeraciones y anotaciones. . .
147
Artículo 30: Use las enumeraciones en lugar de int constantes. . . 147Artículo 31: Utilice los campos de instancia en lugar de los ordinales. . . 158 Artículo 32: Uso EnumSet en lugar de campos de bits. . . 159
Artículo 33: Uso EnumMap en lugar de indexación ordinal. . . 161
Artículo 34: Emular enumeraciones extensibles con interfaces. . . 165
Artículo 35: Prefiero anotaciones a modelos de nomenclatura. . . 169
Artículo 36: utilizar siempre el Anular anotación. . . 176
Artículo 37: Utilice las interfaces de marcador para definir tipos. . . 179
7 Métodos. . . 181
Artículo 38: Compruebe los parámetros de validez. . . 181
Artículo 39: Haga copias de defensa cuando sea necesario. . . 184
Artículo 40: firmas de los métodos de diseño cuidado. . . 189
Artículo 42: Uso varargs juiciosamente. . . 197 Artículo 43: Regreso arrays vacíos o colecciones, no nulos. . . 201
Artículo 44: Escribir comentarios de documentación para todos los elementos de la API expuestas. . . . 203
8 Programación General. . . 0.209
Artículo 45: Reducir al mínimo el alcance de las variables locales. . . .
Artículo 46: Prefiero for-each bucles tradicionales para bucles. . . Artículo 47: Conocer y utilizar las bibliotecas. . . Artículo 48: Evitar flotador y doble si las respuestas exactas
son obligatorios. . .
Artículo 49: Prefiero tipos primitivos a los primitivos en caja. . . Artículo 50: Evite las cadenas donde otros tipos son más apropiadas. .
Artículo 51: Cuidado con el rendimiento de la concatenación de cadenas. . . Artículo 52: Consulte objetos por sus interfaces. . .
Artículo 53: Prefiero interfaces para la reflexión. . . Artículo 54: Use métodos nativos con criterio. . . Artículo 55: Optimizar juiciosamente. . .
Artículo 56: Se adhieren a los convenios de denominación generalmente aceptada. . . . . 209 212 215 218 221 224 227 228 230 233 234 237
9 Excepciones. . . 0.241
Artículo 57: Utilizar excepciones solo para condiciones excepcionales. . . Artículo 58: Uso comprueba excepciones para condiciones recuperables
y las excepciones de tiempo de ejecución de errores de programación. . . Artículo 59: Evitar el uso innecesario de excepciones comprobadas. . . Artículo 60: Favorecer el uso de las excepciones estándar. . . Artículo 61: El tiro excepciones apropiadas a la abstracción. . .
Artículo 62: Documentar todas las excepciones producidas por cada método. . . Artículo 63: Incluir la información sobre fallos de captura en
mensajes de detalle. . .
Artículo 64: Luchar por la atomicidad fracaso. . . Artículo 65: No ignore excepciones. . .
241 244 246 248 250 252 254 256 258
10 Concurrencia. . . 0.259
Artículo 66: Sincronizar el acceso a los datos mutables compartidos. . . Artículo 67: Evitar la sincronización excesiva. . .
259 265
xii CONTENIDOS
Artículo 70: Documento de seguridad de los subprocesos. . . . 278
Artículo 71: Utilice la inicialización perezosa juiciosamente. . . 282
Artículo 72: No depende del programador de subprocesos. . . 286
Artículo 73: Evite los grupos de threads. . . 288
11 serialización. . . 289
Artículo 74: Implementar Serializable juiciosamente. . . 289
Artículo 75: Considere el uso de un formulario serializado personalizado. . . 295 Artículo 76: Escribir readObject métodos defensiva. . . 302
Artículo 77: Para el control de ejemplo, prefieren tipos enum a readResolve . . . 308
Artículo 78: Considere proxies de serialización en lugar de en serie instancias. . . 312
Apéndice: artículos correspondientes a la Primera Edición. . . 317
Referencias. . . 321
Yo
F un colega fuera a decir a usted, "Esposa de mí esta noche, hoy fabrica lacomida inusual en una casa. ? Usted se unirá a "tres cosas probablemente pasan por su mente: tercero, que había sido invitado a la cena; segundo, que el Inglés no era su
cola-la lengua materna de cola-la liga; y en primer lugar, una buena dosis de perplejidad.
Si usted ha estudiado alguna vez una segunda lengua a ti mismo y luego trató de usarlo fuera del aula, ya sabes que hay tres cosas que usted debe dominar: cómo
el lenguaje se estructura (gramática), cómo nombrar las cosas que quieres hablar (Vocabulario), y las formas habituales y eficaces de decir las cosas de todos los días
(Uso). Con demasiada frecuencia, sólo las dos primeras están cubiertas en el aula, y te encuentras hablantes nativos constantemente suprimir su risa a medida que tratan de hacer usted mismo entendido.
Es lo mismo con un lenguaje de programación. Es necesario comprender la
núcleo del lenguaje: ¿es algorítmica, funcional, orientado a objetos? Usted necesita saber el Vocabulario: ¿qué estructuras de datos, operaciones y servicios son proporcionados por la bibliotecas estándar? Y tiene que estar familiarizado con el habitual y efectiva
maneras de estructurar su código. Libros sobre los lenguajes de programación a menudo cubren sólo los dos primeros, o discutir el uso de sólo esporádicamente. Tal vez es porque la primera dos son de alguna manera más fácil de escribir. Gramática y vocabulario son
propias-lazos de la lengua solo, pero el uso es característico de una comunidad que la utiliza. El lenguaje de programación Java, por ejemplo, es orientado a objetos con un solo herencia y apoya una (declaración orientada) estilo de programación imperativa dentro
cada método. Las bibliotecas de abordar el apoyo gráfico de visualización, creación de redes, distri-computing buido, y la seguridad. Pero, ¿cómo es el lenguaje mejor puesto en uso en la práctica? Hay otro punto. Programas, a diferencia de frases habladas ya diferencia de la mayoría libros y revistas, son susceptibles de ser cambiado con el tiempo. Por lo general no es suficiente para producir código que funcione de manera eficaz y sean fácilmente comprensibles por otra per-hijos; también hay que organizar el código para que sea fácil de modificar. Puede haber
diez maneras de escribir código para una tarea T. De esos diez maneras, siete será torpe, ineficiente o desconcertante. De los otros tres, lo que es más probable que sea similar a la código necesario para la tarea T ' en la versión de software del año que viene?
xiv PRÓLOGO
Existen numerosos libros de los cuales se puede aprender la gramática de la Java
Lenguaje de programación, incluyendo El lenguaje de programación Java ™ por Arnold, Gosling, y Holmes [Arnold05] o La especificación del lenguaje Java ™ por
Gos-ling, Alegría, su servidor, y Bracha [JLS]. Del mismo modo, hay docenas de libros sobre las bibliotecas y las API asociadas con el lenguaje de programación Java.
Este libro aborda su tercera necesidad: el uso consuetudinario y eficaz. Joshua
Bloch ha pasado años que se extiende, la implementación y el uso de la programación Java lenguaje de Sun Microsystems; él también ha leído un montón de código de otras personas,
incluyendo la mía. Aquí se ofrece un buen consejo, organizada sistemáticamente, sobre la forma de estructurar su código para que funcione bien, para que otras personas puedan entenderlo, por lo que las modificaciones y mejoras en el futuro son menos propensos a causar dolores de cabeza-tal vez, incluso, para que sus programas serán agradables, elegante y graciosa.
De Guy L. Steele Jr.
Burlington, Massachusetts 04 2001
Prefacio a la Segunda Edición
La
Muchas cosas han pasado a la plataforma Java desde que escribí la primera edición de este libro en 2001, y ya es hora para una segunda edición. El conjunto más significativo de los cambiosfue la incorporación de los genéricos, tipos de enumeración, anotaciones, autoboxing, y la for-each bucle en Java 5. Un primer segundo fue la adición de la nueva biblioteca de concurrencia,
java.util.concurrent, También lanzado en Java 5. Con Gilad Bracha, tuve la buena
fortuna de dirigir a los equipos que diseñaron las nuevas características del lenguaje. También tuve la buena fortuna de formar parte del equipo que diseñó y desarrolló la concurrencia
biblioteca, que fue dirigido por Doug Lea.
El otro gran cambio en la plataforma es la adopción generalizada de la moderna Entornos de desarrollo integrado (IDE), como Eclipse, IntelliJ IDEA, y
NetBeans, y de herramientas de análisis estático, como FindBugs. Aunque no he sido involucrado en estos esfuerzos, me he beneficiado de ellos inmensamente y aprendí que afectan a la experiencia de desarrollo de Java.
En 2004, me mudé de Sun a Google, pero he seguido mi participación en el desarrollo de la plataforma Java en los últimos cuatro años, contribuyendo a la APIs de concurrencia y colecciones a través de los buenos oficios de Google y Java Proceso de Comunidad. También he tenido el placer de utilizar la plataforma Java para
desarrollar bibliotecas para su uso dentro de Google. Ahora sé lo que se siente al ser un usuario. Como fue el caso en 2001 cuando escribí la primera edición, mi objetivo principal es
compartir mi experiencia con ustedes para que pueda imitar mis éxitos y evitar mis fracasos. El nuevo material sigue haciendo un uso liberal de real examen-pios de las bibliotecas de la plataforma Java.
La primera edición tuvo éxito más allá de mis expectativas más optimistas, y yo he hecho mi la mejor manera de permanecer fiel a su espíritu, mientras cubría todo el nuevo material que fue solicitársele que lleve el libro hasta la fecha. Era inevitable que el libro iba a crecer,
y crecer lo hizo, cincuenta hasta siete elementos a setenta y ocho. No sólo tenía que añadir veintitrés artículos, pero revisé a fondo todo el material original y me retiré un
xvi PRÓLOGO
algunos artículos cuyos mejores días habían pasado. En el apéndice, se puede ver cómo el En este libro se refiere al material en la primera edición.
En el prefacio a la primera edición, escribí que el lenguaje de programación Java
y sus bibliotecas eran inmensamente favorable a la calidad y la productividad, y una alegría para trabajar con. Los cambios en las emisiones 5 y 6 han tomado una buena cosa y lo hizo mejor. La plataforma es mucho más grande de lo que era en 2001 y más complejo,
pero una vez que aprenda los patrones y frases hechas para el uso de las nuevas características, que hacen
sus programas mejor y su vida más fácil. Espero que esta edición capta mi conti-UED entusiasmo por la plataforma y ayuda a que su uso de la plataforma y su nuevas características más eficaz y agradable.
San Jose, California 04 2008
Prefacio a la primera edición
En 1996 me detuve en juego y se dirigió al oeste para trabajar para JavaSoft, como lo era entonces conocido, porque estaba claro que allí era donde estaba la acción. En el intervalo de
cinco años que he servido como bibliotecas de la plataforma Java arquitecto. He diseñado, imple-mentado, y mantiene muchas de las bibliotecas y se desempeñó como consultor para muchos otros. Presidiendo estas bibliotecas como la plataforma Java madurado era una vez que-en un-oportunidad de su vida. No es ninguna exageración decir que tuve el privilegio de trabajar con algunos de los grandes ingenieros de software de nuestra generación. En el proceso, he aprendido mucho
sobre el lenguaje de programación Java, lo que funciona, lo que no, y cómo usarlo el lenguaje y sus bibliotecas de la mejor manera.
Este libro es mi intento de compartir mi experiencia con ustedes para que pueda mimetizar litar mis éxitos, evitando mis fracasos. Tomé prestado el formato de Scott
De Meyers A partir del C + + [Meyers98], que consta de cincuenta artículos, cada transmitir-ing una regla específica para mejorar sus programas y diseños. Encontré el formato
ser singularmente eficaz, y espero que tú también.
En muchos casos, me tomé la libertad de ilustrar los artículos con el mundo real ejemplos de las bibliotecas de la plataforma Java. Cuando se describe algo que podría haber hecho mejor, traté de recoger el código que escribí yo mismo, pero de vez en cuando Recojo en algo escrito por un colega. Me disculpo sinceramente si, a pesar de mi
pero en el espíritu de cooperación, a fin de que todos podamos aprovechar la experiencia de aquellos que han ido antes.
Aunque este libro no está dirigido únicamente a los desarrolladores de componentes reutilizables, que
se colorea inevitablemente por mi experiencia escribiendo tales componentes en los últimos dos décadas. Creo que de forma natural en términos de las API exportadas (Application Programming Interfaces), y os animo a hacer lo mismo. Incluso si usted no está desarrollando
componentes reutilizables, pensando en estos términos tiende a mejorar la calidad de la software que escriba. Además, no es raro escribir una reutilizable
compo-nente sin saberlo: Escribes algo útil, compartirlo con su amigo
otro lado del pasillo, y en poco tiempo usted tiene media docena de usuarios. En este punto, usted no ya tener la flexibilidad de cambiar el API en la voluntad y son agradecidos por todo el
esfuerzo que usted pone en el diseño de la API de la primera vez que escribió el software.
Mi enfoque en el diseño de la API puede parecer un poco antinatural para los devotos de la nueva metodologías de desarrollo de software ligero, como Extreme Programming
[Beck99]. Estas metodologías enfatizan escribir el programa más simple que
posiblemente podría trabajar. Si está utilizando uno de estos métodos, usted encontrará que un enfoque en el diseño de la API que sirve bien en la refactorización proceso. La fundamental objetivos de refactorización son la mejora de la estructura del sistema y la evitación de la duplicación de código. Estas metas son imposibles de alcanzar en ausencia de bien-APIs diseñadas para los componentes del sistema.
Ninguna lengua es perfecto, pero algunos son excelentes. He encontrado el Java lenguaje de programación y sus bibliotecas a ser inmensamente favorable a la calidad y productividad, y un placer trabajar con ella. Espero que este libro capta mi entusiasmo y ayuda a que su uso del lenguaje más eficaz y agradable.
Cupertino, California 04 2001
Esta página ha sido dejada en blanco intencionalmente
Agradecimientos para la Segunda Edición
Yo
agradecer a los lectores de la primera edición de este libro para darle tal naturaleza y entusiasta recepción, para la toma de sus ideas para el corazón, y por dejarme saber lo que es un influencia positiva que tuvo en ellos y su trabajo. Doy las gracias a los muchos profesores que utilizado el libro en sus cursos, y los muchos equipos de ingenieros que lo adoptaron.Doy las gracias a todo el equipo de Addison-Wesley para su amabilidad, profesión-lismo, la paciencia, y la gracia bajo presión. A pesar de todo, mi editor Greg Doench
permanecido imperturbable: una multa editor y un perfecto caballero. Mi producción de man-ager, Julie Nahil, era todo lo que un gerente de producción debe ser: diligente,
rápida, organizada y amigable. Mi editor, Barbara Wood, era meticuloso y de buen gusto.
He estado una vez más bendecido con el mejor equipo de revisores imaginables, y le doy mi más sincero agradecimiento a cada uno de ellos. El equipo central, que revisó cada capítulo, consistió en Lexi Baugher, Cindy Bloch, Beth Bottos, Joe Bowbeer, Brian Goetz, Tim Halloran, Brian Kernighan, Rob Konigsberg, Tim Peierls, Bill Pugh, Yoshiki Shibata, Peter Stout, Peter Weinberger, y Frank Yellin. Otro revisores incluyeron Pablo Bellver, Dan Bloch, Dan Bornstein, Kevin Bourrillion, Martin Buchholz, Joe Darcy, Neal Gafter, Laurence Gonsalves, Aaron Green-casa, Barry Hayes, Peter Jones, Angelika Langer, Doug Lea, Bob Lee, Jeremy Manson, Tom May, Mike McCloskey, Andriy Tereshchenko, y Paul Tyma.
Una vez más, estos revisores hicieron numerosas sugerencias que dieron lugar a una gran mejora mentos en este libro y me salvó de muchas situaciones embarazosas. Y de nuevo, cualquier restantes vergüenzas son mi responsabilidad.
Doy gracias especiales a Doug Lea y Tim Peierls, quien se desempeñó como sonando tablas para muchas de las ideas de este libro. Doug y Tim era infaliblemente
ge-unidades organizativas con su tiempo y conocimientos.
Doy gracias a mi gerente de Google, Prabha Krishna, por su continuo apoyo y estímulo.
xx AGRADECIMIENTOS
Finalmente, agradezco a mi esposa, Cindy Bloch, por animarme a escribir, para leer-ción cada elemento en forma cruda, por ayudarme con Framemaker, para escribir el índice, y por aguantarme a mí mientras escribía.
Agradecimientos por la Primera Edición
Doy las gracias a Patrick Chan por sugerir que escribo este libro y por lanzar la idea de Lisa es amable, el jefe de redacción series; Tim Lindholm, el editor técnico series; y Mike Hendrickson, editor ejecutivo de Addison-Wesley. Doy las gracias a Lisa, Tim, y Mike por animarme a continuar con el proyecto y por su paciencia sobrehumana
y la fe inquebrantable que algún día escribir este libro.
Doy las gracias a James Gosling y su equipo original para darme algo grande
Escribo sobre, y agradezco a los muchos ingenieros de la plataforma Java que siguieron Los pasos de James. En particular, agradezco a mis colegas de Sun Java Platform Herramientas y Bibliotecas Grupo por sus ideas, su aliento y su
apoyo-puerto. El equipo está formado por Andrew Bennett, Joe Darcy, Neal Gafter, Iris García, Konstantin Kladko, Ian Little, Mike McCloskey, y Mark Reinhold. Ex
miembros incluyen Zhenghua Li, Bill Maddox, y Naveen Sanjeeva.
Doy gracias a mi manager, Andrew Bennett, y mi director, Larry Abrahams, para prestar su apoyo pleno y entusiasta a este proyecto. Doy las gracias a Rich Green, el VP de Ingeniería de software de Java, para proporcionar un entorno en el inge-ros son libres de pensar de forma creativa y para publicar su trabajo.
He sido bendecido con el mejor equipo de revisores imaginables, y doy mi
más sincero agradecimiento a cada uno de ellos: Andrew Bennett, Cindy Bloch, Dan Bloch, Beth Bottos, Joe Bowbeer, Gilad Bracha, Mary Campione, Joe Darcy, David Eckhardt,
Joe Fialli, Lisa friendly, James Gosling, Peter Haggar, David Holmes, Brian Kernighan, Konstantin Kladko, Doug Lea, Zhenghua Li, Tim Lindholm, Mike McCloskey, Tim Peierls, Mark Reinhold, Ken Russell, Bill Shannon, Peter Stout, Phil Wadler, y dos revisores anónimos. Ellos hicieron numerosas sugerencias que dio lugar a grandes mejoras en este libro y me salvó de muchos
vergüenzas. Cualquier vergüenzas restantes son mi responsabilidad. Numerosos colegas, dentro y fuera de Sun, participaron en técnica discusiones que mejoraron la calidad de este libro. Entre otros, Ben Gomes, Steffen Grarup, Peter Kessler, Richard Roda, John Rose, y David Stoutamire
contribuido ideas útiles. Un agradecimiento especial se debe Doug Lea, quien se desempeñó como caja de resonancia de muchas de las ideas de este libro. Doug ha sido indefectiblemente
generoso con su tiempo y sus conocimientos.
Doy las gracias a Julie Dinicola, Jacqui Doucette, Mike Hendrickson, Heather Olszyk, Tracy Russ, y todo el equipo de Addison-Wesley por su apoyo y
profe-lismo. Incluso bajo un calendario increíblemente apretado, siempre fueron muy amables y servicial.
Doy las gracias de Guy Steele para escribir el prólogo. Me siento honrado de que él eligió participar en este proyecto.
Finalmente, agradezco a mi esposa, Cindy Bloch, para fomentar y ocasionalmente
amenazándome a escribir este libro, para la lectura de cada elemento en su forma cruda, en busca de
ayuda-me ing con Fraayuda-memaker, para escribir el índice, y por aguantarayuda-me a mí mientras yo escribió.
Esta página ha sido dejada en blanco intencionalmente
1
™
Introducción
T
Su libro está diseñado para ayudarle a hacer el uso más eficaz de la Javalenguaje de programación y sus bibliotecas fundamentales, java.lang,java.util, y, en menor medida, java.util.concurrent y java.io. El libro discute
otras bibliotecas de vez en cuando, pero no cubre la interfaz gráfica de usuario programación, APIs empresariales, o los dispositivos móviles.
Este libro consta de setenta y ocho artículos, cada uno de los cuales transmite una regla.
Las prácticas de las normas de captura generalmente celebradas a ser beneficioso por la mejor y más programadores experimentados. Los elementos se agrupan libremente en diez capítulos, cada uno relativa a un aspecto amplio de diseño de software. El libro no se pretende que sea
leer de principio a fin: cada elemento se sostiene por sí, más o menos. Los artículos son
fuertemente con referencias cruzadas para que pueda trazar fácilmente su propio curso a través del libro.
Muchas nuevas características se han añadido a la plataforma en Java 5 (versión 1.5). La mayor parte de
los elementos de este manual utilizan estas características de alguna manera. La siguiente tabla muestra
a dónde ir para la cobertura primaria de estas características:
Característica Genéricos
Las
enumeraciones Anotaciones
Con fines de cada bucle Autoboxing Varargs Importación estática Capítulo o artículo Capítulo 5 Artículos 30 a 34 Artículos 35 a 37 Artículo 46 Los artículos 40, 49 Artículo 42 Artículo 19
2 CAPÍTULO 1 INTRODUCCIÓN
La mayoría de los artículos se ilustran con ejemplos de programas. Una característica clave de este libro
es que contiene ejemplos de código que ilustran muchos patrones de diseño y modismos. En su caso, se les referencias cruzadas a la obra de referencia en
este ámbito [Gamma95].
Muchos artículos contienen uno o más ejemplos de programas que ilustran un poco de práctica que debe evitarse. Tales ejemplos, a veces conocido como antipatrones, son claramente
marcado con un comentario como "/ / Nunca hagas esto!"En cada caso, el elemento explica por qué el ejemplo es malo, y sugiere un enfoque alternativo.
Este libro no es para principiantes: se supone que ya se siente cómodo
con el lenguaje de programación Java. Si no es así, considere uno de los muchos bien
textos introductorios [Arnold05, Sestoft05]. Mientras que el libro está diseñado para ser acce-sible a cualquier persona con un conocimiento práctico de la lengua, se debe proporcionar alimentos para el pensamiento, incluso para programadores avanzados.
La mayor parte de las reglas de este libro se derivan de una serie de principios fundamentales. Clar-dad y la sencillez son de suma importancia. El usuario de un módulo debe
nunca ser sorprendido por su comportamiento. Los módulos deben ser lo más pequeño posible, pero no
más pequeño. (Tal como se utiliza en este libro, el término módulo se refiere a cualquier software reutilizable
componente, a partir de un método individual a un sistema complejo que consta de múltiples los paquetes.) Código debería ser reutiliza en lugar de copiar. Las dependencias entre
módulos deben mantenerse al mínimo. Los errores deben ser detectados tan pronto como sea posi-ble después de que se hacen, a ser posiposi-ble en tiempo de compilación.
Si bien las reglas de este libro no se aplican al 100 por ciento de las veces, lo hacen caracterizar las mejores prácticas de programación en la gran mayoría de los casos. Usted no debe seguir ciegamente estas reglas, pero violarlos sólo ocasionalmente y
con buena razón. Aprender el arte de la programación, como la mayoría de otras disciplinas, consiste primero aprender las reglas y luego aprender cuando romperlas.
En su mayor parte, este libro no es sobre el rendimiento. Se acerca escribiendo pro-gramos que son clara, correcta, útil, robusta, flexible y fácil de mantener. Si puede
hacer eso, por lo general es una cuestión relativamente sencilla para obtener el rendimiento que necesita
(Artículo 55). Algunos elementos hacen discutir los problemas de rendimiento, y algunos de estos artículos
proporcionar los números de rendimiento. Estos números, que se introducen con la frase "En mi máquina," debe considerarse como aproximadas en el mejor.
Por si sirve de algo, mi máquina es una construcción casera de envejecimiento 2,2 GHz dual-core AMD Opteron ™ 170 con 2 gigabytes de RAM, corriendo de Sun 1.6_05 liberación de
el Java SE Development Kit (JDK) encima de Microsoft Windows ® XP Professional SP2. Este JDK tiene dos máquinas virtuales, el cliente de Java HotSpot ™ y el servidor VMs. Las cifras de rendimiento se midieron en la VM Server.
Cuando se habla de las características del lenguaje de programación Java y sus bibliotecas, a veces es necesario hacer referencia a versiones específicas. Por razones de brevedad, este libro utiliza
"los números de versión de ingeniería" en preferencia a los nombres de lanzamiento oficial. Esta tabla muestra la asignación entre los nombres de la versión y los números de versión de la ingeniería.
Oficial Nombre de la liberación JDK 1.1.x / JRE 1.1.x
Java 2 Platform, Standard Edition, v 1.2 Java 2 Platform, Standard Edition, v 1.3 Java 2 Platform, Standard Edition, v 1.4 Java 2 Platform, Standard Edition, v 5.0 Java Platform, Standard Edition 6
Ingeniería Número de versión 1.1 1.2 1.3 1.4 1.5 1.6
Los ejemplos están razonablemente completa, pero desean que se convoque la legibilidad sobre
com-completitud. Ellos utilizan libremente las clases de los paquetes java.util y java.io. En
Para compilar los ejemplos, es posible que tenga que añadir una o más de estas importaciones declaraciones:
java.util import *.;
java.util.concurrent import *.; import java.io. *;
Otros repetitivo se omite de manera similar. El sitio web del libro, http:// java.sun.com / docs / books / efectiva, Contiene una versión ampliada de cada ejemplo, que se puede compilar y ejecutar.
En su mayor parte, este libro utiliza términos técnicos tal como se definen en La
Java Language Specification, Tercera edición [JLS]. Unos términos merecen especial mencionar. El lenguaje soporta cuatro tipos de tipos: interfaces de (Incluyendo
annota-ciones), clases de (Incluyendo enumeraannota-ciones), arrays, y primitivas. Los tres primeros son conocidos
como los tipos de referencia. Instancias de clase y las matrices son objetos; valores primitivos no lo son.
De una clase miembros consistir en su campos, métodos, clases de miembros, y miembro interfaces. De un método firma consiste en su nombre y el tipo de sus obligaciones formales parámetros; la firma hace no incluir el tipo de devolución del método.
4 CAPÍTULO 1 INTRODUCCIÓN
libro se limita a establecer que una clase implementos una interfaz o que una interfaz se extiende otra. Describir el nivel de acceso que se aplica cuando no se especifica ninguno, Este libro utiliza el término descriptivo paquete-privada en lugar de la técnica
cor-plazo rect acceso predeterminado [JLS, 6.6.1].
Este libro utiliza algunos términos técnicos que no están definidos en El Java Lan-guaje Specification. El término API exportada, o simplemente API, se refiere a las clases, interfaces, constructores, miembros y formularios serializados por el cual un programador accede a una clase, interfaz o paquete. (El término API, que es la abreviatura de aplicación interfaz de programación ción, se utiliza con preferencia al término de otra manera preferible interfaz para evitar la confusión con la construcción del lenguaje de ese nombre.) Un pro-Grammer que escribe un programa que utiliza una API se refiere como un usuario de la API. Una clase cuya aplicación utiliza una API es un cliente de la API.
Las clases, interfaces, constructores, miembros y formularios serializados son
colec-mente conocido como Elementos de la API. Una API exportada se compone de los elementos de la API que
son accesibles exterior del paquete que define la API. Estos son los ele-API
mentos que cualquier cliente puede utilizar y el autor de la API se compromete a apoyar. No coincidentemente, también son los elementos para los que la utilidad Javadoc genera
documentación en su modo de funcionamiento por defecto. Libremente hablando, el exportado API de un paquete se compone de los miembros públicos y protegidos y constructores
2
Creación y destrucción de objetos
T
Su capítulo preocupaciones Creación y destrucción de objetos: cuándo y cómo crearellos, cuándo y cómo evitar la creación de ellos, la forma de garantizar que sean destruidos en un tiempo y forma, y la forma de gestionar las acciones de limpieza que deben preceder su
destrucción.
Tema 1: Considere métodos de generador estáticos en lugar de
constructores
La forma normal de una clase para permitir a un cliente para obtener una instancia de sí mismo es pro-cionar un constructor público. Existe otra técnica que debe ser una parte de todos los
kit de herramientas del programador. Una clase puede ofrecer a un público método de fábrica estática, que es
simplemente un método estático que devuelve una instancia de la clase. Aquí está un examen simple plo de Boolean (La clase primitiva caja para el tipo primitivo boolean). Este
método traduce un boolean valor simple en un Boolean referencia de objeto:
static Boolean valueOf (boolean b) {
volver b? Boolean.TRUE: Boolean.FALSE; }
Tenga en cuenta que un método de fábrica estática no es el mismo que el Factory Method patrón desde Patrones de Diseño [Gamma95, p. 107]. El método de fábrica estática se describe en Este artículo no tiene equivalente directo en Patrones de diseño.
Una clase puede ofrecer a sus clientes los métodos estáticos de la fábrica en lugar de, o en Además, los constructores. Proporcionar un método de fábrica estática en lugar de un público constructor tiene tanto ventajas como desventajas.
Una de las ventajas de los métodos de fábrica estáticos es que, a diferencia de los constructores, se
tienen nombres. Si los parámetros de un constructor no lo hacen, en sí mismas,
describir el objeto que se devuelve, una fábrica estática con un nombre bien elegido es fácil-ier de usar y el código de cliente que resulta más fácil de leer. Por ejemplo, el constructor
6 CAPÍTULO 2 Crear y destruir objetos
que devuelve una BigInteger que es probablemente
prime, se habría expresado mejor como un método de fábrica estático denominado Bigin-teger.probablePrime. (Este método fue finalmente añadió en el comunicado de 1.4.)
Una clase sólo puede tener un único constructor con una firma determinada. Programa-dores se han sabido para evitar esta restricción, proporcionando dos constructores
cuyo parámetro listas sólo difieren en el orden de sus tipos de parámetros. Este es un muy mala idea. El usuario de una API como nunca será capaz de recordar lo que constructor es cuál y acabará llamando a la persona equivocada por error. Personas lectura de códigos que utiliza estos constructores no sabrá lo que hace el código con-a ccon-abo en referencicon-a con-a lcon-a documentcon-ación de lcon-a clcon-ase.
Debido a que tienen nombres, métodos de generador estáticos no compartir la restricción discutido en el párrafo anterior. En los casos en que una clase parece requerir múltiples constructores ple con la misma firma, sustituyen a los constructores con estática fac-métodos de historia y cuidadosamente elegidos nombres para resaltar sus diferencias.
Una segunda ventaja de los métodos de fábrica estáticos es que, a diferencia de los constructores,
no son necesarios para crear un nuevo objeto cada vez que están invocados. Este permite que las clases inmutables (artículo 15) para utilizar instancias preconstruidos, o caché casos a medida que se construyeron, y prescinden de ellos varias veces para evitar la creación de objetos duplicados innecesarios. La Boolean.valueOf (boolean) método
ilus-trados esta técnica: nunca crea un objeto. Esta técnica es similar a la
Peso mosca patrón [Gamma95, p. 195]. Se puede mejorar el rendimiento si Se ruega a los objetos equivalentes a menudo, especialmente si son caros de crear.
La capacidad de los métodos de fábrica estáticos para devolver el mismo objeto desde repetida invocaciones permite a clases para mantener un estricto control sobre lo que existen casos en cualquier momento. Las clases que hacen esto se dice que son instancia controlada. Hay varios razones para escribir clases de instancia controlada. Control Instancia permite a una clase
garantiza que sea un producto único (artículo 3) o no instanciable (punto 4). Además, permite una clase inmutable (artículo 15) para que la garantía de que no hay dos casos iguales
existir: a.equals (b) si y sólo si a == b. Si una clase tiene esta garantía, entonces su cli-los padres pueden utilizar el == operador en lugar de la equals (Object) método, que puede como resultado un mejor rendimiento. Tipos Enum (artículo 30) ofrecen esta garantía.
Una tercera ventaja de los métodos de fábrica estáticos es que, a diferencia de los constructores,
pueden devolver un objeto de cualquier subtipo de su tipo de retorno. Esto le da una gran flexibilidad en la elección de la clase del objeto devuelto.
Una aplicación de esta flexibilidad es que una API puede devolver objetos sin
haciendo sus clases públicas. Ocultación de clases de implementación de esta manera conduce a una API muy compacto. Esta técnica se presta a marcos basadas en la interfaz
(Artículo 18), donde las interfaces proporcionan tipos de retorno naturales de métodos de fábrica estáticas.
Las interfaces no pueden tener métodos estáticos, por lo que, por convención, métodos de generador estáticos para
una interfaz llamada Tipo se ponen en una clase no instanciable (punto 4) llamado Tipos.
Por ejemplo, el marco de las colecciones de Java tiene treinta y dos de conveniencia implementaciones de las interfaces de colección, proporcionando colecciones inmodificables, colecciones sincronizado, y similares. Casi todas estas implementaciones son
exportados a través de métodos de fábrica estáticos en una clase no instanciable ( java.util.Col-colecciones). Las clases de los objetos devueltos son todos no pública.
El API Collections Framework es mucho menor de lo que hubiera sido si
exportó treinta y dos clases públicas separadas, una para cada uno de conveniencia imple-mentación. No es sólo la mayor parte de la API que se reduce, pero el conceptual
peso. El usuario sabe que el objeto devuelto tiene precisamente la API especificado por su interfaz, lo que no hay necesidad de leer documentación de la clase adicional para el clases de implementación. Además, utilizando un método de fábrica tales estática requiere el cliente para hacer referencia al objeto devuelto por su interfaz en lugar de su implementación ción de clase, que es generalmente una buena práctica (artículo 52).
No sólo la clase de un objeto devuelto por un método de fábrica static
sea pública, pero la clase puede variar de invocación a la invocación dependiendo
los valores de los parámetros a la fábrica estática. Cualquier clase que es un subtipo de la tipo de retorno declarado es permisible. La clase del objeto devuelto también puede variar de versión a versión para una mayor facilidad de mantenimiento y rendimiento del software. La clase java.util.EnumSet (Artículo 32), introducido en la versión 1.5, no tiene
constructores públicos, sólo las fábricas estáticas. Vuelven uno de dos implementaciones, dependiendo del tamaño del tipo de enumeración subyacente: si tiene sesenta y cuatro o menos elementos, como la mayoría de los tipos de enumeración hacen, las fábricas estáticas devuelven un
RegularEnumSet
ejemplo, que está respaldado por un solo largo; si el tipo de enumeración tiene sesenta y cinco años o más
elementos, las fábricas devuelven un JumboEnumSet ejemplo, respaldado por una largo array. La existencia de estas dos clases de implementación es invisible a los clientes. Si
RegularEnumSet dejó de ofrecer ventajas de rendimiento para los pequeños tipos de enumeración, se podría ser eliminada de una versión futura sin efectos nocivos. Del mismo modo, un futuro
liberación podría añadir una tercera o cuarta aplicación de la EnumSet si resultaba benefi-CIAL para el rendimiento. Los clientes no saben ni les importa la clase del objeto
que regresen de la fábrica; que les importa sólo que es un poco de la subclase de EnumSet. La clase de objeto devuelto por un método de fábrica estática ni siquiera tiene por qué existir en el momento de escribir la clase que contiene el método. Dicha fábrica estática flexibles
métodos forman la base de marcos de proveedores de servicios, tales como la Base de Datos de Java
API Connectivity (JDBC). Un marco de proveedor de servicio es un sistema en el cual múltiples proveedores de servicios implementar un servicio, y el sistema hace que la imple-mentaciones a disposición de sus clientes, que evitan que aquéllas de las impleimple-mentaciones.
8 CAPÍTULO 2 Crear y destruir objetos
Hay tres componentes esenciales de un marco de servicios: una
ser-interfaz de vicio, que los proveedores implementen; un API de registro de proveedores, que el sistema utiliza para registrar las implementaciones, dando a los clientes acceso a las mismas; y un ser-Acceso vicio API, que los clientes utilizan para obtener una instancia del servicio. El servicio
acceso a la API normalmente permite, pero no requiere que el cliente especifique algunos criterios para la elección de un proveedor. En la ausencia de tal especificación, la API devuelve un
instancia de una implementación por defecto. La API de acceso al servicio es la "estática flexibles de fábrica "que forma la base del marco de proveedor de servicios.
Un cuarto componente opcional de un marco de servicios es un servicio
interfaz de proveedor, que los proveedores implementen para crear instancias de su servicio aplicación. En ausencia de un proveedor de servicios de interfaz, las implementaciones están registrados por nombre de clase y una instancia reflexiva (artículo 53). En el caso de los JDBC, Conexión juega la parte de la interfaz de servicio,
DriverManager.reg-isterDriver es la API de registro de proveedor, DriverManager.getConnection es
la API de acceso a los servicios, y Conductor es la interfaz de proveedor de servicios. Existen numerosas variantes del patrón de marco proveedor de servicios. Para
ejemplo, la API de acceso al servicio puede devolver una interfaz de servicio más rica que la requerida del proveedor, utilizando el patrón de adaptador [Gamma95, p. 139]. Aquí hay una aplicación sencilla con una interfaz de proveedor de servicios y un proveedor por defecto:
/ Servicio boceto / marco proveedor / / Interfaz de servicio
Interfaz de servicio público {
Métodos ... / / específica de servicio, entra aquí }
/ / Servicio de interfaz del proveedor Proveedor de interfaz pública { NewService Servicio (); }
/ / Clase no instanciable para el registro del servicio y el acceso Servicios public class {
Servicios privados () {} / / Evita la creación de instancias (artículo 4) / / nombres de servicio con los servicios
privados de los proveedores finales estáticos Mapa <String, SERVICIO> = nueva ConcurrentHashMap <String, SERVICIO> ();
/ / Proveedor de API de registro
public static void registerDefaultProvider (Proveedor p) { registerProvider (DEFAULT_PROVIDER_NAME, p); }
public static void registerProvider (String nombre, Proveedor p) { providers.put (nombre, p);
}
/ / Servicio de acceso a la API
public static Servicio newInstance () {
volver newInstance (DEFAULT_PROVIDER_NAME); }
static Servicio newInstance (String nombre) { Proveedor p = providers.get (nombre); if (p == null)
throw new IllegalArgumentException (
"Ningún proveedor registrado con el nombre:" + nombre); p.newService regresar ();
} }
Una cuarta ventaja de los métodos de fábrica estáticos es que reducen la VER-bosity de crear instancias de tipo con parámetros. Por desgracia, debe
espe-cificar los parámetros de tipo al invocar el constructor de una clase parametrizada incluso si son evidentes por el contexto. Esto normalmente requiere que usted provea la parámetros de tipo dos veces en rápida sucesión:
Map <String Lista <String>> m =
new HashMap <String Lista <String>> ();
Esta especificación redundante deja rápidamente doloroso como la longitud y la complejidad dad del incremento parámetros de tipo. Con fábricas estáticas, sin embargo, el compilador
puede averiguar los parámetros de tipo para usted. Esto se conoce como la inferencia de tipos. Para ejemplo, suponer que HashMap siempre que esta fábrica estática:
public static <K, V> HashMap <K, V> newInstance () { return new HashMap <K, V> ();
}
Posteriormente, se podría sustituir a la declaración prolijo arriba con esta alternativa sucinta:
10 CAPÍTULO 2 Crear y destruir objetos
Desafortunadamente, las implementaciones de recogida estándar, tales como HashMap hacer no tienen métodos de fábrica como de la liberación de 1,6, pero se puede poner estos métodos en su propia clase de utilidad. Más importante aún, usted puede proporcionar este tipo de fábricas de electricidad estática en su
clases con parámetros propios.
La principal desventaja de proporcionar métodos de fábrica sólo estáticas es que clases sin constructores públicos o protegidos no pueden ser subclases. La
mismo es cierto para las clases no públicas devueltos por las fábricas públicas estáticas. Por ejemplo, es imposible crear una subclase de cualquiera de las clases de implementación de conveniencia en el Marco de Colecciones. Podría decirse que esto puede ser una bendición disfrazada, ya que fomenta edades programadores utilizar la composición en vez de la herencia (artículo 16).
Una segunda desventaja de los métodos de fábrica estáticas es que no son fácilmente distinguible de otros métodos estáticos. Ellos no se destacan en API
documentación en la forma en que los constructores hacen, por lo que puede ser difícil de entender cómo crear una instancia de una clase que proporciona métodos de generador estáticos en lugar de
cons-tores. La herramienta Javadoc puede sacar algún día atención a los métodos estáticos de la fábrica. En Mientras tanto, usted puede reducir esta desventaja, llamando la atención a la electricidad estática fac-torios en clase o los comentarios de la interfaz, y mediante la adhesión a nombres común conven-ciones. Estos son algunos nombres comunes para los métodos estáticos de fábrica:
•valueOf-Devuelve una instancia que tiene, hablando en términos generales, el mismo valor que su parámetros. Tales fábricas estáticas son de tipo de conversión efectivamente métodos.
•de-Una alternativa concisa para valueOf, Popularizado por EnumSet (Artículo 32). •getInstance-Devuelve una instancia que se describe por los parámetros, pero
no se puede decir que tienen el mismo valor. En el caso de un singleton, getInstance no toma ningún parámetro y devuelve la única instancia.
•newInstance-Al igual que getInstance, Excepto que newInstance garantiza que cada instancia devuelta es distinta de todas las demás.
•conseguirTipo-Like getInstance, Sino que se utiliza cuando el método de fábrica se encuentra en una
clase ent. Tipo indica el tipo de objeto devuelto por el método de fábrica.
•nuevoTipo-Like newInstance, Sino que se utiliza cuando el método de fábrica se encuentra en una
clase ent. Tipo indica el tipo de objeto devuelto por el método de fábrica.
En resumen, los métodos de generador estáticos y constructores públicos ambos tienen su utiliza, y vale la pena entender sus méritos relativos. Fábricas menudo estáticos son pref-erable, por lo que evitar el reflejo de proporcionar constructores públicos sin antes considerar fábricas estáticas.
Tema 2:
Considere la posibilidad de un constructor cuando se enfrentan
a muchos constructor
parámetros
Fábricas estáticos y constructores comparten una limitación: no escala bien a grande número de parámetros opcionales. Consideremos el caso de una clase que representa el
Etiqueta de información nutricional que aparece en los alimentos envasados. Estas etiquetas tienen algunos
campos obligatorios-tamaño de la porción, porciones por envase, y las calorías por porción-y más de veinte opcional grasa campos-totales, grasas saturadas, grasas trans, colesterol,
de sodio, y así sucesivamente. La mayoría de los productos tienen valores distintos de cero por sólo unos pocos de estos
campos opcionales.
¿Qué clase de constructores o fábricas estáticas debe escribir para una clase de este tipo? Tradicionalmente, los programadores han utilizado el constructor telescópico patrón, en que proporcione un constructor con sólo los parámetros, otra con un requeridas
solo parámetro opcional, una tercera con dos parámetros opcionales, y así sucesivamente, culminación rios de un constructor con todos los parámetros opcionales. Así es como se ve en
práctica. Para ser breves, sólo cuatro campos opcionales se indican:
Patrón constructor / / telescópico - no escala bien! NutritionFacts public class {
int final privado servingSize ;/ / (ml) requiere
raciones privadas finales int ;/ / (por contenedor) requirieron calorías int final privado ;/ / opcional
final privado int grasa ;/ / (g) opcional private int final de sodio ;/ / (mg) opcional carbohidratos final int privado; / / (G) opcional
NutritionFacts públicas (int servingSize, int porciones) { esto (servingSize, porciones, 0);
}
NutritionFacts públicos (int servingSize, int porciones, int calorías) {
esto (servingSize, porciones, calorías, 0); }
NutritionFacts públicos (int servingSize, int porciones, int calorías, grasa int) {
esto (servingSize, porciones, calorías, grasa, 0); }
12 CAPÍTULO 2 Crear y destruir objetos
NutritionFacts públicos (int servingSize, int porciones, int, int calorías de grasa, sodio int, int carbohidratos) { this.servingSize = servingSize;
this.servings = porciones; this.calories = calorías; this.fat = grasa; this.sodium = de sodio;
this.carbohydrate = hidratos de carbono; }
}
Cuando desea crear una instancia, se utiliza el constructor con el menor lista de parámetros que contiene todos los parámetros que desea configurar:
NutritionFacts cocacola =
nuevos NutritionFacts (240, 8, 100, 0, 35, 27);
Normalmente esta invocación constructor requerirá muchos parámetros que usted no lo hace desea ajustar, pero te ves obligado a pasar un valor para ellos de todos modos. En este caso, pasado un valor de 0para grasa. Con "sólo" seis parámetros Esto puede no parecer tan malo, pero pronto se le va de las manos como el número de parámetros aumenta.
En resumen, el patrón constructor telescópica funciona, pero es difícil escribir código de cliente cuando hay muchos parámetros, y más difícil todavía lo lean. La lector se queda preguntándose qué significan todos esos valores, y debe contar con atención
parámetros para averiguar. Secuencias largas de parámetros de forma idéntica con tipo pueden causar errores sutiles. Si el cliente invierte accidentalmente dos de tales parámetros, el compilador
No se quejará, pero el programa se portan mal en tiempo de ejecución (artículo 40). Una segunda alternativa cuando se enfrentan con muchos parámetros de constructor es la JavaBeans patrón, en el que se llama a un constructor sin parámetros para crear el
objeto y luego llamar a los métodos setter para configurar cada parámetro requerido y cada uno parámetro opcional de interés:
/ / JavaBeans Patrón - permite la inconsistencia, mandatos mutabilidad NutritionFacts public class {
/ / Parámetros inicializan a valores por defecto (si los hay)
private int servingSize = -1; / / Necesario; ningún valor predeterminado porciones private int = -1; / / "" ""
calorías private int = 0; int grasa privado = 0; int sodio privada = 0;
int carbohidratos privado = 0; NutritionFacts públicas () {}
/ / Setters public void public void public void public void public void public void }
setServingSize (int val) setServings (int val) setCalories (int val) setFat (int val) setSodium (int val) setCarbohydrate (int val)
{ { { { { { servingSize = val; } porciones = val; } calorías = val; } grasa = val; } sodio = val; }
hidratos de carbono = Val; }
Este patrón tiene ninguna de las desventajas del patrón constructor telescópico.
Es fácil, aunque un poco prolijo, para crear instancias, y fácil de leer el código resultante:
NutritionFacts cocacola = new NutritionFacts (); cocaCola.setServingSize (240);
cocaCola.setServings (8); cocaCola.setCalories (100); cocaCola.setSodium (35); cocaCola.setCarbohydrate (27);
Desafortunadamente, el patrón de JavaBeans tiene graves desventajas de su propia.
Debido a que la construcción se divide en varias llamadas, un JavaBean puede estar en una estado inconsistente hasta la mitad a través de su construcción. La clase no tiene
la opción de hacer cumplir la consistencia simplemente comprobando la validez de la con-parámetros Structor. Intentar utilizar un objeto cuando está en un estado incoherente puede causar fallas que están muy lejos de el código que contiene el error, por lo tanto, difícil de depurar. Una desventaja es que relacionados el patrón de JavaBeans pre-cluye la posibilidad de hacer una clase inmutable (Artículo 15), y requiere
añadido de esfuerzo por parte del programador para garantizar la seguridad para subprocesos. Es posible reducir estos inconvenientes manualmente "congelar" el objeto
cuando su construcción esté completa y no lo que le permite ser utilizado hasta que se congele, pero esta variante es difícil de manejar y rara vez se utiliza en la práctica. Por otra parte, puede causar errores
en tiempo de ejecución, ya que el compilador no puede garantizar que el programador llama a la congelación
método en un objeto antes de usarlo.
Afortunadamente, hay una tercera alternativa que combina la seguridad de la telescópica patrón constructor con la legibilidad del patrón de JavaBeans. Es una forma de la
Constructor patrón [Gamma95, p. 97]. En lugar de hacer el objeto deseado directamente, el cliente llama a un constructor (o de fábrica estática) con todos los parámetros necesarios
y consigue un objeto constructor. A continuación, el cliente llama a los métodos setter-como en el constructor
oponerse a ajustar cada parámetro opcional de interés. Por último, el cliente llama a un parámetro terless construir método para generar el objeto, que es inmutable. El constructor es un
14 CAPÍTULO 2 Crear y destruir objetos
/ / Patrón Constructor
NutritionFacts public class { servingSize final int privado; porciones int final privado; calorías int final privado; grasa final int privado; int final de sodio privado; carbohidratos final int privado;
public class constructor static { / / Parámetros requeridos servingSize final int privado; porciones int final privado;
/ / Opcional private int private int private int private int
parámetros - inicializado a los valores por defecto calorías = 0;
grasas = 0;
hidratos de carbono = 0; de sodio = 0;
Constructor público (int servingSize, int porciones) { this.servingSize = servingSize;
this.servings = porciones; }
calorías Builder público (int val) {Calorías = val; devuelva este; grasa Constructor público (int val) {Grasa = val; devuelva este;
Constructor público carbohidratos (int val) {Carbohidratos = Val; devuelva este; Constructor público de sodio (int val) {Sodio = val; devuelva este; NutritionFacts públicas construyen () { volver nuevos NutritionFacts (this); }
}
NutritionFacts privado (Constructor Constructor) { servingSize = builder.servingSize; porciones = builder.servings; calorías = builder.calories; grasa = builder.fat; sodio = builder.sodium; carbohidratos = builder.carbohydrate; } } } } } }
Tenga en cuenta que NutritionFacts es inmutable, y que todos los valores por defecto de los parámetros
se encuentran en un solo lugar. Métodos de establecimiento del constructor devuelven el propio generador para
que las invocaciones se pueden encadenar. Así es como se ve el código de cliente:
NutritionFacts cocacola = new NutritionFacts.Builder (240, 8).
... calorías (100) de sodio (35) de hidratos de carbono (27) construcción ();
Este código de cliente es fácil de escribir y, sobre todo, para leer. El Generador de pat-simula tern llamados parámetros opcionales como se encuentra en Ada y Python.
Al igual que un constructor, un constructor puede imponer invariantes en sus parámetros. La
construir método puede comprobar estos invariantes. Es crítico que ser comprobados después de copia de los parámetros del constructor para el objeto, y que se pueden verificar en
los campos del objeto en lugar de los campos de generador (Tema 39). Si alguno de los invariantes son
vio-Lated, la construir método debe lanzar una IllegalStateException (Artículo 60). La método de detalle de excepción debe indicar qué invariante es violado (artículo 63). Otra forma de imponer invariantes que involucran a múltiples parámetros es tener métodos setter toman grupos enteros de parámetros en los que algunos deben invariante sostener. Si el invariante no se cumple, el método setter lanza una
IllegalArgu-mentException. Esto tiene la ventaja de detectar el fallo invariante tan pronto
como se pasan los parámetros no válidos, en lugar de esperar a que construir que se invoca.
La menor ventaja de los constructores sobre los constructores es que los constructores pueden tener
mul-tiple VarArgs parámetros. Constructores, al igual que los métodos, sólo puede tener un varargs parámetro. Debido a que los constructores utilizan métodos distintos para configurar cada parámetro, que pueden
tienen hasta VarArgs parámetros a su gusto, hasta uno por método setter.
El patrón Builder es flexible. Un único constructor puede ser usado para construir múltiples objetos. Los parámetros del constructor pueden ser ajustados entre las creaciones de objetos a variar los objetos. El constructor puede rellenar algunos campos automáticamente, como una serie cifra que se incrementa de forma automática cada vez que se crea un objeto.
Un constructor cuyos parámetros se han establecido hace una multa Abstract Factory
[Gamma95, p. 87]. En otras palabras, un cliente puede pasar un constructor de este tipo a un método para
habilitar el método para crear uno o más objetos para el cliente. Para habilitar esta
uso, se necesita un tipo para representar el constructor. Si está utilizando versión 1.5 o una
después suelte, un tipo genérico simple (artículo 26) es suficiente para todo constructores, no importa qué tipo de objeto que están construyendo:
/ / Un constructor de objetos de tipo T interfaz pública Constructor <T> {
16 CAPÍTULO 2 Crear y destruir objetos
Tenga en cuenta que nuestra NutritionFacts.Builder clase podría ser declarada de implementar
Constructor <NutritionFacts>.
Los métodos que toman una Constructor ejemplo sería restringen normalmente el constructor de tipo de parámetro usando un tipo comodín acotada (Artículo 28). Por ejemplo, aquí hay una método que genera un árbol utilizando un cliente proporcionado por Constructor instancia para construir cada
nodo:
Árbol buildTree (Generador de <? Extiende Node> NodeBuilder) {...}
La implementación tradicional Abstract Factory en Java ha sido el Clase
oponerse, con la newInstance método en el papel de la construir método. Este el uso está lleno de problemas. La newInstance método siempre intenta
invoca al constructor sin parámetros de la clase, que puede incluso no existir. Usted no lo hace obtendrá un error en tiempo de compilación si la clase no tiene constructor sin parámetros accesible. En su lugar, el código de cliente debe hacer frente a InstantiationException o
IllegalAc-cessException en tiempo de ejecución, lo cual es desagradable e inconveniente. También, la Newin-postura método propaga las excepciones producidas por el sin parámetros
constructor, a pesar de que newInstance carece de la correspondiente tiros cláusulas. En
otras palabras, Class.newInstance en tiempo de compilación se rompe comprobación excepción. La Constructor interfaz, se muestra más arriba, corrige estas deficiencias.
El patrón Constructor tiene desventajas de su propia. Con el fin de crear una
objeto, primero debe crear su constructor. Mientras que el costo de crear el constructor es
poco probable que sea perceptible en la práctica, podría ser un problema en algunos rendimiento-situaciones críticas. Además, el patrón Builder es más detallado que el telescópico
patrón constructor, por lo que sólo debe utilizarse si hay suficientes parámetros, digamos, cuatro o más. Pero tenga en cuenta que es posible que desee agregar parámetros en el futuro. Si usted comienza con constructores o fábricas estáticas, y añadir un constructor cuando el clase evoluciona hasta el punto que el número de parámetros empieza a ir de las manos, los constructores obsoletos o fábricas estáticos sobresalir como un pulgar dolorido. Hay-tanto, a menudo es mejor comenzar con un constructor en el primer lugar.
En resumen, el patrón Builder es una buena opción en el diseño de las clases cuyos constructores o fábricas estáticas tendrían más que un puñado de
parámetros, especialmente si la mayoría de esos parámetros son opcionales. El código de cliente es mucho más fácil de leer y escribir con los constructores que con la telescópica tradicional