100% encontró este documento útil (4 votos)
3K vistas1226 páginas

Java Language Es

JAVA
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
100% encontró este documento útil (4 votos)
3K vistas1226 páginas

Java Language Es

JAVA
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Java Language

#java
Tabla de contenido
Acerca de 1

Capítulo 1: Empezando con el lenguaje Java 2

Observaciones 2

Ediciones y versiones de Java 2

Instalando Java 3

Compilación y ejecución de programas Java. 3

¿Que sigue? 3

Pruebas 3

Otro 3

Versiones 4

Examples 4

Creando tu primer programa Java 4

Una mirada más cercana al programa Hello World. 6

Capítulo 2: Acceso nativo de Java 11

Examples 11

Introducción a JNA 11

¿Qué es JNA? 11

¿Como puedo usar lo? 11

¿A dónde ir ahora? 12

Capítulo 3: Afirmando 13

Sintaxis 13

Parámetros 13

Observaciones 13

Examples 13

Comprobando aritmética con aseverar. 13

Capítulo 4: Agentes de Java 14

Examples 14

Modificando clases con agentes. 14

Agregar un agente en tiempo de ejecución 15


Configuración de un agente básico 15

Capítulo 5: Ajuste de rendimiento de Java 17

Examples 17

Enfoque general 17

Reduciendo cantidad de cuerdas 17

Un enfoque basado en la evidencia para el ajuste de rendimiento de Java 18

Capítulo 6: Análisis XML utilizando las API de JAXP 20

Observaciones 20

Principios de la interfaz DOM 20

Principios de la interfaz SAX 20

Principios de la interfaz StAX 21

Examples 21

Analizar y navegar un documento utilizando la API DOM 21

Analizar un documento utilizando la API StAX 22

Capítulo 7: Anotaciones 25

Introducción 25

Sintaxis 25

Observaciones 25

Tipos de parametros 25

Examples 25

Anotaciones incorporadas 25

Comprobaciones de anotación en tiempo de ejecución a través de la reflexión. 29

Definición de tipos de anotación. 29

Valores predeterminados 30

Meta-Anotaciones 30

@Objetivo 30

Valores disponibles 30

@Retencion 31

Valores disponibles 32

@Documentado 32

@Heredado 32
@Repeable 33

Obtención de valores de anotación en tiempo de ejecución 33

Repetir anotaciones 34

Anotaciones heredadas 35

Ejemplo 35

Procesamiento de tiempo de compilación utilizando procesador de anotación 36

La anotacion 36

El procesador de anotaciones. 36

embalaje 38

Ejemplo de clase anotada 38

Usando el procesador de anotaciones con javac 39

Integración IDE 39

Netbeans 39

Resultado 40

La idea detrás de las anotaciones. 40

Anotaciones para 'este' y parámetros del receptor. 40

Añadir múltiples valores de anotación 42

Capítulo 8: Apache Commons Lang 43

Examples 43

Implementar el método equals () 43

Implementar el método hashCode () 43

Implementar el método toString () 44

Capítulo 9: API de apilación 46

Introducción 46

Examples 46

Imprimir todos los marcos de pila de la secuencia actual 46

Imprimir la clase de llamada actual 47

Mostrando la reflexión y otros marcos ocultos. 47

Capítulo 10: API de reflexión 49

Introducción 49

Observaciones 49
Actuación 49

Examples 49

Introducción 49

Invocando un método 51

Obtención y configuración de campos 51

Constructor de llamadas 53

Obtención del objeto constructor 53

Nueva Instancia usando Objeto Constructor 53

Obteniendo las constantes de una enumeración 53

Obtener clase dado su nombre (totalmente calificado) 54

Llamar a los constructores sobrecargados utilizando la reflexión. 55

Uso incorrecto de la API de Reflection para cambiar variables privadas y finales 56

Call constructor de clase anidada 57

Proxies dinámicos 57

Evil hacks de Java con Reflection 59

Capítulo 11: AppDynamics y TIBCO BusinessWorks Instrumentation para una fácil integración 61

Introducción 61

Examples 61

Ejemplo de instrumentación de todas las aplicaciones BW en un solo paso para Appdynamics 61

*** Variables comunes. Modifica estos solo. *** 61

Capítulo 12: Applets 63

Introducción 63

Observaciones 63

Examples 63

Applet mínimo 63

Creando una GUI 64

Abrir enlaces desde dentro del applet 65

Cargando imágenes, audio y otros recursos. 65

Cargar y mostrar una imagen. 66

Cargar y reproducir un archivo de audio. 66

Cargar y mostrar un archivo de texto 66

Capítulo 13: Archivo I / O 68


Introducción 68

Examples 68

Leyendo todos los bytes a un byte [] 68

Leyendo una imagen de un archivo. 68

Escribir un byte [] a un archivo 68

Stream vs Writer / Reader API 69

Leyendo un archivo completo a la vez 70

Leyendo un archivo con un escáner 71

Iterando sobre un directorio y filtrando por extensión de archivo 71

Migración de [Link] a Java 7 NIO ([Link]) 72

Apuntar a un camino 72

Caminos relativos a otro camino. 72

Convertir archivo de / a ruta para usar con bibliotecas 72

Compruebe si el archivo existe y elimínelo si existe. 72

Escribir en un archivo a través de un OutputStream 73

Iterando en cada archivo dentro de una carpeta 73

Iteración de la carpeta recursiva 74

Lectura / escritura de archivos usando FileInputStream / FileOutputStream 75

Leyendo de un archivo binario 76

Cierre 76

Copiando un archivo usando InputStream y OutputStream 77

Leyendo un archivo usando Channel y Buffer 77

Copiando un archivo usando el canal 79

Leyendo un archivo usando BufferedInputStream 79

Escribiendo un archivo usando Channel y Buffer 80

Escribiendo un archivo usando PrintStream 80

Iterar sobre un directorio de subdirectorios de impresión en él. 81

Agregando Directorios 81

Bloqueo o redireccionamiento de salida / error estándar 82

Accediendo a los contenidos de un archivo ZIP. 83

Leyendo de un archivo existente 83


Creando un nuevo archivo 83

Capítulo 14: Archivos JAR Multi-Release 84

Introducción 84

Examples 84

Ejemplo de contenido de un archivo Jar multi-release. 84

Creando un Jar multi-release usando la herramienta jar 84

URL de una clase cargada dentro de un Jar multi-release 86

Capítulo 15: Arrays 87

Introducción 87

Sintaxis 87

Parámetros 87

Examples 87

Creación e inicialización de matrices 87

Casos basicos 87

Arrays, colecciones y corrientes 88

Introducción 88

Creación e inicialización de matrices de tipos primitivos. 90

Creando e inicializando arrays multidimensionales. 91

Representación de matriz multidimensional en Java 92

Creación e inicialización de matrices de tipos de referencia 92

Creando e inicializando arrays genéricos 93

Rellenar una matriz después de la inicialización 94

Declaración separada e inicialización de matrices. 94

Es posible que las matrices no se puedan reinicializar con la sintaxis de acceso directo d 95

Creando una matriz de una colección 95

Arrays a una cadena 97

Creación de una lista a partir de una matriz 97

Notas importantes relacionadas con el uso del método [Link] () 98

Matrices multidimensionales y dentadas 99

Cómo se representan los arreglos multidimensionales en Java 100


ArrayIndexOutOfBoundsException 101

Obtener la longitud de una matriz 102

Comparando matrices para la igualdad 103

Arreglos para transmitir 104

Iterando sobre matrices 104

Copiando matrices 107

en bucle 107

[Link] () 107

[Link] () 108

[Link] () 108

[Link] () 108

Matrices de fundición 108

Eliminar un elemento de una matriz 109

Usando ArrayList 109

Usando [Link] 109

Usando Apache Commons Lang 110

Array Covariance 110

¿Cómo cambias el tamaño de una matriz? 111

Una mejor alternativa para cambiar el tamaño de matriz 111

Encontrar un elemento en una matriz 112

Usando [Link] (solo para arreglos ordenados) 112

Uso de [Link] (solo para matrices no primitivas) 112

Usando una Stream 113

Búsqueda lineal utilizando un bucle. 113

Búsqueda lineal utilizando bibliotecas de terceros como [Link] 113

Probando si una matriz contiene un elemento 113

Ordenando matrices 114

Conversión de matrices entre primitivas y tipos de caja. 115

Capítulo 16: Audio 117

Observaciones 117

Examples 117
Reproducir un archivo de audio en bucle 117

Reproducir un archivo MIDI 117

Sonido de metal desnudo 119

Salida de audio básica 120

Capítulo 17: Autoboxing 121

Introducción 121

Observaciones 121

Examples 121

Usando int y entero indistintamente 121

Usando Boolean en la sentencia if 122

Auto-unboxing puede llevar a NullPointerException 123

Memoria y sobrecarga computacional de Autoboxing 123

Casos diferentes cuando Integer e int pueden usarse indistintamente 124

Capítulo 18: Banderas JVM 126

Observaciones 126

Examples 126

-XXaggresivo 126

-XXallocClearChunks 126

-XXallocClearChunkSize 127

-XXcallProfiling 127

-XXdisableFatSpin 127

-XXdisponibilidad a las características de la visión 128

-XXdumpSize 128

-XXexitOnOutOfMemory 128

Capítulo 19: BigDecimal 130

Introducción 130

Examples 130

Los objetos BigDecimal son inmutables. 130

Comparando BigDecimals 130

Operaciones matemáticas con BigDecimal. 130

[Link]ón 130

[Link] 131
[Link] 131

[Link] 131

[Link] resto o módulo 132

6. Poder 132

[Link] 133

[Link] 133

9. Mover punto a la izquierda 133

10. Mover punto a la derecha 133

Usando BigDecimal en lugar de flotar 134

[Link] () 135

Inicialización de BigDecimals con valor cero, uno o diez. 135

Capítulo 20: BigInteger 136

Introducción 136

Sintaxis 136

Observaciones 136

Examples 137

Inicialización 137

Comparando BigIntegers 138

Ejemplos de operaciones matemáticas de BigInteger 139

Operaciones de lógica binaria en BigInteger 141

Generando BigIntegers aleatorios 142

Capítulo 21: ByteBuffer 144

Introducción 144

Sintaxis 144

Examples 144

Uso básico - Creación de un ByteBuffer 144

Uso básico - Escribir datos en el búfer 145

Uso básico - Uso de DirectByteBuffer 145

Capítulo 22: Calendario y sus subclases 147

Observaciones 147

Examples 147
Creando objetos de calendario 147

Aumentar / disminuir los campos del calendario 147

Encontrando AM / PM 148

Restando calendarios 148

Capítulo 23: Características de Java SE 7 149

Introducción 149

Observaciones 149

Examples 149

Nuevas características del lenguaje de programación Java SE 7. 149

Literales binarios 149

La declaración de prueba con recursos 150

Subrayados en literales numéricos 150

Inferencia de tipos para la creación de instancias genéricas 151

Cadenas en las instrucciones del interruptor 151

Capítulo 24: Características de Java SE 8 153

Introducción 153

Observaciones 153

Examples 153

Nuevas características del lenguaje de programación Java SE 8. 153

Capítulo 25: Cargadores de clases 155

Observaciones 155

Examples 155

Instalar y usar un cargador de clases 155

Implementando un classLoader personalizado 155

Cargando un archivo .class externo 156

Capítulo 26: Cifrado RSA 158

Examples 158

Un ejemplo que utiliza un sistema criptográfico híbrido que consiste en OAEP y GCM 158

Capítulo 27: Clase - Reflexión de Java 163

Introducción 163

Examples 163

Método getClass () de la clase Object. 163


Capítulo 28: Clase de fecha 164

Sintaxis 164

Parámetros 164

Observaciones 164

Examples 165

Creando objetos de fecha 165

Comparando objetos de fecha 166

Calendario, fecha y fecha local 166

Antes, después, compare y métodos iguales. 166

isBefore, isAfter, compareTo y es igual a métodos 167

Comparación de fechas antes de Java 8 168

Desde Java 8 168

Convertir la fecha a un determinado formato de cadena 169

Convertir cadena en fecha 169

Una fecha básica de salida. 170

Convertir la representación de cadena formateada de la fecha en el objeto Fecha 170

Creando una fecha específica 171

Objetos Java 8 LocalDate y LocalDateTime 172

Zonas horarias y [Link] 173

Convertir [Link] a [Link] 173

Hora local 174

Capítulo 29: Clase de objetos Métodos y constructor 176

Introducción 176

Sintaxis 176

Examples 176

método toString () 176

método igual () 177

Comparación de clases 179

método hashCode () 180

Usando [Link] () como un atajo 181

Caché interno de códigos hash 182


Métodos de esperar () y notificar () 183

método getClass () 184

método clone () 185

finalizar () método 186

Constructor de objetos 187

Capítulo 30: Clase de propiedades 190

Introducción 190

Sintaxis 190

Observaciones 190

Examples 191

Cargando propiedades 191

Los archivos de propiedades advierten: espacios en blanco al final 191

Guardar propiedades como XML 194

Capítulo 31: Clase EnumSet 196

Introducción 196

Examples 196

Ejemplo de conjunto de enumeración 196

Capítulo 32: Clase inmutable 197

Introducción 197

Observaciones 197

Examples 197

Reglas para definir clases inmutables. 197

Ejemplo sin referencias mutables. 197

Ejemplo con referencias mutables 198

¿Cuál es la ventaja de la inmutabilidad? 199

Capítulo 33: Clase interna local 200

Introducción 200

Examples 200

Clase interna local 200

Capítulo 34: Clases anidadas e internas 201

Introducción 201

Sintaxis 201
Observaciones 201

Terminologia y clasificacion 201

Diferencias semanticas 202

Examples 202

Una pila simple usando una clase anidada 202

Clases anidadas estáticas y no estáticas 203

Modificadores de Acceso para Clases Internas 205

Clases internas anónimas 206

Constructores 207

Método de clases internas locales 207

Acceso a la clase externa desde una clase interna no estática 208

Crear instancia de clase interna no estática desde el exterior. 209

Capítulo 35: Clases y objetos 210

Introducción 210

Sintaxis 210

Examples 210

Clase posible más simple 210

Miembro Objeto vs Miembro Estático 210

Métodos de sobrecarga 211

Construcción y uso de objetos básicos 212

Constructores 215

Inicializando campos finales estáticos usando un inicializador estático 216

Explicando qué es el método de sobrecarga y anulación. 216

Capítulo 36: Clonación de objetos 220

Observaciones 220

Examples 220

Clonación utilizando un constructor de copia. 220

Clonación implementando la interfaz clonable 221

Clonación realizando una copia superficial. 221

Clonación realizando una copia profunda. 222

Clonación utilizando una fábrica de copias. 223

Capítulo 37: Codificación de caracteres 224


Examples 224

Leyendo texto de un archivo codificado en UTF-8 224

Escribiendo texto a un archivo en UTF-8 224

Obtención de la representación en byte de una cadena en UTF-8 225

Capítulo 38: Código oficial de Oracle estándar 226

Introducción 226

Observaciones 226

Examples 226

Convenciones de nombres 226

Nombres de paquetes 226

Clase, Interfaz y Nombres Enum 226

Nombres de los métodos 227

Variables 227

Variables de tipo 227

Constantes 227

Otras directrices sobre nombramiento 228

Archivos fuente de Java 228

Caracteres especiales 228

Declaración del paquete 228

Declaraciones de importación 229

Importaciones de comodines 229

Estructura de clase 229

Orden de los miembros de la clase 229

Agrupación de miembros de la clase. 230

Modificadores 230

Sangría 231

Envolver declaraciones 231

Declaraciones del método de envoltura 232

Expresiones de envoltura 233

Espacio en blanco 233

Espacio en blanco vertical 233


Espacio en blanco horizontal 234

Declaraciones Variables 234

Anotaciones 234

Expresiones lambda 235

Paréntesis redundantes 236

Literales 236

Tirantes 236

Formas cortas 237

Capítulo 39: Colas y deques 238

Examples 238

El uso de la PriorityQueue 238

LinkedList como una cola FIFO 238

Pilas 239

¿Qué es una pila? 239

API de pila 239

Ejemplo 239

BlockingQueue 240

Interfaz de cola 241

Deque 242

Agregar y acceder a los elementos 243

Removiendo elementos 243

Capítulo 40: Colecciones 244

Introducción 244

Observaciones 244

Examples 245

Declarar una ArrayList y agregar objetos 245

Construyendo colecciones a partir de datos existentes 246

Colecciones estandar 246

Marco de Colecciones Java 246

Marco de colecciones de guayaba de Google 246

Mapeo de Colecciones 247


Marco de Colecciones Java 247

Marco de Apache Commons Collections 247

Marco de colecciones de guayaba de Google 247

Unir listas 248

Eliminar elementos de una lista dentro de un bucle 248

INCORRECTO 248

Extracción de iteración de for declaración Omite "Banana": 249

Eliminando en la excepción mejorada for tiros de instrucción : 249

CORRECTO 249

Eliminando en bucle while usando un Iterator 249

Iterando hacia atrás 250

Iterando hacia adelante, ajustando el índice de bucle. 251

Usando una lista de "debería ser eliminado" 251

Filtrando una corriente 251

Utilizando removeIf 251

Colección no modificable 252

Iterando sobre colecciones 252

Iterando sobre la lista 252

Iterando sobre Set 253

Iterando sobre el mapa 254

Colecciones vacias inmutables 254

Colecciones y valores primitivos 255

Eliminar elementos coincidentes de las listas utilizando Iterator. 255

Creando su propia estructura de Iterable para usar con Iterator o para cada bucle. 256

Pitfall: excepciones de modificaciones concurrentes 258

Sub Colecciones 259

Lista de sublistas (int fromIndex, int toIndex) 259

Establecer subSet (fromIndex, toIndex) 259

Mapa de mapa secundario (fromKey, toKey) 260

Capítulo 41: Colecciones alternativas 261

Observaciones 261
Examples 261

Apache HashBag, Guava HashMultiset y Eclipse HashBag 261

1. Usando SynchronizedSortedBag de Apache : 261

2. Usando TreeBag de Eclipse (GC) : 262

3. Usando LinkedHashMultiset desde Guava : 262

Más ejemplos: 263

Multimap en colecciones de guayaba, apache y eclipse 263

Más ejemplos: 266

Comparar operación con colecciones - Crear colecciones 266

Comparar operación con colecciones - Crear colecciones 266

Capítulo 42: Colecciones concurrentes 272

Introducción 272

Examples 272

Colecciones a prueba de hilos 272

Colecciones concurrentes 272

Hilo seguro pero ejemplos no concurrentes 274

Inserción en el mapa de hash concurrente 274

Capítulo 43: Comandos de tiempo de ejecución 276

Examples 276

Añadiendo ganchos de apagado 276

Capítulo 44: Comparable y comparador 277

Sintaxis 277

Observaciones 277

Examples 277

Ordenar una lista usando Comparable o un comparador 278

Comparadores basados en expresiones Lambda 281

Métodos predeterminados del comparador 281

Invertir el orden de un comparador 281

Los métodos de comparar y comparar 281

Clasificación natural (comparable) vs explícita (comparativa) 282

Ordenar entradas de mapa 283


Creando un comparador usando el método de comparación 284

Capítulo 45: Comparación de C ++ 285

Introducción 285

Observaciones 285

Clases definidas dentro de otras construcciones # 285

Definido dentro de otra clase 285

C ++ 285

Java 285

Definido estáticamente dentro de otra clase 285

C ++ 286

Java 286

Definido dentro de un método 286

C ++ 286

Java 286

Anulando vs Sobrecarga 287

Polimorfismo 287

Orden de Construcción / Destrucción 287

Limpieza de objetos 287

Métodos y clases abstractas 288

Modificadores de accesibilidad 288

Ejemplo de C ++ Friend 289

El temido problema del diamante 289

clase [Link] 289

Colecciones Java y Contenedores C ++ 289

Diagrama de flujo de colecciones Java 289

Diagrama de flujo de contenedores C ++ 289

Tipos enteros 289

Examples 290

Miembros de la clase estática 290

Ejemplo de C ++ 290
Ejemplo de Java 291

Clases definidas dentro de otras construcciones 291

Definido dentro de otra clase 291

C ++ 291

Java 291

Definido estáticamente dentro de otra clase 291

C ++ 292

Java 292

Definido dentro de un método 292

C ++ 292

Java 292

Pasar por valor y Pasar por referencia 293

Ejemplo de C ++ (código completo) 293

Ejemplo de Java (código completo) 293

Herencia vs Composición 294

Despreciación por desvalorización 294

Ejemplo de C ++ 294

Ejemplo de Java 294

Métodos y clases abstractas 294

Método abstracto 294

C ++ 294

Java 295

Clase abstracta 295

C ++ 295

Java 295

Interfaz 295

C ++ 295

Java 295

Capítulo 46: Compilador de Java - 'javac' 296

Observaciones 296
Examples 296

El comando 'javac' - empezando 296

Ejemplo simple 296

Ejemplo con paquetes 297

Compilando múltiples archivos a la vez con 'javac'. 298

Opciones 'javac' usadas comúnmente 299

Referencias 299

Compilando para una versión diferente de Java 299

Compilando Java antiguo con un compilador más nuevo 299

Compilando para una plataforma de ejecución anterior 300

Capítulo 47: CompletableFuture 302

Introducción 302

Examples 302

Convertir el método de bloqueo a asíncrono. 302

Ejemplo simple de CompletableFuture 303

Capítulo 48: Conjuntos 304

Examples 304

Declarando un HashSet con valores 304

Tipos y uso de conjuntos 304

HashSet - Clasificación aleatoria 304

LinkedHashSet - Orden de inserción 304

TreeSet - por compareTo() o Comparator 305

Inicialización 305

Fundamentos de set 306

Crear una lista de un conjunto existente 307

Eliminando duplicados utilizando Set 308

Capítulo 49: Constructores 309

Introducción 309

Observaciones 309

Examples 309

Constructor predeterminado 309


Constructor con Argumentos 310

Llamar al constructor padre 311

Capítulo 50: Convertir hacia y desde cuerdas 313

Examples 313

Convertir otros tipos de datos a String 313

Conversión a / desde bytes 313

Codificación / decodificación de Base64 314

Analizar cadenas a un valor numérico 315

Obteniendo un `String` de un` InputStream` 316

Convertir cadena a otros tipos de datos. 317

Capítulo 51: Corrientes 319

Introducción 319

Sintaxis 319

Examples 319

Usando Streams 319

Cierre de arroyos 320

Orden de procesamiento 321

Diferencias de Contenedores (o Colecciones ) 322

Recoge los elementos de una corriente en una colección 322

Recopilar con toList() y toSet() 322

Control explícito sobre la implementación de List o Set 323

Hoja de trucos 325

Corrientes infinitas 325

Corrientes de consumo 326

h21 327

Creando un Mapa de Frecuencia 328

Corriente paralela 328

Impacto en el rendimiento 329

Convertir un flujo de opcionales a un flujo de valores 329

Creando un Stream 329

Encontrar estadísticas sobre flujos numéricos 331

Obtener un trozo de un arroyo 331


Corrientes de concatenación 331

IntStream to String 332

Ordenar usando Stream 332

Arroyos de primitivos 333

Recopilar los resultados de una secuencia en una matriz 333

Encontrar el primer elemento que coincide con un predicado 334

Usando IntStream para iterar sobre los índices 334

Aplanar arroyos con mapa plano () 335

Crear un mapa basado en una corriente 335

Generando cadenas aleatorias utilizando Streams 337

Usando Streams para Implementar Funciones Matemáticas 338

Uso de flujos y referencias de métodos para escribir procesos de autodocumentación 338

Uso de flujos de [Link] para conservar los valores iniciales después del mapeo 339

Categorías de operaciones de flujo 339

Operaciones intermedias: 339

Terminal de Operaciones 340

Operaciones sin Estado 340

Operaciones de estado 340

Convertir un iterador a un flujo 341

Reducción con arroyos 341

Unir un flujo a una sola cadena 344

Capítulo 52: Creando imágenes programáticamente 346

Observaciones 346

Examples 346

Creando una imagen simple programáticamente y mostrándola. 346

Guardar una imagen en el disco 347

Especificando la calidad de renderizado de la imagen. 347

Creando una imagen con la clase BufferedImage 349

Edición y reutilización de imágenes con BufferedImage. 350

Configuración del color de píxel individual en BufferedImage 351

Cómo escalar una imagen almacenada 351

Capítulo 53: Desmontaje y Descompilación. 353


Sintaxis 353

Parámetros 353

Examples 354

Viendo bytecode con javap 354

Capítulo 54: Despliegue de Java 361

Introducción 361

Observaciones 361

Examples 361

Haciendo un JAR ejecutable desde la línea de comando 361

Creando archivos JAR, WAR y EAR 362

Creando archivos JAR y WAR usando Maven 363

Creando archivos JAR, WAR y EAR usando Ant 363

Creando archivos JAR, WAR y EAR usando un IDE 363

Creando archivos JAR, WAR y EAR usando el comando jar . 363

Introducción a Java Web Start 364

Prerrequisitos 364

Un ejemplo de archivo JNLP 365

Configurando el servidor web 365

Habilitar el lanzamiento a través de una página web. 365

Lanzar aplicaciones Web Start desde la línea de comandos. 366

Creando un UberJAR para una aplicación y sus dependencias 366

Creando un UberJAR usando el comando "jar" 366

Creando un UberJAR utilizando Maven 367

Las ventajas y desventajas de los UberJARs. 367

Capítulo 55: Dividir una cadena en partes de longitud fija 369

Observaciones 369

Examples 369

Rompe una cuerda en subcadenas, todas de una longitud conocida 369

Rompe una cadena en subcadenas todas de longitud variable 369

Capítulo 56: Documentando el código de Java 370

Introducción 370
Sintaxis 370

Observaciones 371

Examples 371

Documentación de la clase 371

Método de Documentación 372

Documentacion de campo 372

Documentación del paquete 373

Campo de golf 373

Construyendo Javadocs desde la línea de comando 375

Documentación del código en línea 375

Fragmentos de código dentro de la documentación. 376

Capítulo 57: E / S de consola 378

Examples 378

Lectura de entrada de usuario desde la consola. 378

Utilizando BufferedReader : 378

Utilizando Scanner : 378

Utilizando [Link] : 379

Implementar el comportamiento básico de la línea de comandos 380

Alineación de cuerdas en consola. 381

Ejemplos de cadenas de formato 382

Capítulo 58: Ediciones, versiones, lanzamientos y distribuciones de Java 383

Examples 383

Diferencias entre las distribuciones Java SE JRE o Java SE JDK 383

Java Runtime Environment 383

Kit de desarrollo de Java 383

¿Cuál es la diferencia entre Oracle Hotspot y OpenJDK? 384

Diferencias entre Java EE, Java SE, Java ME y JavaFX 385

Las plataformas de lenguaje de programación Java 385

Java SE 385

Java EE 385

Java ME 386
Java FX 386

Versiones de Java SE 386

Historial de versiones de Java SE 386

Aspectos destacados de la versión de Java SE 387

Capítulo 59: Ejecutor, ExecutorService y grupos de subprocesos 389

Introducción 389

Observaciones 389

Examples 389

Fuego y olvido - Tareas ejecutables 389

ThreadPoolExecutor 390

Recuperando valor de cómputo - Callable 391

Programar tareas para que se ejecuten a una hora determinada, después de un retraso o repe 392

Iniciar una tarea después de un retraso fijo 392

Comenzando tareas a una tasa fija 392

Comenzando tareas con un retraso fijo 393

Manejar Ejecución Rechazada 393

diferencias de manejo de excepciones de submit () vs execute () 394

Casos de uso para diferentes tipos de construcciones de concurrencia. 396

Espere a que se completen todas las tareas en ExecutorService 397

Casos de uso para diferentes tipos de servicios de ejecución 399

Uso de grupos de subprocesos 402

Capítulo 60: El classpath 403

Introducción 403

Observaciones 403

Examples 403

Diferentes formas de especificar el classpath. 403

Agregando todos los JARs en un directorio a la ruta de clase 404

Sintaxis de ruta de clase 405

Classpath dinámico 405

Cargar un recurso desde el classpath 405

Asignación de nombres de clases a rutas de acceso 406

Qué significa el classpath: cómo funcionan las búsquedas 407


La ruta de clases de arranque 407

Capítulo 61: El Comando de Java - 'java' y 'javaw' 409

Sintaxis 409

Observaciones 409

Examples 409

Ejecutando un archivo JAR ejecutable 409

Ejecutando aplicaciones Java a través de una clase "principal" 410

Ejecutando la clase HelloWorld 410

Especificando un classpath 410

Clases de punto de entrada 411

Puntos de entrada de JavaFX 411

Solución de problemas del comando 'java' 411

"Comando no encontrado" 411

"No se pudo encontrar o cargar la clase principal" 412

"El método principal no se encuentra en la clase <nombre>" 413

Otros recursos 413

Ejecutando una aplicación Java con dependencias de biblioteca 414

Espacios y otros caracteres especiales en argumentos. 415

Soluciones usando un shell POSIX 415

Solución para Windows 416

Opciones de Java 416

Configurando las propiedades del sistema con -D 417

Opciones de memoria, pila y recolector de basura 417

Habilitar y deshabilitar aserciones 417

Seleccionando el tipo de máquina virtual 418

Capítulo 62: Encapsulacion 419

Introducción 419

Observaciones 419

Examples 419

Encapsulamiento para mantener invariantes. 419

Encapsulamiento para reducir el acoplamiento. 420


Capítulo 63: Enchufes 422

Introducción 422

Examples 422

Leer de socket 422

Capítulo 64: Enum a partir del número 423

Introducción 423

Examples 423

Enum con nombre al principio 423

Capítulo 65: Enums 424

Introducción 424

Sintaxis 424

Observaciones 424

Restricciones 424

consejos y trucos 424

Examples 425

Declarar y usar una enumeración básica 425

Enums con constructores 428

Utilizando métodos y bloques estáticos. 430

Implementa interfaz 431

Patrón de polimorfismo enum 432

Enums con métodos abstractos 433

Documentando enumeraciones 433

Obtener los valores de una enumeración 434

Enum como un parámetro de tipo limitado 435

Obtener enumeración constante por nombre 435

Implementar el patrón Singleton con una enumeración de un solo elemento. 436

Enumerar con propiedades (campos) 436

Convertir enum a cadena 437

Convertir usando name() 437

Convertir utilizando toString() 437

Por defecto: 438

Ejemplo de ser anulado 438


Enumeración específica del cuerpo 438

Enumeración cero instancia 440

Enums con campos estáticos 440

Comparar y Contiene para los valores Enum 441

Capítulo 66: Errores comunes de Java 443

Introducción 443

Examples 443

Pitfall: utilizando == para comparar objetos de envoltorios primitivos, como Integer 443

Pitfall: olvidarse de liberar recursos 444

Trampa: fugas de memoria 445

Pitfall: usando == para comparar cadenas 446

Pitfall: probar un archivo antes de intentar abrirlo. 448

Pitfall: pensar las variables como objetos 449

Clase de ejemplo 450

Múltiples variables pueden apuntar al mismo objeto. 450

El operador de igualdad NO prueba que dos objetos son iguales 451

Las llamadas a métodos NO pasan objetos en absoluto 452

Pitfall: combinación de asignación y efectos secundarios 453

Pitfall: no entender que String es una clase inmutable 453

Capítulo 67: Errores de Java - Nulls y NullPointerException 455

Observaciones 455

Examples 455

Trampa: el uso innecesario de envolturas primitivas puede llevar a NullPointerExceptions 455

Pitfall - Usar nulo para representar una matriz o colección vacía 456

Pitfall - "Haciendo buenos" nulos inesperados 457

¿Qué significa que "a" o "b" sean nulos? 458

¿El nulo vino de una variable no inicializada? 458

¿El nulo representa un "no se sabe" o "valor perdido"? 458

Si se trata de un error (o un error de diseño), ¿debemos "solucionarlo"? 458

¿Es esto eficiente / bueno para la calidad del código? 459

En resumen 459

Pitfall - Devolver nulo en lugar de lanzar una excepción 459


Pitfall: no se comprueba si un flujo de E / S ni siquiera se inicializa al cerrarlo 460

Pitfall: uso de la "notación Yoda" para evitar la excepción NullPointerException 460

Capítulo 68: Errores de Java - Problemas de rendimiento 462

Introducción 462

Observaciones 462

Examples 462

Pitfall - Los gastos generales de crear mensajes de registro 462

Solución 462

Pitfall - La concatenación de cadenas en un bucle no se escala 463

Pitfall: el uso de 'nuevo' para crear instancias de contenedor primitivas es ineficiente 464

Pitfall - Llamar 'nueva cadena (String)' es ineficiente 465

Pitfall - Calling [Link] () es ineficiente 465

Pitfall - El uso excesivo de tipos de envoltorios primitivos es ineficiente 466

Pitfall - Iterar las claves de un mapa puede ser ineficiente 467

Pitfall: el uso de size () para comprobar si una colección está vacía es ineficiente. 468

Pitfall - Problemas de eficiencia con expresiones regulares 468

Las instancias de Pattern y Matcher deben ser reutilizadas 468

No uses match () cuando deberías usar find () 470

Usar alternativas más eficientes a las expresiones regulares. 470

Retroceso catastrófico 471

Pitfall - Interning Strings para que puedas usar == es una mala idea 472

Fragilidad 472

Costos de usar 'intern ()' 472

El impacto en la recolección de basura. 473

El tamaño de hashtable del grupo de cadenas 473

Interning como un potencial vector de denegación de servicio 473

Pitfall - Las lecturas / escrituras pequeñas en flujos no almacenados en búfer son inefici 474

¿Qué pasa con las corrientes basadas en caracteres? 475

¿Por qué los flujos amortiguados hacen tanta diferencia? 475

¿Las transmisiones amortiguadas son siempre una victoria? 476

¿Es esta la forma más rápida de copiar un archivo en Java? 476

Capítulo 69: Errores de Java - sintaxis de lenguaje 477


Introducción 477

Observaciones 477

Examples 477

Pitfall - Ignorar la visibilidad del método 477

Pitfall - Falta un 'break' en un caso de 'cambio' 477

Pitfall - punto y coma mal colocados y llaves faltantes 478

Trampa: omitir llaves: los problemas de "colgar si" y "colgar de otra manera" 480

Trampa: sobrecargar en lugar de anular 482

Pitfall - Octales literales 483

Pitfall - Declarar clases con los mismos nombres que las clases estándar 483

Pitfall - Usar '==' para probar un booleano 484

Pitfall: las importaciones de comodines pueden hacer que su código sea frágil 485

Pitfall: Usar 'assert' para validar argumentos o entradas de usuario 486

El escollo de los objetos nulos de autoenvasado en primitivos 487

Capítulo 70: Errores de Java - Uso de excepciones 488

Introducción 488

Examples 488

Pitfall - Ignorar o aplastar excepciones 488

Pitfall: captura de Throwable, Exception, Error o RuntimeException 489

Pitfall - Lanzar Throwable, Exception, Error o RuntimeException 490

Declarar Throwable o Exception en los "lanzamientos" de un método es problemático. 491

Pitfall - Catching InterruptedException 492

Pitfall - Uso de excepciones para el control de flujo normal 494

Pitfall - Stacktraces excesivos o inapropiados 495

Pitfall - Subclasificando directamente `Throwable` 495

Capítulo 71: Escáner 497

Sintaxis 497

Parámetros 497

Observaciones 497

Examples 497

Lectura de la entrada del sistema utilizando el escáner 497

Lectura de entrada de archivo utilizando escáner 497


Lee toda la entrada como una cadena usando un escáner 498

Usando delimitadores personalizados 498

Patrón general que realiza las tareas más frecuentes. 499

Lee un int desde la línea de comando 501

Cerrar cuidadosamente un escáner 501

Capítulo 72: Escogiendo Colecciones 503

Introducción 503

Examples 503

Diagrama de flujo de colecciones Java 503

Capítulo 73: Escritor Buffered 504

Sintaxis 504

Observaciones 504

Examples 504

Escribe una línea de texto a archivo 504

Capítulo 74: Estructuras de control básicas 506

Observaciones 506

Examples 506

Si / Else Si / Else Control 506

Para loops 507

Mientras bucles 508

hacer ... mientras bucle 508

Para cada 509

Si / Else 510

Cambiar la declaración 510

Operador ternario 512

Descanso 512

Intenta ... Atrapa ... Finalmente 513

Pausa anidada / continuar 514

Continuar declaración en Java 514

Capítulo 75: Evaluación XML XPath 515

Observaciones 515

Examples 515
Evaluando un NodeList en un documento XML 515

Analizar múltiples expresiones XPath en un solo XML 516

Analizar una sola expresión XPath varias veces en un XML 516

Capítulo 76: Examen de la unidad 518

Introducción 518

Observaciones 518

Marcos de prueba unitaria 518

Herramientas de prueba unitaria 518

Examples 518

¿Qué es la prueba unitaria? 518

Las pruebas deben ser automatizadas 520

Las pruebas deben ser de grano fino 520

Entrar en la prueba de la unidad 521

Capítulo 77: Excepciones y manejo de excepciones. 522

Introducción 522

Sintaxis 522

Examples 522

Atrapando una excepción con try-catch 522

Prueba-captura con un bloque de captura 522

Prueba-captura con múltiples capturas 523

Bloques de captura multi-excepción 524

Lanzar una excepción 525

Encadenamiento de excepciones 525

Excepciones personalizadas 526

La declaración de prueba con recursos 528

¿Qué es un recurso? 528

La declaración básica de prueba con recursos. 528

Las declaraciones mejoradas de prueba con recursos 529

Gestionando múltiples recursos 529

Equivalencia de try-with-resource y clásico try-catch-finally 530

Creación y lectura de stacktraces. 531


Imprimiendo un stacktrace 531

Entendiendo un stacktrace 532

Excepción de encadenamiento y stacktraces anidados. 533

Capturando un stacktrace como una cadena 534

Manipulación InterruptedException 535

La jerarquía de excepciones de Java - Excepciones no verificadas y revisadas 536

Excepciones marcadas versus no verificadas 537

Ejemplos de excepciones verificadas 538

Introducción 539

Declaraciones de retorno en el bloque try catch 541

Funciones avanzadas de excepciones 542

Examinando la pila de llamadas programáticamente 542

Optimizando la construcción de excepciones. 543

Borrado o sustitución del trazo de pila. 544

Excepciones suprimidas 544

Las declaraciones try-finally y try-catch-finally 544

Intento-finalmente 545

prueba-captura-finalmente 545

La cláusula de 'tiros' en una declaración de método. 546

¿Cuál es el punto de declarar excepciones no marcadas como lanzadas? 547

Tiros y anulación de método. 547

Capítulo 78: Expresiones 548

Introducción 548

Observaciones 548

Examples 548

Precedencia del operador 548

Expresiones constantes 550

Usos para expresiones constantes 550

Orden de evaluación de expresiones 551

Ejemplo simple 552

Ejemplo con un operador que tiene un efecto secundario 552

Conceptos básicos de expresión 552


El tipo de expresión 553

El valor de una expresión 554

Declaraciones de Expresión 554

Capítulo 79: Expresiones lambda 555

Introducción 555

Sintaxis 555

Examples 555

Usando expresiones Lambda para ordenar una colección 555

Listas de clasificación 555

Clasificando mapas 556

Introducción a las lambdas de Java. 557

Interfaces funcionales 557

Expresiones lambda 558

Devoluciones implícitas 559

Acceso a variables locales (cierres de valor) 559

Aceptando Lambdas 560

El tipo de expresión lambda 560

Referencias del método 561

Referencia del método de instancia (a una instancia arbitraria) 561

Referencia del método de instancia (a una instancia específica) 561

Referencia de método estático 562

Referencia a un constructor 562

Hoja de trucos 562

Implementando multiples interfaces 563

Lambdas y patrón de ejecución 563

Usando lambda expresión con su propia interfaz funcional 564

`return 'solo regresa de la lambda, no del método externo 565

Cierres de Java con expresiones lambda. 566

Lambda - Ejemplo de oyente 568

Estilo tradicional al estilo Lambda. 569

Lambdas y utilización de memoria. 570


Usar expresiones y predicados lambda para obtener un determinado valor (es) de una lista 570

Capítulo 80: Expresiones regulares 572

Introducción 572

Sintaxis 572

Observaciones 572

Importaciones 572

Escollos 572

Símbolos importantes explicados 572

Otras lecturas 573

Examples 573

Utilizando grupos de captura 573

Usando expresiones regulares con comportamiento personalizado compilando el patrón con ban 574

Personajes de escape 574

Coincidencia con un regex literal. 575

No coincide con una cadena dada 576

A juego con una barra invertida 576

Capítulo 81: Fechas y hora ([Link]. *) 578

Examples 578

Manipulaciones de fecha simple 578

Fecha y hora 578

Operaciones en fechas y horarios. 579

Instante 579

Uso de varias clases de Date Time API 579

Formato de fecha y hora 581

Calcular la diferencia entre 2 fechas locales 582

Capítulo 82: FileUpload a AWS 583

Introducción 583

Examples 583

Subir archivo a s3 bucket 583

Capítulo 83: Formato numérico 586

Examples 586

Formato numérico 586


Capítulo 84: FTP (Protocolo de transferencia de archivos) 587

Sintaxis 587

Parámetros 587

Examples 587

Conexión e inicio de sesión en un servidor FTP 587

Capítulo 85: Generación de números aleatorios 593

Observaciones 593

Examples 593

Números pseudoaleatorios 593

Números pseudoaleatorios en rango específico 593

Generación de números pseudoaleatorios criptográficamente seguros. 594

Seleccionar números aleatorios sin duplicados 595

Generando números aleatorios con una semilla especificada 596

Generando números aleatorios usando apache-common lang3 596

Capítulo 86: Generando Código Java 598

Examples 598

Generar POJO desde JSON 598

Capítulo 87: Genéricos 599

Introducción 599

Sintaxis 599

Observaciones 599

Examples 599

Creando una clase genérica 599

Extendiendo una clase genérica 600

Parámetros de tipo múltiple 602

Declarar un método genérico 602

El diamante 603

Requerir múltiples límites superiores ("extiende A y B") 604

Creando una clase genérica limitada 605

Decidir entre 'T', `? super T`, y `? extiende T` 606

Beneficios de la clase genérica y la interfaz 607


Controles de tipo más fuertes en tiempo de compilación 608

Eliminación de moldes 608

Permitiendo a los programadores implementar algoritmos genéricos 608

Vinculación de parámetro genérico a más de 1 tipo 608

Nota: 609

Creando un tipo genérico 609

Soluciones 609

Refiriéndose al tipo genérico declarado dentro de su propia declaración. 610

Uso de instanceof con Genéricos. 611

Diferentes formas de implementar una interfaz genérica (o extender una clase genérica) 613

Usando genéricos para auto-cast 614

Obtenga una clase que satisfaga el parámetro genérico en tiempo de ejecución 615

Capítulo 88: Gerente de seguridad 617

Examples 617

Habilitando el SecurityManager 617

Clases de sandboxing cargadas por un ClassLoader 617

Implementando reglas de negación de políticas. 618

La clase de DeniedPermission 619

La clase DenyingPolicy 623

Manifestación 625

Capítulo 89: Gestión de memoria de Java 627

Observaciones 627

Examples 627

Finalización 627

Los finalizadores solo se ejecutan una vez. 628

Activación manual de GC 628

Recolección de basura 628

El enfoque de C ++ - nuevo y eliminar 628

El enfoque de Java - recolección de basura 629

¿Qué sucede cuando un objeto se vuelve inalcanzable? 630

Ejemplos de objetos alcanzables e inalcanzables 630

Configuración de los tamaños Heap, PermGen y Stack 631


Fugas de memoria en Java 632

Los objetos alcanzables pueden fugarse 632

Los cachés pueden ser fugas de memoria. 633

Capítulo 90: Gráficos 2D en Java 635

Introducción 635

Examples 635

Ejemplo 1: dibujar y rellenar un rectángulo utilizando Java 635

Ejemplo 2: Dibujo y relleno oval 637

Capítulo 91: Hechiceros y Setters 638

Introducción 638

Examples 638

Adición de Getters y Setters 638

Usar un setter o getter para implementar una restricción 639

¿Por qué usar Getters y Setters? 639

Capítulo 92: Herencia 642

Introducción 642

Sintaxis 642

Observaciones 642

Examples 642

Clases abstractas 642

Herencia estática 644

Usando 'final' para restringir la herencia y anular 645

Clases finales 645

Casos de uso para las clases finales. 646

Métodos finales 646

El principio de sustitución de Liskov 647

Herencia 647

Herencia y métodos estáticos 649

Sombreado variable 650

Reducción y ampliación de referencias de objetos. 650

Programación a una interfaz 651

Clase abstracta y uso de la interfaz: "Is-a" relationship vs "Has-a" capacity 654


Anulando en herencia 657

Capítulo 93: Hora local 659

Sintaxis 659

Parámetros 659

Observaciones 659

Examples 659

Modificación de tiempo 659

Zonas horarias y su diferencia horaria. 660

Cantidad de tiempo entre dos LocalTime 660

Introducción 661

Capítulo 94: HttpURLConnection 663

Observaciones 663

Examples 663

Obtener el cuerpo de respuesta de una URL como una cadena 663

Datos POST 664

Cómo funciona 665

Eliminar recurso 665

Cómo funciona 665

Compruebe si el recurso existe 666

Explicación: 666

Ejemplo: 666

Capítulo 95: Implementaciones del sistema de plugin Java 667

Observaciones 667

Examples 667

Utilizando URLClassLoader 667

Capítulo 96: InputStreams y OutputStreams 672

Sintaxis 672

Observaciones 672

Examples 672

Leyendo InputStream en una cadena 672

Escritura de bytes en un OutputStream 672


Cierre de arroyos 673

Copiar el flujo de entrada al flujo de salida 674

Envolviendo flujos de entrada / salida 674

Combinaciones utiles 674

Lista de envoltorios de flujo de entrada / salida 675

Ejemplo de DataInputStream 676

Capítulo 97: Instalando Java (Edición Estándar) 677

Introducción 677

Examples 677

Configurando% PATH% y% JAVA_HOME% después de instalar en Windows 677

Suposiciones 677

Pasos de configuración 677

Revisa tu trabajo 678

Selección de una versión adecuada de Java SE 678

Lanzamiento de Java y nombre de versión 679

¿Qué necesito para el desarrollo de Java? 680

Instalación de un JDK de Java en Linux 680

Usando el Administrador de paquetes 680

Instalación desde un archivo de Oracle Java RPM. 682

Instalación de un JDK o JRE de Java en Windows 682

Instalando un Java JDK en macOS 683

Configurando y cambiando versiones de Java en Linux usando alternativas 685

Usando Alternativas 685

Instalaciones basadas en arco 686

Listado de entornos instalados 686

Cambio de entorno actual 686

Comprobación y configuración posterior a la instalación en Linux 686

Instalando Oracle Java en Linux con el último archivo tar 688

Rendimiento esperado: 689

Capítulo 98: Instrumentos de cuerda 690

Introducción 690

Observaciones 690
Examples 691

Comparando cuerdas 691

No use el operador == para comparar cadenas 692

Comparando cadenas en una instrucción switch 692

Comparando cadenas con valores constantes 693

Ordenaciones de cuerdas 693

Comparando con cuerdas internadas 694

Cambiando el caso de los personajes dentro de una cadena 695

Encontrar una cadena dentro de otra cadena 696

Obtener la longitud de una cadena 697

Subcadenas 698

Obtención del personaje nth en una cadena 698

Plataforma independiente de nueva línea separadora. 699

Añadiendo el método toString () para objetos personalizados 699

Dividir cuerdas 700

Uniendo cuerdas con un delimitador 703

Cuerdas de inversión 704

Contar las apariciones de una subcadena o carácter en una cadena 704

Concatenación de cadenas y StringBuilders 705

Reemplazo de partes de cuerdas 706

Coincidencia exacta 707

Reemplazar el carácter único con otro carácter único: 707

Reemplace la secuencia de caracteres con otra secuencia de caracteres: 707

Regex 707

Reemplazar todos los partidos: 707

Reemplazar solo el primer partido: 708

Eliminar espacios en blanco desde el principio y el final de una cadena 708

Cadena de almacenamiento y almacenamiento en montón 708

Interruptor insensible a la caja 711

Capítulo 99: Interfaces 712

Introducción 712
Sintaxis 712

Examples 712

Declarar e implementar una interfaz 712

Implementando multiples interfaces 713

Extendiendo una interfaz 714

Usando interfaces con genéricos 715

Utilidad de las interfaces. 717

Implementando interfaces en una clase abstracta. 719

Métodos predeterminados 719

Implementación del patrón observador 719

Problema del diamante 720

Utilice métodos predeterminados para resolver problemas de compatibilidad 721

Modificadores en interfaces 722

Variables 722

Métodos 722

Reforzar los parámetros de tipo acotado. 723

Capítulo 100: Interfaces funcionales 725

Introducción 725

Examples 725

Lista de interfaces funcionales estándar de Java Runtime Library por firma 725

Capítulo 101: Interfaz de herramientas JVM 728

Observaciones 728

Examples 728

Iterar sobre objetos accesibles desde objeto (Heap 1.0) 728

Obtener entorno JVMTI 730

Ejemplo de inicialización dentro del método Agent_OnLoad 731

Capítulo 102: Interfaz de salida de cola 732

Introducción 732

Observaciones 732

Examples 732

Añadiendo elementos a Deque 732

Eliminando Elementos de Deque 732


Recuperando elemento sin quitar 733

Iterando a través de Deque 733

Capítulo 103: Interfaz fluida 734

Observaciones 734

Examples 734

Verdad - Marco de prueba de fluidez 734

Estilo de programación fluido 734

Capítulo 104: Interfaz nativa de Java 737

Parámetros 737

Observaciones 737

Examples 737

Llamando a los métodos de C ++ desde Java 737

Código Java 738

Código C ++ 738

Salida 739

Llamando a métodos Java desde C ++ (callback) 739

Código Java 739

Código C ++ 740

Salida 740

Obteniendo el descriptor 740

Cargando bibliotecas nativas 741

Búsqueda de archivos de destino 741

Capítulo 105: Invocación de método remoto (RMI) 743

Observaciones 743

Examples 743

Cliente-Servidor: invocando métodos en una JVM desde otra 743

Devolución de llamada: invocar métodos en un "cliente" 745

Visión general 745

Las interfaces remotas compartidas 745

Las implementaciones 746

Ejemplo de RMI simple con implementación de cliente y servidor 749

Paquete de servidor 749


Paquete de cliente 751

Prueba tu aplicación 752

Capítulo 106: Iterador e iterable 753

Introducción 753

Observaciones 753

Examples 753

Usando Iterable en for loop 753

Usando el iterador crudo 753

Creando tu propio iterable. 754

Eliminar elementos utilizando un iterador 755

Capítulo 107: JavaBean 757

Introducción 757

Sintaxis 757

Observaciones 757

Examples 758

Bean Java Básico 758

Capítulo 108: JAXB 759

Introducción 759

Sintaxis 759

Parámetros 759

Observaciones 759

Examples 759

Escribir un archivo XML (ordenando un objeto) 759

Lectura de un archivo XML (no riguroso) 760

Usando XmlAdapter para generar el formato xml deseado 761

Configuración automática de asignación de campos / propiedades XML (@XmlAccessorType) 762

Configuración manual de asignación de campos / propiedades XML 764

Especificando una instancia de XmlAdapter para (re) usar datos existentes 764

Ejemplo 765

Clase de usuario 765

Adaptador 765

Ejemplos de XML 767


Usando el adaptador 767

Vincular un espacio de nombres XML a una clase Java serializable. 767

Usando XmlAdapter para recortar la cadena. 768

Capítulo 109: JAX-WS 769

Examples 769

Autenticación básica 769

Capítulo 110: JMX 770

Introducción 770

Examples 770

Ejemplo simple con Platform MBean Server 770

Capítulo 111: JNDI 775

Examples 775

RMI a través de JNDI 775

Capítulo 112: JShell 780

Introducción 780

Sintaxis 780

Observaciones 780

Importaciones por defecto 780

Examples 781

Entrando y saliendo de JShell 781

A partir de JShell 781

Saliendo de JShell 781

Expresiones 781

Variables 781

Métodos y Clases 782

Editando Fragmentos 782

Capítulo 113: JSON en Java 784

Introducción 784

Observaciones 784

Examples 784

Codificación de datos como JSON 784

Decodificación de datos JSON 785


Métodos optXXX vs getXXX 785

Objeto a JSON (Gson Library) 786

JSON a Objeto (Biblioteca Gson) 786

Extraer un solo elemento de JSON 786

Usando Jackson Object Mapper 787

Detalles 787

Instancia de ObjectMapper 787

Deserialización: 787

Método para la serialización: 788

Iteración json 788

JSON Builder - métodos de encadenamiento 788

[Link] 789

JsonArray a la lista de Java (Gson Library) 789

Deserializar la colección JSON a la colección de Objetos usando Jackson 790

Deserialización de matriz JSON 790

Enfoque de TypeFactory 791

Tipo de enfoque de referencia 791

Deserialización del mapa JSON 791

Enfoque de TypeFactory 791

Tipo de enfoque de referencia 791

Detalles 791

Nota 792

Capítulo 114: Just in Time (JIT) compilador 793

Observaciones 793

Historia 793

Examples 793

Visión general 793

Capítulo 115: La clase [Link] 796

Examples 796

Uso básico para la comprobación del objeto nulo. 796

Para el método de verificación nulo 796


Para el método de check in no nulo 796

Uso de referencia del método [Link] () en la API de flujo 796

Capítulo 116: Las trampas de Java - Hilos y concurrencia 797

Examples 797

Trampa: uso incorrecto de esperar () / notificar () 797

El problema de "notificación perdida" 797

El error "Estado del monitor ilegal" 797

Esperar / notificar es de muy bajo nivel 798

Pitfall - Extendiendo '[Link]' 798

Pitfall - Demasiados hilos hace que una aplicación sea más lenta. 799

Pitfall - La creación de hilos es relativamente cara 800

Pitfall: las variables compartidas requieren una sincronización adecuada 801

¿Funcionará según lo previsto? 802

¿Cómo solucionamos el problema? 802

¿Pero no es la asignación atómica? 803

¿Por qué hicieron esto? 803

¿Por qué no puedo reproducir esto? 805

Capítulo 117: Lectores y escritores 806

Introducción 806

Examples 806

BufferedReader 806

Introducción 806

Conceptos básicos sobre el uso de un BufferedReader 806

El tamaño del búfer BufferedReader 807

El método [Link] () 807

Ejemplo: leer todas las líneas de un archivo en una lista 807

Ejemplo de StringWriter 807

Capítulo 118: LinkedHashMap 809

Introducción 809

Examples 809

Clase LinkedHashMap de Java 809


Capítulo 119: Lista vs SET 811

Introducción 811

Examples 811

Lista vs conjunto 811

Capítulo 120: Literales 812

Introducción 812

Examples 812

Literales hexadecimales, octales y binarios. 812

Usando el guión bajo para mejorar la legibilidad 812

Secuencias de escape en literales. 813

Unicode se escapa 814

Escapar en expresiones regulares 814

Decimales enteros literales 814

Literales enteros ordinarios 814

Literales enteros largos 815

Literales booleanos 815

Literales de cuerda 816

Cuerdas largas 816

Interning de literales de cuerda. 816

El literal nulo 817

Literales de punto flotante 817

Formas decimales simples 817

Formas decimales escaladas 818

Formas hexadecimales 818

Guiones bajos 819

Casos especiales 819

Literales de personajes 819

Capítulo 121: Liza 821

Introducción 821

Sintaxis 821

Observaciones 821
Examples 822

Ordenar una lista genérica 822

Creando una lista 824

Operaciones de acceso posicional 825

Iterando sobre elementos en una lista 827

Eliminar elementos de la lista B que están presentes en la lista A 827

Encontrando elementos comunes entre 2 listas. 828

Convertir una lista de enteros en una lista de cadenas 828

Creación, adición y eliminación de elementos de un ArrayList 829

Sustitución in situ de un elemento de lista 829

Haciendo una lista no modificable 830

Mover objetos alrededor de la lista 830

Clases implementando Lista - Pros y Contras 831

Clases implementando la lista 831

Pros y contras de cada implementación en términos de complejidad de tiempo 832

Lista de arreglo 832

Lista de atributos 833

CopyOnWriteArrayList 833

Lista enlazada 833

Lista de roles 833

RoleUnresolvedList 834

Apilar 834

Vector 834

Capítulo 122: Localización e internacionalización. 835

Observaciones 835

Recursos Generales 835

Recursos de Java 835

Examples 835

Fechas formateadas automáticamente usando "locale" 835

Deja que Java haga el trabajo por ti. 836

Comparación de cuerdas 836

Lugar 837
Idioma 837

Creando una Localidad 837

Java ResourceBundle 837

Configuración regional 838

Capítulo 123: log4j / log4j2 839

Introducción 839

Sintaxis 839

Observaciones 839

Final de vida para Log4j 1 alcanzado 839

Examples 840

Como obtener Log4j 840

Cómo usar Log4j en código Java 841

Configuración de archivo de propiedades 841

Archivo de configuración [Link] básico 842

Migración de log4j 1.x a 2.x 842

Propiedades-Archivo para iniciar sesión en DB 843

Filtrar Logoutput por nivel (log4j 1.x) 844

Capítulo 124: Los operadores 846

Introducción 846

Observaciones 846

Examples 846

El operador de concatenación de cuerdas (+) 846

Optimización y eficiencia. 847

Los operadores aritméticos (+, -, *, /,%) 848

Operandos y tipos de resultados, y promoción numérica. 849

El significado de división 850

El significado del resto 850

Desbordamiento de enteros 851

Valores de punto flotante INF y NAN 851

Los operadores de igualdad (==,! =) 852

Los operadores numéricos == y != 852


Los operadores booleanos == y != 853

Los operadores Reference == y != 853

Acerca de los casos de borde de NaN 854

Los operadores de incremento / decremento (++ / -) 854

El Operador Condicional (? :) 855

Sintaxis 855

Uso común 856

Los operadores bitwise y lógicos (~, &, |, ^) 857

Tipos de operandos y tipos de resultados. 857

La instancia del operador 858

Los operadores de asignación (=, + =, - =, * =, / =,% =, << =, >> =, >>> =, & =, | = y ^ = 859

Los operadores condicionales y condicionales u (&& y ||) 861

Ejemplo: usar && como guardia en una expresión 861

Ejemplo: usar && para evitar un cálculo costoso 862

Los operadores de turno (<<, >> y >>>) 862

El operador Lambda (->) 863

Los operadores relacionales (<, <=,>,> =) 864

Capítulo 125: Manipulación de bits 866

Observaciones 866

Examples 866

Empaquetar / desempaquetar valores como fragmentos de bits 866

Comprobación, configuración, borrado y conmutación de bits individuales. Utilizando mascar 867

Expresando el poder de 2 867

Comprobando si un número es una potencia de 2 868

clase [Link] 870

Cambio firmado / no firmado 871

Capítulo 126: Mapa débil 872

Introducción 872

Examples 872

Conceptos de HashHashmap 872

Capítulo 127: Mapa Enum 874

Introducción 874
Examples 874

Ejemplo de libro de mapas Enum 874

Capítulo 128: Mapas 875

Introducción 875

Observaciones 875

Examples 875

Agregar un elemento 875

Añadir varios elementos 876

Usando métodos de mapa predeterminados desde Java 8 877

Borrar el mapa 879

Iterando a través de los contenidos de un Mapa. 880

Fusionar, combinar y componer mapas. 881

Componiendo el Mapa <X, Y> y el Mapa <Y, Z> para obtener el Mapa <X, Z> 882

Comprobar si existe la clave 882

Los mapas pueden contener valores nulos 882

Iterando entradas de mapa de manera eficiente 883

Usar objeto personalizado como clave 886

Uso de HashMap 886

Creación e inicialización de mapas 887

Introducción 887

Capítulo 129: Máquina virtual de Java (JVM) 890

Examples 890

Estos son los fundamentos. 890

Capítulo 130: Método dinámico de envío 891

Introducción 891

Observaciones 891

Examples 891

Método dinámico de envío - Código de ejemplo 891

Capítulo 131: Métodos de la fábrica de recolección 894

Introducción 894

Sintaxis 894
Parámetros 894

Examples 895

Lista Ejemplos de métodos de fábrica 895

Conjunto Ejemplos de métodos de fábrica 895

Mapa Ejemplos de métodos de fábrica 895

Capítulo 132: Métodos predeterminados 896

Introducción 896

Sintaxis 896

Observaciones 896

Métodos predeterminados 896

Métodos estáticos 896

Referencias: 897

Examples 897

Uso básico de los métodos por defecto. 897

Acceso a otros métodos de interfaz dentro del método predeterminado 898

Accediendo a métodos predeterminados sobrescritos desde la implementación de la clase 899

¿Por qué usar métodos predeterminados? 899

Clase, clase abstracta y prioridad de método de interfaz 900

Método predeterminado colisión de herencia múltiple 901

Capítulo 133: Modelo de memoria de Java 903

Observaciones 903

Examples 903

Motivación para el modelo de memoria. 903

Reordenación de asignaciones 904

Efectos de cachés de memoria 905

Sincronización adecuada 905

El modelo de memoria 905

Relaciones de antes-antes 906

Comportamiento 906

Orden del programa y orden de sincronización 906

Sucede antes de la orden 907

Razonamiento antes del razonamiento aplicado a algunos ejemplos. 908


Código de un solo hilo 908

Comportamiento de 'volátil' en un ejemplo con 2 hilos 908

Volátil con tres hilos. 909

Cómo evitar tener que entender el modelo de memoria. 910

Capítulo 134: Modificación Bytecode 912

Examples 912

¿Qué es Bytecode? 912

¿Cuál es la lógica detrás de esto? 912

Bueno, tiene que haber más derecho? 912

¿Cómo puedo escribir / editar el bytecode? 912

¡Me gustaría aprender más sobre el bytecode! 913

Cómo editar archivos jar con ASM 913

Cómo cargar un ClassNode como una clase 916

Cómo cambiar el nombre de las clases en un archivo jar 916

Javassist Basic 917

Capítulo 135: Modificadores sin acceso 919

Introducción 919

Examples 919

final 919

volátil 920

estático 921

resumen 922

sincronizado 923

transitorio 924

strictfp 924

Capítulo 136: Módulos 925

Sintaxis 925

Observaciones 925

Examples 925

Definiendo un módulo básico. 925

Capítulo 137: Moneda y dinero 927


Examples 927

Añadir moneda personalizada 927

Capítulo 138: Motor de JavaScript Nashorn 928

Introducción 928

Sintaxis 928

Observaciones 928

Examples 928

Establecer variables globales 928

Hola Nashorn 929

Ejecutar archivo JavaScript 929

Salida de script de intercepción 930

Evaluar cadenas aritméticas 930

Uso de objetos Java en JavaScript en Nashorn 930

Implementando una interfaz desde script 931

Establecer y obtener variables globales. 932

Capítulo 139: NIO - Redes 933

Observaciones 933

Examples 933

Usando Selector para esperar eventos (ejemplo con OP_CONNECT) 933

Capítulo 140: Nuevo archivo I / O 935

Sintaxis 935

Examples 935

Creando caminos 935

Recuperar información sobre una ruta 935

Manipulando caminos 936

Unirse a dos caminos 936

Normalizando un camino 936

Recuperando información utilizando el sistema de archivos. 936

Comprobando la existencia 936

Comprobando si una ruta apunta a un archivo o directorio 937

Obteniendo propiedades 937


Obteniendo el tipo MIME 938

Archivos de lectura 938

Escribiendo archivos 938

Capítulo 141: Objetos inmutables 939

Observaciones 939

Examples 939

Creación de una versión inmutable de un tipo mediante copia defensiva. 939

La receta para una clase inmutable. 940

Fallas típicas de diseño que evitan que una clase sea inmutable. 941

Capítulo 142: Objetos seguros 945

Sintaxis 945

Examples 945

SealedObject ([Link]) 945

SignedObject ([Link]) 945

Capítulo 143: Opcional 947

Introducción 947

Sintaxis 947

Examples 947

Devolver valor predeterminado si Opcional está vacío 947

Mapa 948

Lanzar una excepción, si no hay valor. 949

Filtrar 949

Usando contenedores opcionales para tipos de números primitivos 950

Ejecutar código solo si hay un valor presente 950

Proporcionar perezosamente un valor predeterminado utilizando un Proveedor 950

Mapa plano 951

Capítulo 144: Operaciones de punto flotante de Java 952

Introducción 952

Examples 952

Comparando valores de punto flotante 952

OverFlow y UnderFlow 954

Formato de los valores de punto flotante 955


Adherencia estricta a la especificación IEEE 956

Capítulo 145: Paquetes 958

Introducción 958

Observaciones 958

Examples 958

Usando paquetes para crear clases con el mismo nombre 958

Uso del alcance del paquete protegido 958

Capítulo 146: Polimorfismo 960

Introducción 960

Observaciones 960

Examples 960

Método de sobrecarga 960

Método Anulando 962

Agregar comportamiento agregando clases sin tocar el código existente 963

Funciones virtuales 964

Polimorfismo y diferentes tipos de anulación. 965

Capítulo 147: Preferencias 970

Examples 970

Añadiendo oyentes de eventos 970

PreferenceChangeEvent 970

NodeChangeEvent 970

Obtención de subnodos de preferencias 971

Coordinar las preferencias de acceso a través de múltiples instancias de aplicaciones 972

Preferencias de exportación 972

Importando preferencias 973

Eliminar oyentes de eventos 974

Obteniendo valores de preferencias 975

Configuración de valores de preferencias 975

Usando preferencias 975

Capítulo 148: Procesamiento de argumentos de línea de comando 977

Sintaxis 977

Parámetros 977
Observaciones 977

Examples 977

Procesamiento de argumentos utilizando GWT ToolBase 977

Procesando argumentos a mano 978

Un comando sin argumentos. 978

Un comando con dos argumentos. 978

Un comando con opciones de "bandera" y al menos un argumento 979

Capítulo 149: Proceso 980

Observaciones 980

Examples 980

Ejemplo simple (versión de Java <1.5) 980

Usando la clase ProcessBuilder 980

Bloqueo frente a llamadas no bloqueadas 981

[Link] 981

Pitfall: [Link], Process y ProcessBuilder no entienden la sintaxis de shell 982

Espacios en las rutas 982

Redireccionamiento, tuberías y otra sintaxis de shell. 983

Los comandos de shell incorporados no funcionan 983

Capítulo 150: Programación Concurrente (Hilos) 985

Introducción 985

Observaciones 985

Examples 985

Multihilo básico 985

Productor-consumidor 986

Usando ThreadLocal 987

CountDownLatch 988

Sincronización 989

Operaciones atómicas 991

Creación de un sistema básico de punto muerto. 992

Pausa de ejecucion 993

Visualizar barreras de lectura / escritura mientras se usa sincronizado / volátil 994

Creando una instancia [Link] 995


Interrupción de hilo / hilos de parada 997

Ejemplo de productor / consumidor múltiple con cola global compartida 999

Acceso exclusivo de lectura / lectura simultánea 1001

Objeto ejecutable 1002

Semáforo 1003

Agregue dos arreglos `int` usando un Threadpool 1004

Obtenga el estado de todas las hebras iniciadas por su programa, excluyendo las hebras del 1004

Callable y Futuro 1005

Bloqueos como ayudas de sincronización 1007

Capítulo 151: Programación paralela con el framework Fork / Join. 1009

Examples 1009

Horquilla / Unir tareas en Java 1009

Capítulo 152: Publicación por entregas 1011

Introducción 1011

Examples 1011

Serialización básica en Java 1011

Serialización con Gson 1013

Serialización con Jackson 2 1013

Serialización personalizada 1014

Versiones y serialVersionUID 1017

Cambios compatibles 1017

Cambios incompatibles 1018

Deserialización JSON personalizada con Jackson 1018

Capítulo 153: Puntos de referencia 1021

Introducción 1021

Examples 1021

Ejemplo simple de JMH 1021

Capítulo 154: Recursion 1024

Introducción 1024

Observaciones 1024

Diseñando un Método Recursivo 1024

Salida 1024
Eliminación de Java y Tail-Call 1024

Examples 1024

La idea básica de la recursión. 1024

Cálculo del Número N. de Fibonacci 1025

Cálculo de la suma de enteros de 1 a N 1026

Cálculo de la enésima potencia de un número 1026

Invertir una cadena usando Recursión 1026

Atravesando una estructura de datos de árbol con recursión 1027

Tipos de recursion 1027

StackOverflowError & recursion to loop 1028

Ejemplo 1028

Solución 1028

Ejemplo 1028

La recursión profunda es problemática en Java 1030

Por qué la eliminación de la llamada de cola no está implementada en Java (todavía) 1031

Capítulo 155: Recursos (en classpath) 1032

Introducción 1032

Observaciones 1032

Examples 1033

Cargando una imagen de un recurso 1033

Cargando la configuración por defecto 1033

Cargando recursos del mismo nombre desde múltiples archivos JAR 1034

Encontrar y leer recursos usando un cargador de clases 1034

Rutas de recursos absolutos y relativos 1034

Obtención de una Clase o Classloader 1034

Los metodos de get 1035

Capítulo 156: Redes 1036

Sintaxis 1036

Examples 1036

Comunicación básica de cliente y servidor mediante un socket 1036

Servidor: Iniciar y esperar las conexiones entrantes. 1036

Servidor: Manejo de clientes. 1036


Cliente: Conectarse al servidor y enviar un mensaje. 1036

Cierre de enchufes y manejo de excepciones. 1037

Servidor básico y cliente - ejemplos completos 1037

Cargando TrustStore y KeyStore desde InputStream 1038

Ejemplo de socket: leer una página web utilizando un socket simple 1039

Comunicación básica cliente / servidor mediante UDP (datagrama) 1040

Multidifusión 1041

Deshabilite temporalmente la verificación SSL (para propósitos de prueba) 1043

Descargando un archivo usando el canal 1043

Notas 1044

Capítulo 157: Referencias de objetos 1045

Observaciones 1045

Examples 1045

Referencias de objetos como parámetros del método. 1045

Capítulo 158: Registro ([Link]) 1048

Examples 1048

Usando el registrador predeterminado 1048

Niveles de registro 1048

Registro de mensajes complejos (eficientemente) 1049

Capítulo 159: Seguridad y criptografía 1052

Examples 1052

Calcular los hash criptográficos 1052

Generar datos criptográficamente aleatorios 1052

Generar pares de claves públicas / privadas 1053

Calcular y verificar firmas digitales 1053

Cifrar y descifrar datos con claves públicas / privadas 1054

Capítulo 160: Seguridad y criptografía 1055

Introducción 1055

Observaciones 1055

Examples 1055

La jce 1055

Claves y gestión de claves 1055


Vulnerabilidades comunes de Java 1055

Preocupaciones de redes 1055

Aleatoriedad y tu 1055

Hashing y Validación 1056

Capítulo 161: ServiceLoader 1057

Observaciones 1057

Examples 1057

Servicio de registrador 1057

Servicio 1057

Implementaciones del servicio. 1057

META-INF / services / [Link] 1058

Uso 1058

Ejemplo simple de ServiceLoader 1058

Capítulo 162: Servicio de impresión de Java 1061

Introducción 1061

Examples 1061

Descubriendo los servicios de impresión disponibles. 1061

Descubriendo el servicio de impresión predeterminado 1061

Creación de un trabajo de impresión desde un servicio de impresión 1062

Construyendo el Doc que será impreso. 1062

Definiendo atributos de solicitud de impresión 1063

Escuchar cambio de estado de solicitud de trabajo de impresión 1063

El argumento PrintJobEvent pje 1064

Otra forma de lograr el mismo objetivo. 1064

Capítulo 163: Singletons 1066

Introducción 1066

Examples 1066

Enum Singleton 1066

Hilo seguro Singleton con doble control de bloqueo 1066

Singleton sin uso de Enum (inicialización impaciente) 1067

Inicialización perezosa segura para subprocesos utilizando la clase de soporte | Implement 1067

Extendiendo singleton (herencia singleton) 1068


Capítulo 164: Sockets de Java 1071

Introducción 1071

Observaciones 1071

Examples 1071

Un simple servidor TCP con respaldo 1071

Capítulo 165: SortedMap 1075

Introducción 1075

Examples 1075

Introducción al mapa ordenado. 1075

Capítulo 166: StringBuffer 1076

Introducción 1076

Examples 1076

Clase de búfer de cadena 1076

Capítulo 167: StringBuilder 1078

Introducción 1078

Sintaxis 1078

Observaciones 1078

Examples 1078

Repetir una cadena n veces 1078

Comparando StringBuffer, StringBuilder, Formatter y StringJoiner 1079

Capítulo 168: [Link] 1081

Observaciones 1081

Examples 1081

Instalar [Link] a través de la reflexión 1081

Creación de una instancia de [Link] a través de bootclasspath 1081

Obtención de instancia de inseguro 1081

Usos de inseguros 1082

Capítulo 169: súper palabra clave 1084

Examples 1084

Uso de palabras clave super con ejemplos 1084

Nivel de constructor 1084


Nivel de método 1085

Nivel variable 1085

Capítulo 170: Tabla de picadillo 1087

Introducción 1087

Examples 1087

Tabla de picadillo 1087

Capítulo 171: ThreadLocal 1088

Observaciones 1088

Examples 1088

ThreadLocal Java 8 inicialización funcional 1088

Uso básico de ThreadLocal 1088

Múltiples hilos con un objeto compartido. 1090

Capítulo 172: Tipo de conversión 1092

Sintaxis 1092

Examples 1092

Fundición primitiva no numérica 1092

Fundición primitiva numérica 1092

Fundición de objetos 1093

Promoción Numérica Básica 1093

Probar si un objeto puede ser lanzado usando instanceof 1093

Capítulo 173: Tipos atómicos 1094

Introducción 1094

Parámetros 1094

Observaciones 1094

Examples 1094

Creando Tipos Atómicos 1094

Motivación para los tipos atómicos 1095

¿Cómo se implementan los tipos atómicos? 1096

¿Cómo funcionan los tipos atómicos? 1096

Capítulo 174: Tipos de datos de referencia 1098

Examples 1098
Creando un tipo de referencia 1098

Desreferenciación 1098

Capítulo 175: Tipos de datos primitivos 1099

Introducción 1099

Sintaxis 1099

Observaciones 1099

Examples 1100

El primitivo int 1100

El primitivo corto 1100

El primitivo largo 1101

El primitivo booleano 1102

El byte primitivo 1102

El flotador primitivo 1103

El doble primitivo 1104

El primitivo char 1104

Representación de valor negativo 1105

Consumo de memoria de primitivas vs. primitivas en caja 1106

Cachés de valor en caja 1107

Primitivas de conversión 1107

Tipos primitivos Cheatsheet 1108

Capítulo 176: Tipos de referencia 1110

Examples 1110

Diferentes tipos de referencia 1110

Capítulo 177: Tokenizador de cuerdas 1112

Introducción 1112

Examples 1112

StringTokenizer dividido por el espacio 1112

StringTokenizer Dividir por comas ',' 1112

Capítulo 178: TreeMap y TreeSet 1113

Introducción 1113

Examples 1113

TreeMap de un tipo de Java simple 1113


TreeSet de un tipo de Java simple 1113

TreeMap / TreeSet de un tipo de Java personalizado 1114

TreeMap y TreeSet Thread Safety 1116

Capítulo 179: Usando la palabra clave estática 1118

Sintaxis 1118

Examples 1118

Usando static para declarar constantes 1118

Usando estática con esto 1118

Referencia a miembro no estático del contexto estático 1119

Capítulo 180: Usando otros lenguajes de scripting en Java 1121

Introducción 1121

Observaciones 1121

Examples 1121

Evaluando un archivo javascript en modo de script de nashorn 1121

Capítulo 181: Usando ThreadPoolExecutor en aplicaciones MultiThreaded. 1124

Introducción 1124

Examples 1124

Realización de tareas asíncronas donde no se necesita un valor de retorno utilizando una i 1124

Realización de tareas asíncronas donde se necesita un valor de retorno utilizando una inst 1125

Definición de tareas asíncronas en línea usando Lambdas 1128

Capítulo 182: Varargs (Argumento Variable) 1130

Observaciones 1130

Examples 1130

Especificando un parámetro varargs 1130

Trabajando con los parámetros de Varargs 1130

Capítulo 183: Visibilidad (control de acceso a los miembros de una clase) 1132

Sintaxis 1132

Observaciones 1132

Examples 1132

Miembros de la interfaz 1132

Visibilidad pública 1133

Visibilidad privada 1133


Visibilidad del paquete 1134

Visibilidad Protegida 1134

Resumen de los Modificadores de Acceso de los Miembros de la Clase 1135

Capítulo 184: XJC 1136

Introducción 1136

Sintaxis 1136

Parámetros 1136

Observaciones 1136

Examples 1136

Generando código Java desde un simple archivo XSD 1136

Esquema XSD ([Link]) 1136

Usando xjc 1137

Archivos de resultados 1137

[Link] 1138

Capítulo 185: XOM - Modelo de objetos XML 1139

Examples 1139

Leyendo un archivo XML 1139

Escribir en un archivo XML 1141

Creditos 1145
Acerca de
You can share this PDF with anyone you feel could benefit from it, downloaded the latest version
from: java-language

It is an unofficial and free Java Language ebook created for educational purposes. All the content
is extracted from Stack Overflow Documentation, which is written by many hardworking individuals
at Stack Overflow. It is neither affiliated with Stack Overflow nor official Java Language.

The content is released under Creative Commons BY-SA, and the list of contributors to each
chapter are provided in the credits section at the end of this book. Images may be copyright of
their respective owners unless otherwise specified. All trademarks and registered trademarks are
the property of their respective company owners.

Use the content presented in this book at your own risk; it is not guaranteed to be correct nor
accurate, please send your feedback and corrections to info@[Link]

[Link] 1
Capítulo 1: Empezando con el lenguaje Java
Observaciones
El lenguaje de programación de Java es ...

• Uso general : está diseñado para ser utilizado para escribir software en una amplia
variedad de dominios de aplicación y carece de funciones especializadas para cualquier
dominio específico.

• Basado en clase : su estructura de objeto se define en clases. Las instancias de clase


siempre tienen esos campos y métodos especificados en sus definiciones de clase (ver
Clases y Objetos ). Esto contrasta con lenguajes no basados en clases como JavaScript.

• Escritura estática : el compilador verifica en el momento de la compilación que se respetan


los tipos de variables. Por ejemplo, si un método espera un argumento de tipo String , ese
argumento debe ser de hecho una cadena cuando se llama al método.

• Orientado a objetos : la mayoría de las cosas en un programa Java son instancias de


clase, es decir, paquetes de estado (campos) y comportamiento (métodos que operan sobre
datos y forman la interfaz del objeto con el mundo exterior).

• Portátil : se puede compilar en cualquier plataforma con javac y los archivos de clase
resultantes se pueden ejecutar en cualquier plataforma que tenga una JVM.

El objetivo de Java es permitir que los desarrolladores de aplicaciones "escriban una vez, se
ejecuten en cualquier lugar" (WORA), lo que significa que el código compilado de Java puede
ejecutarse en todas las plataformas que admiten Java sin la necesidad de una recompilación.

El código Java se compila a un código de bytes (los archivos .class ) que, a su vez, son
interpretados por la Máquina Virtual de Java (JVM). En teoría, el código de bytes creado por un
compilador de Java debería ejecutarse de la misma manera en cualquier JVM, incluso en un tipo
diferente de computadora. La JVM podría (y en los programas del mundo real) elegir compilar en
comandos de máquina nativos las partes del código de bytes que se ejecutan a menudo. Esto se
denomina "compilación Just-in-time (JIT)".

Ediciones y versiones de Java


Hay tres "ediciones" de Java definidas por Sun / Oracle:

• Java Standard Edition (SE) es la edición que está diseñada para uso general.
• Java Enterprise Edition (EE) agrega una gama de facilidades para crear servicios de "grado
empresarial" en Java. Java EE se cubre por separado .
• Java Micro Edition (ME) se basa en un subconjunto de Java SE y está diseñado para su uso
en dispositivos pequeños con recursos limitados.

[Link] 2
Hay un tema separado en las ediciones de Java SE / EE / ME .

Cada edición tiene múltiples versiones. Las versiones de Java SE se enumeran a continuación.

Instalando Java
Hay un tema separado sobre la instalación de Java (edición estándar) .

Compilación y ejecución de programas Java.


Hay temas separados sobre:

• Compilando el código fuente de Java


• Despliegue de Java incluyendo la creación de archivos JAR
• Ejecutando aplicaciones Java
• El classpath

¿Que sigue?
Aquí hay enlaces a temas para continuar aprendiendo y entendiendo el lenguaje de programación
Java. Estos temas son los conceptos básicos de la programación de Java para comenzar.

• Tipos de datos primitivos en Java


• Operadores en Java
• Cuerdas en java
• Estructuras de control básicas en Java
• Clases y objetos en Java
• Arrays en Java
• Estándares de código de Java

Pruebas
Si bien Java no tiene soporte para realizar pruebas en la biblioteca estándar, existen bibliotecas
de terceros que están diseñadas para admitir pruebas. Las dos bibliotecas de pruebas de
unidades más populares son:

• JUnit ( Sitio Oficial )


• TestNG ( Sitio Oficial )

Otro
• Los patrones de diseño para Java están cubiertos en los patrones de diseño .

[Link] 3
• La programación para Android está cubierta en Android .
• Las tecnologías Java Enterprise Edition están cubiertas en Java EE .
• Las tecnologías Oracle JavaFX están cubiertas en JavaFX .
1. En la sección Versiones , la fecha de finalización de la vida útil (gratuita) es cuando Oracle dejará de publicar
nuevas actualizaciones de Java SE en sus sitios públicos de descarga. Los clientes que necesitan acceso continuo a
correcciones de errores críticos y correcciones de seguridad, así como el mantenimiento general de Java SE pueden
obtener soporte a largo plazo a través del soporte de Oracle Java SE .

Versiones

Fin de la vida (libre Fecha de


Versión de Java SE Nombre clave 1) lanzamiento

Java SE 9 (acceso
Ninguna futuro 2017-07-27
temprano)

Java SE 8 Araña futuro 2014-03-18

Java SE 7 Delfín 2015-04-14 2011-07-28

Java SE 6 Mustango 2013-04-16 2006-12-23

Java SE 5 Tigre 2009-11-04 2004-10-04

Java SE 1.4 Esmerejón antes del 2009-11-04 2002-02-06

Java SE 1.3 Cernícalo antes del 2009-11-04 2000-05-08

Patio de
Java SE 1.2 antes del 2009-11-04 1998-12-08
recreo

Java SE 1.1 Ninguna antes del 2009-11-04 1997-02-19

Java SE 1.0 Roble antes del 2009-11-04 1996-01-21

Examples
Creando tu primer programa Java

Cree un nuevo archivo en su editor de texto o IDE llamado [Link] . Luego pegue este
bloque de código en el archivo y guarde:

public class HelloWorld {


public static void main(String[] args) {
[Link]("Hello, World!");
}
}

[Link] 4
Corre en vivo en Ideone

Nota: Para que Java reconozca esto como una public class (y no arroje un error de tiempo de
compilación ), el nombre del archivo debe ser el mismo que el nombre de la clase ( HelloWorld en
este ejemplo) con una extensión .java . También debe haber un modificador de acceso public
antes de él.

Las convenciones de nomenclatura recomiendan que las clases de Java comiencen con un
carácter en mayúscula y estén en formato de caja de camello (en el que la primera letra de cada
palabra se escribe con mayúscula). Las convenciones recomiendan contra guiones bajos ( _ ) y
signos de dólar ( $ ).

Para compilar, abra una ventana de terminal y navegue al directorio de [Link] :

cd /path/to/containing/folder/

Nota: cd es el comando terminal para cambiar el directorio.

Ingrese javac seguido del nombre del archivo y la extensión de la siguiente manera:

$ javac [Link]

Es bastante común que el error 'javac' is not recognized as an internal or external command,
operable program or batch file. incluso cuando haya instalado el JDK y pueda ejecutar el
programa desde IDE ej. eclipse etc. Dado que la ruta no se agrega al entorno de forma
predeterminada.

En caso de que obtenga esto en Windows, para resolverlo, primero intente [Link] su ruta
[Link] , es muy probable que esté en su C:\Program Files\Java\jdk(version number)\bin . A
continuación, intente ejecutarlo con a continuación.

$ C:\Program Files\Java\jdk(version number)\bin\javac [Link]

Anteriormente, cuando llamábamos a javac , era igual que el comando anterior. Solo en ese caso,
su OS sabía dónde residía javac . Así que vamos a decirlo ahora, de esta manera no tienes que
escribir todo el camino cada vez. Necesitaríamos agregar esto a nuestro PATH

Para editar la PATH entorno PATH en Windows XP / Vista / 7/8/10:

• Panel de control ⇒ Sistema ⇒ Configuración avanzada del sistema


• Cambie a la pestaña "Avanzado" ⇒ Variables de entorno
• En "Variables del sistema", desplácese hacia abajo para seleccionar "RUTA" ⇒ Editar

No puedes deshacer esto así que ten cuidado. Primero copia tu ruta existente al bloc de notas.
Luego, para obtener la ruta de acceso exacta a su javac busque manualmente la carpeta donde
reside javac haga clic en la barra de direcciones y luego cópiela. Debería verse como c:\Program
Files\Java\jdk1.8.0_xx\bin

En el campo "Valor variable", pegue este EN FRENTE de todos los directorios existentes, seguido

[Link] 5
de un punto y coma (;). NO BORRAR ninguna entrada existente.

Variable name : PATH


Variable value : c:\Program Files\Java\jdk1.8.0_xx\bin;[Existing Entries...]

Ahora esto debería resolverse.

Para sistemas basados en Linux intente aquí .

Nota: javac comando javac invoca el compilador de Java.

El compilador generará entonces un código de bytes archivo llamado [Link] que puede
ser ejecutado en la máquina virtual de Java (JVM) . El compilador del lenguaje de programación
Java, javac , lee los archivos de origen escritos en el lenguaje de programación Java y los compila
en archivos de clase de código de bytecode . Opcionalmente, el compilador también puede
procesar las anotaciones encontradas en los archivos de origen y de clase utilizando la API de
Procesamiento de Anotación Pluggable . El compilador es una herramienta de línea de comandos,
pero también se puede invocar utilizando la API del compilador de Java.

Para ejecutar su programa, ingrese java seguido del nombre de la clase que contiene el método
main ( HelloWorld en nuestro ejemplo). Observe cómo se omite .class :

$ java HelloWorld

Nota: el comando java ejecuta una aplicación Java.

Esto saldrá a su consola:

¡Hola Mundo!

¡Has codificado y construido exitosamente tu primer programa Java!

Nota: Para que los comandos de Java ( java , javac , etc.) sean reconocidos, deberá asegurarse
de que:

• Se instala un JDK (por ejemplo, Oracle , OpenJDK y otras fuentes)


• Sus variables de entorno están configuradas correctamente

Deberá usar un compilador ( javac ) y un ejecutor ( java ) proporcionado por su JVM. Para saber
qué versiones tiene instaladas, ingrese java -version y javac -version en la línea de comandos. El
número de versión de su programa se imprimirá en el terminal (por ejemplo, 1.8.0_73 ).

Una mirada más cercana al programa Hello


World.
El programa "Hello World" contiene un solo archivo, que consiste en una definición de clase

[Link] 6
HelloWorld , un método main y una declaración dentro del método main .

public class HelloWorld {

La palabra clave de class comienza la definición de clase para una clase llamada HelloWorld .
Cada aplicación Java contiene al menos una definición de clase ( Más información sobre clases ).

public static void main(String[] args) {

Este es un método de punto de entrada (definido por su nombre y firma de public static void
main(String[]) ) desde el cual JVM puede ejecutar su programa. Cada programa de Java debería
tener uno. Es:

• public: lo que significa que el método también se puede llamar desde cualquier lugar desde
fuera del programa. Ver Visibilidad para más información sobre esto.
• static : significa que existe y se puede ejecutar por sí mismo (a nivel de clase sin crear un
objeto).
• void : significa que no devuelve ningún valor. Nota: Esto es diferente a C y C ++ donde se
espera un código de retorno como int (la forma de Java es [Link]() ).

Este método principal acepta:

• Una matriz (normalmente llamada args ) de String s pasa como argumentos a la función
principal (por ejemplo, desde los argumentos de la línea de comando )

Casi todo esto es necesario para un método de punto de entrada de Java.

Piezas no requeridas:

• El nombre args es un nombre de variable, por lo que puede llamarse como quieras, aunque
normalmente se llama args .
• Si su tipo de parámetro es una matriz ( String[] args ) o Varargs ( String... args ) no
importa porque las matrices se pueden pasar a varargs.

Nota: una sola aplicación puede tener varias clases que contengan un método de punto de
entrada ( main ). El punto de entrada de la aplicación está determinado por el nombre de clase
pasado como un argumento al comando java .

Dentro del método principal, vemos la siguiente declaración:

[Link]("Hello, World!");

Vamos a desglosar esta declaración elemento por elemento:

Elemento Propósito

esto denota que la siguiente expresión llamará a la clase System , desde el


System
paquete [Link] .

[Link] 7
Elemento Propósito

este es un "operador de puntos". Los operadores de puntos le brindan acceso


a una clase de miembros 1 ; Es decir, sus campos (variables) y sus métodos.
.
En este caso, este operador de punto le permite hacer referencia al campo
estático de out dentro de la clase System .

este es el nombre del campo estático del tipo PrintStream dentro de la clase
out
System contiene la funcionalidad de salida estándar.

este es otro operador de puntos. Este operador de puntos proporciona acceso


.
al método println dentro de la variable out .

este es el nombre de un método dentro de la clase PrintStream. Este método,


println en particular, imprime el contenido de los parámetros en la consola e inserta
una nueva línea después.

este paréntesis indica que se está accediendo a un método (y no a un campo)


(
y comienza a pasar los parámetros al método println .

"Hello, este es el literal de cadena que se pasa como parámetro al método println .
World!" Las comillas dobles en cada extremo delimitan el texto como una cadena.

este paréntesis significa el cierre de los parámetros que se pasan al método


)
println .

; este punto y coma marca el final de la declaración.

Nota: Cada declaración en Java debe terminar con un punto y coma ( ; ).

El cuerpo del método y el cuerpo de la clase se cierran.

} // end of main function scope


} // end of class HelloWorld scope

Aquí hay otro ejemplo que demuestra el paradigma OO. Vamos a modelar un equipo de fútbol
con un miembro (¡sí, uno!). Puede haber más, pero lo discutiremos cuando lleguemos a los
arreglos.

Primero, definamos nuestra clase de Team :

public class Team {


Member member;
public Team(Member member) { // who is in this Team?
[Link] = member; // one 'member' is in this Team!
}
}

Ahora, definamos nuestra clase de Member :

[Link] 8
class Member {
private String name;
private String type;
private int level; // note the data type here
private int rank; // note the data type here as well

public Member(String name, String type, int level, int rank) {


[Link] = name;
[Link] = type;
[Link] = level;
[Link] = rank;
}
}

¿Por qué usamos private aquí? Bueno, si alguien desea saber su nombre, debe preguntarle
directamente, en lugar de buscar en su bolsillo y sacar su tarjeta de Seguro Social. Este private
hace algo así: impide que las entidades externas accedan a sus variables. Solo puede devolver
miembros private través de las funciones de obtención (que se muestran a continuación).

Después de ponerlo todo junto, y de agregar los métodos de obtención y el método principal,
como se mencionó anteriormente, tenemos:

public class Team {


Member member;
public Team(Member member) {
[Link] = member;
}

// here's our main method


public static void main(String[] args) {
Member myMember = new Member("Aurieel", "light", 10, 1);
Team myTeam = new Team(myMember);
[Link]([Link]());
[Link]([Link]());
[Link]([Link]());
[Link]([Link]());
}
}

class Member {
private String name;
private String type;
private int level;
private int rank;

public Member(String name, String type, int level, int rank) {


[Link] = name;
[Link] = type;
[Link] = level;
[Link] = rank;
}

/* let's define our getter functions here */


public String getName() { // what is your name?
return [Link]; // my name is ...
}

public String getType() { // what is your type?

[Link] 9
return [Link]; // my type is ...
}

public int getLevel() { // what is your level?


return [Link]; // my level is ...
}

public int getRank() { // what is your rank?


return [Link]; // my rank is
}
}

Salida:

Aurieel
light
10
1

Corre en ideone

Una vez más, el método main dentro de la clase de Test es el punto de entrada a nuestro
programa. Sin el método main , no podemos decirle a la Máquina Virtual Java (JVM) desde dónde
comenzar la ejecución del programa.

1 - Debido a que la clase HelloWorld tiene poca relación con la clase System , solo puede acceder a datos public .

Lea Empezando con el lenguaje Java en línea: [Link]


con-el-lenguaje-java

[Link] 10
Capítulo 2: Acceso nativo de Java
Examples
Introducción a JNA

¿Qué es JNA?
Java Native Access (JNA) es una biblioteca desarrollada por la comunidad que proporciona a los
programas Java un acceso fácil a las bibliotecas compartidas nativas (archivos .dll en Windows,
archivos .so en Unix ...)

¿Como puedo usar lo?


• En primer lugar, descargue la última versión de JNA y haga referencia a su [Link] en
CLASSPATH de su proyecto.

• En segundo lugar, copie, compile y ejecute el siguiente código Java

Para el propósito de esta introducción, suponemos que la plataforma nativa en uso es


Windows. Si está ejecutando en otra plataforma, simplemente reemplace la cadena
"msvcrt" con la cadena "c" en el código a continuación.

El pequeño programa Java a continuación imprimirá un mensaje en la consola llamando a la


printf C printf .

[Link]

package [Link];

import [Link];
import [Link];

// We declare the printf function we need and the library containing it (msvcrt)...
public interface CRuntimeLibrary extends Library {

CRuntimeLibrary INSTANCE =
(CRuntimeLibrary) [Link]("msvcrt", [Link]);

void printf(String format, Object... args);


}

[Link]

package [Link];

// Now we call the printf function...

[Link] 11
public class MyFirstJNAProgram {
public static void main(String args[]) {
[Link]("Hello World from JNA !");
}
}

¿A dónde ir ahora?
Salta a otro tema aquí o salta al sitio oficial .

Lea Acceso nativo de Java en línea: [Link]


java

[Link] 12
Capítulo 3: Afirmando
Sintaxis
• afirmar expresión1 ;
• afirmar expresión1 : expresión2 ;

Parámetros

Parámetro Detalles

La declaración de aserción lanza un AssertionError si esta expresión se evalúa


expresión1
como false .

Opcional. Cuando se utiliza, AssertionError s arrojado por la declaración de


expresión2
aserción tiene este mensaje.

Observaciones
Por defecto, las aserciones están deshabilitadas en tiempo de ejecución.

Para habilitar aserciones, debe ejecutar java con el indicador -ea .

java -ea [Link]

Las aserciones son declaraciones que arrojarán un error si su expresión se evalúa como false .
Las afirmaciones solo deben usarse para probar el código; nunca deben ser utilizados en la
producción.

Examples
Comprobando aritmética con aseverar.

a = 1 - [Link](1 - a % 2);

// This will throw an error if my arithmetic above is wrong.


assert a >= 0 && a <= 1 : "Calculated value of " + a + " is outside of expected bounds";

return a;

Lea Afirmando en línea: [Link]

[Link] 13
Capítulo 4: Agentes de Java
Examples
Modificando clases con agentes.

En primer lugar, asegúrese de que el agente que se está utilizando tenga los siguientes atributos
en el archivo [Link]:

Can-Redefine-Classes: true
Can-Retransform-Classes: true

Iniciar un agente java permitirá que el agente acceda a la clase de Instrumentación. Con
Instrumentation puede llamar a addTransformer (transformador ClassFileTransformer) .
ClassFileTransformers te permitirá reescribir los bytes de las clases. La clase tiene un solo
método que suministra el ClassLoader que carga la clase, el nombre de la clase, una instancia de
[Link], es ProtectionDomain y, por último, los bytes de la propia clase.

Se parece a esto:

byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,


ProtectionDomain protectionDomain, byte[] classfileBuffer)

Modificar una clase puramente de bytes puede llevar siglos. Para remediar esto, hay bibliotecas
que se pueden usar para convertir los bytes de clase en algo más utilizable.

En este ejemplo, usaré ASM, pero otras alternativas como Javassist y BCEL tienen
características similares.

ClassNode getNode(byte[] bytes) {


// Create a ClassReader that will parse the byte array into a ClassNode
ClassReader cr = new ClassReader(bytes);
ClassNode cn = new ClassNode();
try {
// This populates the ClassNode
[Link](cn, ClassReader.EXPAND_FRAMES);
cr = null;
} catch (Exception e) {
[Link]();
}
return cn;
}

Desde aquí se pueden hacer cambios al objeto ClassNode. Esto hace que cambiar el acceso al
campo / método sea increíblemente fácil. Además, con la API del árbol de ASM, la modificación
del código de bytes de los métodos es muy sencilla.

Una vez que las ediciones hayan finalizado, puede volver a convertir el ClassNode en bytes con
el siguiente método y devolverlos en el método de transformación :

[Link] 14
public static byte[] getNodeBytes(ClassNode cn, boolean useMaxs) {
ClassWriter cw = new ClassWriter(useMaxs ? ClassWriter.COMPUTE_MAXS :
ClassWriter.COMPUTE_FRAMES);
[Link](cw);
byte[] b = [Link]();
return b;
}

Agregar un agente en tiempo de ejecución

Los agentes se pueden agregar a una JVM en tiempo de ejecución. Para cargar un agente,
deberá usar [Link] (Id . De cadena) de Attach API. A continuación, puede cargar
un jar de agente compilado con el siguiente método:

public static void loadAgent(String agentPath) {


String vmName = [Link]().getName();
int index = [Link]('@');
String pid = [Link](0, index);
try {
File agentFile = new File(agentPath);
VirtualMachine vm = [Link](pid);
[Link]([Link](), "");
[Link]([Link]());
} catch (Exception e) {
throw new RuntimeException(e);
}
}

Esto no llamará premain ((String agentArgs, Instrumentation inst) en el agente cargado, sino que
llamará a agentmain (String agentArgs, Instrumentation inst) . Esto requiere que Agent-Class esté
configurado en el agente [Link].

Configuración de un agente básico

La clase Premain contendrá el método "premain (String agentArgs Instrumentation inst)"

Aquí hay un ejemplo:

import [Link];

public class PremainExample {


public static void premain(String agentArgs, Instrumentation inst) {
[Link](agentArgs);
}
}

Cuando esté compilado en un archivo jar, abra el Manifiesto y asegúrese de que tenga el atributo
de clase principal.

Aquí hay un ejemplo:

Premain-Class: PremainExample

[Link] 15
Para usar el agente con otro programa java "myProgram", debe definir el agente en los
argumentos de JVM:

java -javaagent:[Link] -jar [Link]

Lea Agentes de Java en línea: [Link]

[Link] 16
Capítulo 5: Ajuste de rendimiento de Java
Examples
Enfoque general

Internet está repleto de consejos para mejorar el rendimiento de los programas Java. Quizás el
consejo número uno sea la conciencia. Eso significa:

• Identificar posibles problemas de rendimiento y cuellos de botella.


• Utilizar herramientas de análisis y pruebas.
• Conocer buenas prácticas y malas prácticas.

El primer punto se debe hacer durante la etapa de diseño si se habla de un nuevo sistema o
módulo. Si se habla de código heredado, las herramientas de análisis y prueba entran en escena.
La herramienta más básica para analizar el rendimiento de su JVM es JVisualVM, que se incluye
en el JDK.

El tercer punto es principalmente sobre la experiencia y la investigación extensa, y por supuesto,


consejos crudos que se mostrarán en esta página y otras, como esta .

Reduciendo cantidad de cuerdas

En Java, es demasiado "fácil" crear muchas instancias de String que no son necesarias. Esa y
otras razones pueden hacer que su programa tenga muchas cadenas que el GC está ocupado
limpiando.

Algunas formas en las que podrías estar creando instancias de String:

myString += "foo";

O peor aún, en un bucle o recursión:

for (int i = 0; i < N; i++) {


myString += "foo" + i;
}

El problema es que cada + crea una nueva Cadena (generalmente, ya que los nuevos
compiladores optimizan algunos casos). Se puede hacer una optimización posible utilizando
StringBuilder o StringBuffer :

StringBuffer sb = new StringBuffer(myString);


for (int i = 0; i < N; i++) {
[Link]("foo").append(i);
}
myString = [Link]();

[Link] 17
Si crea cadenas largas con frecuencia (por ejemplo, SQL), use una API de construcción de
cadenas.

Otras cosas a considerar:

• Reducir el uso de replace , substring , etc.


• Evite [Link]() , especialmente en el código de acceso frecuente.
• Las impresiones de registro que están destinadas a ser filtradas (debido al nivel de registro,
por ejemplo) no deben generarse (el nivel de registro debe verificarse de antemano).
• Utilice bibliotecas como esta si es necesario.
• StringBuilder es mejor si la variable se utiliza de manera no compartida (a través de hilos).

Un enfoque basado en la evidencia para el ajuste de rendimiento de Java

Donald Knuth a menudo es citado diciendo esto:

"Los programadores pierden enormes cantidades de tiempo pensando o


preocupándose por la velocidad de las partes no críticas de sus programas, y estos
intentos de eficiencia en realidad tienen un fuerte impacto negativo cuando se
consideran la depuración y el mantenimiento. Debemos olvidar las pequeñas
eficiencias, por ejemplo 97% del tiempo : la optimización prematura es la raíz de todo
mal. Sin embargo, no debemos dejar pasar nuestras oportunidades en ese 3% crítico
".

fuente

Teniendo en cuenta este sabio consejo, este es el procedimiento recomendado para optimizar
programas:

1. En primer lugar, diseñe y codifique su programa o biblioteca con un enfoque en la


simplicidad y la corrección. Para empezar, no dediques mucho esfuerzo al rendimiento.

2. Llegue a un estado de trabajo y (idealmente) desarrolle pruebas unitarias para las partes
clave del código base.

3. Desarrollar una prueba de rendimiento de nivel de aplicación. El punto de referencia debe


cubrir los aspectos críticos de rendimiento de su aplicación y debe realizar una serie de
tareas que son típicas de cómo se usará la aplicación en producción.

4. Medir el rendimiento.

5. Compare el rendimiento medido con sus criterios para determinar qué tan rápido debe ser la
aplicación. (Evite criterios poco realistas, inalcanzables o no cuantificables como "lo más
rápido posible".)

6. Si ha cumplido con los criterios, PARE. Tu trabajo está hecho. (Cualquier esfuerzo adicional
es probablemente una pérdida de tiempo.)

7. Perfile la aplicación mientras ejecuta su prueba de rendimiento.

[Link] 18
8. Examine los resultados de la creación de perfiles y elija los "hotspots de rendimiento" más
grandes (no optimizados); Es decir, las secciones del código donde la aplicación parece
estar gastando más tiempo.

9. Analice la sección del código del hotspot para tratar de entender por qué es un cuello de
botella y piense en una manera de hacerlo más rápido.

10. Implementar eso como un cambio de código propuesto, probar y depurar.

11. Vuelva a ejecutar el punto de referencia para ver si el cambio de código ha mejorado el
rendimiento:

• En caso afirmativo, vuelva al paso 4.


• Si No, abandone el cambio y vuelva al paso 9. Si no está progresando, elija un punto
de acceso diferente para su atención.

Eventualmente, llegará a un punto en el que la aplicación es lo suficientemente rápida o ha


considerado todos los hotspots importantes. En este punto es necesario detener este enfoque. Si
una sección del código consume (por ejemplo) el 1% del tiempo total, incluso una mejora del 50%
solo hará que la aplicación sea un 0,5% más rápida en general.

Claramente, hay un punto más allá del cual la optimización del punto de acceso es una pérdida
de esfuerzo. Si llegas a ese punto, debes adoptar un enfoque más radical. Por ejemplo:

• Mira la complejidad algorítmica de tus algoritmos centrales.


• Si la aplicación pasa mucho tiempo recolectando basura, busque formas de reducir la tasa
de creación de objetos.
• Si las partes clave de la aplicación son CPU intensivas y de un solo hilo, busque
oportunidades para el paralelismo.
• Si la aplicación ya tiene varios subprocesos, busque cuellos de botella de concurrencia.

Pero siempre que sea posible, confíe en las herramientas y la medición en lugar del instinto para
dirigir su esfuerzo de optimización.

Lea Ajuste de rendimiento de Java en línea: [Link]


rendimiento-de-java

[Link] 19
Capítulo 6: Análisis XML utilizando las API de
JAXP
Observaciones
El análisis XML es la interpretación de documentos XML para manipular su contenido mediante
construcciones sensibles, ya sean "nodos", "atributos", "documentos", "espacios de nombres" o
eventos relacionados con estas construcciones.

Java tiene una API nativa para el manejo de documentos XML, llamada JAXP, o API de Java para
el procesamiento XML . JAXP y una implementación de referencia se han incluido en todas las
versiones de Java desde Java 1.4 (JAXP v1.1) y han evolucionado desde entonces. Java 8
enviado con la versión 1.6 de JAXP.

La API proporciona diferentes formas de interactuar con documentos XML, que son:

• La interfaz DOM (Modelo de Objeto de Documento)


• La interfaz SAX (API simple para XML)
• La interfaz StAX (Streaming API para XML)

Principios de la interfaz DOM


La interfaz DOM apunta a proporcionar una forma compatible con W3C DOM de interpretar XML.
Varias versiones de JAXP han admitido varios niveles de especificación de DOM (hasta el nivel
3).

Bajo la interfaz del Modelo de objetos de documento, un documento XML se representa como un
árbol, comenzando con el "Elemento del documento". El tipo base de la API es el tipo de Node ,
permite navegar de un Node a su padre, sus hijos o sus hermanos (aunque, no todos los Node
pueden tener hijos, por ejemplo, los nodos de Text son finales en el árbol, y nunca tener hijos).
Las etiquetas XML se representan como Element s, que amplían notablemente el Node con
métodos relacionados con atributos.

La interfaz DOM es muy útil ya que permite un análisis de una línea de documentos XML como
árboles y permite una modificación fácil del árbol construido (adición de nodo, supresión, copia,
...) y, finalmente, su serialización (de nuevo al disco). ) modificaciones posteriores. Sin embargo,
esto tiene un precio: el árbol reside en la memoria, por lo tanto, los árboles DOM no siempre son
prácticos para grandes documentos XML. Además, la construcción del árbol no siempre es la
forma más rápida de tratar con el contenido XML, especialmente si uno no está interesado en
todas las partes del documento XML.

Principios de la interfaz SAX

[Link] 20
La API de SAX es una API orientada a eventos para tratar con documentos XML. Bajo este
modelo, los componentes de un documento XML se interpretan como eventos (por ejemplo, "se
ha abierto una etiqueta", "se ha cerrado una etiqueta", "se ha encontrado un nodo de texto", "se
ha encontrado un comentario"). ..

La API de SAX utiliza un enfoque de "análisis de inserción", donde un Parser SAX es responsable
de interpretar el documento XML e invoca métodos en un delegado (un ContentHandler ) para
tratar cualquier evento que se encuentre en el documento XML. Por lo general, uno nunca escribe
un analizador, pero proporciona un controlador para recopilar todas las informaciones necesarias
del documento XML.

La interfaz SAX supera las limitaciones de la interfaz DOM manteniendo solo los datos mínimos
necesarios en el nivel del analizador (por ejemplo, contextos de espacios de nombres, estado de
validación), por lo tanto, solo las informaciones que guarda ContentHandler , de las que usted, el
desarrollador, es responsable, son guardado en la memoria. La desventaja es que no hay manera
de "retroceder en el tiempo / el documento XML" con este enfoque: mientras que DOM permite
que un Node regrese a su padre, no existe tal posibilidad en SAX.

Principios de la interfaz StAX


La API StAX adopta un enfoque similar para procesar XML como la API SAX (es decir, impulsada
por eventos), la única diferencia muy significativa es que StAX es un analizador de extracción
(donde SAX era un analizador de inserción). En SAX, el Parser está en control y utiliza
devoluciones de llamada en el ContentHandler . En Stax, usted llama al analizador y controla
cuándo / si desea obtener el siguiente "evento" XML.

La API comienza con XMLStreamReader (o XMLEventReader ), que son las puertas de acceso a
través de las cuales el desarrollador puede preguntar a nextEvent() , de forma nextEvent() .

Examples
Analizar y navegar un documento utilizando la API DOM

Teniendo en cuenta el siguiente documento:

<?xml version='1.0' encoding='UTF-8' ?>


<library>
<book id='1'>Effective Java</book>
<book id='2'>Java Concurrency In Practice</book>
</library>

Uno puede usar el siguiente código para construir un árbol DOM a partir de una String :

import [Link];
import [Link];
import [Link];
import [Link];

[Link] 21
import [Link];
import [Link];
import [Link];

public class DOMDemo {

public static void main(String[] args) throws Exception {


String xmlDocument = "<?xml version='1.0' encoding='UTF-8' ?>"
+ "<library>"
+ "<book id='1'>Effective Java</book>"
+ "<book id='2'>Java Concurrency In Practice</book>"
+ "</library>";

DocumentBuilderFactory documentBuilderFactory = [Link]();


// This is useless here, because the XML does not have namespaces, but this option is
usefull to know in cas
[Link](true);
DocumentBuilder documentBuilder = [Link]();
// There are various options here, to read from an InputStream, from a file, ...
Document document = [Link](new InputSource(new StringReader(xmlDocument)));

// Root of the document


[Link]("Root of the XML Document: " +
[Link]().getLocalName());

// Iterate the contents


NodeList firstLevelChildren = [Link]().getChildNodes();
for (int i = 0; i < [Link](); i++) {
Node item = [Link](i);
[Link]("First level child found, XML tag name is: " +
[Link]());
[Link]("\tid attribute of this tag is : " +
[Link]().getNamedItem("id").getTextContent());
}

// Another way would have been


NodeList allBooks = [Link]().getElementsByTagName("book");
}
}

El código produce lo siguiente:

Root of the XML Document: library


First level child found, XML tag name is: book
id attribute of this tag is : 1
First level child found, XML tag name is: book
id attribute of this tag is : 2

Analizar un documento utilizando la API StAX

Teniendo en cuenta el siguiente documento:

<?xml version='1.0' encoding='UTF-8' ?>


<library>
<book id='1'>Effective Java</book>
<book id='2'>Java Concurrency In Practice</book>
<notABook id='3'>This is not a book element</notABook>

[Link] 22
</library>

Uno puede usar el siguiente código para analizarlo y construir un mapa de títulos de libros por ID
de libro.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class StaxDemo {

public static void main(String[] args) throws Exception {


String xmlDocument = "<?xml version='1.0' encoding='UTF-8' ?>"
+ "<library>"
+ "<book id='1'>Effective Java</book>"
+ "<book id='2'>Java Concurrency In Practice</book>"
+ "<notABook id='3'>This is not a book element </notABook>"
+ "</library>";

XMLInputFactory xmlInputFactory = [Link]();


// Various flavors are possible, e.g. from an InputStream, a Source, ...
XMLStreamReader xmlStreamReader = [Link](new
StringReader(xmlDocument));

Map<Integer, String> bookTitlesById = new HashMap<>();

// We go through each event using a loop


while ([Link]()) {
switch ([Link]()) {
case XMLStreamConstants.START_ELEMENT:
[Link]("Found start of element: " +
[Link]());
// Check if we are at the start of a <book> element
if ("book".equals([Link]())) {
int bookId = [Link]([Link]("",
"id"));
String bookTitle = [Link]();
[Link](bookId, bookTitle);
}
break;
// A bunch of other things are possible : comments, processing instructions,
Whitespace...
default:
break;
}
[Link]();
}

[Link](bookTitlesById);
}

Esto produce:

Found start of element: library


Found start of element: book

[Link] 23
Found start of element: book
Found start of element: notABook
{1=Effective Java, 2=Java Concurrency In Practice}

En esta muestra, uno debe tener cuidado con algunas cosas:

1. El uso de [Link] funciona porque hemos verificado primero que


el analizador está en el estado START_ELEMENT . En todos los demás estados (excepto
ATTRIBUTES ), el analizador está obligado a lanzar la IllegalStateException , porque los
atributos solo pueden aparecer al principio de los elementos.

2. Lo mismo ocurre con [Link]() , funciona porque estamos en un


START_ELEMENT y sabemos en este documento que el elemento <book> no tiene nodos
secundarios que no sean de texto.

Para el análisis de documentos más complejos (elementos más profundos, anidados, ...), es una
buena práctica "delegar" el analizador a sub-métodos u otros objetos, por ejemplo, tener una
clase o método BookParser , y hacer que se ocupe de cada elemento de START_ELEMENT a
END_ELEMENT de la etiqueta XML del libro.

También se puede usar un objeto de Stack para mantener datos importantes arriba y abajo del
árbol.

Lea Análisis XML utilizando las API de JAXP en línea:


[Link]

[Link] 24
Capítulo 7: Anotaciones
Introducción
En Java, una anotación es una forma de metadatos sintácticos que se pueden agregar al código
fuente de Java. Proporciona datos sobre un programa que no forma parte del programa en sí. Las
anotaciones no tienen ningún efecto directo en el funcionamiento del código que anotan. Clases,
métodos, variables, parámetros y paquetes pueden ser anotados.

Sintaxis
• @AnnotationName // 'Anotación de marcador' (sin parámetros)
• @AnnotationName (someValue) // establece el parámetro con el nombre 'valor'
• @AnnotationName (param1 = value1) // parámetro con nombre
• @AnnotationName (param1 = value1, param2 = value2) // múltiples parámetros nombrados
• @AnnotationName (param1 = {1, 2, 3}) // parámetro de matriz con nombre
• @AnnotationName ({value1}) // array con un solo elemento como parámetro con el nombre
'value'

Observaciones

Tipos de parametros
Solo se permiten expresiones constantes de los siguientes tipos para los parámetros, así como
matrices de estos tipos:

• String
• Class
• tipos primitivos
• Tipos de enumeración
• Tipos de anotaciones

Examples
Anotaciones incorporadas

La edición estándar de Java viene con algunas anotaciones predefinidas. No es necesario que los
defina por sí mismo y puede usarlos inmediatamente. Permiten al compilador habilitar algunas
comprobaciones fundamentales de métodos, clases y código.

@Anular

Esta anotación se aplica a un método y dice que este método debe anular un método de

[Link] 25
superclase o implementar una definición de método de superclase abstracta. Si esta anotación se
utiliza con cualquier otro tipo de método, el compilador arrojará un error.

Superclase de concreto

public class Vehicle {


public void drive() {
[Link]("I am driving");
}
}

class Car extends Vehicle {


// Fine
@Override
public void drive() {
[Link]("Brrrm, brrm");
}
}

Clase abstracta

abstract class Animal {


public abstract void makeNoise();
}

class Dog extends Animal {


// Fine
@Override
public void makeNoise() {
[Link]("Woof");
}
}

No funciona

class Logger1 {
public void log(String logString) {
[Link](logString);
}
}

class Logger2 {
// This will throw compile-time error. Logger2 is not a subclass of Logger1.
// log method is not overriding anything
@Override
public void log(String logString) {
[Link]("Log 2" + logString);
}
}

El propósito principal es detectar errores, donde crees que estás anulando un método, pero en
realidad estás definiendo uno nuevo.

class Vehicle {
public void drive() {
[Link]("I am driving");

[Link] 26
}
}

class Car extends Vehicle {


// Compiler error. "dirve" is not the correct method name to override.
@Override
public void dirve() {
[Link]("Brrrm, brrm");
}
}

Tenga en cuenta que el significado de @Override ha cambiado con el tiempo:

• En Java 5, significaba que el método anotado tenía que anular un método no abstracto
declarado en la cadena de superclase.
• Desde Java 6 en adelante, también se satisface si el método anotado implementa un
método abstracto declarado en la jerarquía de superclase / interfaz de clases.

(Ocasionalmente, esto puede causar problemas al realizar un back-port del código a Java 5.)

@Obsoleto

Esto marca el método como obsoleto. Puede haber varias razones para esto:

• la API es defectuosa y no es práctico de arreglar,

• el uso de la API puede llevar a errores,

• la API ha sido sustituida por otra API,

• la API está obsoleta,

• la API es experimental y está sujeta a cambios incompatibles,

• o cualquier combinación de los anteriores.

El motivo específico de la desaprobación se puede encontrar en la documentación de la API.

La anotación hará que el compilador emita un error si lo usa. Los IDE también pueden resaltar
este método de alguna manera como desaprobado

class ComplexAlgorithm {
@Deprecated
public void oldSlowUnthreadSafeMethod() {
// stuff here
}

public void quickThreadSafeMethod() {


// client code should use this instead
}
}

@SuppressWarnings

[Link] 27
En casi todos los casos, cuando el compilador emite una advertencia, la acción más apropiada es
corregir la causa. En algunos casos (por ejemplo, el código genérico que usa un código pre-
genérico seguro para los tipos) puede que no sea posible y es mejor suprimir las advertencias
que espera y no puede corregir, por lo que puede ver más claramente las advertencias
inesperadas.

Esta anotación se puede aplicar a toda una clase, método o línea. Toma la categoría de
advertencia como parámetro.

@SuppressWarnings("deprecation")
public class RiddledWithWarnings {
// several methods calling deprecated code here
}

@SuppressWarning("finally")
public boolean checkData() {
// method calling return from within finally block
}

Es mejor limitar el alcance de la anotación tanto como sea posible, para evitar que también se
supriman las advertencias inesperadas. Por ejemplo, al limitar el alcance de la anotación a una
sola línea:

ComplexAlgorithm algorithm = new ComplexAlgorithm();


@SuppressWarnings("deprecation") [Link]();
// we marked this method deprecated in an example above

@SuppressWarnings("unsafe") List<Integer> list = getUntypeSafeList();


// old library returns, non-generic List containing only integers

Las advertencias admitidas por esta anotación pueden variar de compilador a compilador. Solo
las advertencias unchecked y de deprecation se mencionan específicamente en el JLS. Se
ignorarán los tipos de advertencia no reconocidos.

@SafeVarargs

Debido al borrado de tipo, el void method(T... t) se convertirá al void method(Object[] t) lo que


significa que el compilador no siempre puede verificar que el uso de varargs es de tipo seguro.
Por ejemplo:

private static <T> void generatesVarargsWarning(T... lists) {

Hay casos en que el uso es seguro, en cuyo caso puede anotar el método con la anotación
SafeVarargs para suprimir la advertencia. Esto obviamente oculta la advertencia si su uso no es
seguro también.

@FunctionalInterface

Esta es una anotación opcional utilizada para marcar un FunctionalInterface. Hará que el
compilador se queje si no cumple con la especificación FunctionalInterface (tiene un solo método
abstracto)

[Link] 28
@FunctionalInterface
public interface ITrade {
public boolean check(Trade t);
}

@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
}

Comprobaciones de anotación en tiempo de ejecución a través de la


reflexión.

La API de Reflection de Java permite al programador realizar varias comprobaciones y


operaciones en campos de clase, métodos y anotaciones durante el tiempo de ejecución. Sin
embargo, para que una anotación sea visible en el tiempo de ejecución, la RetentionPolicy debe
cambiarse a RUNTIME , como se muestra en el siguiente ejemplo:

@interface MyDefaultAnnotation {

@Retention([Link])
@interface MyRuntimeVisibleAnnotation {

public class AnnotationAtRuntimeTest {

@MyDefaultAnnotation
static class RuntimeCheck1 {
}

@MyRuntimeVisibleAnnotation
static class RuntimeCheck2 {
}

public static void main(String[] args) {


Annotation[] annotationsByType = [Link]();
Annotation[] annotationsByType2 = [Link]();

[Link]("default retention: " + [Link](annotationsByType));


[Link]("runtime retention: " + [Link](annotationsByType2));
}
}

Definición de tipos de anotación.

Los tipos de anotación se definen con @interface . Los parámetros se definen de manera similar a
los métodos de una interfaz regular.

@interface MyAnnotation {
String param1();
boolean param2();
int[] param3(); // array parameter

[Link] 29
}

Valores predeterminados

@interface MyAnnotation {
String param1() default "someValue";
boolean param2() default true;
int[] param3() default {};
}

Meta-Anotaciones
Las meta-anotaciones son anotaciones que se pueden aplicar a los tipos de anotación. La meta-
anotación predefinida especial define cómo se pueden usar los tipos de anotación.

@Objetivo
La meta-anotación de @Target restringe los tipos a los que se puede aplicar la anotación.

@Target([Link])
@interface MyAnnotation {
// this annotation can only be applied to methods
}

Se pueden agregar varios valores utilizando la notación de matriz, por ejemplo,


@Target({[Link], [Link]})

Valores disponibles

ejemplo de uso en el elemento de


Tipo de elemento objetivo
destino

@Retention([Link])
ANNOTATION_TYPE tipos de anotaciones @interface MyAnnotation

@MyAnnotation
CONSTRUCTOR constructores public MyClass() {}

campos, constantes de @XmlAttribute


CAMPO private int count;
enumeración

[Link] 30
ejemplo de uso en el elemento de
Tipo de elemento objetivo
destino

for (@LoopVariable int i = 0; i < 100;


i++) {
Declaraciones variables
VARIABLE LOCAL @Unused
dentro de los métodos. String resultVariable;
}

paquete (en package- @Deprecated


PAQUETE package [Link];
[Link] )

@XmlElement
MÉTODO metodos public int getCount() {...}

public Rectangle(
@NamedArg("width") double
width,
Parámetros de método /
PARÁMETRO @NamedArg("height") double
constructor height) {
...
}

clases, interfaces, @XmlRootElement


TIPO public class Report {}
enumeraciones

Java SE 8
ejemplo de uso en el elemento de
Tipo de elemento objetivo
destino

Declaraciones de parámetros public <@MyAnnotation T> void f(T


TYPE_PARAMETER t) {}
de tipo

Object o = "42";
TYPE_USE Uso de un tipo String s = (@MyAnnotation String)
o;

@Retencion
La meta-anotación de @Retention define la visibilidad de la anotación durante el proceso de

[Link] 31
compilación o ejecución de las aplicaciones. De forma predeterminada, las anotaciones se
incluyen en los archivos .class , pero no son visibles en tiempo de ejecución. Para hacer que una
anotación sea accesible en tiempo de ejecución, [Link] debe establecerse en
esa anotación.

@Retention([Link])
@interface MyAnnotation {
// this annotation can be accessed with reflections at runtime
}

Valores disponibles

Política de
Efecto
retención

La anotación está disponible en el archivo .class , pero no en tiempo de


CLASE
ejecución

La anotación está disponible en tiempo de ejecución y se puede acceder a


RUNTIME
través de la reflexión

La anotación está disponible en tiempo de compilación, pero no se agrega a


FUENTE los archivos .class . La anotación se puede utilizar, por ejemplo, por un
procesador de anotaciones.

@Documentado
La meta-anotación @Documented se usa para marcar anotaciones cuyo uso debe ser documentado
por los generadores de documentación API como javadoc . No tiene valores. Con @Documented ,
todas las clases que usan la anotación la incluirán en su página de documentación generada. Sin
@Documented , no es posible ver qué clases usan la anotación en la documentación.

@Heredado
La meta-anotación @Inherited es relevante para las anotaciones que se aplican a las clases. No
tiene valores. Marcar una anotación como @Inherited altera la forma en que funciona la consulta
de anotación.

• Para una anotación no heredada, la consulta solo examina la clase que se está
examinando.
• Para una anotación heredada, la consulta también verificará la cadena de superclase
(recursivamente) hasta que se encuentre una instancia de la anotación.

Tenga en cuenta que solo se consultan las superclases: se ignorarán todas las anotaciones
asociadas a las interfaces en la jerarquía de clases.

[Link] 32
@Repeable
La meta-anotación @Repeatable se agregó en Java 8. Indica que se pueden adjuntar múltiples
instancias de la anotación al destino de la anotación. Esta meta-anotación no tiene valores.

Obtención de valores de anotación en tiempo de ejecución

Puede obtener las propiedades actuales de la anotación utilizando Reflexión para obtener el
Método o el Campo o la Clase que tiene aplicada una anotación, y luego obtener las propiedades
deseadas.

@Retention([Link])
@interface MyAnnotation {
String key() default "foo";
String value() default "bar";
}

class AnnotationExample {
// Put the Annotation on the method, but leave the defaults
@MyAnnotation
public void testDefaults() throws Exception {
// Using reflection, get the public method "testDefaults", which is this method with
no args
Method method = [Link]("testDefaults", null);

// Fetch the Annotation that is of type MyAnnotation from the Method


MyAnnotation annotation = (MyAnnotation)[Link]([Link]);

// Print out the settings of the Annotation


print(annotation);
}

//Put the Annotation on the method, but override the settings


@MyAnnotation(key="baz", value="buzz")
public void testValues() throws Exception {
// Using reflection, get the public method "testValues", which is this method with no
args
Method method = [Link]("testValues", null);

// Fetch the Annotation that is of type MyAnnotation from the Method


MyAnnotation annotation = (MyAnnotation)[Link]([Link]);

// Print out the settings of the Annotation


print(annotation);
}

public void print(MyAnnotation annotation) {


// Fetch the MyAnnotation 'key' & 'value' properties, and print them out
[Link]([Link]() + " = " + [Link]());
}

public static void main(String[] args) {


AnnotationExample example = new AnnotationExample();
try {
[Link]();
[Link]();

[Link] 33
} catch( Exception e ) {
// Shouldn't throw any Exceptions
[Link]("Exception [" + [Link]().getName() + "] - " +
[Link]());
[Link]([Link]);
}
}
}

La salida será

foo = bar
baz = buzz

Repetir anotaciones

Hasta Java 8, dos instancias de la misma anotación no se podían aplicar a un solo elemento. La
solución estándar era usar una anotación de contenedor que contenga una matriz de alguna otra
anotación:

// [Link]
@Retention([Link])
public @interface Author {
String value();
}

// [Link]
@Retention([Link])
public @interface Authors {
Author[] value();
}

// [Link]
@Authors({
@Author("Mary"),
@Author("Sam")
})
public class Test {
public static void main(String[] args) {
Author[] authors = [Link]([Link]).value();
for (Author author : authors) {
[Link]([Link]());
// Output:
// Mary
// Sam
}
}
}

Java SE 8

Java 8 proporciona una forma más limpia y transparente de usar anotaciones de contenedor,
utilizando la anotación @Repeatable . Primero agregamos esto a la clase de Author :

@Repeatable([Link])

[Link] 34
Esto le dice a Java que trate las múltiples anotaciones de @Author como si estuvieran rodeadas
por el contenedor @Authors . También podemos usar [Link]() para acceder a
la matriz @Author por su propia clase, en lugar de a través de su contenedor:

@Author("Mary")
@Author("Sam")
public class Test {
public static void main(String[] args) {
Author[] authors = [Link]([Link]);
for (Author author : authors) {
[Link]([Link]());
// Output:
// Mary
// Sam
}
}
}

Anotaciones heredadas

Por defecto, las anotaciones de clase no se aplican a los tipos que las extienden. Esto se puede
cambiar agregando la anotación @Inherited a la definición de anotación

Ejemplo
Considere las siguientes 2 anotaciones:

@Inherited
@Target([Link])
@Retention([Link])
public @interface InheritedAnnotationType {
}

@Target([Link])
@Retention([Link])
public @interface UninheritedAnnotationType {
}

Si se anotan tres clases así:

@UninheritedAnnotationType
class A {
}

@InheritedAnnotationType
class B extends A {
}

class C extends B {
}

[Link] 35
ejecutando este código

[Link](new A().getClass().getAnnotation([Link]));
[Link](new B().getClass().getAnnotation([Link]));
[Link](new C().getClass().getAnnotation([Link]));
[Link]("_________________________________");
[Link](new A().getClass().getAnnotation([Link]));
[Link](new B().getClass().getAnnotation([Link]));
[Link](new C().getClass().getAnnotation([Link]));

imprimirá un resultado similar a este (dependiendo de los paquetes de la anotación):

null
@InheritedAnnotationType()
@InheritedAnnotationType()
_________________________________
@UninheritedAnnotationType()
null
null

Tenga en cuenta que las anotaciones solo pueden heredarse de las clases, no de las interfaces.

Procesamiento de tiempo de compilación utilizando procesador de anotación

Este ejemplo muestra cómo realizar la comprobación de tiempo de compilación de un elemento


anotado.

La anotacion
La anotación @Setter es un marcador que se puede aplicar a los métodos. La anotación se
descartará durante la compilación y no estará disponible posteriormente.

package annotation;

import [Link];
import [Link];
import [Link];
import [Link];

@Retention([Link])
@Target([Link])
public @interface Setter {
}

El procesador de anotaciones.
El SetterProcessor utiliza la clase SetterProcessor para procesar las anotaciones. Comprueba, si
los métodos anotados con la anotación @Setter son public , static métodos no static con un
nombre que comienza con set y que tienen una letra mayúscula como cuarta letra. Si una de

[Link] 36
estas condiciones no se cumple, se escribe un error en el Messager . El compilador escribe esto en
stderr, pero otras herramientas podrían usar esta información de manera diferente. Por ejemplo,
el IDE de NetBeans permite al usuario especificar procesadores de anotación que se utilizan para
mostrar mensajes de error en el editor.

package [Link];

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

@SupportedAnnotationTypes({"[Link]"})
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class SetterProcessor extends AbstractProcessor {

private Messager messager;

@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
{
// get elements annotated with the @Setter annotation
Set<? extends Element> annotatedElements =
[Link]([Link]);

for (Element element : annotatedElements) {


if ([Link]() == [Link]) {
// only handle methods as targets
checkMethod((ExecutableElement) element);
}
}

// don't claim annotations to allow other processors to process them


return false;
}

private void checkMethod(ExecutableElement method) {


// check for valid name
String name = [Link]().toString();
if (![Link]("set")) {
printError(method, "setter name must start with \"set\"");
} else if ([Link]() == 3) {
printError(method, "the method name must contain more than just \"set\"");
} else if ([Link]([Link](3))) {
if ([Link]().size() != 1) {
printError(method, "character following \"set\" must be upper case");
}
}

[Link] 37
// check, if setter is public
if (![Link]().contains([Link])) {
printError(method, "setter must be public");
}

// check, if method is static


if ([Link]().contains([Link])) {
printError(method, "setter must not be static");
}
}

private void printError(Element element, String message) {


[Link]([Link], message, element);
}

@Override
public void init(ProcessingEnvironment processingEnvironment) {
[Link](processingEnvironment);

// get messager for printing errors


messager = [Link]();
}

embalaje
Para ser aplicado por el compilador, el procesador de anotaciones debe estar disponible para el
SPI (ver ServiceLoader ).

Para hacer esto, se debe agregar un archivo de texto META-


INF/services/[Link] al archivo jar que contiene el procesador de
anotaciones y la anotación además de los otros archivos. El archivo debe incluir el nombre
completo del procesador de anotaciones, es decir, debe tener este aspecto

[Link]

Asumiremos que el archivo jar se llama [Link] continuación.

Ejemplo de clase anotada


La siguiente clase es una clase de ejemplo en el paquete predeterminado con las anotaciones
aplicadas a los elementos correctos de acuerdo con la política de retención. Sin embargo, solo el
procesador de anotaciones solo considera el segundo método como un objetivo de anotación
válido.

import [Link];

public class AnnotationProcessorTest {

@Setter

[Link] 38
private void setValue(String value) {}

@Setter
public void setString(String value) {}

@Setter
public static void main(String[] args) {}

Usando el procesador de anotaciones con


javac
Si el procesador de anotaciones se descubre utilizando el SPI, se utiliza automáticamente para
procesar elementos anotados. Ej. Compilar la clase AnnotationProcessorTest usando

javac -cp [Link] [Link]

produce la siguiente salida

[Link][Link] error: setter must be public


private void setValue(String value) {}
^
[Link][Link] error: setter name must start with "set"
public static void main(String[] args) {}
^
2 errors

En lugar de compilar normalmente. No se crea ningún archivo .class .

Esto se podría evitar especificando la opción -proc:none para javac . También puede renunciar a la
compilación habitual especificando -proc:only lugar.

Integración IDE
Netbeans
Los procesadores de anotación se pueden utilizar en el editor de NetBeans. Para hacer esto, el
procesador de anotaciones debe especificarse en la configuración del proyecto:

1. Build a Project Properties > Compiling > Compiling

2. agregar marcas de verificación para Enable Annotation Processing y Enable Annotation


Processing in Editor

3. haga clic en Add junto a la lista de procesadores de anotaciones

[Link] 39
4. en la ventana emergente que aparece, ingrese el nombre de clase completamente calificado
del procesador de anotaciones y haga clic en Ok .

Resultado

La idea detrás de las anotaciones.

La especificación del lenguaje Java describe las anotaciones de la siguiente manera:

Una anotación es un marcador que asocia información con una construcción de


programa, pero no tiene efecto en el tiempo de ejecución.

Las anotaciones pueden aparecer antes de los tipos o declaraciones. Es posible que aparezcan
en un lugar donde se puedan aplicar tanto a un tipo como a una declaración.
A qué se aplica exactamente una anotación se rige por la "meta-anotación" @Target . Consulte
"Definición de tipos de anotación" para obtener más información.

Las anotaciones se utilizan para una multitud de propósitos. Los marcos como Spring y Spring-
MVC hacen uso de anotaciones para definir dónde se deben inyectar las dependencias o dónde
se deben enrutar las solicitudes.

Otros marcos usan anotaciones para la generación de código. Lombok y JPA son ejemplos
principales, que usan anotaciones para generar código Java (y SQL).

Este tema tiene como objetivo proporcionar una visión global de:

• ¿Cómo definir tus propias anotaciones?

• ¿Qué anotaciones proporciona el lenguaje Java?

• ¿Cómo se utilizan las anotaciones en la práctica?

Anotaciones para 'este' y parámetros del receptor.

Cuando se introdujeron las anotaciones de Java por primera vez, no había ninguna disposición

[Link] 40
para anotar el objetivo de un método de instancia o el parámetro de constructor oculto para un
constructor de clases internas. Esto se solucionó en Java 8 con la adición de declaraciones de
parámetros del receptor ; ver JLS 8.4.1 .

El parámetro receptor es un dispositivo sintáctico opcional para un método de


instancia o un constructor de clase interno. Para un método de instancia, el parámetro
receptor representa el objeto para el que se invoca el método. Para el constructor de
una clase interna, el parámetro receptor representa la instancia inmediatamente
adjunta del objeto recién construido. De cualquier manera, el parámetro del receptor
existe únicamente para permitir que el tipo del objeto representado se indique en el
código fuente, de modo que el tipo pueda ser anotado. El parámetro receptor no es un
parámetro formal; más precisamente, no es una declaración de ningún tipo de variable
(§4.12.3), nunca se vincula a ningún valor pasado como un argumento en una
expresión de invocación de método o expresión de creación de instancia de clase
calificada, y no tiene ningún efecto en absoluto correr tiempo

El siguiente ejemplo ilustra la sintaxis para ambos tipos de parámetros del receptor:

public class Outer {


public class Inner {
public Inner (Outer this) {
// ...
}
public void doIt(Inner this) {
// ...
}
}
}

El único propósito de los parámetros del receptor es permitirle agregar anotaciones. Por ejemplo,
puede tener una anotación personalizada @IsOpen cuyo propósito es afirmar que un objeto
Closeable no se ha cerrado cuando se llama a un método. Por ejemplo:

public class MyResource extends Closeable {


public void update(@IsOpen MyResource this, int value) {
// ...
}

public void close() {


// ...
}
}

En un nivel, la anotación @IsOpen sobre this podría simplemente servir como documentación. Sin
embargo, potencialmente podríamos hacer más. Por ejemplo:

• Un procesador de anotaciones podría insertar una verificación de tiempo de ejecución de


que this no está en estado cerrado cuando se llama a la update .
• Un verificador de código podría realizar un análisis de código estático para encontrar casos
donde this podría cerrarse cuando se llama a la update .

[Link] 41
Añadir múltiples valores de anotación

Un parámetro de anotación puede aceptar múltiples valores si se define como una matriz. Por
ejemplo, la anotación estándar @SuppressWarnings se define así:

public @interface SuppressWarnings {


String[] value();
}

El parámetro de value es una matriz de cadenas. Puede establecer varios valores utilizando una
notación similar a los inicializadores de matriz:

@SuppressWarnings({"unused"})
@SuppressWarnings({"unused", "javadoc"})

Si solo necesita establecer un único valor, se pueden omitir los paréntesis:

@SuppressWarnings("unused")

Lea Anotaciones en línea: [Link]

[Link] 42
Capítulo 8: Apache Commons Lang
Examples
Implementar el método equals ()

Para implementar fácilmente el método equals de un objeto, puede usar la clase EqualsBuilder .

Seleccionando los campos:

@Override
public boolean equals(Object obj) {

if(!(obj instanceof MyClass)) {


return false;
}
MyClass theOther = (MyClass) obj;

EqualsBuilder builder = new EqualsBuilder();


[Link](field1, theOther.field1);
[Link](field2, theOther.field2);
[Link](field3, theOther.field3);

return [Link]();
}

Usando la reflexión:

@Override
public boolean equals(Object obj) {
return [Link](this, obj, false);
}

el parámetro booleano es para indicar si los iguales deben verificar los campos transitorios.

Usando la reflexión evitando algunos campos:

@Override
public boolean equals(Object obj) {
return [Link](this, obj, "field1", "field2");
}

Implementar el método hashCode ()

Para implementar hashCode método hashCode de un objeto, puede usar la clase HashCodeBuilder .

Seleccionando los campos:

@Override
public int hashCode() {

[Link] 43
HashCodeBuilder builder = new HashCodeBuilder();
[Link](field1);
[Link](field2);
[Link](field3);

return [Link]();
}

Usando la reflexión:

@Override
public int hashCode() {
return [Link](this, false);
}

el parámetro booleano indica si debe usar campos transitorios.

Usando la reflexión evitando algunos campos:

@Override
public int hashCode() {
return [Link](this, "field1", "field2");
}

Implementar el método toString ()

Para implementar fácilmente el método toString de un objeto, puede usar la clase ToStringBuilder
.

Seleccionando los campos:

@Override
public String toString() {

ToStringBuilder builder = new ToStringBuilder(this);


[Link](field1);
[Link](field2);
[Link](field3);

return [Link]();
}

Resultado de ejemplo:

[Link]@dd7123[<null>,0,false]

Dando nombres explícitos a los campos:

@Override
public String toString() {

ToStringBuilder builder = new ToStringBuilder(this);

[Link] 44
[Link]("field1",field1);
[Link]("field2",field2);
[Link]("field3",field3);

return [Link]();
}

Resultado de ejemplo:

[Link]@dd7404[field1=<null>,field2=0,field3=false]

Podrías cambiar el estilo vía parámetro:

@Override
public String toString() {

ToStringBuilder builder = new ToStringBuilder(this,


ToStringStyle.MULTI_LINE_STYLE);
[Link]("field1", field1);
[Link]("field2", field2);
[Link]("field3", field3);

return [Link]();
}

Resultado de ejemplo:

[Link]@ebbf5c[
field1=<null>
field2=0
field3=false
]

Hay algunos estilos, por ejemplo JSON, sin nombre de clase, cortos, etc.

Vía la reflexión:

@Override
public String toString() {
return [Link](this);
}

También puedes indicar el estilo:

@Override
public String toString() {
return [Link](this, ToStringStyle.JSON_STYLE);
}

Lea Apache Commons Lang en línea: [Link]


lang

[Link] 45
Capítulo 9: API de apilación
Introducción
Antes de Java 9, el acceso a los marcos de la pila de hilos estaba limitado a una clase interna
[Link] . Específicamente el método [Link]::getCallerClass .
Algunas bibliotecas se basan en este método que está en desuso.

Una API estándar alternativo ahora se proporciona en el JDK 9 a través de la


[Link] clase, y está diseñado para ser eficiente al permitir el acceso perezoso para
los marcos de pila. Algunas aplicaciones pueden usar esta API para atravesar la pila de ejecución
y filtrar en las clases.

Examples
Imprimir todos los marcos de pila de la secuencia actual

Lo siguiente imprime todos los marcos de pila del hilo actual:

1 package test;
2
3 import [Link];
4 import [Link];
5 import [Link];
6 import [Link];
7 import [Link];
8
9 public class StackWalkerExample {
10
11 public static void main(String[] args) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
12 Method fooMethod = [Link]("foo", (Class<?>[])null);
13 [Link](null, (Object[]) null);
14 }
15 }
16
17 class FooHelper {
18 protected static void foo() {
19 [Link]();
20 }
21 }
22
23 class BarHelper {
24 protected static void bar() {
25 List<StackFrame> stack = [Link]()
26 .walk((s) -> [Link]([Link]()));
27 for(StackFrame frame : stack) {
28 [Link]([Link]() + " " + [Link]() + " " +
[Link]());
29 }
30 }
31 }

[Link] 46
Salida:

[Link] 26 bar
[Link] 19 foo
[Link] 13 main

Imprimir la clase de llamada actual

A continuación se imprime la clase de llamada actual. Tenga en cuenta que, en este caso,
StackWalker debe crearse con la opción RETAIN_CLASS_REFERENCE , para que Class instancias de la
Class se conserven en los objetos StackFrame . De lo contrario se produciría una excepción.

public class StackWalkerExample {

public static void main(String[] args) {


[Link]();
}

class FooHelper {
protected static void foo() {
[Link]();
}
}

class BarHelper {
protected static void bar() {

[Link]([Link](Option.RETAIN_CLASS_REFERENCE).getCallerClass());
}
}

Salida:

class [Link]

Mostrando la reflexión y otros marcos ocultos.

Un par de otras opciones permiten que los seguimientos de pila incluyan marcos de
implementación y / o reflexión. Esto puede ser útil para propósitos de depuración. Por ejemplo,
podemos agregar la opción SHOW_REFLECT_FRAMES a la instancia de StackWalker momento de la
creación, para que también se impriman los marcos para los métodos reflectivos:

package test;

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

[Link] 47
public class StackWalkerExample {

public static void main(String[] args) throws NoSuchMethodException, SecurityException,


IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Method fooMethod = [Link]("foo", (Class<?>[])null);
[Link](null, (Object[]) null);
}
}

class FooHelper {
protected static void foo() {
[Link]();
}
}

class BarHelper {
protected static void bar() {
// show reflection methods
List<StackFrame> stack = [Link](Option.SHOW_REFLECT_FRAMES)
.walk((s) -> [Link]([Link]()));
for(StackFrame frame : stack) {
[Link]([Link]() + " " + [Link]() + " " +
[Link]());
}
}
}

Salida:

[Link] 27 bar
[Link] 20 foo
[Link] -2 invoke0
[Link] 62 invoke
[Link] 43 invoke
[Link] 563 invoke
[Link] 14 main

Tenga en cuenta que los números de línea para algunos métodos de reflexión pueden no estar
disponibles, por lo que [Link]() puede devolver valores negativos.

Lea API de apilación en línea: [Link]

[Link] 48
Capítulo 10: API de reflexión
Introducción
Reflection es comúnmente utilizado por programas que requieren la capacidad de examinar o
modificar el comportamiento en tiempo de ejecución de las aplicaciones que se ejecutan en la
JVM. Java Reflection API se usa para ese propósito donde permite inspeccionar clases,
interfaces, campos y métodos en tiempo de ejecución, sin saber sus nombres en el momento de
la compilación. Y también hace posible instanciar nuevos objetos, e invocar métodos utilizando la
reflexión.

Observaciones

Actuación
Tenga en cuenta que la reflexión puede disminuir el rendimiento, solo úselo cuando su tarea no
pueda completarse sin reflexión.

Desde el tutorial de Java La API de reflexión :

Debido a que la reflexión involucra tipos que se resuelven dinámicamente, ciertas


optimizaciones de máquinas virtuales Java no se pueden realizar. En consecuencia,
las operaciones de reflexión tienen un rendimiento más lento que sus contrapartes no
reflexivas, y deben evitarse en las secciones de código que se llaman con frecuencia
en aplicaciones sensibles al rendimiento.

Examples
Introducción

Lo esencial

La API de reflexión permite verificar la estructura de clase del código en tiempo de ejecución e
invocar el código dinámicamente. Esto es muy poderoso, pero también es peligroso ya que el
compilador no es capaz de determinar estáticamente si las invocaciones dinámicas son válidas.

Un ejemplo simple sería obtener los constructores públicos y los métodos de una clase
determinada:

import [Link];
import [Link];

// This is a object representing the String class (not an instance of String!)


Class<String> clazz = [Link];

[Link] 49
Constructor<?>[] constructors = [Link](); // returns all public constructors of
String
Method[] methods = [Link](); // returns all public methods from String and parents

Con esta información es posible instanciar el objeto y llamar a diferentes métodos dinámicamente.

Reflexión y tipos genéricos.

La información de tipo genérico está disponible para:

• Parámetros del método, utilizando getGenericParameterTypes() .


• Método devuelve los tipos, usando getGenericReturnType() .
• Campos públicos , utilizando getGenericType .

El siguiente ejemplo muestra cómo extraer la información de tipo genérico en los tres casos:

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class GenericTest {

public static void main(final String[] args) throws Exception {


final Method method = [Link]("testMethod", [Link]);
final Field field = [Link]("testField");

[Link]("Method parameter:");
final Type parameterType = [Link]()[0];
displayGenericType(parameterType, "\t");

[Link]("Method return type:");


final Type returnType = [Link]();
displayGenericType(returnType, "\t");

[Link]("Field type:");
final Type fieldType = [Link]();
displayGenericType(fieldType, "\t");

private static void displayGenericType(final Type type, final String prefix) {


[Link](prefix + [Link]());
if (type instanceof ParameterizedType) {
for (final Type subtype : ((ParameterizedType) type).getActualTypeArguments()) {
displayGenericType(subtype, prefix + "\t");
}
}

public Map<String, Map<Integer, List<String>>> testField;

public List<Number> testMethod(final Map<String, Double> arg) {


return null;
}

[Link] 50
}

Esto resulta en el siguiente resultado:

Method parameter:
[Link]<[Link], [Link]>
[Link]
[Link]
Method return type:
[Link]<[Link]>
[Link]
Field type:
[Link]<[Link], [Link]<[Link],
[Link]<[Link]>>>
[Link]
[Link]<[Link], [Link]<[Link]>>
[Link]
[Link]<[Link]>
[Link]

Invocando un método

Usando la reflexión, se puede invocar un método de un objeto durante el tiempo de ejecución.

El ejemplo muestra cómo invocar los métodos de un objeto String .

import [Link];
import [Link];

String s = "Hello World!";

// method without parameters


// invoke [Link]()
Method method1 = [Link]("length");
int length = (int) [Link](s); // variable length contains "12"

// method with parameters


// invoke [Link](6)
Method method2 = [Link]("substring", [Link]);
String substring = (String) [Link](s, 6); // variable substring contains "World!"

Obtención y configuración de campos

Usando la API de Reflection, es posible cambiar u obtener el valor de un campo en tiempo de


ejecución. Por ejemplo, podría usarlo en una API para recuperar diferentes campos según un
factor, como el sistema operativo. También puede eliminar modificadores como final para
permitir que los campos de modificación sean finales.

Para hacerlo, deberá usar el método Clase # getField () de una manera como la que se muestra a
continuación:

// Get the field in class SomeClass "NAME".

[Link] 51
Field nameField = [Link]("NAME");

// Get the field in class Field "modifiers". Note that it does not
// need to be static
Field modifiersField = [Link]("modifiers");

// Allow access from anyone even if it's declared private


[Link](true);

// Get the modifiers on the "NAME" field as an int.


int existingModifiersOnNameField = [Link]();

// Bitwise AND NOT [Link] (16) on the existing modifiers


// Readup here [Link]
// if you're unsure what bitwise operations are.
int newModifiersOnNameField = existingModifiersOnNameField & ~[Link];

// Set the value of the modifiers field under an object for non-static fields
[Link](nameField, newModifiersOnNameField);

// Set it to be accessible. This overrides normal Java


// private/protected/package/etc access control checks.
[Link](true);

// Set the value of "NAME" here. Note the null argument.


// Pass null when modifying static fields, as there is no instance object
[Link](null, "Hacked by reflection...");

// Here I can directly access it. If needed, use reflection to get it. (Below)
[Link]([Link]);

Obtener campos es mucho más fácil. Podemos usar Field # get () y sus variantes para obtener su
valor:

// Get the field in class SomeClass "NAME".


Field nameField = [Link]("NAME");

// Set accessible for private fields


[Link](true);

// Pass null as there is no instance, remember?


String name = (String) [Link](null);

Tenga en cuenta esto:

Cuando use Class # getDeclaredField , utilícelo para obtener un campo en la clase en sí:

class HackMe extends Hacked {


public String iAmDeclared;
}

class Hacked {
public String someState;
}

Aquí, HackMe#iAmDeclared es campo declarado. Sin embargo, HackMe#someState no es un campo


declarado, ya que se hereda de su superclase, hackeado.

[Link] 52
Constructor de llamadas

Obtención del objeto constructor


Puedes obtener la clase Constructor del objeto Class esta manera:

Class myClass = ... // get a class object


Constructor[] constructors = [Link]();

Donde la variable de constructors tendrá una instancia de Constructor para cada constructor
público declarado en la clase.

Si conoce los tipos de parámetros precisos del constructor al que desea acceder, puede filtrar el
constructor específico. El siguiente ejemplo devuelve el constructor público de la clase dada que
toma un Integer como parámetro:

Class myClass = ... // get a class object


Constructor constructor = [Link](new Class[]{[Link]});

Si ningún constructor coincide con los argumentos de constructor NoSuchMethodException se lanza


una NoSuchMethodException .

Nueva Instancia usando Objeto Constructor

Class myClass = [Link] // get a class object


Constructor constructor = [Link]([Link]);
MyObj myObj = (MyObj) [Link]([Link](123));

Obteniendo las constantes de una enumeración

Dando esta enumeración como ejemplo:

enum Compass {
NORTH(0),
EAST(90),
SOUTH(180),
WEST(270);
private int degree;
Compass(int deg){
degree = deg;
}
public int getDegree(){
return degree;
}
}

En Java, una clase de enumeración es como cualquier otra clase, pero tiene algunas constantes
definidas para los valores de enumeración. Además, tiene un campo que es una matriz que
contiene todos los valores y dos métodos estáticos con values() nombre values() y

[Link] 53
.
valueOf(String)
Podemos ver esto si usamos Reflection para imprimir todos los campos de esta clase

for(Field f : [Link]())
[Link]([Link]());

La salida será:

NORTE
ESTE
SUR
OESTE
la licenciatura
ENUM $ VALORES

Así que podríamos examinar clases de enumeración con Reflexión como cualquier otra clase.
Pero la API de Reflection ofrece tres métodos específicos de enumeración.

control de enumeración

[Link]();

Devuelve true para las clases que representan un tipo de enumeración.

recuperando valores

Object[] values = [Link]();

Devuelve una matriz de todos los valores de enumeración como [Link] () pero sin la
necesidad de una instancia.

enumeración constante

for(Field f : [Link]()){
if([Link]())
[Link]([Link]());
}

Enumera todos los campos de clase que son valores de enumeración.

Obtener clase dado su nombre (totalmente calificado)

Dada una String contiene el nombre de una clase, se puede acceder a su objeto de Class usando
[Link] :

Class clazz = null;


try {
clazz = [Link]("[Link]");
} catch (ClassNotFoundException ex) {

[Link] 54
throw new IllegalStateException(ex);
}

Java SE 1.2

Puede especificarse, si la clase debería inicializarse (segundo parámetro de forName ) y qué


ClassLoader debería usarse (tercer parámetro):

ClassLoader classLoader = ...


boolean initialize = ...
Class clazz = null;
try {
clazz = [Link]("[Link]", initialize, classLoader);
} catch (ClassNotFoundException ex) {
throw new IllegalStateException(ex);
}

Llamar a los constructores sobrecargados utilizando la reflexión.

Ejemplo: invocar diferentes constructores pasando parámetros relevantes

import [Link].*;

class NewInstanceWithReflection{
public NewInstanceWithReflection(){
[Link]("Default constructor");
}
public NewInstanceWithReflection( String a){
[Link]("Constructor :String => "+a);
}
public static void main(String args[]) throws Exception {

NewInstanceWithReflection object =
(NewInstanceWithReflection)[Link]("NewInstanceWithReflection").newInstance();
Constructor constructor = [Link]( new
Class[] {[Link]});
NewInstanceWithReflection object1 =
(NewInstanceWithReflection)[Link](new Object[]{"StackOverFlow"});

}
}

salida:

Default constructor
Constructor :String => StackOverFlow

Explicación:

1. Crear instancia de clase usando [Link] : llama al constructor predeterminado


2. Invoque getDeclaredConstructor de la clase pasando tipos de parámetros como Class array
3. Después de obtener el constructor, cree newInstance pasando un valor de parámetro como
Object array

[Link] 55
Uso incorrecto de la API de Reflection para cambiar variables privadas y
finales

La reflexión es útil cuando se usa correctamente para el propósito correcto. Al utilizar la reflexión,
puede acceder a las variables privadas y reinicializar las variables finales.

A continuación se muestra el fragmento de código, que no se recomienda.

import [Link].*;

public class ReflectionDemo{


public static void main(String args[]){
try{
Field[] fields = [Link]();
A a = new A();
for ( Field field:fields ) {
if([Link]().equalsIgnoreCase("name")){
[Link](true);
[Link](a, "StackOverFlow");
[Link]("[Link]="+[Link](a));
}
if([Link]().equalsIgnoreCase("age")){
[Link](a, 20);
[Link]("[Link]="+[Link](a));
}
if([Link]().equalsIgnoreCase("rep")){
[Link](true);
[Link](a,"New Reputation");
[Link]("[Link]="+[Link](a));
}
if([Link]().equalsIgnoreCase("count")){
[Link](a,25);
[Link]("[Link]="+[Link](a));
}
}
}catch(Exception err){
[Link]();
}
}
}

class A {
private String name;
public int age;
public final String rep;
public static int count=0;

public A(){
name = "Unset";
age = 0;
rep = "Reputation";
count++;
}
}

Salida:

[Link] 56
[Link]=StackOverFlow
[Link]=20
[Link]=New Reputation
[Link]=25

Explicación:

En el escenario normal, no se puede acceder a private variables private fuera de la clase


declarada (sin los métodos get y set). final variables final no pueden ser reasignadas después
de la inicialización.

rompe ambas barreras se puede utilizar para cambiar las variables privadas y finales
Reflection
como se explicó anteriormente.

[Link](true) es la clave para lograr la funcionalidad deseada.

Call constructor de clase anidada

Si desea crear una instancia de una clase anidada interna, debe proporcionar un objeto de clase
de la clase envolvente como un parámetro adicional con la Clase # getDeclaredConstructor .

public class Enclosing{


public class Nested{
public Nested(String a){
[Link]("Constructor :String => "+a);
}
}
public static void main(String args[]) throws Exception {
Class<?> clazzEnclosing = [Link]("Enclosing");
Class<?> clazzNested = [Link]("Enclosing$Nested");
Enclosing objEnclosing = (Enclosing)[Link]();
Constructor<?> constructor = [Link](new
Class[]{[Link], [Link]});
Nested objInner = (Nested)[Link](new Object[]{objEnclosing,
"StackOverFlow"});
}
}

Si la clase anidada es estática, no necesitará esta instancia adjunta.

Proxies dinámicos

Los proxies dinámicos realmente no tienen mucho que ver con Reflection, pero son parte de la
API. Es básicamente una forma de crear una implementación dinámica de una interfaz. Esto
podría ser útil al crear servicios de maqueta.
Un proxy dinámico es una instancia de una interfaz que se crea con el llamado controlador de
invocación que intercepta todas las llamadas de método y permite el manejo de su invocación
manualmente.

public class DynamicProxyTest {

public interface MyInterface1{

[Link] 57
public void someMethod1();
public int someMethod2(String s);
}

public interface MyInterface2{


public void anotherMethod();
}

public static void main(String args[]) throws Exception {


// the dynamic proxy class
Class<?> proxyClass = [Link](
[Link](),
new Class[] {[Link], [Link]});
// the dynamic proxy class constructor
Constructor<?> proxyConstructor =
[Link]([Link]);

// the invocation handler


InvocationHandler handler = new InvocationHandler(){
// this method is invoked for every proxy method call
// method is the invoked method, args holds the method parameters
// it must return the method result
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String methodName = [Link]();

if([Link]("someMethod1")){
[Link]("someMethod1 was invoked!");
return null;
}
if([Link]("someMethod2")){
[Link]("someMethod2 was invoked!");
[Link]("Parameter: " + args[0]);
return 42;
}
if([Link]("anotherMethod")){
[Link]("anotherMethod was invoked!");
return null;
}
[Link]("Unkown method!");
return null;
}
};

// create the dynamic proxy instances


MyInterface1 i1 = (MyInterface1) [Link](handler);
MyInterface2 i2 = (MyInterface2) [Link](handler);

// and invoke some methods


i1.someMethod1();
i1.someMethod2("stackoverflow");
[Link]();
}
}

El resultado de este código es este:

someMethod1 was invoked!


someMethod2 was invoked!

[Link] 58
Parameter: stackoverflow
anotherMethod was invoked!

Evil hacks de Java con Reflection

La API de Reflection podría usarse para cambiar los valores de los campos privados y finales
incluso en la biblioteca predeterminada de JDK. Esto podría usarse para manipular el
comportamiento de algunas clases bien conocidas como veremos.

Lo que no es posible

Comencemos primero con la única limitación significa que el único campo que no podemos
cambiar con Reflexión. Ese es el Java SecurityManager . Se declara en [Link] as

private static volatile SecurityManager security = null;

Pero no se incluirá en la clase del sistema si ejecutamos este código

for(Field f : [Link]())
[Link](f);

debe al fieldFilterMap en [Link] que contiene el mapa en sí y el


fieldFilterMap
campo de seguridad en [Link] y los protege contra cualquier acceso con Reflection. Por
eso no pudimos desactivar el SecurityManager .

Cuerdas locas

Cada cadena Java está representada por la JVM como una instancia de la clase de String . Sin
embargo, en algunas situaciones, la JVM ahorra espacio de almacenamiento utilizando la misma
instancia para las cadenas que son. Esto sucede para los literales de cadena, y también para las
cadenas que han sido "internadas" llamando a [Link]() . Entonces, si tiene "hello" en su
código varias veces, siempre será la misma instancia de objeto.

Se supone que las cuerdas son inmutables, pero es posible usar la reflexión "malvada" para
cambiarlas. El siguiente ejemplo muestra cómo podemos cambiar los caracteres en una cadena
reemplazando su campo de value .

public class CrazyStrings {


static {
try {
Field f = [Link]("value");
[Link](true);
[Link]("hello", "you stink!".toCharArray());
} catch (Exception e) {
}
}
public static void main(String args[]) {
[Link]("hello");
}
}

[Link] 59
Así que este código imprimirá "apestas!"

1 = 42

La misma idea podría ser usada con la clase entera.

public class CrazyMath {


static {
try {
Field value = [Link]("value");
[Link](true);
[Link]([Link](1), 42);
} catch (Exception e) {
}
}
public static void main(String args[]) {
[Link]([Link](1));
}
}

Todo es verdad

Y de acuerdo con este post de stackoverflow podemos usar la reflexión para hacer algo realmente
malo.

public class Evil {


static {
try {
Field field = [Link]("FALSE");
[Link](true);
Field modifiersField = [Link]("modifiers");
[Link](true);
[Link](field, [Link]() & ~[Link]);
[Link](null, true);
} catch (Exception e) {
}
}
public static void main(String args[]){
[Link]("Everything is %s", false);
}
}

Tenga en cuenta que lo que estamos haciendo aquí hará que la JVM se comporte de forma
inexplicable. Esto es muy peligroso.

Lea API de reflexión en línea: [Link]

[Link] 60
Capítulo 11: AppDynamics y TIBCO
BusinessWorks Instrumentation para una
fácil integración
Introducción
Como AppDynamics pretende proporcionar una manera de medir el rendimiento de las
aplicaciones, la velocidad de desarrollo, la entrega (implementación) de las aplicaciones es un
factor esencial para que los esfuerzos de DevOps sean un verdadero éxito. La supervisión de una
aplicación TIBCO BW con AppD es generalmente simple y no requiere mucho tiempo, pero
cuando se implementan grandes conjuntos de aplicaciones, la instrumentación rápida es la clave.
Esta guía muestra cómo instrumentar todas sus aplicaciones BW en un solo paso sin modificar
cada aplicación antes de implementar.

Examples
Ejemplo de instrumentación de todas las aplicaciones BW en un solo paso
para Appdynamics

1. Localice y abra su archivo TIBCO BW [Link] tícicamente bajo TIBCO_HOME / bw /


5.12 / bin / [Link] (entorno Linux)

2. Busca la línea que dice:

*** Variables comunes. Modifica estos solo.


***
3. Agregue la siguiente línea justo después de esa sección [Link] =%
[Link]%

4. Vaya al final del archivo y agregue (reemplace? Con sus propios valores según sea
necesario o elimine el indicador que no se aplica): [Link] = -javaagent:
/opt/appd/current/appagent/[Link] - [Link] =? -
[Link] =? -[Link] =? -
[Link] =? -[Link] =% [Link]%
-[Link] =? -[Link] =? -
[Link] =? -[Link] =? -
[Link] =? -[Link] =? -
[Link] =? -[Link] =?

5. Guardar archivo y volver a desplegar. Todas sus aplicaciones ahora deben ser

[Link] 61
instrumentadas automáticamente en el momento del despliegue.

Lea AppDynamics y TIBCO BusinessWorks Instrumentation para una fácil integración en línea:
[Link]
para-una-facil-integracion

[Link] 62
Capítulo 12: Applets
Introducción
Los applets han sido parte de Java desde su lanzamiento oficial y se han utilizado para enseñar
Java y programación durante varios años.

Los últimos años han visto un impulso activo para alejarse de los applets y otros complementos
del navegador, con algunos navegadores que los bloquean o no los apoyan activamente.

En 2016, Oracle anunció sus planes de dejar de usar el complemento, pasando a una web sin
complementos

Ya están disponibles las API más nuevas y mejores

Observaciones
Un applet es una aplicación Java que normalmente se ejecuta dentro de un navegador web. La
idea básica es interactuar con el usuario sin la necesidad de interactuar con el servidor y transferir
información. Este concepto fue muy exitoso alrededor del año 2000 cuando la comunicación por
Internet era lenta y costosa.

Un applet ofrece cinco métodos para controlar su ciclo de vida.

nombre del
descripción
método

init() se llama una vez cuando se carga el applet

destroy() se llama una vez cuando el applet se elimina de la memoria

start() se llama cada vez que el applet se hace visible

stop() se llama cada vez que el applet se superpone con otras ventanas

paint() se llama cuando es necesario o se activa manualmente llamando a


repaint()

Examples
Applet mínimo

Un applet muy simple dibuja un rectángulo e imprime una cadena en la pantalla.

public class MyApplet extends JApplet{

[Link] 63
private String str = "StackOverflow";

@Override
public void init() {
setBackground([Link]);
}
@Override
public void destroy() {}
@Override
public void start() {}
@Override
public void stop() {}
@Override
public void paint(Graphics g) {
[Link]([Link]);
[Link](1,1,300,150);
[Link]([Link]);
[Link](new Font("TimesRoman", [Link], 48));
[Link](str, 10, 80);
}
}

La clase principal de un applet se extiende desde [Link] .

Java SE 1.2

Antes de Java 1.2 y la introducción de los applets de API swing se extendió desde
[Link] .

Los applets no requieren un método principal. El punto de entrada está controlado por el ciclo de
vida. Para usarlos, necesitan estar incrustados en un documento HTML. Este es también el punto
donde se define su tamaño.

<html>
<head></head>
<body>
<applet code="[Link]" width="400" height="200"></applet>
</body>
</html>

Creando una GUI

Los applets podrían usarse fácilmente para crear una GUI. Actúan como un Container y tienen un
método add() que toma cualquier componente awt o swing .

public class MyGUIApplet extends JApplet{

private JPanel panel;


private JButton button;
private JComboBox<String> cmbBox;
private JTextField textField;

@Override
public void init(){

[Link] 64
panel = new JPanel();
button = new JButton("ClickMe!");
[Link](new ActionListener(){
@Override
public void actionPerformed(ActionEvent ae) {
if(((String)[Link]()).equals("greet")) {
[Link](null,"Hello " + [Link]());
} else {
[Link](null,[Link]() + " stinks!");
}
}
});
cmbBox = new JComboBox<>(new String[]{"greet", "offend"});
textField = new JTextField("John Doe");
[Link](cmbBox);
[Link](textField);
[Link](button);
add(panel);
}
}

Abrir enlaces desde dentro del applet

Puede usar el método getAppletContext() para obtener un objeto AppletContext que le permite
solicitar al navegador que abra un enlace. Para ello utiliza el método showDocument() . Su segundo
parámetro le dice al navegador que use una nueva ventana _blank o la que muestra el applet
_self .

public class MyLinkApplet extends JApplet{


@Override
public void init(){
JButton button = new JButton("ClickMe!");
[Link](new ActionListener(){
@Override
public void actionPerformed(ActionEvent ae) {
AppletContext a = getAppletContext();
try {
URL url = new URL("[Link]
[Link](url,"_blank");
} catch (Exception e) { /* omitted for brevity */ }
}
});
add(button);
}
}

Cargando imágenes, audio y otros recursos.

Los applets de Java son capaces de cargar diferentes recursos. Pero como se ejecutan en el
navegador web del cliente, debe asegurarse de que estos recursos sean accesibles. Los applets
no pueden acceder a los recursos del cliente como el sistema de archivos local.

Si desea cargar recursos desde la misma URL en la que está almacenado el Applet, puede usar
el método getCodeBase() para recuperar la URL base. Para cargar recursos, los applets ofrecen los
métodos getImage() y getAudioClip() para cargar imágenes o archivos de audio.

[Link] 65
Cargar y mostrar una imagen.

public class MyImgApplet extends JApplet{

private Image img;

@Override
public void init(){
try {
img = getImage(new URL("[Link]
[Link]"));
} catch (MalformedURLException e) { /* omitted for brevity */ }
}
@Override
public void paint(Graphics g) {
[Link](img, 0, 0, this);
}
}

Cargar y reproducir un archivo de audio.

public class MyAudioApplet extends JApplet{

private AudioClip audioClip;

@Override
public void init(){
try {
audioClip = getAudioClip(new URL("URL/TO/AN/AUDIO/[Link]"));
} catch (MalformedURLException e) { /* omitted for brevity */ }
}
@Override
public void start() {
[Link]();
}
@Override
public void stop(){
[Link]();
}
}

Cargar y mostrar un archivo de texto

public class MyTextApplet extends JApplet{


@Override
public void init(){
JTextArea textArea = new JTextArea();
JScrollPane sp = new JScrollPane(textArea);

[Link] 66
add(sp);
// load text
try {
URL url = new URL("[Link]
InputStream in = [Link]();
BufferedReader bf = new BufferedReader(new InputStreamReader(in));
String line = "";
while((line = [Link]()) != null) {
[Link](line + "\n");
}
} catch(Exception e) { /* omitted for brevity */ }
}
}

Lea Applets en línea: [Link]

[Link] 67
Capítulo 13: Archivo I / O
Introducción
La E / S de Java (entrada y salida) se utiliza para procesar la entrada y producir la salida. Java
utiliza el concepto de flujo para agilizar la operación de E / S. El paquete [Link] contiene todas las
clases necesarias para las operaciones de entrada y salida. El manejo de archivos también se
realiza en java mediante la API de E / S de Java.

Examples
Leyendo todos los bytes a un byte []

Java 7 introdujo la clase de archivos muy útil

Java SE 7

import [Link];
import [Link];
import [Link];

Path path = [Link]("path/to/file");

try {
byte[] data = [Link](path);
} catch(IOException e) {
[Link]();
}

Leyendo una imagen de un archivo.

import [Link];
import [Link];

...

try {
Image img = [Link](new File("~/Desktop/[Link]"));
} catch (IOException e) {
[Link]();
}

Escribir un byte [] a un archivo

Java SE 7

byte[] bytes = { 0x48, 0x65, 0x6c, 0x6c, 0x6f };

try(FileOutputStream stream = new FileOutputStream("Hello [Link]")) {


[Link](bytes);

[Link] 68
} catch (IOException ioe) {
// Handle I/O Exception
[Link]();
}

Java SE 7

byte[] bytes = { 0x48, 0x65, 0x6c, 0x6c, 0x6f };

FileOutputStream stream = null;


try {
stream = new FileOutputStream("Hello [Link]");
[Link](bytes);
} catch (IOException ioe) {
// Handle I/O Exception
[Link]();
} finally {
if (stream != null) {
try {
[Link]();
} catch (IOException ignored) {}
}
}

La mayoría de las API de archivos [Link] aceptan tanto String como File como argumentos, por
lo que también podría usar

File file = new File("Hello [Link]");


FileOutputStream stream = new FileOutputStream(file);

Stream vs Writer / Reader API

Los flujos proporcionan el acceso más directo al contenido binario, por lo que cualquier
implementación de InputStream / OutputStream siempre opera en int s y byte s.

// Read a single byte from the stream


int b = [Link]();
if (b >= 0) { // A negative value represents the end of the stream, normal values are in the
range 0 - 255
// Write the byte to another stream
[Link](b);
}

// Read a chunk
byte[] data = new byte[1024];
int nBytesRead = [Link](data);
if (nBytesRead >= 0) { // A negative value represents end of stream
// Write the chunk to another stream
[Link](data, 0, nBytesRead);
}

Hay algunas excepciones, probablemente la más notable, PrintStream que agrega la "capacidad
de imprimir representaciones de varios valores de datos de manera conveniente". Esto permite
utilizar [Link] como InputStream binario y como salida textual utilizando métodos como
[Link]() .

[Link] 69
Además, algunas implementaciones de flujo funcionan como una interfaz para contenidos de alto
nivel, como objetos Java (consulte Serialización) o tipos nativos, por ejemplo, DataOutputStream /
DataInputStream .

Con las clases Writer y Reader , Java también proporciona una API para flujos de caracteres
explícitos. Aunque la mayoría de las aplicaciones basarán estas implementaciones en flujos, la
API de flujo de caracteres no expone ningún método para contenido binario.

// This example uses the platform's default charset, see below


// for a better implementation.

Writer writer = new OutputStreamWriter([Link]);


[Link]("Hello world!");

Reader reader = new InputStreamReader([Link]);


char singleCharacter = [Link]();

Siempre que sea necesario codificar caracteres en datos binarios (por ejemplo, al usar las clases
InputStreamWriter / OutputStreamWriter ), debe especificar un conjunto de caracteres si no desea
depender del conjunto de caracteres predeterminado de la plataforma. En caso de duda, utilice
una codificación compatible con Unicode, por ejemplo, UTF-8 que sea compatible con todas las
plataformas Java. Por lo tanto, probablemente debería alejarse de clases como FileWriter y
FileReader ya que siempre usan el conjunto de caracteres predeterminado de la plataforma. Una
mejor manera de acceder a los archivos utilizando secuencias de caracteres es esta:

Charset myCharset = StandardCharsets.UTF_8;

Writer writer = new OutputStreamWriter( new FileOutputStream("[Link]"), myCharset );


[Link]('Ä');
[Link]();
[Link]();

Reader reader = new InputStreamReader( new FileInputStream("[Link]"), myCharset );


char someUnicodeCharacter = [Link]();
[Link]();

Uno de los Reader s más utilizados es BufferedReader que proporciona un método para leer líneas
enteras de texto de otro lector y es probablemente la forma más sencilla de leer una línea de
caracteres en línea de secuencia:

// Read from baseReader, one line at a time


BufferedReader reader = new BufferedReader( baseReader );
String line;
while((line = [Link]()) != null) {
// Remember: [Link] is a stream, not a writer!
[Link](line);
}

Leyendo un archivo completo a la vez

File f = new File(path);


String content = new Scanner(f).useDelimiter("\\Z").next();

[Link] 70
\ Z es el símbolo EOF (fin de archivo). Cuando se establece como delimitador, el Escáner leerá el
relleno hasta que se alcance el indicador EOF.

Leyendo un archivo con un escáner

Leyendo un archivo línea por línea

public class Main {

public static void main(String[] args) {


try {
Scanner scanner = new Scanner(new File("[Link]"));
while([Link]())
{
String line = [Link]();
//do stuff
}
} catch (FileNotFoundException e) {
[Link]();
}
}
}

palabra por palabra

public class Main {

public static void main(String[] args) {


try {
Scanner scanner = new Scanner(new File("[Link]"));
while([Link]())
{
String line = [Link]();
//do stuff
}
} catch (FileNotFoundException e) {
[Link]();
}
}
}

y también puede cambiar el delimitador utilizando el método [Link] ()

Iterando sobre un directorio y filtrando por extensión de archivo

public void iterateAndFilter() throws IOException {


Path dir = [Link]("C:/foo/bar");
PathMatcher imageFileMatcher =
[Link]().getPathMatcher(
"regex:.*(?i:jpg|jpeg|png|gif|bmp|jpe|jfif)");

try (DirectoryStream<Path> stream = [Link](dir,


entry -> [Link]([Link]()))) {

for (Path path : stream) {


[Link]([Link]());

[Link] 71
}
}
}

Migración de [Link] a Java 7 NIO ([Link])

Estos ejemplos asumen que ya sabes lo que es NIO de Java 7 en general, y estás acostumbrado
a escribir código usando [Link] . Utilice estos ejemplos como un medio para encontrar
rápidamente más documentación centrada en NIO para la migración.

Hay mucho más en el NIO de Java 7, como los archivos asignados en memoria o la apertura de
un archivo ZIP o JAR utilizando FileSystem . Estos ejemplos solo cubrirán un número limitado de
casos de uso básicos.

Como regla básica, si está acostumbrado a realizar una operación de lectura / escritura del
sistema de archivos utilizando un método de instancia [Link] , lo encontrará como un
método estático dentro de [Link] .

Apuntar a un camino
// -> IO
File file = new File("[Link]");

// -> NIO
Path path = [Link]("[Link]");

Caminos relativos a otro camino.


// Forward slashes can be used in place of backslashes even on a Windows operating system
// -> IO
File folder = new File("C:/");
File fileInFolder = new File(folder, "[Link]");

// -> NIO
Path directory = [Link]("C:/");
Path pathInDirectory = [Link]("[Link]");

Convertir archivo de / a ruta para usar con


bibliotecas
// -> IO to NIO
Path pathFromFile = new File("[Link]").toPath();

// -> NIO to IO
File fileFromPath = [Link]("[Link]").toFile();

[Link] 72
Compruebe si el archivo existe y elimínelo si
existe.
// -> IO
if ([Link]()) {
boolean deleted = [Link]();
if (!deleted) {
throw new IOException("Unable to delete file");
}
}

// -> NIO
[Link](path);

Escribir en un archivo a través de un


OutputStream
Hay varias formas de escribir y leer desde un archivo utilizando NIO para diferentes limitaciones
de rendimiento y memoria, legibilidad y casos de uso, como FileChannel , [Link](Path path,
byte\[\] bytes, OpenOption... options) . .. En este ejemplo, solo se cubre OutputStream , pero se
recomienda encarecidamente que conozca los archivos asignados en memoria y los diversos
métodos estáticos disponibles en [Link] .

List<String> lines = [Link](


[Link]([Link]().getTimeInMillis()),
"line one",
"line two");

// -> IO
if ([Link]()) {
// Note: Not atomic
throw new IOException("File already exists");
}
try (FileOutputStream outputStream = new FileOutputStream(file)) {
for (String line : lines) {
[Link]((line + [Link]()).getBytes(StandardCharsets.UTF_8));
}
}

// -> NIO
try (OutputStream outputStream = [Link](path, StandardOpenOption.CREATE_NEW)) {
for (String line : lines) {
[Link]((line + [Link]()).getBytes(StandardCharsets.UTF_8));
}
}

Iterando en cada archivo dentro de una

[Link] 73
carpeta
// -> IO
for (File selectedFile : [Link]()) {
// Note: Depending on the number of files in the directory [Link]() may take a
long time to return
[Link](([Link]() ? "d" : "f") + " " +
[Link]());
}

// -> NIO
[Link](directory, [Link]([Link]), 1, new
SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path selectedPath, BasicFileAttributes attrs)
throws IOException {
[Link]("d " + [Link]());
return [Link];
}

@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws
IOException {
[Link]("f " + [Link]());
return [Link];
}
});

Iteración de la carpeta recursiva


// -> IO
recurseFolder(folder);

// -> NIO
// Note: Symbolic links are NOT followed unless explicitly passed as an argument to
[Link]
[Link](directory, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws
IOException {
[Link]("d " + [Link]());
return [Link];
}

@Override
public FileVisitResult visitFile(Path selectedPath, BasicFileAttributes attrs) throws
IOException {
[Link]("f " + [Link]());
return [Link];
}
});

private static void recurseFolder(File folder) {


for (File selectedFile : [Link]()) {

[Link] 74
[Link](([Link]() ? "d" : "f") + " " +
[Link]());
if ([Link]()) {
// Note: Symbolic links are followed
recurseFolder(selectedFile);
}
}
}

Lectura / escritura de archivos usando FileInputStream / FileOutputStream

Escribir en un archivo [Link]:

String filepath ="C:\\[Link]";


FileOutputStream fos = null;
try {
fos = new FileOutputStream(filepath);
byte[] buffer = "This will be written in [Link]".getBytes();
[Link](buffer, 0, [Link]);
[Link]();
} catch (FileNotFoundException e) {
[Link]();
} catch (IOException e) {
[Link]();
} finally{
if(fos != null)
[Link]();
}

Leer del archivo [Link]:

String filepath ="C:\\[Link]";


FileInputStream fis = null;
try {
fis = new FileInputStream(filepath);
int length = (int) new File(filepath).length();
byte[] buffer = new byte[length];
[Link](buffer, 0, length);
} catch (FileNotFoundException e) {
[Link]();
} catch (IOException e) {
[Link]();
} finally{
if(fis != null)
[Link]();
}

Tenga en cuenta que desde Java 1.7 se introdujo la declaración try-with-resources lo que hizo
que la implementación de la operación de lectura / escritura sea mucho más sencilla:

Escribir en un archivo [Link]:

String filepath ="C:\\[Link]";


try (FileOutputStream fos = new FileOutputStream(filepath)){
byte[] buffer = "This will be written in [Link]".getBytes();
[Link](buffer, 0, [Link]);

[Link] 75
} catch (FileNotFoundException e) {
[Link]();
} catch (IOException e) {
[Link]();
}

Leer del archivo [Link]:

String filepath ="C:\\[Link]";


try (FileInputStream fis = new FileInputStream(filepath)){
int length = (int) new File(filepath).length();
byte[] buffer = new byte[length];
[Link](buffer, 0, length);
} catch (FileNotFoundException e) {
[Link]();
} catch (IOException e) {
[Link]();
}

Leyendo de un archivo binario

Puede leer un archivo binario utilizando este fragmento de código en todas las versiones
recientes de Java:

Java SE 1.4

File file = new File("path_to_the_file");


byte[] data = new byte[(int) [Link]()];
DataInputStream stream = new DataInputStream(new FileInputStream(file));
[Link](data);
[Link]();

Si está utilizando Java 7 o posterior, hay una forma más sencilla de usar la nio API :

Java SE 7

Path path = [Link]("path_to_the_file");


byte [] data = [Link](path);

Cierre

Un archivo puede ser bloqueado usando la API FileChannel que se puede adquirir de los streams y
readers de Input Input.

Ejemplo con streams

// Abrir una secuencia de archivos FileInputStream ios = new FileInputStream (nombre de


archivo);

// get underlying channel


FileChannel channel = [Link]();

[Link] 76
/*
* try to lock the file. true means whether the lock is shared or not i.e. multiple
processes can acquire a
* shared lock (for reading only) Using false with readable channel only will generate an
exception. You should
* use a writable channel (taken from FileOutputStream) when using false. tryLock will
always return immediately
*/
FileLock lock = [Link](0, Long.MAX_VALUE, true);

if (lock == null) {
[Link]("Unable to acquire lock");
} else {
[Link]("Lock acquired successfully");
}

// you can also use blocking call which will block until a lock is acquired.
[Link]();

// Once you have completed desired operations of file. release the lock
if (lock != null) {
[Link]();
}

// close the file stream afterwards


// Example with reader
RandomAccessFile randomAccessFile = new RandomAccessFile(filename, "rw");
FileChannel channel = [Link]();
//repeat the same steps as above but now you can use shared as true or false as the
channel is in read write mode

Copiando un archivo usando InputStream y OutputStream

Podemos copiar directamente los datos de una fuente a un sumidero de datos utilizando un bucle.
En este ejemplo, estamos leyendo datos de un InputStream y, al mismo tiempo, escribimos en un
OutputStream. Una vez que hayamos terminado de leer y escribir, tenemos que cerrar el recurso.

public void copy(InputStream source, OutputStream destination) throws IOException {


try {
int c;
while ((c = [Link]()) != -1) {
[Link](c);
}
} finally {
if (source != null) {
[Link]();
}
if (destination != null) {
[Link]();
}
}
}

Leyendo un archivo usando Channel y Buffer

utiliza un Buffer para leer / escribir datos. Un búfer es un contenedor de tamaño fijo donde
Channel
podemos escribir un bloque de datos a la vez. Channel es bastante más rápido que la E / S basada

[Link] 77
en flujo.

Para leer los datos de un archivo usando Channel necesitamos los siguientes pasos:

1. Necesitamos una instancia de FileInputStream . FileInputStream tiene un método llamado


getChannel() que devuelve un canal.
2. Llame al método getChannel() de FileInputStream y adquiera Channel.
3. Crear un ByteBuffer. ByteBuffer es un contenedor de tamaño fijo de bytes.
4. El canal tiene un método de lectura y tenemos que proporcionar un ByteBuffer como
argumento para este método de lectura. ByteBuffer tiene dos modos: modo de solo lectura y
modo de solo escritura. Podemos cambiar el modo usando el método de llamada flip() . El
búfer tiene una posición, límite y capacidad. Una vez que se crea un búfer con un tamaño
fijo, su límite y capacidad son los mismos que el tamaño y la posición comienza desde cero.
Mientras se escribe un búfer con datos, su posición aumenta gradualmente. Cambio de
modo significa, cambiando la posición. Para leer datos desde el principio de un búfer,
tenemos que establecer la posición a cero. método flip () cambiar la posición
5. Cuando llamamos al método de lectura del Channel , se llena el búfer usando datos.
6. Si necesitamos leer los datos de ByteBuffer , debemos voltear el búfer para cambiar su
modo de solo escritura al modo de solo lectura y luego seguir leyendo los datos del búfer.
7. Cuando ya no hay datos para leer, el método de read() del canal devuelve 0 o -1.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class FileChannelRead {

public static void main(String[] args) {

File inputFile = new File("[Link]");

if (![Link]()) {
[Link]("The input file doesn't exit.");
return;
}

try {
FileInputStream fis = new FileInputStream(inputFile);
FileChannel fileChannel = [Link]();
ByteBuffer buffer = [Link](1024);

while ([Link](buffer) > 0) {


[Link]();
while ([Link]()) {
byte b = [Link]();
[Link]((char) b);
}
[Link]();
}

[Link]();
} catch (IOException e) {
[Link]();

[Link] 78
}
}
}

Copiando un archivo usando el canal

Podemos usar el Channel para copiar el contenido del archivo más rápido. Para hacerlo, podemos
usar el método transferTo() de FileChannel .

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class FileCopier {

public static void main(String[] args) {


File sourceFile = new File("[Link]");
File sinkFile = new File("[Link]");
copy(sourceFile, sinkFile);
}

public static void copy(File sourceFile, File destFile) {


if (![Link]() || ![Link]()) {
[Link]("Source or destination file doesn't exist");
return;
}

try (FileChannel srcChannel = new FileInputStream(sourceFile).getChannel();


FileChannel sinkChanel = new FileOutputStream(destFile).getChannel()) {

[Link](0, [Link](), sinkChanel);


} catch (IOException e) {
[Link]();
}
}
}

Leyendo un archivo usando BufferedInputStream

La lectura de archivos utilizando un BufferedInputStream generalmente es más rápida que


FileInputStream porque mantiene un búfer interno para almacenar bytes leídos desde la secuencia
de entrada subyacente.

import [Link];
import [Link];
import [Link];

public class FileReadingDemo {

public static void main(String[] args) {


String source = "[Link]";

[Link] 79
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source))) {
byte data;
while ((data = (byte) [Link]()) != -1) {
[Link]((char) data);
}
} catch (IOException e) {
[Link]();
}

}
}

Escribiendo un archivo usando Channel y Buffer

Para escribir datos en un archivo usando Channel necesitamos los siguientes pasos:

1. Primero, necesitamos obtener un objeto de FileOutputStream


2. Adquiera FileChannel llamando al método getChannel() desde FileOutputStream
3. Crea un ByteBuffer y luego llénalo con datos
4. Luego tenemos que llamar al método flip() del ByteBuffer y pasarlo como un argumento del
método write() del FileChannel
5. Una vez que hayamos terminado de escribir, tenemos que cerrar el recurso.

import [Link].*;
import [Link].*;
public class FileChannelWrite {

public static void main(String[] args) {

File outputFile = new File("[Link]");


String text = "I love Bangladesh.";

try {
FileOutputStream fos = new FileOutputStream(outputFile);
FileChannel fileChannel = [Link]();
byte[] bytes = [Link]();
ByteBuffer buffer = [Link](bytes);
[Link](buffer);
[Link]();
} catch ([Link] e) {
[Link]();
}
}
}

Escribiendo un archivo usando PrintStream

Podemos usar la clase PrintStream para escribir un archivo. Tiene varios métodos que le permiten
imprimir cualquier valor de tipo de datos. println() método println() agrega una nueva línea. Una
vez que hayamos terminado de imprimir, tenemos que vaciar el PrintStream .

import [Link];
import [Link];
import [Link];

[Link] 80
public class FileWritingDemo {
public static void main(String[] args) {
String destination = "[Link]";

try(PrintStream ps = new PrintStream(destination)){


[Link]("Stackoverflow documentation seems fun.");
[Link]();
[Link]("I love Java!");
[Link]("Today is: %1$tm/%1$td/%1$tY", [Link]());

[Link]();
} catch (FileNotFoundException e) {
[Link]();
}

}
}

Iterar sobre un directorio de subdirectorios de impresión en él.

public void iterate(final String dirPath) throws IOException {


final DirectoryStream<Path> paths = [Link]([Link](dirPath));
for (final Path path : paths) {
if ([Link](path)) {
[Link]([Link]());
}
}
}

Agregando Directorios

Para crear un nuevo directorio a partir de una instancia de un File , deberá utilizar uno de los dos
métodos siguientes: mkdirs() o mkdir() .

• mkdir() : crea el directorio nombrado por este nombre de ruta abstracto. ( fuente )
• mkdirs() : crea el directorio nombrado por esta ruta de acceso abstracta, incluidos los
directorios primarios necesarios pero no existentes. Tenga en cuenta que si esta operación
falla, es posible que haya logrado crear algunos de los directorios principales necesarios. (
fuente )

Nota: createNewFile() no creará un nuevo directorio solo un archivo.

File singleDir = new File("C:/Users/SomeUser/Desktop/A New Folder/");

File multiDir = new File("C:/Users/SomeUser/Desktop/A New Folder 2/Another Folder/");

// assume that neither "A New Folder" or "A New Folder 2" exist

[Link](); // will make a new file called "A New [Link]"


[Link](); // will make the directory
[Link](); // will make the directory

[Link](); // will throw a IOException


[Link](); // will not work

[Link] 81
[Link](); // will make the directory

Bloqueo o redireccionamiento de salida / error estándar

A veces, una biblioteca de terceros mal diseñada escribirá diagnósticos no deseados en las
[Link] [Link] o [Link] . Las soluciones recomendadas para esto serían encontrar una
mejor biblioteca o (en el caso de código abierto) solucionar el problema y contribuir con un parche
para los desarrolladores.

Si las soluciones anteriores no son factibles, entonces debería considerar redirigir los flujos.

Redireccionamiento en la línea de comando.

En un sistema UNIX, Linux o MacOSX se puede hacer desde el shell usando > redirección. Por
ejemplo:

$ java -jar [Link] arg1 arg2 > /dev/null 2>&1


$ java -jar [Link] arg1 arg2 > [Link] 2> [Link]

El primero redirige la salida estándar y el error estándar a "/ dev / null", que desecha todo lo
escrito en esas secuencias. El segundo redirige la salida estándar a "[Link]" y el error estándar a
"[Link]".

(Para obtener más información sobre la redirección, consulte la documentación del shell de
comandos que está utilizando. Se aplican consejos similares a Windows).

Alternativamente, puede implementar la redirección en un script de envoltura o un archivo por


lotes que inicie la aplicación Java.

Redirección dentro de una aplicación Java

También es posible redirigir las secuencias dentro de una aplicación Java usando [Link]()
y [Link]() . Por ejemplo, el siguiente fragmento de código redirige la salida estándar y el
error estándar a 2 archivos de registro:

[Link](new PrintStream(new FileOutputStream(new File("[Link]"))));


[Link](new PrintStream(new FileOutputStream(new File("[Link]"))));

Si desea deshacerse de la salida por completo, puede crear una secuencia de salida que
"escribe" en un descriptor de archivo no válido. Esto es funcionalmente equivalente a escribir en "/
dev / null" en UNIX.

[Link](new PrintStream(new FileOutputStream(new FileDescriptor())));


[Link](new PrintStream(new FileOutputStream(new FileDescriptor())));

Precaución: tenga cuidado con el uso de setOut y setErr :

1. La redirección afectará a toda la JVM.


2. Al hacer esto, está quitando la capacidad del usuario para redirigir los flujos desde la línea

[Link] 82
de comandos.

Accediendo a los contenidos de un archivo ZIP.

La API del sistema de archivos de Java 7 permite leer y agregar entradas desde o hacia un
archivo Zip usando la API del archivo NIO de Java de la misma manera que opera en cualquier
otro sistema de archivos.

FileSystem es un recurso que debe cerrarse correctamente después de su uso, por lo tanto, debe
usarse el bloque try-with-resources.

Leyendo de un archivo existente

Path pathToZip = [Link]("path/to/[Link]");


try(FileSystem zipFs = [Link](pathToZip, null)) {
Path root = [Link]("/");
... //access the content of the zip file same as ordinary files
} catch(IOException ex) {
[Link]();
}

Creando un nuevo archivo

Map<String, String> env = new HashMap<>();


[Link]("create", "true"); //required for creating a new zip file
[Link]("encoding", "UTF-8"); //optional: default is UTF-8
URI uri = [Link]("jar:file:/path/to/[Link]");
try (FileSystem zipfs = [Link](uri, env)) {
Path newFile = [Link]("/[Link]");
//writing to file
[Link](newFile, "Hello world".getBytes());
} catch(IOException ex) {
[Link]();
}

Lea Archivo I / O en línea: [Link]

[Link] 83
Capítulo 14: Archivos JAR Multi-Release
Introducción
Una de las características introducidas en Java 9 es el Jar de lanzamiento múltiple (MRJAR), que
permite agrupar código dirigido a múltiples lanzamientos de Java dentro del mismo archivo Jar. La
característica se especifica en JEP 238 .

Examples
Ejemplo de contenido de un archivo Jar multi-release.

Al establecer Multi-Release: true en el archivo [Link], el archivo Jar se convierte en un


Jar multi-release y el tiempo de ejecución de Java (siempre que sea compatible con el formato
MRJAR) seleccionará las versiones apropiadas de las clases dependiendo de la versión principal
actual .

La estructura de dicho Jar es la siguiente:

jar root
- [Link]
- [Link]
- [Link]
- [Link]
- META-INF
- versions
- 9
- [Link]
- [Link]
- 10
- [Link]

• En JDKs <9, solo las clases en la entrada raíz son visibles para el tiempo de ejecución de
Java.
• En un JDK 9, las clases A y B se cargarán desde el directorio root/META-INF/versions/9 ,
mientras que C y D se cargarán desde la entrada base.
• En un JDK 10, la clase A se cargaría desde el directorio root/META-INF/versions/10 .

Creando un Jar multi-release usando la herramienta jar

El comando jar se puede usar para crear un Jar de varias versiones que contiene dos versiones
de la misma clase compilada para Java 8 y Java 9, aunque con una advertencia que indica que
las clases son idénticas:

C:\Users\manouti>jar --create --file [Link] -C sampleproject-base demo --release 9 -C


sampleproject-9 demo
Warning: entry META-INF/versions/9/demo/[Link] contains a class that
is identical to an entry already in the jar

[Link] 84
La opción --release 9 le dice a jar que incluya todo lo que sigue (el paquete de demo dentro del
directorio sampleproject-9 ) dentro de una entrada versionada en MRJAR, es decir, bajo root/META-
INF/versions/9 . El resultado son los siguientes contenidos:

jar root
- demo
- [Link]
- META-INF
- versions
- 9
- demo
- [Link]

Ahora creamos una clase llamada Main que imprime la URL de SampleClass y la agregamos para
la versión Java 9:

package demo;

import [Link];

public class Main {

public static void main(String[] args) throws Exception {


URL url = [Link]().getResource("demo/[Link]");
[Link](url);
}
}

Si compilamos esta clase y volvemos a ejecutar el comando jar, obtenemos un error:

C:\Users\manouti>jar --create --file [Link] -C sampleproject-base demo --release 9 -C


sampleproject-9 demoentry: META-INF/versions/9/demo/[Link], contains a new public class
not found in base entries
Warning: entry META-INF/versions/9/demo/[Link], multiple resources with same name
Warning: entry META-INF/versions/9/demo/[Link] contains a class that
is identical to an entry already in the jar
invalid multi-release jar file [Link] deleted

La razón es que la herramienta jar impide agregar clases públicas a las entradas versionadas si
no se agregan a las entradas base también. Esto se hace para que MRJAR exponga la misma
API pública para las diferentes versiones de Java. Tenga en cuenta que en tiempo de ejecución,
esta regla no es necesaria. Solo se puede aplicar con herramientas como el jar . En este caso
particular, el propósito de Main es ejecutar código de ejemplo, por lo que simplemente podemos
agregar una copia en la entrada base. Si la clase formara parte de una implementación más
nueva que solo necesitamos para Java 9, se podría hacer no pública.

Para agregar Main a la entrada raíz, primero debemos compilarlo para apuntar a una versión
anterior a Java 9. Esto se puede hacer usando la nueva opción --release de javac :

C:\Users\manouti\sampleproject-base\demo>javac --release 8 [Link]


C:\Users\manouti\sampleproject-base\demo>cd ../..
C:\Users\manouti>jar --create --file [Link] -C sampleproject-base demo --release 9 -C
sampleproject-9 demo

[Link] 85
La ejecución de la clase Main muestra que SampleClass se carga desde el directorio versionado:

C:\Users\manouti>java --class-path [Link] [Link]


jar:file:/C:/Users/manouti/[Link]!/META-INF/versions/9/demo/[Link]

URL de una clase cargada dentro de un Jar multi-release

Teniendo en cuenta el siguiente Jar multi-lanzamiento:

jar root
- demo
- [Link]
- META-INF
- versions
- 9
- demo
- [Link]

La siguiente clase imprime la URL de SampleClass :

package demo;

import [Link];

public class Main {

public static void main(String[] args) throws Exception {


URL url = [Link]().getResource("demo/[Link]");
[Link](url);
}
}

Si la clase se compila y se agrega en la entrada versionada para Java 9 en MRJAR, ejecutarla


resultaría en:

C:\Users\manouti>java --class-path [Link] [Link]


jar:file:/C:/Users/manouti/[Link]!/META-INF/versions/9/demo/[Link]

Lea Archivos JAR Multi-Release en línea: [Link]


multi-release

[Link] 86
Capítulo 15: Arrays
Introducción
Las matrices permiten el almacenamiento y la recuperación de una cantidad arbitraria de valores.
Son análogos a los vectores en matemáticas. Las matrices de matrices son análogas a las
matrices y actúan como matrices multidimensionales. Las matrices pueden almacenar cualquier
tipo de datos: primitivas como int o tipos de referencia como Object .

Sintaxis
• ArrayType[] myArray; // Declarando matrices
• ArrayType myArray[]; // Otra sintaxis válida (menos utilizada y desaconsejada)
• ArrayType[][][] myArray; // Declaración de matrices irregulares multidimensionales
(repetición [] s)
• ArrayType myVar = myArray[index]; // Elemento de acceso (lectura) en el índice
• myArray[index] = value; // Asignar valor al index de posición de la matriz
• ArrayType[] myArray = new ArrayType[arrayLength]; // Sintaxis de inicialización de matriz
• int[] ints = {1, 2, 3}; // Sintaxis de inicialización de la matriz con los valores
proporcionados, la longitud se deduce del número de valores proporcionados: {[valor1 [,
valor2] *]}
• new int[]{4, -5, 6} // Can be used as argument, without a local variable
• int[] ints = new int[3]; // same as {0, 0, 0}
• int[][] ints = {{1, 2}, {3}, null}; // Inicialización de matriz multidimensional. int []
extiende Object (y también lo hace anyType []), por lo que null es un valor válido.

Parámetros

Parámetro Detalles

Tipo de la matriz. Puede ser primitivo ( int , long , byte ) u Objetos ( String ,
ArrayType
MyObject , etc.).

índice El índice se refiere a la posición de un determinado objeto en una matriz.

Cada matriz, cuando se crea, necesita una longitud determinada especificada.


longitud Esto se hace al crear una matriz vacía ( new int[3] ) o implícito al especificar
valores ( {1, 2, 3} ).

Examples
Creación e inicialización de matrices

[Link] 87
Casos basicos
int[] numbers1 = new int[3]; // Array for 3 int values, default value is 0
int[] numbers2 = { 1, 2, 3 }; // Array literal of 3 int values
int[] numbers3 = new int[] { 1, 2, 3 }; // Array of 3 int values initialized
int[][] numbers4 = { { 1, 2 }, { 3, 4, 5 } }; // Jagged array literal
int[][] numbers5 = new int[5][]; // Jagged array, one dimension 5 long
int[][] numbers6 = new int[5][4]; // Multidimensional array: 5x4

Las matrices se pueden crear utilizando cualquier tipo de referencia o primitivo.

float[] boats = new float[5]; // Array of five 32-bit floating point numbers.
double[] header = new double[] { 4.56, 332.267, 7.0, 0.3367, 10.0 };
// Array of five 64-bit floating point numbers.
String[] theory = new String[] { "a", "b", "c" };
// Array of three strings (reference type).
Object[] dArt = new Object[] { new Object(), "We love Stack Overflow.", new Integer(3) };
// Array of three Objects (reference type).

Para el último ejemplo, tenga en cuenta que los subtipos del tipo de matriz declarada están
permitidos en la matriz.

Las matrices para tipos definidos por el usuario también pueden construirse de manera similar a
los tipos primitivos

UserDefinedClass[] udType = new UserDefinedClass[5];

Arrays, colecciones y corrientes


Java SE 1.2

// Parameters require objects, not primitives

// Auto-boxing happening for int 127 here


Integer[] initial = { 127, [Link]( 42 ) };
List<Integer> toList = [Link]( initial ); // Fixed size!

// Note: Works with all collections


Integer[] fromCollection = [Link]( new Integer[[Link]()] );

//Java doesn't allow you to create an array of a parameterized type


List<String>[] list = new ArrayList<String>[2]; // Compilation error!

Java SE 8

// Streams - JDK 8+
Stream<Integer> toStream = [Link]( initial );
Integer[] fromStream = [Link]( Integer[]::new );

[Link] 88
Introducción
Una matriz es una estructura de datos que contiene un número fijo de valores primitivos o
referencias a instancias de objetos.

Cada elemento de una matriz se denomina elemento, y se accede a cada elemento por su índice
numérico. La longitud de una matriz se establece cuando se crea la matriz:

int size = 42;


int[] array = new int[size];

El tamaño de una matriz se fija en el tiempo de ejecución cuando se inicializa. No se puede


cambiar después de la inicialización. Si el tamaño debe ser mutable en el tiempo de ejecución, se
debe usar una clase de Collection como ArrayList su lugar. ArrayList almacena elementos en una
matriz y admite el cambio de tamaño asignando una nueva matriz y copiando elementos de la
matriz antigua.

Si la matriz es de un tipo primitivo, es decir

int[] array1 = { 1,2,3 };


int[] array2 = new int[10];

Los valores se almacenan en la propia matriz. En ausencia de un inicializador (como en la array2


anterior), el valor predeterminado asignado a cada elemento es 0 (cero).

Si el tipo de matriz es una referencia de objeto, como en

SomeClassOrInterface[] array = new SomeClassOrInterface[10];

entonces la matriz contiene referencias a objetos de tipo SomeClassOrInterface . Esas referencias


pueden referirse a una instancia de SomeClassOrInterface o cualquier subclase (para clases) o
clase de implementación (para interfaces) de SomeClassOrInterface . Si la declaración de la matriz
no tiene inicializador, el valor predeterminado de null se asigna a cada elemento.

Debido a que todas las matrices están int indexadas, el tamaño de una matriz debe ser
especificado por una int . El tamaño de la matriz no se puede especificar como un long :

long size = 23L;


int[] array = new int[size]; // Compile-time error:
// incompatible types: possible lossy conversion from
// long to int

Las matrices utilizan un sistema de índice de base cero , lo que significa que la indexación
comienza en 0 y termina en length - 1 .

Por ejemplo, la siguiente imagen representa una matriz con tamaño 10 . Aquí, el primer elemento
está en el índice 0 y el último elemento está en el índice 9 , en lugar de que el primer elemento
esté en el índice 1 y el último elemento en el índice 10 (consulte la figura a continuación).

[Link] 89
Los accesos a elementos de matrices se realizan en tiempo constante . Eso significa que
acceder al primer elemento de la matriz tiene el mismo costo (en el tiempo) de acceder al
segundo elemento, al tercer elemento y así sucesivamente.

Java ofrece varias formas de definir e inicializar matrices, incluidas las notaciones literales y de
constructor . Al declarar matrices utilizando el new Type[length] constructor new Type[length] ,
cada elemento se inicializará con los siguientes valores predeterminados:

• 0 para tipos numéricos primitivos : byte , short , int , long , float y double .
• '\u0000' (carácter nulo) para el tipo char .
• false para el tipo boolean .
• null para los tipos de referencia .

Creación e inicialización de matrices de tipos


primitivos.
int[] array1 = new int[] { 1, 2, 3 }; // Create an array with new operator and
// array initializer.
int[] array2 = { 1, 2, 3 }; // Shortcut syntax with array initializer.
int[] array3 = new int[3]; // Equivalent to { 0, 0, 0 }
int[] array4 = null; // The array itself is an object, so it
// can be set as null.

Al declarar una matriz, [] aparecerá como parte del tipo al comienzo de la declaración (después
del nombre del tipo), o como parte del declarador para una variable en particular (después del
nombre de la variable), o ambos:

int array5[]; /*
equivalent to */ int[] array5;
int a, b[], c[][]; /*
equivalent to */ int a; int[] b; int[][] c;
int[] a, b[]; /*
equivalent to */ int[] a; int[][] b;
int a, []b, c[][]; /*
Compilation Error, because [] is not part of the type at beginning
of the declaration, rather it is before 'b'. */
// The same rules apply when declaring a method that returns an array:
int foo()[] { ... } /* equivalent to */ int[] foo() { ... }

En el siguiente ejemplo, ambas declaraciones son correctas y pueden compilarse y ejecutarse sin
ningún problema. Sin embargo, tanto la Convención de codificación de Java como la Guía de
estilo de Google Java desalientan el formulario entre corchetes después del nombre de la
variable: los corchetes identifican el tipo de matriz y deben aparecer con la designación de tipo .
Lo mismo se debe utilizar para las firmas de retorno de método.

[Link] 90
float array[]; /* and */ int foo()[] { ... } /* are discouraged */
float[] array; /* and */ int[] foo() { ... } /* are encouraged */

El tipo desalentado está pensado para adaptarse a los usuarios de C en transición , que están
familiarizados con la sintaxis de C que tiene los corchetes después del nombre de la variable.

En Java, es posible tener matrices de tamaño 0 :

int[] array = new int[0]; // Compiles and runs fine.


int[] array2 = {}; // Equivalent syntax.

Sin embargo, como se trata de una matriz vacía, no se pueden leer ni asignar elementos de ella:

array[0] = 1; // Throws [Link].


int i = array2[0]; // Also throws ArrayIndexOutOfBoundsException.

Estas matrices vacías suelen ser útiles como valores de retorno, por lo que el código de llamada
solo tiene que preocuparse de tratar con una matriz, en lugar de un valor null potencial que
puede llevar a una NullPointerException .

La longitud de una matriz debe ser un entero no negativo:

int[] array = new int[-1]; // Throws [Link]

El tamaño de la matriz se puede determinar utilizando un campo final público llamado length :

[Link]([Link]); // Prints 0 in this case.

Nota : [Link] devuelve el tamaño real de la matriz y no el número de elementos de la matriz


a los que se asignó un valor, a diferencia de [Link]() que devuelve la cantidad de
elementos de la matriz a los que se asignó un valor.

Creando e inicializando arrays


multidimensionales.
La forma más sencilla de crear una matriz multidimensional es la siguiente:

int[][] a = new int[2][3];

Creará dos matrices int tres longitudes: a[0] y a[1] . Esto es muy similar a la inicialización clásica
de estilo C de matrices multidimensionales rectangulares.

Puedes crear e inicializar al mismo tiempo:

int[][] a = { {1, 2}, {3, 4}, {5, 6} };

[Link] 91
A diferencia de C , donde solo se admiten matrices multidimensionales rectangulares, las
matrices internas no tienen que ser de la misma longitud, ni siquiera definidas:

int[][] a = { {1}, {2, 3}, null };

Aquí, a[0] es una matriz int una longitud, mientras que a[1] es una matriz int dos longitudes y
a[2] es null . Las matrices de este tipo se denominan matrices irregulares o matrices irregulares ,
es decir, son matrices de matrices. Las matrices multidimensionales en Java se implementan
como matrices de matrices, es decir, array[i][j][k] es equivalente a ((array[i])[j])[k] . A
diferencia de C # , la array[i,j] sintaxis array[i,j] no es compatible con Java.

Representación de matriz multidimensional


en Java

Fuente - Live en Ideone

Creación e inicialización de matrices de tipos


de referencia
String[] array6 = new String[] { "Laurel", "Hardy" }; // Create an array with new
// operator and array initializer.
String[] array7 = { "Laurel", "Hardy" }; // Shortcut syntax with array
// initializer.
String[] array8 = new String[3]; // { null, null, null }
String[] array9 = null; // null

Vivir en Ideone

Además de los String literales y primitivas mostradas anteriormente, la sintaxis de acceso directo

[Link] 92
para array de inicialización también trabaja con canónicas Object tipos:

Object[] array10 = { new Object(), new Object() };

Debido a que las matrices son covariantes, una matriz de tipo de referencia se puede inicializar
como una matriz de una subclase, aunque se ArrayStoreException una ArrayStoreException si
intenta establecer un elemento en algo diferente a una String :

Object[] array11 = new String[] { "foo", "bar", "baz" };


array11[1] = "qux"; // fine
array11[1] = new StringBuilder(); // throws ArrayStoreException

La sintaxis de acceso directo no se puede usar para esto porque la sintaxis de acceso directo
tendría un tipo implícito de Object[] .

Una matriz se puede inicializar con cero elementos utilizando String[] emptyArray = new String[0]
. Por ejemplo, una matriz con una longitud cero como esta se usa para crear una Array partir de
una Collection cuando el método necesita el tipo de tiempo de ejecución de un objeto.

Tanto en los tipos primitivos como en los de referencia, una inicialización de matriz vacía (por
ejemplo, String[] array8 = new String[3] ) inicializará la matriz con el valor predeterminado para
cada tipo de datos .

Creando e inicializando arrays genéricos


En las clases genéricas, las matrices de tipos genéricos no se pueden inicializar de esta manera
debido al borrado de tipos :

public class MyGenericClass<T> {


private T[] a;

public MyGenericClass() {
a = new T[5]; // Compile time error: generic array creation
}
}

En su lugar, se pueden crear utilizando uno de los siguientes métodos: (tenga en cuenta que
estos generarán advertencias sin marcar)

1. Al crear una matriz de Object y convertirla en el tipo genérico:

a = (T[]) new Object[5];

Este es el método más simple, pero como la matriz subyacente aún es del tipo Object[] ,
este método no proporciona seguridad de tipo. Por lo tanto, este método de crear una matriz
se usa mejor solo dentro de la clase genérica, no se expone públicamente.

2. Al usar [Link] con un parámetro de clase:

[Link] 93
public MyGenericClass(Class<T> clazz) {
a = (T[]) [Link](clazz, 5);
}

Aquí la clase de T tiene que pasarse explícitamente al constructor. El tipo de retorno de


[Link] es siempre Object . Sin embargo, este método es más seguro porque la
matriz recién creada siempre es del tipo T[] y, por lo tanto, se puede externalizar de manera
segura.

Rellenar una matriz después de la


inicialización
Java SE 1.2

[Link]() se puede usar para llenar una matriz con el mismo valor después de la
inicialización:

[Link](array8, "abc"); // { "abc", "abc", "abc" }

Vivir en Ideone

fill() también puede asignar un valor a cada elemento del rango especificado de la matriz:

[Link](array8, 1, 2, "aaa"); // Placing "aaa" from index 1 to 2.

Vivir en Ideone

Java SE 8

Desde la versión 8 de Java, el método setAll y su parallelSetAll Concurrent setAll se pueden


usar para establecer cada elemento de una matriz en valores generados. A estos métodos se les
pasa una función de generador que acepta un índice y devuelve el valor deseado para esa
posición.

El siguiente ejemplo crea una matriz de enteros y establece todos sus elementos en su valor de
índice respectivo:

int[] array = new int[5];


[Link](array, i -> i); // The array becomes { 0, 1, 2, 3, 4 }.

Vivir en Ideone

Declaración separada e inicialización de


matrices.
[Link] 94
El valor de un índice para un elemento de matriz debe ser un número entero (0, 1, 2, 3, 4, ...) y
menor que la longitud de la matriz (los índices se basan en cero). De lo contrario, se lanzará una
ArrayIndexOutOfBoundsException :

int[] array9; // Array declaration - uninitialized


array9 = new int[3]; // Initialize array - { 0, 0, 0 }
array9[0] = 10; // Set index 0 value - { 10, 0, 0 }
array9[1] = 20; // Set index 1 value - { 10, 20, 0 }
array9[2] = 30; // Set index 2 value - { 10, 20, 30 }

Es posible que las matrices no se puedan


reinicializar con la sintaxis de acceso directo
del inicializador de matriz
No es posible reinicializar una matriz a través de una sintaxis de acceso directo con un
inicializador de matriz, ya que un inicializador de matriz solo se puede especificar en una
declaración de campo o declaración de variable local, o como parte de una expresión de creación
de matriz.

Sin embargo, es posible crear una nueva matriz y asignarla a la variable que se utiliza para hacer
referencia a la antigua matriz. Si bien esto hace que la matriz referenciada por esa variable se
reinicialice, el contenido de la variable es una matriz completamente nueva. Para hacer esto, el
new operador se puede usar con un inicializador de matriz y asignarse a la variable de matriz:

// First initialization of array


int[] array = new int[] { 1, 2, 3 };

// Prints "1 2 3 ".


for (int i : array) {
[Link](i + " ");
}

// Re-initializes array to a new int[] array.


array = new int[] { 4, 5, 6 };

// Prints "4 5 6 ".


for (int i : array) {
[Link](i + " ");
}

array = { 1, 2, 3, 4 }; // Compile-time error! Can't re-initialize an array via shortcut


// syntax with array initializer.

Vivir en Ideone

Creando una matriz de una colección

Dos métodos en [Link] crean una matriz de una colección:

[Link] 95
• Object[] toArray()

• <T> T[] toArray(T[] a)

Object[] toArray() se puede utilizar de la siguiente manera:

Java SE 5

Set<String> set = new HashSet<String>();


[Link]("red");
[Link]("blue");

// although set is a Set<String>, toArray() returns an Object[] not a String[]


Object[] objectArray = [Link]();

<T> T[] toArray(T[] a) se puede utilizar de la siguiente manera:

Java SE 5

Set<String> set = new HashSet<String>();


[Link]("red");
[Link]("blue");

// The array does not need to be created up front with the correct size.
// Only the array type matters. (If the size is wrong, a new array will
// be created with the same type.)
String[] stringArray = [Link](new String[0]);

// If you supply an array of the same size as collection or bigger, it


// will be populated with collection values and returned (new array
// won't be allocated)
String[] stringArray2 = [Link](new String[[Link]()]);

La diferencia entre ellos es más que tener resultados tipificados frente a los no tipificados. Su
rendimiento también puede diferir (para más detalles, lea esta sección de análisis de rendimiento
):

• utiliza una arraycopy vectorizada, que es mucho más rápida que la


Object[] toArray()
arraycopy comprobación de arraycopy utilizada en T[] toArray(T[] a) .
• T[] toArray(new T[non-zero-size]) necesita poner a cero la matriz en el tiempo de ejecución,
mientras que T[] toArray(new T[0]) no. Tal evitación hace que la última llamada sea más
rápida que la anterior. Análisis detallado aquí: Arrays of Wisdom of the Ancients .

Java SE 8

A partir de Java SE 8+, donde se introdujo el concepto de Stream , es posible utilizar el Stream
producido por la colección para crear una nueva matriz utilizando el método [Link] .

String[] strings = [Link]().toArray(String[]::new);

Ejemplos tomados de dos respuestas ( 1 , 2 ) a Convertir 'ArrayList a' String [] 'en Java en
desbordamiento de pila.

[Link] 96
Arrays a una cadena

Java SE 5

Desde Java 1.5, puede obtener una representación en String del contenido de la matriz
especificada sin iterar sobre todos sus elementos. Simplemente use [Link](Object[]) o
[Link](Object[]) para arreglos multidimensionales:

int[] arr = {1, 2, 3, 4, 5};


[Link]([Link](arr)); // [1, 2, 3, 4, 5]

int[][] arr = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
[Link]([Link](arr)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

[Link]() método [Link]() utiliza el método [Link]() para producir


valores de String de cada elemento de la matriz, además de la matriz de tipo primitiva, puede
usarse para todo tipo de matrices. Por ejemplo:

public class Cat { /* implicitly extends Object */


@Override
public String toString() {
return "CAT!";
}
}

Cat[] arr = { new Cat(), new Cat() };


[Link]([Link](arr)); // [CAT!, CAT!]

Si no existe una toString() anulada para la clase, se utilizará la toString() de Object heredada.
Por lo general, la salida no es muy útil, por ejemplo:

public class Dog {


/* implicitly extends Object */
}

Dog[] arr = { new Dog() };


[Link]([Link](arr)); // [Dog@17ed40e0]

Creación de una lista a partir de una matriz

El método [Link]() se puede usar para devolver una List tamaño fijo que contiene los
elementos de la matriz dada. La List resultante será del mismo tipo de parámetro que el tipo base
de la matriz.

String[] stringArray = {"foo", "bar", "baz"};


List<String> stringList = [Link](stringArray);

Nota : esta lista está respaldada por ( una vista de) la matriz original, lo que significa que

[Link] 97
cualquier cambio en la lista cambiará la matriz y viceversa. Sin embargo, los cambios en la lista
que cambiarían su tamaño (y por lo tanto la longitud de la matriz) generarán una excepción.

Para crear una copia de la lista, use el constructor de [Link] tomando una Collection
como un argumento:

Java SE 5

String[] stringArray = {"foo", "bar", "baz"};


List<String> stringList = new ArrayList<String>([Link](stringArray));

Java SE 7

En Java SE 7 y versiones posteriores, se pueden usar un par de corchetes angulares <> (conjunto
vacío de argumentos de tipo), lo que se denomina Diamante . El compilador puede determinar los
argumentos de tipo del contexto. Esto significa que la información de tipo se puede omitir al llamar
al constructor de ArrayList y se deducirá automáticamente durante la compilación. Esto se
denomina Inferencia de tipos, que forma parte de Java Generics .

// Using [Link]()

String[] stringArray = {"foo", "bar", "baz"};


List<String> stringList = new ArrayList<>([Link](stringArray));

// Using [Link]()

String[] stringArray = {"foo", "bar", "baz"};


ArrayList<String> list = new ArrayList<>();
[Link]([Link](stringArray));

// Using [Link]()

String[] stringArray = {"foo", "bar", "baz"};


ArrayList<String> list = new ArrayList<>();
[Link](list, stringArray);

Un punto que vale la pena mencionar sobre el Diamante es que no se puede usar con Clases
Anónimas .

Java SE 8

// Using Streams

int[] ints = {1, 2, 3};


List<Integer> list = [Link](ints).boxed().collect([Link]());

String[] stringArray = {"foo", "bar", "baz"};


List<Object> list = [Link](stringArray).collect([Link]());

Notas importantes relacionadas con el uso del método


[Link] ()

[Link] 98
• Este método devuelve List , que es una instancia de Arrays$ArrayList (clase interna estática
de Arrays ) y no [Link] . La List resultante es de tamaño fijo. Eso significa que
agregar o quitar elementos no es compatible y emitirá una UnsupportedOperationException :

[Link]("something"); // throws [Link]

• Se puede crear una nueva List pasando una List respaldada por una matriz al constructor
de una Nueva List . Esto crea una nueva copia de los datos, que tiene un tamaño variable y
que no está respaldado por la matriz original:

List<String> modifiableList = new ArrayList<>([Link]("foo", "bar"));

• Llamar a <T> List<T> asList(T... a) en una matriz primitiva, como int[] , producirá una
List<int[]> cuyo único elemento es la matriz primitiva de origen en lugar de los elementos
reales de la matriz de origen.

El motivo de este comportamiento es que los tipos primitivos no pueden utilizarse en lugar
de los parámetros de tipo genérico, por lo que la matriz primitiva completa reemplaza el
parámetro de tipo genérico en este caso. Para convertir una matriz primitiva en una List , en
primer lugar, convierta la matriz primitiva en una matriz del tipo de envoltura correspondiente
(es decir, llame a [Link] en un Integer[] lugar de a int[] ).

Por lo tanto, esto imprimirá false :

int[] arr = {1, 2, 3}; // primitive array of int


[Link]([Link](arr).contains(1));

Ver demostración

Por otro lado, esto se imprimirá true :

Integer[] arr = {1, 2, 3}; // object array of Integer (wrapper for int)
[Link]([Link](arr).contains(1));

Ver demostración

Esto también se imprimirá true , porque la matriz se interpretará como un Integer[] ):

[Link]([Link](1,2,3).contains(1));

Ver demostración

Matrices multidimensionales y dentadas

Es posible definir una matriz con más de una dimensión. En lugar de acceder al proporcionar un
índice único, se accede a una matriz multidimensional especificando un índice para cada
dimensión.

[Link] 99
La declaración de matriz multidimensional se puede hacer agregando [] para cada dimensión a
una decoración de matriz regular. Por ejemplo, para hacer una matriz int bidimensional, agregue
otro conjunto de corchetes a la declaración, como int[][] . Esto continúa para matrices
tridimensionales ( int[][][] ) y así sucesivamente.

Para definir una matriz bidimensional con tres filas y tres columnas:

int rows = 3;
int columns = 3;
int[][] table = new int[rows][columns];

La matriz se puede indexar y asignarle valores con esta construcción. Tenga en cuenta que los
valores no asignados son los valores predeterminados para el tipo de una matriz, en este caso 0
para int .

table[0][0] = 0;
table[0][1] = 1;
table[0][2] = 2;

También es posible crear una instancia de una dimensión a la vez, e incluso hacer matrices no
rectangulares. Estos se conocen más comúnmente como matrices dentadas .

int[][] nonRect = new int[4][];

Es importante tener en cuenta que aunque es posible definir cualquier dimensión de la matriz
dentada, se debe definir su nivel anterior.

// valid
String[][] employeeGraph = new String[30][];

// invalid
int[][] unshapenMatrix = new int[][10];

// also invalid
int[][][] misshapenGrid = new int[100][][10];

Cómo se representan los arreglos


multidimensionales en Java

[Link] 100
Fuente de la imagen: [Link]

Intialización literal de matriz dentada

Las matrices multidimensionales y matrices irregulares también se pueden inicializar con una
expresión literal. Lo siguiente declara y llena una matriz int 2x3:

int[][] table = {
{1, 2, 3},
{4, 5, 6}
};

Nota : los subarreglos irregulares también pueden ser null . Por ejemplo, el siguiente código
declara y llena una matriz int bidimensional cuyo primer subarreglo es null , el segundo
subarreglo es de longitud cero, el tercer subarreglo es de una longitud y el último subarreglo es
una matriz de dos longitudes:

int[][] table = {
null,
{},
{1},
{1,2}
};

Para matrices multidimensionales es posible extraer matrices de dimensión de nivel inferior por
sus índices:

int[][][] arr = new int[3][3][3];


int[][] arr1 = arr[0]; // get first 3x3-dimensional array from arr
int[] arr2 = arr1[0]; // get first 3-dimensional array from arr1
int[] arr3 = arr[0]; // error: cannot convert from int[][] to int[]

ArrayIndexOutOfBoundsException

[Link] 101
La ArrayIndexOutOfBoundsException produce cuando se accede a un índice no existente de una
matriz.

Las matrices están indexadas en base a cero, por lo que el índice del primer elemento es 0 y el
índice del último elemento es la capacidad de la matriz menos 1 (es decir, [Link] - 1 ).

Por lo tanto, cualquier solicitud de un elemento de matriz por el índice i tiene que satisfacer la
condición 0 <= i < [Link] , de lo contrario se ArrayIndexOutOfBoundsException la
ArrayIndexOutOfBoundsException .

El siguiente código es un ejemplo simple donde se lanza una ArrayIndexOutOfBoundsException .

String[] people = new String[] { "Carol", "Andy" };

// An array will be created:


// people[0]: "Carol"
// people[1]: "Andy"

// Notice: no item on index 2. Trying to access it triggers the exception:


[Link](people[2]); // throws an ArrayIndexOutOfBoundsException.

Salida:

Exception in thread "main" [Link]: 2


at [Link]([Link])

Tenga en cuenta que el índice ilegal al que se accede también se incluye en la excepción ( 2 en el
ejemplo); esta información podría ser útil para encontrar la causa de la excepción.

Para evitar esto, simplemente verifique que el índice esté dentro de los límites de la matriz:

int index = 2;
if (index >= 0 && index < [Link]) {
[Link](people[index]);
}

Obtener la longitud de una matriz

Las matrices son objetos que proporcionan espacio para almacenar hasta su tamaño de
elementos del tipo especificado. El tamaño de una matriz no se puede modificar después de crear
la matriz.

int[] arr1 = new int[0];


int[] arr2 = new int[2];
int[] arr3 = new int[]{1, 2, 3, 4};
int[] arr4 = {1, 2, 3, 4, 5, 6, 7};

int len1 = [Link]; // 0


int len2 = [Link]; // 2
int len3 = [Link]; // 4

[Link] 102
int len4 = [Link]; // 7

El campo de length en una matriz almacena el tamaño de una matriz. Es un campo final y no
puede ser modificado.

Este código muestra la diferencia entre la length de una matriz y la cantidad de objetos que
almacena una matriz.

public static void main(String[] args) {


Integer arr[] = new Integer[] {1,2,3,null,5,null,7,null,null,null,11,null,13};

int arrayLength = [Link];


int nonEmptyElementsCount = 0;

for (int i=0; i<arrayLength; i++) {


Integer arrElt = arr[i];
if (arrElt != null) {
nonEmptyElementsCount++;
}
}

[Link]("Array 'arr' has a length of "+arrayLength+"\n"


+ "and it contains "+nonEmptyElementsCount+" non-empty values");
}

Resultado:

Array 'arr' has a length of 13


and it contains 7 non-empty values

Comparando matrices para la igualdad

Los tipos de arreglos heredan las implementaciones de equals() (y hashCode() ) de


[Link] , por lo que equals() solo devolverá true cuando se compare con el mismo objeto
de arreglo. Para comparar arreglos de igualdad en función de sus valores, use
[Link] , que está sobrecargado para todos los tipos de arreglos.

int[] a = new int[]{1, 2, 3};


int[] b = new int[]{1, 2, 3};
[Link]([Link](b)); //prints "false" because a and b refer to different objects
[Link]([Link](a, b)); //prints "true" because the elements of a and b have
the same values

Cuando el tipo de elemento es un tipo de referencia, [Link]() llama a equals() en los


elementos de la matriz para determinar la igualdad. En particular, si el tipo de elemento es en sí
mismo un tipo de matriz, se utilizará la comparación de identidad. Para comparar matrices
multidimensionales para la igualdad, use [Link]() lugar como se muestra a
continuación:

int a[] = { 1, 2, 3 };
int b[] = { 1, 2, 3 };

[Link] 103
Object[] aObject = { a }; // aObject contains one element
Object[] bObject = { b }; // bObject contains one element

[Link]([Link](aObject, bObject)); // false


[Link]([Link](aObject, bObject));// true

Debido a que los conjuntos y mapas utilizan equals() y hashCode() , los arreglos generalmente no
son útiles como elementos de conjunto o claves de mapa. hashCode() en una clase auxiliar que
implemente equals() y hashCode() en términos de los elementos de la matriz, o hashCode() a
instancias de List y almacene las listas.

Arreglos para transmitir

Java SE 8

Convertir una matriz de objetos a Stream :

String[] arr = new String[] {"str1", "str2", "str3"};


Stream<String> stream = [Link](arr);

La conversión de una matriz de primitivas a Stream usando [Link]() transformará la matriz


a una especialización primitiva de Stream:

int[] intArr = {1, 2, 3};


IntStream intStream = [Link](intArr);

También puede limitar el Stream a un rango de elementos en la matriz. El índice de inicio es


inclusivo y el índice de finalización es exclusivo:

int[] values = {1, 2, 3, 4};


IntStream intStream = [Link](values, 2, 4);

Un método similar a [Link]() aparece en la clase Stream : [Link]() . La diferencia es que


[Link]() usa un parámetro varargs, por lo que puede escribir algo como:

Stream<Integer> intStream = [Link](1, 2, 3);


Stream<String> stringStream = [Link]("1", "2", "3");
Stream<Double> doubleStream = [Link](new Double[]{1.0, 2.0});

Iterando sobre matrices

Puede iterar sobre matrices usando un bucle mejorado para (también conocido como foreach) o
usando índices de matrices:

int[] array = new int[10];

// using indices: read and write


for (int i = 0; i < [Link]; i++) {
array[i] = i;
}

[Link] 104
Java SE 5

// extended for: read only


for (int e : array) {
[Link](e);
}

Vale la pena señalar aquí que no hay una forma directa de usar un iterador en un Array, pero a
través de la biblioteca de Arrays se puede convertir fácilmente en una lista para obtener un objeto
Iterable .

Para arrays en caja use [Link] :

Integer[] boxed = {1, 2, 3};


Iterable<Integer> boxedIt = [Link](boxed); // list-backed iterable
Iterator<Integer> fromBoxed1 = [Link]();

Para matrices primitivas (usando java 8) use flujos (específicamente en este ejemplo -
[Link] -> IntStream ):

int[] primitives = {1, 2, 3};


IntStream primitiveStream = [Link](primitives); // list-backed iterable
[Link] fromPrimitive1 = [Link]();

Si no puede usar secuencias (no java 8), puede elegir usar la biblioteca de guayabas de google:

Iterable<Integer> fromPrimitive2 = [Link](primitives);

En arreglos bidimensionales o más, ambas técnicas pueden usarse de una manera un poco más
compleja.

Ejemplo:

int[][] array = new int[10][10];

for (int indexOuter = 0; indexOuter < [Link]; indexOuter++) {


for (int indexInner = 0; indexInner < array[indexOuter].length; indexInner++) {
array[indexOuter][indexInner] = indexOuter + indexInner;
}
}

Java SE 5

for (int[] numbers : array) {


for (int value : numbers) {
[Link](value);
}
}

Es imposible establecer un Array en un valor no uniforme sin usar un bucle basado en índices.

[Link] 105
Por supuesto, también puede usar bucles while o do-while while cuando se iteran utilizando
índices.

Una nota de precaución: cuando utilice índices de matriz, asegúrese de que el índice esté entre
0 y [Link] - 1 (ambos inclusive). No haga suposiciones de código rígido en la longitud de la
matriz, de lo contrario podría romper su código si la longitud de la matriz cambia pero sus valores
codificados no lo hacen.

Ejemplo:

int[] numbers = {1, 2, 3, 4};

public void incrementNumbers() {


// DO THIS :
for (int i = 0; i < [Link]; i++) {
numbers[i] += 1; //or this: numbers[i] = numbers[i] + 1; or numbers[i]++;
}

// DON'T DO THIS :
for (int i = 0; i < 4; i++) {
numbers[i] += 1;
}
}

También es mejor si no usa cálculos sofisticados para obtener el índice, pero si lo usa para iterar
y si necesita valores diferentes, calcúlelos.

Ejemplo:

public void fillArrayWithDoubleIndex(int[] array) {


// DO THIS :
for (int i = 0; i < [Link]; i++) {
array[i] = i * 2;
}

// DON'T DO THIS :
int doubleLength = [Link] * 2;
for (int i = 0; i < doubleLength; i += 2) {
array[i / 2] = i;
}
}

Acceso a matrices en orden inverso

int[] array = {0, 1, 1, 2, 3, 5, 8, 13};


for (int i = [Link] - 1; i >= 0; i--) {
[Link](array[i]);
}

Uso de matrices temporales para reducir la repetición de código

Iterar sobre una matriz temporal en lugar de repetir el código puede hacer que su código sea más
limpio. Se puede utilizar donde se realiza la misma operación en múltiples variables.

[Link] 106
// we want to print out all of these
String name = "Margaret";
int eyeCount = 16;
double height = 50.2;
int legs = 9;
int arms = 5;

// copy-paste approach:
[Link](name);
[Link](eyeCount);
[Link](height);
[Link](legs);
[Link](arms);

// temporary array approach:


for(Object attribute : new Object[]{name, eyeCount, height, legs, arms})
[Link](attribute);

// using only numbers


for(double number : new double[]{eyeCount, legs, arms, height})
[Link]([Link](number));

Tenga en cuenta que este código no debe usarse en secciones críticas para el rendimiento, ya
que se crea una matriz cada vez que se ingresa al bucle, y las variables primitivas se copiarán en
la matriz y, por lo tanto, no se podrán modificar.

Copiando matrices

Java proporciona varias formas de copiar una matriz.

en bucle
int[] a = { 4, 1, 3, 2 };
int[] b = new int[[Link]];
for (int i = 0; i < [Link]; i++) {
b[i] = a[i];
}

Tenga en cuenta que el uso de esta opción con una matriz de objetos en lugar de una matriz
primitiva llenará la copia con referencia al contenido original en lugar de una copia de la misma.

[Link] ()
Dado que las matrices son Object en Java, puede usar [Link]() .

int[] a = { 4, 1, 3, 2 };
int[] b = [Link](); // [4, 1, 3, 2]

Tenga en cuenta que el método [Link] para una matriz realiza una copia superficial , es

[Link] 107
decir, devuelve una referencia a una nueva matriz que hace referencia a los mismos elementos
que la matriz de origen.

[Link] ()
[Link] proporciona una manera fácil de realizar la copia de una matriz a otra. Aquí está
el uso básico:

int[] a = {4, 1, 3, 2};


int[] b = [Link](a, [Link]); // [4, 1, 3, 2]

Tenga en cuenta que [Link] también proporciona una sobrecarga que le permite cambiar
el tipo de la matriz:

Double[] doubles = { 1.0, 2.0, 3.0 };


Number[] numbers = [Link](doubles, [Link], Number[].class);

[Link] ()
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int
length) Copia una matriz de la matriz de origen especificada, comenzando en la
posición especificada, a la posición especificada de la matriz de destino.

A continuación un ejemplo de uso.

int[] a = { 4, 1, 3, 2 };
int[] b = new int[[Link]];
[Link](a, 0, b, 0, [Link]); // [4, 1, 3, 2]

[Link] ()
Utilizado principalmente para copiar una parte de una matriz, también puede usarla para copiar
una matriz completa a otra como se muestra a continuación

int[] a = { 4, 1, 3, 2 };
int[] b = [Link](a, 0, [Link]); // [4, 1, 3, 2]

Matrices de fundición

Las matrices son objetos, pero su tipo está definido por el tipo de los objetos contenidos. Por lo
tanto, uno no puede simplemente lanzar A[] a T[] , pero cada miembro A de A[] específico debe
ser lanzado a un objeto T Ejemplo genérico:

[Link] 108
public static <T, A> T[] castArray(T[] target, A[] array) {
for (int i = 0; i < [Link]; i++) {
target[i] = (T) array[i];
}
return target;
}

Por lo tanto, dada una matriz A[] :

T[] target = new T[[Link]];


target = castArray(target, array);

Java SE proporciona el método [Link](original, newLength, newType) para este propósito:

Double[] doubles = { 1.0, 2.0, 3.0 };


Number[] numbers = [Link](doubles, [Link], Number[].class);

Eliminar un elemento de una matriz

Java no proporciona un método directo en [Link] para eliminar un elemento de una


matriz. Para realizarlo, puede copiar la matriz original en una nueva sin el elemento para eliminar
o convertir su matriz en otra estructura que permita la eliminación.

Usando ArrayList
Puede convertir la matriz en una [Link] , eliminar el elemento y volver a convertir la lista
en una matriz de la siguiente manera:

String[] array = new String[]{"foo", "bar", "baz"};

List<String> list = new ArrayList<>([Link](array));


[Link]("foo");

// Creates a new array with the same size as the list and copies the list
// elements to it.
array = [Link](new String[[Link]()]);

[Link]([Link](array)); //[bar, baz]

Usando [Link]
[Link]()se puede usar para hacer una copia de la matriz original y eliminar el elemento
que desee. A continuación un ejemplo:

int[] array = new int[] { 1, 2, 3, 4 }; // Original array.


int[] result = new int[[Link] - 1]; // Array which will contain the result.
int index = 1; // Remove the value "2".

// Copy the elements at the left of the index.


[Link](array, 0, result, 0, index);

[Link] 109
// Copy the elements at the right of the index.
[Link](array, index + 1, result, index, [Link] - index - 1);

[Link]([Link](result)); //[1, 3, 4]

Usando Apache Commons Lang


Para eliminar fácilmente un elemento, puede usar la biblioteca Lang de Apache Commons y
especialmente el método estático removeElement() de la clase ArrayUtils . A continuación un
ejemplo:

int[] array = new int[]{1,2,3,4};


array = [Link](array, 2); //remove first occurrence of 2
[Link]([Link](array)); //[1, 3, 4]

Array Covariance

Las matrices de objetos son covariantes, lo que significa que así como Integer es una subclase
de Number , Integer[] es una subclase de Number[] . Esto puede parecer intuitivo, pero puede
resultar en un comportamiento sorprendente:

Integer[] integerArray = {1, 2, 3};


Number[] numberArray = integerArray; // valid
Number firstElement = numberArray[0]; // valid
numberArray[0] = 4L; // throws ArrayStoreException at runtime

Aunque Integer[] es una subclase de Number[] , solo puede contener Integer s, y al intentar
asignar un elemento Long se genera una excepción de tiempo de ejecución.

Tenga en cuenta que este comportamiento es exclusivo de las matrices y que se puede evitar
utilizando una List genérica en su lugar:

List<Integer> integerList = [Link](1, 2, 3);


//List<Number> numberList = integerList; // compile error
List<? extends Number> numberList = integerList;
Number firstElement = [Link](0);
//[Link](0, 4L); // compile error

No es necesario que todos los elementos de la matriz compartan el mismo tipo, siempre que sean
una subclase del tipo de la matriz:

interface I {}

class A implements I {}
class B implements I {}
class C implements I {}

I[] array10 = new I[] { new A(), new B(), new C() }; // Create an array with new
// operator and array initializer.

[Link] 110
I[] array11 = { new A(), new B(), new C() }; // Shortcut syntax with array
// initializer.

I[] array12 = new I[3]; // { null, null, null }

I[] array13 = new A[] { new A(), new A() }; // Works because A implements I.

Object[] array14 = new Object[] { "Hello, World!", 3.14159, 42 }; // Create an array with
// new operator and array initializer.

Object[] array15 = { new A(), 64, "My String" }; // Shortcut syntax


// with array initializer.

¿Cómo cambias el tamaño de una matriz?

La respuesta simple es que no puedes hacer esto. Una vez que se ha creado una matriz, su
tamaño no se puede cambiar. En cambio, una matriz solo puede "redimensionarse" creando una
nueva matriz con el tamaño apropiado y copiando los elementos de la matriz existente a la nueva.

String[] listOfCities = new String[3]; // array created with size 3.


listOfCities[0] = "New York";
listOfCities[1] = "London";
listOfCities[2] = "Berlin";

Supongamos (por ejemplo) que es necesario agregar un nuevo elemento a la matriz listOfCities
definida como se listOfCities anteriormente. Para hacer esto, necesitarás:

1. crear una nueva matriz con tamaño 4,


2. copie los 3 elementos existentes de la matriz antigua a la nueva matriz en las
compensaciones 0, 1 y 2, y
3. agregue el nuevo elemento a la nueva matriz en el desplazamiento 3.

Hay varias formas de hacer lo anterior. Antes de Java 6, la forma más concisa era:

String[] newArray = new String[[Link] + 1];


[Link](listOfCities, 0, newArray, 0, [Link]);
newArray[[Link]] = "Sydney";

Desde Java 6 en adelante, los métodos [Link] y [Link] pueden hacer esto de
manera más simple:

String[] newArray = [Link](listOfCities, [Link] + 1);


newArray[[Link]] = "Sydney";

Para otras formas de copiar una matriz, consulte el siguiente ejemplo. Tenga en cuenta que
necesita una copia de matriz con una longitud diferente a la original al cambiar el tamaño.

• Copiando matrices

Una mejor alternativa para cambiar el tamaño de matriz

[Link] 111
Hay dos inconvenientes principales con el cambio de tamaño de una matriz como se describe
anteriormente:

• Es ineficiente. Hacer una matriz más grande (o más pequeña) implica copiar muchos o
todos los elementos de la matriz existente, y asignar un nuevo objeto de matriz. Cuanto
mayor sea la matriz, más caro se vuelve.
• Debe poder actualizar cualquier variable "viva" que contenga referencias a la matriz anterior.

Una alternativa es crear la matriz con un tamaño suficientemente grande para comenzar. Esto
solo es viable si puede determinar ese tamaño con precisión antes de asignar la matriz . Si no
puede hacer eso, entonces surge nuevamente el problema de cambiar el tamaño de la matriz.

La otra alternativa es utilizar una clase de estructura de datos proporcionada por la biblioteca de
clases Java SE o una biblioteca de terceros. Por ejemplo, el marco de "colecciones" de Java SE
proporciona varias implementaciones de las API de List , Set y Map con diferentes propiedades de
tiempo de ejecución. La clase ArrayList es la más cercana a las características de rendimiento de
una matriz simple (p. Ej., Búsqueda O (N), obtención y configuración O (1), inserción y eliminación
aleatoria O (N) al tiempo que proporciona un cambio de tamaño más eficiente sin el problema de
actualización de referencia.

(La eficiencia de cambio de tamaño para ArrayList proviene de su estrategia de duplicar el


tamaño de la matriz de respaldo en cada cambio de tamaño. Para un caso de uso típico, esto
significa que solo cambia el tamaño ocasionalmente. Cuando amortiza durante la vida útil de la
lista, el costo del cambio de tamaño por inserción es O(1) . Puede ser posible usar la misma
estrategia al cambiar el tamaño de una matriz simple).

Encontrar un elemento en una matriz

Hay muchas maneras de encontrar la ubicación de un valor en una matriz. Los siguientes
fragmentos de ejemplo suponen que la matriz es una de las siguientes:

String[] strings = new String[] { "A", "B", "C" };


int[] ints = new int[] { 1, 2, 3, 4 };

Además, cada uno establece el index o el index index2 en el índice del elemento requerido, o -1 si
el elemento no está presente.

Usando [Link] (solo para arreglos ordenados)

int index = [Link](strings, "A");


int index2 = [Link](ints, 1);

Uso de [Link] (solo para matrices no primitivas)

int index = [Link](strings).indexOf("A");


int index2 = [Link](ints).indexOf(1); // compilation error

[Link] 112
Usando una Stream
Java SE 8

int index = [Link](0, [Link])


.filter(i -> "A".equals(strings[i]))
.findFirst()
.orElse(-1); // If not present, gives us -1.
// Similar for an array of primitives

Búsqueda lineal utilizando un bucle.

int index = -1;


for (int i = 0; i < [Link]; i++) {
if ("A".equals(array[i])) {
index = i;
break;
}
}
// Similar for an array of primitives

Búsqueda lineal utilizando bibliotecas de terceros como


[Link]

int index = [Link](strings, "A");


int index2 = [Link](ints, 1);

Nota: Usar una búsqueda lineal directa es más eficiente que envolver en una lista.

Probando si una matriz contiene un elemento


Los ejemplos anteriores se pueden adaptar para probar si la matriz contiene un elemento
simplemente probando para ver si el índice calculado es mayor o igual a cero.

Alternativamente, también hay algunas variaciones más concisas:

boolean isPresent = [Link](strings).contains("A");

Java SE 8

boolean isPresent = Stream<String>.of(strings).anyMatch(x -> "A".equals(x));

boolean isPresent = false;


for (String s : strings) {
if ("A".equals(s)) {
isPresent = true;
break;
}

[Link] 113
}

boolean isPresent = [Link](ints, 4);

Ordenando matrices

La clasificación de matrices se puede hacer fácilmente con la matriz de matrices .

import [Link];

// creating an array with integers


int[] array = {7, 4, 2, 1, 19};
// this is the sorting part just one function ready to be used
[Link](array);
// prints [1, 2, 4, 7, 19]
[Link]([Link](array));

Clasificación de matrices de cuerdas:

String no es un dato numérico, define su propio orden, que se denomina orden lexicográfico,
también conocido como orden alfabético. Cuando ordena una matriz de String usando el método
sort() , la matriz se ordena en el orden natural definido por la interfaz comparable, como se
muestra a continuación:

Orden creciente

String[] names = {"John", "Steve", "Shane", "Adam", "Ben"};


[Link]("String array before sorting : " + [Link](names));
[Link](names);
[Link]("String array after sorting in ascending order : " +
[Link](names));

Salida:

String array before sorting : [John, Steve, Shane, Adam, Ben]


String array after sorting in ascending order : [Adam, Ben, John, Shane, Steve]

Orden decreciente

[Link](names, 0, [Link], [Link]());


[Link]("String array after sorting in descending order : " +
[Link](names));

Salida:

String array after sorting in descending order : [Steve, Shane, John, Ben, Adam]

Ordenar una matriz de objetos

[Link] 114
Para ordenar una matriz de objetos, todos los elementos deben implementar una interfaz
Comparable o Comparator para definir el orden de la clasificación.

Podemos usar cualquiera de los métodos de sort(Object[]) para ordenar una matriz de objetos
en su orden natural, pero debe asegurarse de que todos los elementos de la matriz deben
implementar Comparable .

Además, también deben ser mutuamente comparables, por ejemplo, [Link](e2) no debe
lanzar una ClassCastException para ningún elemento e1 y e2 en la matriz. Alternativamente, puede
ordenar una matriz de objetos en orden personalizado usando el método de sort(T[], Comparator)
como se muestra en el siguiente ejemplo.

// How to Sort Object Array in Java using Comparator and Comparable


Course[] courses = new Course[4];
courses[0] = new Course(101, "Java", 200);
courses[1] = new Course(201, "Ruby", 300);
courses[2] = new Course(301, "Python", 400);
courses[3] = new Course(401, "Scala", 500);

[Link]("Object array before sorting : " + [Link](courses));

[Link](courses);
[Link]("Object array after sorting in natural order : " +
[Link](courses));

[Link](courses, new [Link]());


[Link]("Object array after sorting by price : " + [Link](courses));

[Link](courses, new [Link]());


[Link]("Object array after sorting by name : " + [Link](courses));

Salida:

Object array before sorting : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401
Scala@500 ]
Object array after sorting in natural order : [#101 Java@200 , #201 Ruby@300 , #301 Python@400
, #401 Scala@500 ]
Object array after sorting by price : [#101 Java@200 , #201 Ruby@300 , #301 Python@400 , #401
Scala@500 ]
Object array after sorting by name : [#101 Java@200 , #301 Python@400 , #201 Ruby@300 , #401
Scala@500 ]

Conversión de matrices entre primitivas y tipos de caja.

A veces es necesaria la conversión de tipos primitivos a tipos en caja .

Para convertir la matriz, es posible usar flujos (en Java 8 y superior):

Java SE 8

int[] primitiveArray = {1, 2, 3, 4};


Integer[] boxedArray =
[Link](primitiveArray).boxed().toArray(Integer[]::new);

[Link] 115
Con versiones inferiores, puede ser iterando la matriz primitiva y copiándola explícitamente a la
matriz en caja:

Java SE 8

int[] primitiveArray = {1, 2, 3, 4};


Integer[] boxedArray = new Integer[[Link]];
for (int i = 0; i < [Link]; ++i) {
boxedArray[i] = primitiveArray[i]; // Each element is autoboxed here
}

De manera similar, una matriz en caja se puede convertir en una matriz de su contraparte
primitiva:

Java SE 8

Integer[] boxedArray = {1, 2, 3, 4};


int[] primitiveArray =
[Link](boxedArray).mapToInt(Integer::intValue).toArray();

Java SE 8

Integer[] boxedArray = {1, 2, 3, 4};


int[] primitiveArray = new int[[Link]];
for (int i = 0; i < [Link]; ++i) {
primitiveArray[i] = boxedArray[i]; // Each element is outboxed here
}

Lea Arrays en línea: [Link]

[Link] 116
Capítulo 16: Audio
Observaciones
En lugar de usar el Clip muestra [Link], también puede usar el AudioClip que es de
la API del applet. Sin embargo, se recomienda usar Clip ya que AudioClip es más antiguo y
presenta funcionalidades limitadas.

Examples
Reproducir un archivo de audio en bucle

Importaciones necesarias:

import [Link];
import [Link];

Este código creará un clip y lo reproducirá continuamente una vez iniciado:

Clip clip = [Link]();


[Link]([Link](new URL(filename)));
[Link]();
[Link](Clip.LOOP_CONTINUOUSLY);

Obtenga una matriz con todos los tipos de archivos compatibles:

[Link] [] audioFileTypes = [Link]();

Reproducir un archivo MIDI

Los archivos MIDI se pueden reproducir utilizando varias clases del paquete [Link] . Un
Sequencer realiza la reproducción del archivo MIDI, y muchos de sus métodos pueden usarse para
configurar controles de reproducción como el conteo de bucles, el tempo, el silenciamiento de
pistas y otros.

La reproducción general de datos MIDI se puede hacer de esta manera:

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

public class MidiPlayback {


public static void main(String[] args) {
try {

[Link] 117
Sequencer sequencer = [Link](); // Get the default Sequencer
if (sequencer==null) {
[Link]("Sequencer device not supported");
return;
}
[Link](); // Open device
// Create sequence, the File must contain MIDI file data.
Sequence sequence = [Link](new File(args[0]));
[Link](sequence); // load it into sequencer
[Link](); // start the playback
} catch (MidiUnavailableException | InvalidMidiDataException | IOException ex) {
[Link]();
}
}
}

Para detener la reproducción usa:

[Link](); // Stop the playback

Se puede configurar un secuenciador para silenciar una o más de las pistas de la secuencia
durante la reproducción, por lo que ninguno de los instrumentos en esos juegos especificados. El
siguiente ejemplo configura la primera pista en la secuencia a silenciar:

import [Link];
// ...

Track[] track = [Link]();


[Link](track[0]);

Un secuenciador puede reproducir una secuencia repetidamente si se da el recuento de bucles. A


continuación se establece el secuenciador para reproducir una secuencia cuatro veces e
indefinidamente:

[Link](3);
[Link](Sequencer.LOOP_CONTINUOUSLY);

El secuenciador no siempre tiene que reproducir la secuencia desde el principio, ni tiene que
reproducir la secuencia hasta el final. Puede comenzar y terminar en cualquier punto
especificando la marca en la secuencia para comenzar y terminar en. También es posible
especificar manualmente qué tic en la secuencia debe jugar el secuenciador desde:

[Link](512);
[Link](32768);
[Link](8192);

Los secuenciadores también pueden reproducir un archivo MIDI a un determinado tempo, que
puede controlarse especificando el tempo en tiempos por minuto (BPM) o microsegundos por
cuarto de nota (MPQ). El factor en el que se reproduce la secuencia también se puede ajustar.

[Link](1250f);
[Link](4750f);

[Link] 118
[Link](1.5f);

Cuando termine de usar el Sequencer , recuerde cerrarla

[Link]();

Sonido de metal desnudo

También puedes usar el metal casi al desnudo al producir sonido con java. Este código escribirá
datos binarios sin procesar en el búfer de audio del sistema operativo para generar sonido. Es
extremadamente importante comprender las limitaciones y los cálculos necesarios para generar
un sonido como este. Dado que la reproducción es básicamente instantánea, los cálculos deben
realizarse casi en tiempo real.

Como tal, este método es inutilizable para un muestreo de sonido más complicado. Para tales
fines, el uso de herramientas especializadas es el mejor enfoque.

El siguiente método genera y emite directamente una onda rectangular de una frecuencia dada en
un volumen dado para una duración determinada.

public void rectangleWave(byte volume, int hertz, int msecs) {


final SourceDataLine dataLine;
// 24 kHz x 8bit, single-channel, signed little endian AudioFormat
AudioFormat af = new AudioFormat(24_000, 8, 1, true, false);
try {
dataLine = [Link](af);
[Link](af, 10_000); // audio buffer size: 10k samples
} catch (LineUnavailableException e) {
throw new RuntimeException(e);
}

int waveHalf = 24_000 / hertz; // samples for half a period


byte[] buffer = new byte[waveHalf * 20];
int samples = msecs * (24_000 / 1000); // 24k (samples / sec) / 1000 (ms/sec) * time(ms)

[Link](); // starts playback


int sign = 1;

for (int i = 0; i < samples; i += [Link]) {


for (int j = 0; j < 20; j++) { // generate 10 waves into buffer
sign *= -1;
// fill from the jth wave-half to the j+1th wave-half with volume
[Link](buffer, waveHalf * j, waveHalf * (j+1), (byte) (volume * sign));
}
[Link](buffer, 0, [Link]); //
}
[Link](); // forces buffer drain to hardware
[Link](); // ends playback
}

Para una forma más diferenciada de generar diferentes ondas de sonido, son necesarios cálculos
sinusales y posiblemente tamaños de muestra más grandes. Esto da como resultado un código
significativamente más complejo y, por consiguiente, se omite aquí.

[Link] 119
Salida de audio básica

El Hola Audio! de Java que reproduce un archivo de sonido desde el almacenamiento local o de
Internet tiene el siguiente aspecto. Funciona para archivos .wav sin comprimir y no debe usarse
para reproducir archivos mp3 o comprimidos.

import [Link].*;
import [Link];
import [Link].*;

public class SoundClipTest {

// Constructor
public SoundClipTest() {
try {
// Open an audio input stream.
File soundFile = new File("/usr/share/sounds/alsa/Front_Center.wav"); //you could
also get the sound file with an URL
AudioInputStream audioIn = [Link](soundFile);
AudioFormat format = [Link]();
// Get a sound clip resource.
[Link] info = new [Link]([Link], format);
Clip clip = (Clip)[Link](info);
// Open audio clip and load samples from the audio input stream.
[Link](audioIn);
[Link]();
} catch (UnsupportedAudioFileException e) {
[Link]();
} catch (IOException e) {
[Link]();
} catch (LineUnavailableException e) {
[Link]();
}
}

public static void main(String[] args) {


new SoundClipTest();
}
}

Lea Audio en línea: [Link]

[Link] 120
Capítulo 17: Autoboxing
Introducción
Autoboxing es la conversión automática que realiza el compilador de Java entre los tipos
primitivos y sus correspondientes clases de envoltorios de objetos. Ejemplo, conversión de int ->
Entero, doble -> Doble ... Si la conversión es a la inversa, esto se llama unboxing. Por lo general,
esto se usa en Colecciones que no pueden contener más que Objetos, donde se necesitan tipos
primitivos de boxeo antes de configurarlos en la colección.

Observaciones
Autoboxing puede tener problemas de rendimiento cuando se utiliza con frecuencia en su código.

• [Link]
• ¿El autoempaquetamiento integral y el boxeo automático dan problemas de rendimiento?

Examples
Usando int y entero indistintamente

A medida que usa tipos genéricos con clases de utilidad, a menudo puede encontrar que los tipos
de números no son muy útiles cuando se especifican como tipos de objetos, ya que no son
iguales a sus contrapartes primitivas.

List<Integer> ints = new ArrayList<Integer>();

Java SE 7

List<Integer> ints = new ArrayList<>();

Afortunadamente, las expresiones que evalúan a int pueden usarse en lugar de un Integer
cuando sea necesario.

for (int i = 0; i < 10; i++)


[Link](i);

El [Link](i); declaración es equivalente a:

[Link]([Link](i));

Y retiene las propiedades de Integer#valueOf , como tener los mismos objetos de Integer
almacenados en caché por la JVM cuando está dentro del rango de almacenamiento en caché de
números.

[Link] 121
Esto también se aplica a:

• byte y Byte
• short y Short
• float y Float
• double y Double
• long y Long
• char y Character
• boolean y Boolean

Se debe tener cuidado, sin embargo, en situaciones ambiguas. Considere el siguiente código:

List<Integer> ints = new ArrayList<Integer>();


[Link](1);
[Link](2);
[Link](3);
[Link](1); // ints is now [1, 3]

La interfaz [Link] contiene tanto un remove(int index) (Método de interfaz de List ) como
un remove(Object o) (método heredado de [Link] ). En este caso no se lleva a cabo
ningún boxeo y se llama a la remove(int index) .

Un ejemplo más del extraño comportamiento del código Java causado por los enteros automoxing
con valores en el rango de -128 a 127 :

Integer a = 127;
Integer b = 127;
Integer c = 128;
Integer d = 128;
[Link](a == b); // true
[Link](c <= d); // true
[Link](c >= d); // true
[Link](c == d); // false

Esto sucede porque el operador >= llama implícitamente a intValue() que devuelve int mientras
que == compara las referencias , no los valores de int .

De forma predeterminada, Java almacena en caché los valores en el rango [-128, 127] , por lo
que el operador == funciona porque los Integers en este rango hacen referencia a los mismos
objetos si sus valores son los mismos. El valor máximo del rango -XX:AutoBoxCacheMax se puede
definir con la -XX:AutoBoxCacheMax JVM. Por lo tanto, si ejecuta el programa con -
XX:AutoBoxCacheMax=1000 , el siguiente código se imprimirá true :

Integer a = 1000;
Integer b = 1000;
[Link](a == b); // true

Usando Boolean en la sentencia if

Debido al auto-boxeo, uno puede usar un Boolean en una sentencia if :

[Link] 122
Boolean a = [Link];
if (a) { // a gets converted to boolean
[Link]("It works!");
}

Eso funciona para while , do while y la condición en las declaraciones for también.

Tenga en cuenta que, si el valor Boolean es null , se lanzará una NullPointerException en la


conversión.

Auto-unboxing puede llevar a NullPointerException

Este código compila:

Integer arg = null;


int x = arg;

Pero se bloqueará en tiempo de ejecución con una [Link] en la segunda


línea.

El problema es que un int primitivo no puede tener un valor null .

Este es un ejemplo minimalista, pero en la práctica a menudo se manifiesta en formas más


sofisticadas. La NullPointerException no es muy intuitiva y suele ser de poca ayuda para localizar
estos errores.

Confíe en el autoboxing y el auto-boxeo con cuidado, asegúrese de que los valores unboxed no
tengan valores null en el tiempo de ejecución.

Memoria y sobrecarga computacional de Autoboxing

Autoboxing puede venir en una sobrecarga de memoria sustancial. Por ejemplo:

Map<Integer, Integer> square = new HashMap<Integer, Integer>();


for(int i = 256; i < 1024; i++) {
[Link](i, i * i); // Autoboxing of large integers
}

normalmente consumirá una cantidad sustancial de memoria (alrededor de 60kb para 6k de datos
reales).

Además, los enteros en caja generalmente requieren viajes de ida y vuelta adicionales en la
memoria, y por lo tanto hacen que los cachés de CPU sean menos efectivos. En el ejemplo
anterior, la memoria a la que se accede se extiende a cinco ubicaciones diferentes que pueden
estar en regiones completamente diferentes de la memoria: 1. el objeto HashMap , 2. el objeto de
Entry[] table del mapa, 3. el objeto Entry , 4. el objeto objeto key entradas (boxeo de la clave
primitiva), 5. objeto de value entradas (boxeo del valor primitivo).

class Example {
int primitive; // Stored directly in the class `Example`

[Link] 123
Integer boxed; // Reference to another memory location
}

La lectura en boxed requiere dos accesos de memoria, accediendo solo a uno primitive .

Al obtener datos de este mapa, el código aparentemente inocente

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
sumOfSquares += [Link](i);
}

es equivalente a:

int sumOfSquares = 0;
for(int i = 256; i < 1024; i++) {
sumOfSquares += [Link]([Link](i)).intValue();
}

Normalmente, el código anterior causa la creación y recolección de elementos no utilizados de un


objeto Integer para cada operación Map#get(Integer) . (Vea la Nota a continuación para más
detalles).

Para reducir esta sobrecarga, varias bibliotecas ofrecen colecciones optimizadas para tipos
primitivos que no requieren boxeo. Además de evitar la sobrecarga del boxeo, esta colección
requerirá aproximadamente 4 veces menos memoria por entrada. Si bien Java Hotspot puede
optimizar el autoboxing al trabajar con objetos en la pila en lugar del montón, no es posible
optimizar la sobrecarga de memoria y la indirección de la memoria resultante.

Las transmisiones Java 8 también tienen interfaces optimizadas para tipos de datos primitivos,
como IntStream que no requieren boxeo.

Nota: un tiempo de ejecución de Java típico mantiene un caché simple de Integer y otro objeto de
envoltorio primitivo que utilizan los métodos de fábrica valueOf , y mediante autofijación. Para
Integer , el rango predeterminado de este caché es de -128 a +127. Algunas JVM proporcionan
una opción de línea de comandos JVM para cambiar el tamaño / rango de la memoria caché.

Casos diferentes cuando Integer e int pueden usarse indistintamente

Caso 1: Mientras se usa en lugar de argumentos de método.

Si un método requiere un objeto de la clase envoltura como argumento. Luego, indistintamente,


se le puede pasar una variable del tipo primitivo respectivo y viceversa.

Ejemplo:

int i;
Integer j;
void ex_method(Integer i)//Is a valid statement
void ex_method1(int j)//Is a valid statement

[Link] 124
Caso 2: Mientras se pasan valores de retorno:

Cuando un método devuelve una variable de tipo primitivo, entonces se puede pasar un objeto de
la clase envoltura correspondiente como valor de retorno de manera intercambiable y viceversa.

Ejemplo:

int i;
Integer j;
int ex_method()
{...
return j;}//Is a valid statement
Integer ex_method1()
{...
return i;//Is a valid statement
}

Caso 3: Al realizar operaciones.

Siempre que se realicen operaciones en números, la variable de tipo primitivo y el objeto de la


respectiva clase envoltura se pueden usar indistintamente.

int i=5;
Integer j=new Integer(7);
int k=i+j;//Is a valid statement
Integer m=i+j;//Is also a valid statement

Trampa : recuerde inicializar o asignar un valor a un objeto de la clase contenedora.

Si bien el uso de un objeto de la clase de envoltorio y la variable primitiva no se olvida, nunca se


olvida o se pierde para inicializar o asignar un valor al objeto de la clase de envoltorio, de lo
contrario, puede provocar una excepción de puntero nulo en el tiempo de ejecución.

Ejemplo:

public class Test{


Integer i;
int j;
public void met()
{j=i;//Null pointer exception
SOP(j);
SOP(i);}
public static void main(String[] args)
{Test t=new Test();
[Link]();//Null pointer exception
}

En el ejemplo anterior, el valor del objeto no está asignado ni inicializado y, por lo tanto, en tiempo
de ejecución, el programa ejecutará una excepción de puntero nulo. Por lo tanto, el valor del
objeto nunca debe dejarse sin inicializar ni asignar.

Lea Autoboxing en línea: [Link]

[Link] 125
Capítulo 18: Banderas JVM
Observaciones
Se recomienda encarecidamente que utilice estas opciones solamente:

• Si tienes una comprensión profunda de tu sistema.


• Tenga en cuenta que, si se usa incorrectamente, estas opciones pueden tener un efecto
negativo en la estabilidad o el rendimiento de su sistema.

Información recogida de documentación oficial de Java .

Examples
-XXaggresivo

-XXaggressive es una colección de configuraciones que hacen que la JVM funcione a alta
velocidad y alcance un estado estable lo antes posible. Para lograr este objetivo, la JVM utiliza
más recursos internos al inicio; sin embargo, requiere una optimización menos adaptable una vez
que se alcanza el objetivo. Le recomendamos que utilice esta opción para aplicaciones de larga
duración que requieren un uso intensivo de la memoria y que funcionan solas.

Uso:

-XXaggressive:<param>

<param> Descripción

Programa optimizaciones adaptativas antes y permite nuevas optimizaciones,


opt
que se espera sean las predeterminadas en futuras versiones.

Configura el sistema de memoria para cargas de trabajo intensivas en memoria y


establece una expectativa para habilitar grandes cantidades de recursos de
memory
memoria para garantizar un alto rendimiento. JRockit JVM también utilizará
páginas grandes, si están disponibles.

-XXallocClearChunks

Esta opción le permite borrar un TLA para referencias y valores en el tiempo de asignación de
TLA y obtener previamente el siguiente fragmento. Cuando se declara un entero, una referencia o
cualquier otra cosa, tiene un valor predeterminado de 0 o nulo (según el tipo). En el momento
adecuado, deberá borrar estas referencias y valores para liberar la memoria del montón para que
Java pueda usarla o reutilizarla. Puede hacerlo cuando se asigna el objeto o, al usar esta opción,
cuando solicita un nuevo TLA.

[Link] 126
Uso:

-XXallocClearChunks

-XXallocClearChunks=<true | false>

Lo anterior es una opción booleana y generalmente se recomienda en sistemas IA64; En última


instancia, su uso depende de la aplicación. Si desea establecer el tamaño de los trozos borrados,
combine esta opción con -XXallocClearChunkSize . Si usa este indicador pero no especifica un valor
booleano, el valor predeterminado es true .

-XXallocClearChunkSize

Cuando se usa con -XXallocClearChunkSize , esta opción establece el tamaño de los trozos que se
borrarán. Si se utiliza este indicador pero no se especifica ningún valor, el valor predeterminado
es 512 bytes.

Uso:

-XXallocClearChunks -XXallocClearChunkSize=<size>[k|K][m|M][g|G]

-XXcallProfiling

Esta opción permite el uso de perfiles de llamadas para optimizaciones de código. El perfil
registra estadísticas útiles de tiempo de ejecución específicas para la aplicación y puede, en
muchos casos, aumentar el rendimiento porque JVM puede actuar sobre esas estadísticas.

Nota: esta opción es compatible con JRockit JVM R27.3.0 y la versión posterior.
Puede convertirse en predeterminado en futuras versiones.

Uso:

java -XXcallProfiling myApp

Esta opción está deshabilitada por defecto. Debes habilitarlo para usarlo.

-XXdisableFatSpin

Esta opción deshabilita el código de giro de bloqueo de grasa en Java, permitiendo que los hilos
que bloquean el intento de adquirir un bloqueo de grasa se duerman directamente.

Los objetos en Java se convierten en un bloqueo tan pronto como cualquier hilo entra en un
bloque sincronizado en ese objeto. Todos los bloqueos se mantienen (es decir, permanecen
bloqueados) hasta que se liberan por el hilo de bloqueo. Si el bloqueo no se va a liberar muy
rápido, se puede inflar a un "bloqueo grueso". El "giro" se produce cuando un hilo que quiere un
bloqueo específico comprueba continuamente ese bloqueo para ver si aún está en uso. Bucle
apretado ya que hace el cheque. Girar contra un bloqueo de grasa es generalmente beneficioso,

[Link] 127
aunque, en algunos casos, puede ser costoso y puede afectar el rendimiento. -XXdisableFatSpin
permite desactivar el giro contra un bloqueo grueso y eliminar el impacto potencial de
rendimiento.

Uso:

-XXdisableFatSpin

-XXdisponibilidad a las características de la visión

Esta opción deshabilita los cambios de estrategia del recolector de basura. Esta opción no afecta
a las heurísticas de compactación ni a las de tamaño de vivero. Por defecto, las heurísticas de
recolección de basura están habilitadas.

Uso:

-XXdisableFatSpin

-XXdumpSize

Esta opción hace que se genere un archivo de volcado y le permite especificar el tamaño relativo
de ese archivo (es decir, pequeño, mediano o grande).

Uso:

-XXdumpsize:<size>

<tamaño> Descripción

none No genera un archivo de volcado.

En Windows, se genera un pequeño archivo de volcado (en Linux se genera un


volcado de núcleo completo). Un pequeño volcado solo incluye las pilas de
small hilos, incluidas sus huellas y muy poco más. Este fue el valor predeterminado
en JRockit JVM 8.1 con los paquetes de servicio 1 y 2, así como 7.0 con el
paquete de servicio 3 y superior).

Hace que se genere un volcado normal en todas las plataformas. Este archivo
normal de volcado incluye toda la memoria excepto el montón java. Este es el valor
predeterminado para JRockit JVM 1.4.2 y versiones posteriores.

Incluye todo lo que está en la memoria, incluido el montón de Java. Esta opción
large
hace que -XXdumpSize sea equivalente a -XXdumpFullState .

-XXexitOnOutOfMemory

Esta opción hace que JRockit JVM salga en la primera aparición de un error de falta de memoria.

[Link] 128
Se puede usar si prefiere reiniciar una instancia de JRockit JVM en lugar de eliminar los errores
de memoria. Ingrese este comando al inicio para forzar a JRockit JVM a salir en la primera vez
que ocurra un error de falta de memoria.

Uso:

-XXexitOnOutOfMemory

Lea Banderas JVM en línea: [Link]

[Link] 129
Capítulo 19: BigDecimal
Introducción
La clase BigDecimal proporciona operaciones para aritmética (sumar, restar, multiplicar, dividir),
manipulación de escala, redondeo, comparación, hash y conversión de formato. El BigDecimal
representa números decimales firmados de precisión arbitraria e inmutables. Esta clase se
utilizará en una necesidad de cálculo de alta precisión.

Examples
Los objetos BigDecimal son inmutables.

Si desea calcular con BigDecimal, tiene que usar el valor devuelto porque los objetos BigDecimal
son inmutables:

BigDecimal a = new BigDecimal("42.23");


BigDecimal b = new BigDecimal("10.001");

[Link](b); // a will still be 42.23

BigDecimal c = [Link](b); // c will be 52.231

Comparando BigDecimals

El método compareTo debe usarse para comparar BigDecimals :

BigDecimal a = new BigDecimal(5);


[Link](new BigDecimal(0)); // a is greater, returns 1
[Link](new BigDecimal(5)); // a is equal, returns 0
[Link](new BigDecimal(10)); // a is less, returns -1

Comúnmente no se debe utilizar la equals método ya que considera dos BigDecimals iguales sólo
si son iguales en valor y también de la escala:

BigDecimal a = new BigDecimal(5);


[Link](new BigDecimal(5)); // value and scale are equal, returns true
[Link](new BigDecimal(5.00)); // value is equal but scale is not, returns false

Operaciones matemáticas con BigDecimal.

Este ejemplo muestra cómo realizar operaciones matemáticas básicas con BigDecimals.

[Link]ón

[Link] 130
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a + b
BigDecimal result = [Link](b);
[Link](result);

Resultado: 12

[Link]
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a - b
BigDecimal result = [Link](b);
[Link](result);

Resultado: -2

[Link]
Al multiplicar dos BigDecimal s, el resultado tendrá una escala igual a la suma de las escalas de
los operandos.

BigDecimal a = new BigDecimal("5.11");


BigDecimal b = new BigDecimal("7.221");

//Equivalent to result = a * b
BigDecimal result = [Link](b);
[Link](result);

Resultado: 36.89931

Para cambiar la escala del resultado, utilice el método de multiplicación sobrecargada que permite
pasar MathContext , un objeto que describe las reglas para los operadores, en particular la
precisión y el modo de redondeo del resultado. Para obtener más información sobre los modos de
redondeo disponibles, consulte la documentación de Oracle.

BigDecimal a = new BigDecimal("5.11");


BigDecimal b = new BigDecimal("7.221");

MathContext returnRules = new MathContext(4, RoundingMode.HALF_DOWN);

//Equivalent to result = a * b
BigDecimal result = [Link](b, returnRules);
[Link](result);

Resultado: 36.90

[Link] 131
[Link]
La división es un poco más complicada que las otras operaciones aritméticas, por ejemplo,
considere el siguiente ejemplo:

BigDecimal a = new BigDecimal("5");


BigDecimal b = new BigDecimal("7");

BigDecimal result = [Link](b);


[Link](result);

Esperamos que esto dé algo similar a: 0.7142857142857143, pero obtendríamos:

Resultado: [Link]: Expansión decimal sin terminación;


No hay un resultado decimal representable exacto.

Esto funcionaría perfectamente bien cuando el resultado fuera un decimal de terminación, por
ejemplo, si quisiera dividir 5 por 2, pero para aquellos números que al dividir darían un resultado
no final, obtendríamos una ArithmeticException . En el escenario del mundo real, uno no puede
predecir los valores que se encontrarían durante la división, por lo que necesitamos especificar la
Escala y el Modo de redondeo para la división BigDecimal. Para obtener más información sobre
la escala y el modo de redondeo, consulte la documentación de Oracle .

Por ejemplo, podría hacer:

BigDecimal a = new BigDecimal("5");


BigDecimal b = new BigDecimal("7");

//Equivalent to result = a / b (Upto 10 Decimal places and Round HALF_UP)


BigDecimal result = [Link](b,10,RoundingMode.HALF_UP);
[Link](result);

Resultado: 0.7142857143

[Link] resto o módulo


BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = a % b
BigDecimal result = [Link](b);
[Link](result);

Resultado: 5

6. Poder

[Link] 132
BigDecimal a = new BigDecimal("5");

//Equivalent to result = a^10


BigDecimal result = [Link](10);
[Link](result);

Resultado: 9765625

[Link]
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = MAX(a,b)


BigDecimal result = [Link](b);
[Link](result);

Resultado: 7

[Link]
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");

//Equivalent to result = MIN(a,b)


BigDecimal result = [Link](b);
[Link](result);

Resultado: 5

9. Mover punto a la izquierda


BigDecimal a = new BigDecimal("5234.49843776");

//Moves the decimal point to 2 places left of current position


BigDecimal result = [Link](2);
[Link](result);

Resultado: 52.3449843776

10. Mover punto a la derecha


BigDecimal a = new BigDecimal("5234.49843776");

//Moves the decimal point to 3 places right of current position


BigDecimal result = [Link](3);

[Link] 133
[Link](result);

Resultado: 5234498.43776

Existen muchas más opciones y una combinación de parámetros para los ejemplos mencionados
anteriormente (por ejemplo, hay 6 variaciones del método de división), este conjunto no es una
lista exhaustiva y cubre algunos ejemplos básicos.

Usando BigDecimal en lugar de flotar

Debido a la forma en que el tipo flotante se representa en la memoria de la computadora, los


resultados de las operaciones que utilizan este tipo pueden ser inexactos, algunos valores se
almacenan como aproximaciones. Buenos ejemplos de esto son los cálculos monetarios. Si es
necesaria una alta precisión, deben usarse otros tipos. por ejemplo, Java 7 proporciona
BigDecimal.

import [Link];

public class FloatTest {

public static void main(String[] args) {


float accountBalance = 10000.00f;
[Link]("Operations using float:");
[Link]("1000 operations for 1.99");
for(int i = 0; i<1000; i++){
accountBalance -= 1.99f;
}
[Link]([Link]("Account balance after float operations: %f",
accountBalance));

BigDecimal accountBalanceTwo = new BigDecimal("10000.00");


[Link]("Operations using BigDecimal:");
[Link]("1000 operations for 1.99");
BigDecimal operation = new BigDecimal("1.99");
for(int i = 0; i<1000; i++){
accountBalanceTwo = [Link](operation);
}
[Link]([Link]("Account balance after BigDecimal operations: %f",
accountBalanceTwo));
}

La salida de este programa es:

Operations using float:


1000 operations for 1.99
Account balance after float operations: 8009,765625
Operations using BigDecimal:
1000 operations for 1.99
Account balance after BigDecimal operations: 8010,000000

Para un saldo inicial de 10000.00, después de 1000 operaciones por 1.99, esperamos que el
saldo sea 8010.00. El uso del tipo de coma flotante nos da una respuesta en torno al 8009.77, lo
que es inaceptablemente impreciso en el caso de los cálculos monetarios. Usar BigDecimal nos

[Link] 134
da el resultado adecuado.

[Link] ()

La clase BigDecimal contiene un caché interno de los números utilizados con frecuencia, por
ejemplo, de 0 a 10. Los métodos [Link] () se proporcionan con preferencia a los
constructores con parámetros de tipo similar, es decir, en el ejemplo siguiente se prefiere a b.

BigDecimal a = [Link](10L); //Returns cached Object reference


BigDecimal b = new BigDecimal(10L); //Does not return cached Object reference

BigDecimal a = [Link](20L); //Does not return cached Object reference


BigDecimal b = new BigDecimal(20L); //Does not return cached Object reference

BigDecimal a = [Link](15.15); //Preferred way to convert a double (or float) into


a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal
from the result of using [Link](double)
BigDecimal b = new BigDecimal(15.15); //Return unpredictable result

Inicialización de BigDecimals con valor cero, uno o diez.

BigDecimal proporciona propiedades estáticas para los números cero, uno y diez. Es una buena
práctica usar estos en lugar de usar los números reales:

• [Link]
• [Link]
• [Link]

Al usar las propiedades estáticas, evitas una creación de instancias innecesaria, también tienes
un literal en tu código en lugar de un 'número mágico'.

//Bad example:
BigDecimal bad0 = new BigDecimal(0);
BigDecimal bad1 = new BigDecimal(1);
BigDecimal bad10 = new BigDecimal(10);

//Good Example:
BigDecimal good0 = [Link];
BigDecimal good1 = [Link];
BigDecimal good10 = [Link];

Lea BigDecimal en línea: [Link]

[Link] 135
Capítulo 20: BigInteger
Introducción
La clase BigInteger se usa para operaciones matemáticas que involucran enteros grandes con
magnitudes demasiado grandes para tipos de datos primitivos. Por ejemplo, 100 factorial es 158
dígitos, mucho más grande de lo que puede representar un long . BigInteger proporciona
análogos a todos los operadores enteros primitivos de Java y todos los métodos relevantes de
[Link] , así como algunas otras operaciones.

Sintaxis
• BigInteger variable_name = new BigInteger ("12345678901234567890"); // un entero
decimal como una cadena
• BigInteger variable_name = new BigInteger
("1010101101010101010100110001100111010110001111100001011010010", 2) // un
entero binario como una cadena
• BigInteger variable_name = new BigInteger ("ab54a98ceb1f0800", 16) // un entero
hexadecimal como una cadena
• BigInteger variable_name = new BigInteger (64, new Random ()); // un generador de
números pseudoaleatorios que suministra 64 bits para construir un entero
• BigInteger variable_name = new BigInteger (new byte [] {0, -85, 84, -87, -116, -21, 31, 10, -
46}); // firmó la representación complementaria de dos de un entero (big endian)
• BigInteger variable_name = new BigInteger (1, nuevo byte [] {- 85, 84, -87, -116, -21, 31, 10,
-46}); // representación de complemento de dos sin signo de un entero positivo (big endian)

Observaciones
BigIntegeres inmutable. Por lo tanto no puedes cambiar su estado. Por ejemplo, lo siguiente no
funcionará ya que la sum no se actualizará debido a la inmutabilidad.

BigInteger sum = [Link];


for(int i = 1; i < 5000; i++) {
[Link]([Link](i));
}

Asigna el resultado a la variable sum para que funcione.

sum = [Link]([Link](i));

Java SE 8

La documentación oficial de BigInteger indica que las implementaciones de BigInteger deben


admitir todos los enteros entre -2 2147483647 y 2 2147483647 (exclusivo). ¡Esto significa que

[Link] 136
BigInteger puede tener más de 2 mil millones de bits!

Examples
Inicialización

La clase [Link] proporciona operaciones análogas a todos los operadores de


enteros primitivos de Java y para todos los métodos relevantes de [Link] . Como el
paquete [Link] no está disponible automáticamente, es posible que tenga que importar
[Link] antes de poder usar el nombre de clase simple.

Para convertir valores long o int en BigInteger use:

long longValue = Long.MAX_VALUE;


BigInteger valueFromLong = [Link](longValue);

o, para enteros:

int intValue = Integer.MIN_VALUE; // negative


BigInteger valueFromInt = [Link](intValue);

que ampliarán el intValue número entero de largo, utilizando la extensión bit de signo para los
valores negativos, por lo que los valores negativos permanecerán negativo.

Para convertir una String numérica a BigInteger use:

String decimalString = "-1";


BigInteger valueFromDecimalString = new BigInteger(decimalString);

El siguiente constructor se utiliza para traducir la representación de cadena de un BigInteger en el


radix especificado en un BigInteger .

String binaryString = "10";


int binaryRadix = 2;
BigInteger valueFromBinaryString = new BigInteger(binaryString , binaryRadix);

Java también admite la conversión directa de bytes a una instancia de BigInteger . Actualmente
solo se puede usar la codificación big endian firmada y sin firmar:

byte[] bytes = new byte[] { (byte) 0x80 };


BigInteger valueFromBytes = new BigInteger(bytes);

Esto generará una instancia de BigInteger con valor -128 ya que el primer bit se interpreta como
el bit de signo.

byte[] unsignedBytes = new byte[] { (byte) 0x80 };


int sign = 1; // positive

[Link] 137
BigInteger valueFromUnsignedBytes = new BigInteger(sign, unsignedBytes);

Esto generará una instancia de BigInteger con valor 128, ya que los bytes se interpretan como un
número sin firma y el signo se establece explícitamente en 1, un número positivo.

Hay constantes predefinidas para valores comunes:

• [Link] - valor de "0".


• [Link] - valor de "1".
• [Link] - valor de "10".

También hay [Link] (valor de "2"), pero no puedes usarlo en tu código porque es private .

Comparando BigIntegers

Puede comparar BigIntegers igual que compara String u otros objetos en Java.

Por ejemplo:

BigInteger one = [Link](1);


BigInteger two = [Link](2);

if([Link](two)){
[Link]("Equal");
}
else{
[Link]("Not Equal");
}

Salida:

Not Equal

Nota:

En general, no use el operador == para comparar BigIntegers

• operador == : compara referencias; es decir, si dos valores se refieren al mismo objeto


• Método equals() : compara el contenido de dos BigIntegers.

Por ejemplo, BigIntegers no debe compararse de la siguiente manera:

if (firstBigInteger == secondBigInteger) {
// Only checks for reference equality, not content equality!
}

Si lo hace, puede provocar un comportamiento inesperado, ya que el operador == solo comprueba


la igualdad de referencia. Si ambos BigIntegers contienen el mismo contenido, pero no se refieren
al mismo objeto, esto fallará. En su lugar, compare BigIntegers utilizando los métodos equals ,
como se explicó anteriormente.

[Link] 138
También puede comparar su BigInteger con valores constantes como 0,1,10.

por ejemplo:

BigInteger reallyBig = [Link](1);


if([Link](reallyBig)){
//code when they are equal.
}

También puede comparar dos BigIntegers usando el compareTo() , como sigue: compareTo()
devuelve 3 valores.

• 0: Cuando ambos son iguales .


• 1: Cuando el primero es mayor que el segundo (el que está entre paréntesis).
• -1: Cuando el primero es menor que el segundo.

BigInteger reallyBig = [Link](10);


BigInteger reallyBig1 = [Link](100);

if([Link](reallyBig1) == 0){
//code when both are equal.
}
else if([Link](reallyBig1) == 1){
//code when reallyBig is greater than reallyBig1.
}
else if([Link](reallyBig1) == -1){
//code when reallyBig is less than reallyBig1.
}

Ejemplos de operaciones matemáticas de BigInteger

BigInteger se encuentra en un objeto inmutable, por lo que debe asignar los resultados de
cualquier operación matemática a una nueva instancia de BigInteger.

Adición: 10 + 10 = 20

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("10");

BigInteger sum = [Link](value2);


[Link](sum);

salida: 20

Sustracción: 10 - 9 = 1

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("9");

BigInteger sub = [Link](value2);


[Link](sub);

salida: 1

[Link] 139
División: 10/5 = 2

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("5");

BigInteger div = [Link](value2);


[Link](div);

salida: 2

División: 17/4 = 4

BigInteger value1 = new BigInteger("17");


BigInteger value2 = new BigInteger("4");

BigInteger div = [Link](value2);


[Link](div);

salida: 4

Multiplicación: 10 * 5 = 50

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("5");

BigInteger mul = [Link](value2);


[Link](mul);

salida: 50

Potencia: 10 ^ 3 = 1000

BigInteger value1 = new BigInteger("10");


BigInteger power = [Link](3);
[Link](power);

salida: 1000

Resto: 10% 6 = 4

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("6");

BigInteger power = [Link](value2);


[Link](power);

salida: 4

GCD: el divisor común más grande (GCD) para 12 y 18 es 6 .

BigInteger value1 = new BigInteger("12");


BigInteger value2 = new BigInteger("18");

[Link] 140
[Link]([Link](value2));

Salida: 6

Máximo de dos BigIntegers:

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("11");

[Link]([Link](value2));

Salida: 11

Mínimo de dos BigIntegers:

BigInteger value1 = new BigInteger("10");


BigInteger value2 = new BigInteger("11");

[Link]([Link](value2));

Salida: 10

Operaciones de lógica binaria en BigInteger

BigInteger admite las operaciones lógicas binarias que también están disponibles para los tipos
de Number . Al igual que con todas las operaciones, se implementan llamando a un método.

Binario o

BigInteger val1 = new BigInteger("10");


BigInteger val2 = new BigInteger("9");

[Link](val2);

Salida: 11 (que es equivalente a 10 | 9 )

Binario y

BigInteger val1 = new BigInteger("10");


BigInteger val2 = new BigInteger("9");

[Link](val2);

Salida: 8 (que es equivalente a 10 & 9 )

Xor binario:

BigInteger val1 = new BigInteger("10");


BigInteger val2 = new BigInteger("9");

[Link] 141
[Link](val2);

Salida: 3 (que es equivalente a 10 ^ 9 )

Giro a la derecha:

BigInteger val1 = new BigInteger("10");

[Link](1); // the argument be an Integer

Salida: 5 (equivalente a 10 >> 1 )

Shift izquierdo:

BigInteger val1 = new BigInteger("10");

[Link](1); // here parameter should be Integer

Salida: 20 (equivalente a 10 << 1 )

Inversión binaria (no):

BigInteger val1 = new BigInteger("10");

[Link]();

Salida: 5

NAND (y no): *

BigInteger val1 = new BigInteger("10");


BigInteger val2 = new BigInteger("9");

[Link](val2);

Salida: 7

Generando BigIntegers aleatorios

La clase BigInteger tiene un constructor dedicado a generar BigIntegers aleatorios, dada una
instancia de [Link] y un int que especifica cuántos bits tendrá el BigInteger . Su uso es
bastante simple: cuando se llama al constructor BigInteger(int, Random) siguiente manera:

BigInteger randomBigInt = new BigInteger(bitCount, sourceOfRandomness);

luego terminarás con un BigInteger cuyo valor está entre 0 (inclusive) y 2 bitCount (exclusivo).

Esto también significa que el new BigInteger(2147483647, sourceOfRandomness) puede devolver todo
BigInteger positivo dado suficiente tiempo.

[Link] 142
¿Cuál será la sourceOfRandomness La sourceOfRandomness depende de usted. Por ejemplo, un new
Random() es suficientemente bueno en la mayoría de los casos:

new BigInteger(32, new Random());

Si está dispuesto a renunciar a la velocidad para obtener números aleatorios de mayor calidad,
puede usar un new SecureRandom () lugar:

import [Link];

// somewhere in the code...


new BigInteger(32, new SecureRandom());

¡Incluso puede implementar un algoritmo sobre la marcha con una clase anónima! Tenga en
cuenta que el despliegue de su propio algoritmo RNG lo terminará con una aleatoriedad de
baja calidad , por lo que siempre asegúrese de usar un algoritmo que se demuestre que sea
decente a menos que desee que los BigInteger resultantes sean predecibles.

new BigInteger(32, new Random() {


int seed = 0;

@Override
protected int next(int bits) {
seed = ((22695477 * seed) + 1) & 2147483647; // Values shamelessly stolen from
Wikipedia
return seed;
}
});

Lea BigInteger en línea: [Link]

[Link] 143
Capítulo 21: ByteBuffer
Introducción
La clase ByteBuffer se introdujo en Java 1.4 para facilitar el trabajo en datos binarios. Es
especialmente adecuado para usar con datos de tipo primitivo. Permite la creación, pero también
la manipulación posterior de un byte[] s en un nivel de abstracción superior

Sintaxis
• byte [] arr = new byte [1000];
• ByteBuffer buffer = [Link] (arr);
• ByteBuffer buffer = [Link] (1024);
• ByteBuffer buffer = [Link] (1024);
• byte b = [Link] ();
• byte b = [Link] (10);
• corto s = [Link] (10);
• [Link] ((byte) 120);
• [Link] ('a');

Examples
Uso básico - Creación de un ByteBuffer

Hay dos formas de crear un ByteBuffer , donde uno puede subdividirse de nuevo.

Si ya tiene un byte[] existente, puede "envolverlo" en un ByteBuffer para simplificar el


procesamiento:

byte[] reqBuffer = new byte[BUFFER_SIZE];


int readBytes = [Link](reqBuffer);
final ByteBuffer reqBufferWrapper = [Link](reqBuffer);

Esta sería una posibilidad para el código que maneja las interacciones de redes de bajo nivel.

Si no tiene un byte[] ya existente byte[] , puede crear un ByteBuffer sobre una matriz que está
asignada específicamente para el búfer de esta manera:

final ByteBuffer respBuffer = [Link](RESPONSE_BUFFER_SIZE);


putResponseData(respBuffer);
[Link]([Link]());

Si la ruta del código es extremadamente crítica para el rendimiento y necesita acceso directo a
la memoria del sistema , ByteBuffer puede incluso asignar búferes directos utilizando
#allocateDirect()

[Link] 144
Uso básico - Escribir datos en el búfer

Dado un ByteBuffer ejemplo uno puede escribir datos de tipo primitivo a él utilizando relativa y
absoluta put . La sorprendente diferencia es que al poner los datos utilizando el método relativo ,
se realiza un seguimiento del índice en el que se insertan los datos, mientras que el método
absoluto siempre requiere proporcionar un índice para put los datos.

Ambos métodos permiten "encadenar" llamadas. Dado un búfer suficientemente dimensionado,


se puede hacer lo siguiente:

[Link](0xCAFEBABE).putChar('c').putFloat(0.25).putLong(0xDEADBEEFCAFEBABE);

que es equivalente a:

[Link](0xCAFEBABE);
[Link]('c');
[Link](0.25);
[Link](0xDEADBEEFCAFEBABE);

Tenga en cuenta que el método que opera en byte s no tiene un nombre especial. Además, tenga
en cuenta que también es válido pasar tanto un ByteBuffer como un byte[] para put . Aparte de
eso, todos los tipos primitivos tienen métodos de put especializados.

Una nota adicional: el índice dado cuando se usa put* absoluto put* siempre se cuenta en byte .

Uso básico - Uso de DirectByteBuffer

DirectByteBuffer es una implementación especial de ByteBuffer que no tiene byte[] debajo.

Podemos asignar dicho ByteBuffer llamando a:

ByteBuffer directBuffer = [Link](16);

Esta operación asignará 16 bytes de memoria. El contenido de los buffers directos puede residir
fuera del montón de recolección de basura normal.

Podemos verificar si ByteBuffer es directo llamando a:

[Link](); // true

La principal característica de DirectByteBuffer es que JVM intentará trabajar de forma nativa en la


memoria asignada sin ningún búfer adicional, por lo que las operaciones realizadas en él pueden
ser más rápidas que las realizadas en ByteBuffers con arrays ubicados debajo.

Se recomienda usar DirectByteBuffer con operaciones de IO pesadas que dependen de la


velocidad de ejecución, como la comunicación en tiempo real.

Debemos tener en cuenta que si intentamos utilizar el método array() obtendremos la

[Link] 145
UnsupportedOperationException . Por lo tanto, es una buena práctica comprobar si nuestro
ByteBuffer lo tiene (matriz de bytes) antes de intentar acceder a él:

byte[] arrayOfBytes;
if([Link]()) {
arrayOfBytes = [Link]();
}

Otro uso del buffer de bytes directo es interoperar a través de JNI. Como un búfer de bytes directo
no usa un byte[] , sino un bloque de memoria real, es posible acceder a esa memoria
directamente a través de un puntero en el código nativo. Esto puede ahorrarle un poco de
problemas y gastos generales al calcular entre Java y la representación nativa de los datos.

La interfaz JNI define varias funciones para manejar buffers de bytes directos: Soporte NIO .

Lea ByteBuffer en línea: [Link]

[Link] 146
Capítulo 22: Calendario y sus subclases
Observaciones
A partir de Java 8, Calendar y sus subclases han sido reemplazados por el paquete [Link] y sus
subpaquetes. Deberían ser preferibles, a menos que una API heredada requiera Calendario.

Examples
Creando objetos de calendario

Calendar objetos del Calendar se pueden crear usando getInstance() o usando el constructor
GregorianCalendar .

Es importante tener en cuenta que los meses en el Calendar están basados en cero, lo que
significa que ENERO se representa con un valor int 0. Para proporcionar un mejor código,
siempre use las constantes del Calendar , como el [Link] . ENERO para evitar
malentendidos.

Calendar calendar = [Link]();


Calendar gregorianCalendar = new GregorianCalendar();
Calendar gregorianCalendarAtSpecificDay = new GregorianCalendar(2016, [Link], 1);
Calendar gregorianCalendarAtSpecificDayAndTime = new GregorianCalendar(2016, [Link],
1, 6, 55, 10);

Nota : utilice siempre las constantes del mes: la representación numérica es engañosa , por
ejemplo, [Link] tiene el valor 0

Aumentar / disminuir los campos del calendario

add() y roll() se pueden usar para aumentar / disminuir los campos del Calendar .

Calendar calendar = new GregorianCalendar(2016, [Link], 31); // 31 March 2016

El método add() afecta a todos los campos y se comporta de manera efectiva si se agregaran o
restaran fechas reales del calendario

[Link]([Link], -6);

La operación anterior elimina seis meses del calendario y nos lleva al 30 de septiembre de 2015.

Para cambiar un campo en particular sin afectar a los otros campos, use roll() .

[Link]([Link], -6);

La operación anterior elimina seis meses del mes actual, por lo que el mes se identifica como

[Link] 147
septiembre. Ningún otro campo ha sido ajustado; El año no ha cambiado con esta operación.

Encontrando AM / PM

Con la clase Calendario es fácil encontrar AM o PM.

Calendar cal = [Link]();


[Link](new Date());
if ([Link](Calendar.AM_PM) == [Link])
[Link]("It is PM");

Restando calendarios

Para obtener una diferencia entre dos Calendar , use el método getTimeInMillis() :

Calendar c1 = [Link]();
Calendar c2 = [Link]();
[Link]([Link], [Link]([Link]) + 1);

[Link]([Link]() - [Link]()); //outputs 86400000 (24 * 60 *


60 * 1000)

Lea Calendario y sus subclases en línea: [Link]


subclases

[Link] 148
Capítulo 23: Características de Java SE 7
Introducción
En este tema, encontrará un resumen de las nuevas características agregadas al lenguaje de
programación Java en Java SE 7. Hay muchas otras características nuevas en otros campos
como JDBC y Java Virtual Machine (JVM) que no se cubrirán. en este tema.

Observaciones
Mejoras en Java SE 7

Examples
Nuevas características del lenguaje de programación Java SE 7.

• Literales binarios : los tipos integrales (byte, short, int y long) también se pueden expresar
utilizando el sistema de números binarios. Para especificar un literal binario, agregue el
prefijo 0b o 0B al número.
• Cadenas en declaraciones de switch : puede usar un objeto String en la expresión de una
declaración de switch
• La declaración try-with-resources : La declaración try-with-resources es una declaración try
que declara uno o más recursos. Un recurso es como un objeto que debe cerrarse después
de que el programa haya terminado con él. La declaración try-with-resources asegura que
cada recurso se cierre al final de la declaración. Cualquier objeto que implemente
[Link], que incluye todos los objetos que implementan [Link],
puede usarse como un recurso.
• Captura de múltiples tipos de excepciones y reingreso de excepciones con la verificación de
tipos mejorada : un solo bloque de captura puede manejar más de un tipo de excepción.
Esta característica puede reducir la duplicación de código y disminuir la tentación de atrapar
una excepción demasiado amplia.
• Subrayados en literales numéricos : cualquier número de guiones bajos (_) puede aparecer
en cualquier lugar entre los dígitos en un literal numérico. Esta función le permite, por
ejemplo, separar grupos de dígitos en literales numéricos, lo que puede mejorar la
legibilidad de su código.
• Inferencia de tipos para la creación de instancias genéricas : puede reemplazar los
argumentos de tipo requeridos para invocar al constructor de una clase genérica con un
conjunto vacío de parámetros de tipo (<>) siempre que el compilador pueda inferir los
argumentos de tipo del contexto. Este par de soportes angulares se llama informalmente el
diamante.
• Advertencias y errores mejorados del compilador cuando se usan parámetros formales no
confiables con métodos de Varargs

Literales binarios

[Link] 149
// An 8-bit 'byte' value:
byte aByte = (byte)0b00100001;

// A 16-bit 'short' value:


short aShort = (short)0b1010000101000101;

// Some 32-bit 'int' values:


int anInt1 = 0b10100001010001011010000101000101;
int anInt2 = 0b101;
int anInt3 = 0B101; // The B can be upper or lower case.

// A 64-bit 'long' value. Note the "L" suffix:


long aLong = 0b1010000101000101101000010100010110100001010001011010000101000101L;

La declaración de prueba con recursos

El ejemplo lee la primera línea de un archivo. Utiliza una instancia de BufferedReader para leer
datos del archivo. BufferedReader es un recurso que debe cerrarse una vez que el programa haya
terminado con él:

static String readFirstLineFromFile(String path) throws IOException {


try (BufferedReader br = new BufferedReader(new FileReader(path))) {
return [Link]();
}
}

En este ejemplo, el recurso declarado en la declaración try-with-resources es un BufferedReader .


La declaración de declaración aparece entre paréntesis inmediatamente después de la palabra
clave try. La clase BufferedReader , en Java SE 7 y versiones posteriores, implementa la interfaz
[Link] . Debido a que la instancia de BufferedReader se declara en una sentencia
try-with-resource, se cerrará sin importar si la sentencia de prueba se completa normalmente o de
manera abrupta (como resultado del método [Link] una IOException ).

Subrayados en literales numéricos

El siguiente ejemplo muestra otras formas en que puede usar el guión bajo en literales numéricos:

long creditCardNumber = 1234_5678_9012_3456L;


long socialSecurityNumber = 999_99_9999L;
float pi = 3.14_15F;
long hexBytes = 0xFF_EC_DE_5E;
long hexWords = 0xCAFE_BABE;
long maxLong = 0x7fff_ffff_ffff_ffffL;
byte nybbles = 0b0010_0101;
long bytes = 0b11010010_01101001_10010100_10010010;

Puede colocar guiones bajos solo entre dígitos; No puedes colocar guiones bajos en los
siguientes lugares:

• Al principio o al final de un número


• Adyacente a un punto decimal en un literal de punto flotante
• Antes de un sufijo F o L

[Link] 150
• En posiciones donde se espera una cadena de dígitos

Inferencia de tipos para la creación de instancias genéricas

Puedes usar

Map<String, List<String>> myMap = new HashMap<>();

en lugar de

Map<String, List<String>> myMap = new HashMap<String, List<String>>();

Sin embargo, no puedes usar

List<String> list = new ArrayList<>();


[Link]("A");

// The following statement should fail since addAll expects


// Collection<? extends String>

[Link](new ArrayList<>());

porque no se puede compilar. Tenga en cuenta que el diamante a menudo funciona en las
llamadas de método; sin embargo, se sugiere que use el diamante principalmente para
declaraciones de variables.

Cadenas en las instrucciones del interruptor

public String getTypeOfDayWithSwitchStatement(String dayOfWeekArg) {


String typeOfDay;
switch (dayOfWeekArg) {
case "Monday":
typeOfDay = "Start of work week";
break;
case "Tuesday":
case "Wednesday":
case "Thursday":
typeOfDay = "Midweek";
break;
case "Friday":
typeOfDay = "End of work week";
break;
case "Saturday":
case "Sunday":
typeOfDay = "Weekend";
break;
default:
throw new IllegalArgumentException("Invalid day of the week: " + dayOfWeekArg);
}
return typeOfDay;
}

Lea Características de Java SE 7 en línea:

[Link] 151
[Link]

[Link] 152
Capítulo 24: Características de Java SE 8
Introducción
En este tema, encontrará un resumen de las nuevas características agregadas al lenguaje de
programación Java en Java SE 8. Hay muchas otras características nuevas en otros campos,
como JDBC y Java Virtual Machine (JVM) que no se cubrirán en este tema.

Observaciones
Referencia: Mejoras en Java SE 8.

Examples
Nuevas características del lenguaje de programación Java SE 8.

• Lambda Expressions , una nueva característica de lenguaje, se ha introducido en esta


versión. Le permiten tratar la funcionalidad como un argumento de método, o un código
como datos. Las expresiones Lambda le permiten expresar instancias de interfaces de un
solo método (denominadas interfaces funcionales) de manera más compacta.
○ Las referencias de los métodos proporcionan expresiones lambda fáciles de leer para
los métodos que ya tienen un nombre.
○ Los métodos predeterminados permiten agregar nuevas funciones a las interfaces de
las bibliotecas y garantizar la compatibilidad binaria con el código escrito para las
versiones anteriores de esas interfaces.
○ Las API nuevas y mejoradas que aprovechan las expresiones y secuencias de
Lambda en Java SE 8 describen clases nuevas y mejoradas que aprovechan las
expresiones y secuencias de lambda.
• Inferencia de tipos mejorada: el compilador de Java aprovecha la tipificación de destino para
inferir los parámetros de tipo de una invocación de método genérico. El tipo de destino de
una expresión es el tipo de datos que el compilador de Java espera dependiendo de dónde
aparezca la expresión. Por ejemplo, puede usar el tipo de destino de una declaración de
asignación para la inferencia de tipo en Java SE 7. Sin embargo, en Java SE 8, puede usar
el tipo de destino para la inferencia de tipo en más contextos.
○ Mecanografía de objetivos en expresiones Lambda
○ Inferencia de tipos
• Las anotaciones repetidas permiten aplicar el mismo tipo de anotación más de una vez a la
misma declaración o tipo de uso.
• Las anotaciones de tipo ofrecen la posibilidad de aplicar una anotación en cualquier lugar
donde se use un tipo, no solo en una declaración. Usada con un sistema de tipo enchufable,
esta característica permite una mejor verificación de tipos de su código.
• Reflexión de parámetros de método : puede obtener los nombres de los parámetros
formales de cualquier método o constructor con el método
[Link] . (Las clases Method y Constructor extienden la

[Link] 153
clase Executable y, por lo tanto, heredan el método [Link] ) Sin embargo,
los archivos .class no almacenan nombres de parámetros formales de forma
predeterminada. Para almacenar nombres de parámetros formales en un archivo .class
particular, y así habilitar la API de Reflection para recuperar nombres de parámetros
formales, compile el archivo de origen con la opción -parameters del compilador javac.
• Date-time-api - Se agregó una nueva api de tiempo en [Link] . Si se usa esto, no es
necesario que designe zona horaria.

Lea Características de Java SE 8 en línea:


[Link]

[Link] 154
Capítulo 25: Cargadores de clases
Observaciones
Un cargador de clases es una clase cuyo propósito principal es mediar la ubicación y carga de las
clases utilizadas por una aplicación. Un cargador de clases también puede encontrar y cargar
recursos .

Las clases estándar del cargador de clases pueden cargar clases y recursos de directorios en el
sistema de archivos y de archivos JAR y ZIP. También pueden descargar y almacenar en caché
los archivos JAR y ZIP desde un servidor remoto.

Los cargadores de clases normalmente están encadenados, de modo que la JVM intentará cargar
las clases de las bibliotecas de clases estándar con preferencia a las fuentes proporcionadas por
la aplicación. Los cargadores de clases personalizados permiten que el programador altere esto.
También puede hacer cosas como descifrar archivos de bytecode y modificación de bytecode.

Examples
Instalar y usar un cargador de clases

Este ejemplo básico muestra cómo una aplicación puede instanciar un cargador de clases y
usarlo para cargar dinámicamente una clase.

URL[] urls = new URL[] {new URL("file:/home/me/[Link]")};


Classloader loader = new URLClassLoader(urls);
Class<?> myObjectClass = [Link]("[Link]");

El cargador de clases creado en este ejemplo tendrá el cargador de clases predeterminado como
principal, y primero intentará encontrar cualquier clase en el cargador de clases principal antes de
buscar en "[Link]". Si la clase solicitada ya se ha cargado, la llamada findClass devolverá la
referencia a la clase cargada anteriormente.

La llamada a findClass puede fallar de varias maneras. Los más comunes son:

• Si no se puede encontrar la clase nombrada, la llamada con la ClassNotFoundException .


• Si la clase nombrada depende de alguna otra clase que no se puede encontrar, la llamada
lanzará NoClassDefFoundError .

Implementando un classLoader personalizado

Cada cargador personalizado debe extender directa o indirectamente la clase


[Link] . Los principales puntos de extensión son los siguientes métodos:

• findClass(String): sobrecargue este método si su cargador de clases sigue el modelo de


delegación estándar para la carga de clases.

[Link] 155
• loadClass(String, boolean) : sobrecargue este método para implementar un modelo de
delegación alternativo.
• findResource y findResources : sobrecargue estos métodos para personalizar la carga de
recursos.

Los métodos defineClass que son responsables de cargar realmente la clase desde una matriz de
bytes son final para evitar la sobrecarga. Cualquier comportamiento personalizado debe
realizarse antes de llamar a defineClass .

Aquí hay un sencillo que carga una clase específica de una matriz de bytes:

public class ByteArrayClassLoader extends ClassLoader {


private String classname;
private byte[] classfile;

public ByteArrayClassLoader(String classname, byte[] classfile) {


[Link] = classname;
[Link] = [Link]();
}

@Override
protected Class findClass(String classname) throws ClassNotFoundException {
if ([Link]([Link])) {
return defineClass(classname, classfile, 0, [Link]);
} else {
throw new ClassNotFoundException(classname);
}
}
}

Dado que solo hemos anulado el método findClass , este cargador de clases personalizado se
comportará de la siguiente manera cuando se llame a loadClass .

1. El método loadClass del cargador de clases llama a findLoadedClass para ver si este cargador
de clases ya ha cargado una clase con este nombre. Si eso tiene éxito, el objeto Class
resultante se devuelve al solicitante.
2. El método loadClass luego delega al cargador de clases principal llamando a su llamada
loadClass . Si el padre puede manejar la solicitud, devolverá un objeto de Class que luego se
devolverá al solicitante.
3. Si el cargador de clases principal no puede cargar la clase, findClass luego llama a nuestro
método findClass , pasando el nombre de la clase a cargar.
4. Si el nombre solicitado coincide con [Link] , llamamos a defineClass para cargar la
clase real de la [Link] bytes [Link] . El objeto de Class resultante se
devuelve.
5. Si el nombre no coincide, lanzamos la ClassNotFoundException .

Cargando un archivo .class externo

Para cargar una clase primero necesitamos definirla. La clase está definida por el ClassLoader .
Solo hay un problema, Oracle no escribió el código del ClassLoader con esta característica
disponible. Para definir la clase, necesitaremos acceder a un método llamado defineClass() que

[Link] 156
es un método privado del ClassLoader .

Para acceder a él, lo que haremos es crear una nueva clase, ByteClassLoader , y extenderla a
ClassLoader . Ahora que hemos extendido nuestra clase a ClassLoader , podemos acceder a los
métodos privados de ClassLoader . Para hacer que defineClass() esté disponible, crearemos un
nuevo método que actuará como un espejo para el método defineClass() privado. Para llamar al
método privado necesitaremos el nombre de la clase, name , los bytes de clase, classBytes , offset
del primer byte, que será 0 porque classBytes datos 'comienza en classBytes[0] , y offset del último
byte, que será [Link] porque representa el tamaño de los datos, que será el último
desplazamiento.

public class ByteClassLoader extends ClassLoader {

public Class<?> defineClass(String name, byte[] classBytes) {


return defineClass(name, classBytes, 0, [Link]);
}

Ahora, tenemos un defineClass() público defineClass() . Puede invocarse pasando el nombre de


la clase y los bytes de la clase como argumentos.

Digamos que tenemos una clase llamada MyClass en el paquete stackoverflow ...

Para llamar al método, necesitamos los bytes de la clase, así que creamos un objeto Path que
representa la ruta de nuestra clase usando el método [Link]() y pasando la ruta de la clase
binaria como un argumento. Ahora, podemos obtener los bytes de la clase con
[Link](path) . Así que creamos una instancia de ByteClassLoader y usamos el método
que creamos, defineClass() . Ya tenemos los bytes de clase, pero para llamar a nuestro método
también necesitamos el nombre de clase que viene dado por el nombre del paquete (punto) el
nombre canónico de clase, en este caso [Link] .

Path path = [Link]("[Link]");

ByteClassLoader loader = new ByteClassLoader();


[Link]("[Link]", [Link](path);

Nota : el método defineClass() devuelve un objeto Class<?> . Puedes guardarlo si quieres.

Para cargar la clase, solo llamamos a loadClass() y pasamos el nombre de la clase. Este método
puede lanzar una ClassNotFoundException por lo que necesitamos usar un bloque cat de prueba

try{
[Link]("[Link]");
} catch(ClassNotFoundException e){
[Link]();
}

Lea Cargadores de clases en línea: [Link]

[Link] 157
Capítulo 26: Cifrado RSA
Examples
Un ejemplo que utiliza un sistema criptográfico híbrido que consiste en OAEP
y GCM

El siguiente ejemplo encripta los datos utilizando un sistema criptográfico híbrido que consiste en
AES GCM y OAEP, utilizando sus tamaños de parámetros predeterminados y un tamaño de clave
AES de 128 bits.

OAEP es menos vulnerable al relleno de los ataques de Oracle que el relleno PKCS # 1 v1.5.
GCM también está protegido contra ataques oracle de relleno.

El descifrado se puede realizar recuperando primero la longitud de la clave encapsulada y luego


recuperando la clave encapsulada. La clave encapsulada se puede descifrar utilizando la clave
privada RSA que forma un par de claves con la clave pública. Después de eso, el texto cifrado
cifrado AES / GCM se puede descifrar al texto plano original.

El protocolo consiste en:

1. un campo de longitud para la clave RSAPrivateKey ( RSAPrivateKey pierde un método


getKeySize() );
2. la clave encapsulada / encapsulada, del mismo tamaño que el tamaño de la clave RSA en
bytes;
3. el texto cifrado GCM y la etiqueta de autenticación de 128 bits (agregada automáticamente
por Java).

Notas:

• Para utilizar correctamente este código, debe proporcionar una clave RSA de al menos
2048 bits; cuanto más grande, mejor (pero más lento, especialmente durante el descifrado);
• Para utilizar AES-256, primero debe instalar los archivos de políticas de criptografía ilimitada
;
• En lugar de crear su propio protocolo, es posible que desee utilizar un formato de
contenedor como la Sintaxis de mensajes criptográficos (CMS / PKCS # 7) o PGP en su
lugar.

Así que aquí está el ejemplo:

/**
* Encrypts the data using a hybrid crypto-system which uses GCM to encrypt the data and OAEP
to encrypt the AES key.
* The key size of the AES encryption will be 128 bit.
* All the default parameter choices are used for OAEP and GCM.
*
* @param publicKey the RSA public key used to wrap the AES key
* @param plaintext the plaintext to be encrypted, not altered

[Link] 158
* @return the ciphertext
* @throws InvalidKeyException if the key is not an RSA public key
* @throws NullPointerException if the plaintext is null
*/
public static byte[] encryptData(PublicKey publicKey, byte[] plaintext)
throws InvalidKeyException, NullPointerException {

// --- create the RSA OAEP cipher ---

Cipher oaep;
try {
// SHA-1 is the default and not vulnerable in this setting
// use OAEPParameterSpec to configure more than just the hash
oaep = [Link]("RSA/ECB/OAEPwithSHA1andMGF1Padding");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for RSA cipher (mandatory algorithm for
runtimes)", e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for OAEP padding (present in the standard Java
runtime sinze XX)", e);
}
[Link](Cipher.WRAP_MODE, publicKey);

// --- wrap the plaintext in a buffer

// will throw NullPointerException if plaintext is null


ByteBuffer plaintextBuffer = [Link](plaintext);

// --- generate a new AES secret key ---

KeyGenerator aesKeyGenerator;
try {
aesKeyGenerator = [Link]("AES");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES key generator (mandatory algorithm for
runtimes)", e);
}
// for AES-192 and 256 make sure you've got the rights (install the
// Unlimited Crypto Policy files)
[Link](128);
SecretKey aesKey = [Link]();

// --- wrap the new AES secret key ---

byte[] wrappedKey;
try {
wrappedKey = [Link](aesKey);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(
"AES key should always fit OAEP with normal sized RSA key", e);
}

// --- setup the AES GCM cipher mode ---

Cipher aesGCM;
try {
aesGCM = [Link]("AES/GCM/Nopadding");
// we can get away with a zero nonce since the key is randomly generated

[Link] 159
// 128 bits is the recommended (maximum) value for the tag size
// 12 bytes (96 bits) is the default nonce size for GCM mode encryption
GCMParameterSpec staticParameterSpec = new GCMParameterSpec(128, new byte[12]);
[Link](Cipher.ENCRYPT_MODE, aesKey, staticParameterSpec);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES cipher (mandatory algorithm for
runtimes)", e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for GCM (present in the standard Java runtime
sinze XX)", e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(
"IvParameterSpec not accepted by this implementation of GCM", e);
}

// --- create a buffer of the right size for our own protocol ---

ByteBuffer ciphertextBuffer = [Link](


[Link]
+ [Link](128 / [Link])
+ [Link]([Link]));

// - element 1: make sure that we know the size of the wrapped key
[Link]((short) [Link]);

// - element 2: put in the wrapped key


[Link](wrappedKey);

// - element 3: GCM encrypt into buffer


try {
[Link](plaintextBuffer, ciphertextBuffer);
} catch (ShortBufferException | IllegalBlockSizeException | BadPaddingException e) {
throw new RuntimeException("Cryptographic exception, AES/GCM encryption should not
fail here", e);
}

return [Link]();
}

Por supuesto, el cifrado no es muy útil sin descifrado. Tenga en cuenta que esto devolverá
información mínima si el descifrado falla.

/**
* Decrypts the data using a hybrid crypto-system which uses GCM to encrypt
* the data and OAEP to encrypt the AES key. All the default parameter
* choices are used for OAEP and GCM.
*
* @param privateKey
* the RSA private key used to unwrap the AES key
* @param ciphertext
* the ciphertext to be encrypted, not altered
* @return the plaintext
* @throws InvalidKeyException
* if the key is not an RSA private key
* @throws NullPointerException
* if the ciphertext is null
* @throws IllegalArgumentException
* with the message "Invalid ciphertext" if the ciphertext is invalid (minimize

[Link] 160
information leakage)
*/
public static byte[] decryptData(PrivateKey privateKey, byte[] ciphertext)
throws InvalidKeyException, NullPointerException {

// --- create the RSA OAEP cipher ---

Cipher oaep;
try {
// SHA-1 is the default and not vulnerable in this setting
// use OAEPParameterSpec to configure more than just the hash
oaep = [Link]("RSA/ECB/OAEPwithSHA1andMGF1Padding");
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for RSA cipher (mandatory algorithm for
runtimes)",
e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for OAEP padding (present in the standard Java
runtime sinze XX)",
e);
}
[Link](Cipher.UNWRAP_MODE, privateKey);

// --- wrap the ciphertext in a buffer

// will throw NullPointerException if ciphertext is null


ByteBuffer ciphertextBuffer = [Link](ciphertext);

// sanity check #1
if ([Link]() < 2) {
throw new IllegalArgumentException("Invalid ciphertext");
}
// - element 1: the length of the encapsulated key
int wrappedKeySize = [Link]() & 0xFFFF;
// sanity check #2
if ([Link]() < wrappedKeySize + 128 / [Link]) {
throw new IllegalArgumentException("Invalid ciphertext");
}

// --- unwrap the AES secret key ---

byte[] wrappedKey = new byte[wrappedKeySize];


// - element 2: the encapsulated key
[Link](wrappedKey);
SecretKey aesKey;
try {
aesKey = (SecretKey) [Link](wrappedKey, "AES",
Cipher.SECRET_KEY);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES cipher (mandatory algorithm for
runtimes)",
e);
} catch (InvalidKeyException e) {
throw new RuntimeException(
"Invalid ciphertext");
}

// --- setup the AES GCM cipher mode ---

[Link] 161
Cipher aesGCM;
try {
aesGCM = [Link]("AES/GCM/Nopadding");
// we can get away with a zero nonce since the key is randomly
// generated
// 128 bits is the recommended (maximum) value for the tag size
// 12 bytes (96 bits) is the default nonce size for GCM mode
// encryption
GCMParameterSpec staticParameterSpec = new GCMParameterSpec(128,
new byte[12]);
[Link](Cipher.DECRYPT_MODE, aesKey, staticParameterSpec);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(
"Runtime doesn't have support for AES cipher (mandatory algorithm for
runtimes)",
e);
} catch (NoSuchPaddingException e) {
throw new RuntimeException(
"Runtime doesn't have support for GCM (present in the standard Java runtime
sinze XX)",
e);
} catch (InvalidAlgorithmParameterException e) {
throw new RuntimeException(
"IvParameterSpec not accepted by this implementation of GCM",
e);
}

// --- create a buffer of the right size for our own protocol ---

ByteBuffer plaintextBuffer = [Link](aesGCM


.getOutputSize([Link]()));

// - element 3: GCM ciphertext


try {
[Link](ciphertextBuffer, plaintextBuffer);
} catch (ShortBufferException | IllegalBlockSizeException
| BadPaddingException e) {
throw new RuntimeException(
"Invalid ciphertext");
}

return [Link]();
}

Lea Cifrado RSA en línea: [Link]

[Link] 162
Capítulo 27: Clase - Reflexión de Java
Introducción
La clase [Link] proporciona muchos métodos que pueden usarse para obtener
metadatos, examinar y cambiar el comportamiento del tiempo de ejecución de una clase.

Los paquetes [Link] y [Link] proporcionan clases para la reflexión de java.

Donde se usa

La API de reflexión se utiliza principalmente en:

IDE (entorno de desarrollo integrado), por ejemplo, Eclipse, MyEclipse, NetBeans, etc.
Herramientas de prueba de depurador, etc.

Examples
Método getClass () de la clase Object.

class Simple { }

class Test {
void printName(Object obj){
Class c = [Link]();
[Link]([Link]());
}
public static void main(String args[]){
Simple s = new Simple();

Test t = new Test();


[Link](s);
}
}

Lea Clase - Reflexión de Java en línea: [Link]


reflexion-de-java

[Link] 163
Capítulo 28: Clase de fecha
Sintaxis
• Date object = new Date();
• Date object = new Date(long date);

Parámetros

Parámetro Explicación

Sin Crea un nuevo objeto Date utilizando el tiempo de asignación (al milisegundo
parametro más cercano)

Crea un nuevo objeto Fecha con la hora establecida en el número de


fecha larga
milisegundos desde "la época" (1 de enero de 1970, [Link] GMT)

Observaciones
Representación

Internamente, un objeto de fecha Java se representa como un largo; es el número de


milisegundos desde un tiempo específico (conocido como la época ). La clase de fecha de Java
original tenía métodos para tratar con zonas horarias, etc., pero estos estaban en desuso en favor
de la nueva clase de calendario.

Por lo tanto, si todo lo que desea hacer en su código es una hora específica, puede crear una
clase de Fecha y almacenarla, etc. Si desea imprimir una versión legible por humanos de esa
fecha, sin embargo, cree una clase de Calendario. y use su formato para producir horas, minutos,
segundos, días, zonas horarias, etc. Recuerde que un milisegundo específico se muestra como
horas diferentes en diferentes zonas horarias; Normalmente, usted desea mostrar uno en la zona
horaria "local", pero los métodos de formato deben tener en cuenta que es posible que desee
mostrarlo para otro.

También tenga en cuenta que los relojes utilizados por las JVM no suelen tener una precisión de
milisegundos; el reloj solo puede "marcar" cada 10 milisegundos y, por lo tanto, si sincroniza las
cosas, no puede confiar en medirlas con precisión a ese nivel.

Declaración de importación

import [Link];

La clase de Date se puede importar del paquete [Link] .

Precaución

[Link] 164
Date instancias de Date son mutables, por lo que su uso puede dificultar la escritura de código
seguro para subprocesos o puede proporcionar accidentalmente acceso de escritura al estado
interno. Por ejemplo, en la siguiente clase, el método getDate() permite a la persona que llama
modificar la fecha de la transacción:

public final class Transaction {


private final Date date;

public Date getTransactionDate() {


return date;
}
}

La solución es devolver una copia del campo de date o usar las nuevas API en [Link]
introducidas en Java 8.

La mayoría de los métodos de construcción en la clase Date han quedado en desuso y no deben
usarse. En casi todos los casos, es recomendable utilizar la clase Calendar para las operaciones
de fecha.

Java 8

Java 8 introduce una nueva API de fecha y hora en el paquete [Link] , que incluye LocalDate y
LocalTime . Las clases en el paquete [Link] proporcionan una API revisada que es más fácil
de usar. Si está escribiendo en Java 8, le recomendamos encarecidamente que utilice esta nueva
API. Consulte Fechas y hora ([Link]. *) .

Examples
Creando objetos de fecha

Date date = new Date();


[Link](date); // Thu Feb 25 [Link] IST 2016

Aquí, este objeto Date contiene la fecha y hora actuales en que se creó este objeto.

Calendar calendar = [Link]();


[Link](90, [Link], 11);
Date myBirthDate = [Link]();
[Link](myBirthDate); // Mon Dec 31 [Link] IST 1990

Date objetos de Date se crean mejor a través de una instancia de Calendar , ya que el uso de los
constructores de datos está obsoleto y no se recomienda. Para hacerlo, necesitamos obtener una
instancia de la clase Calendar del método de fábrica. Luego podemos establecer el año, mes y día
del mes utilizando números o, en el caso de las constantes de los meses que se proporcionan en
la clase Calendario, para mejorar la legibilidad y reducir los errores.

[Link](90, [Link], 11, 8, 32, 35);


Date myBirthDatenTime = [Link]();

[Link] 165
[Link](myBirthDatenTime); // Mon Dec 31 [Link] IST 1990

Junto con la fecha, también podemos pasar el tiempo en el orden de horas, minutos y segundos.

Comparando objetos de fecha

Calendario, fecha y fecha local


Java SE 8

Antes, después, compare y métodos iguales.


//Use of Calendar and Date objects
final Date today = new Date();
final Calendar calendar = [Link]();
[Link](1990, [Link], 1, 0, 0, 0);
Date birthdate = [Link]();

final Calendar calendar2 = [Link]();


[Link](1990, [Link], 1, 0, 0, 0);
Date samebirthdate = [Link]();

//Before example
[Link]("Is %1$tF before %2$tF? %3$b%n", today, birthdate,
[Link]([Link](birthdate)));
[Link]("Is %1$tF before %1$tF? %3$b%n", today, today,
[Link]([Link](today)));
[Link]("Is %2$tF before %1$tF? %3$b%n", today, birthdate,
[Link]([Link](today)));

//After example
[Link]("Is %1$tF after %2$tF? %3$b%n", today, birthdate,
[Link]([Link](birthdate)));
[Link]("Is %1$tF after %1$tF? %3$b%n", today, birthdate,
[Link]([Link](today)));
[Link]("Is %2$tF after %1$tF? %3$b%n", today, birthdate,
[Link]([Link](today)));

//Compare example
[Link]("Compare %1$tF to %2$tF: %3$d%n", today, birthdate,
[Link]([Link](birthdate)));
[Link]("Compare %1$tF to %1$tF: %3$d%n", today, birthdate,
[Link]([Link](today)));
[Link]("Compare %2$tF to %1$tF: %3$d%n", today, birthdate,
[Link]([Link](today)));

//Equal example
[Link]("Is %1$tF equal to %2$tF? %3$b%n", today, birthdate,
[Link]([Link](birthdate)));
[Link]("Is %1$tF equal to %2$tF? %3$b%n", birthdate, samebirthdate,
[Link]([Link](samebirthdate)));
[Link](
"Because [Link]() -> %1$d is different from [Link]() ->
%2$d, there are millisecondes!%n",

[Link] 166
[Link]([Link]()), [Link]([Link]()));

//Clear ms from calendars


[Link]([Link]);
[Link]([Link]);
birthdate = [Link]();
samebirthdate = [Link]();

[Link]("Is %1$tF equal to %2$tF after clearing ms? %3$b%n", birthdate,


samebirthdate,
[Link]([Link](samebirthdate)));

Java SE 8

isBefore, isAfter, compareTo y es igual a


métodos
//Use of LocalDate
final LocalDate now = [Link]();
final LocalDate birthdate2 = [Link](2012, 6, 30);
final LocalDate birthdate3 = [Link](2012, 6, 30);

//Hours, minutes, second and nanoOfsecond can also be configured with an other class
LocalDateTime
//[Link](year, month, dayOfMonth, hour, minute, second, nanoOfSecond);

//isBefore example
[Link]("Is %1$tF before %2$tF? %3$b%n", now, birthdate2,
[Link]([Link](birthdate2)));
[Link]("Is %1$tF before %1$tF? %3$b%n", now, birthdate2,
[Link]([Link](now)));
[Link]("Is %2$tF before %1$tF? %3$b%n", now, birthdate2,
[Link]([Link](now)));

//isAfter example
[Link]("Is %1$tF after %2$tF? %3$b%n", now, birthdate2,
[Link]([Link](birthdate2)));
[Link]("Is %1$tF after %1$tF? %3$b%n", now, birthdate2,
[Link]([Link](now)));
[Link]("Is %2$tF after %1$tF? %3$b%n", now, birthdate2,
[Link]([Link](now)));

//compareTo example
[Link]("Compare %1$tF to %2$tF %3$d%n", now, birthdate2,
[Link]([Link](birthdate2)));
[Link]("Compare %1$tF to %1$tF %3$d%n", now, birthdate2,
[Link]([Link](now)));
[Link]("Compare %2$tF to %1$tF %3$d%n", now, birthdate2,
[Link]([Link](now)));

//equals example
[Link]("Is %1$tF equal to %2$tF? %3$b%n", now, birthdate2,
[Link]([Link](birthdate2)));
[Link]("Is %1$tF to %2$tF? %3$b%n", birthdate2, birthdate3,
[Link]([Link](birthdate3)));

[Link] 167
//isEqual example
[Link]("Is %1$tF equal to %2$tF? %3$b%n", now, birthdate2,
[Link]([Link](birthdate2)));
[Link]("Is %1$tF to %2$tF? %3$b%n", birthdate2, birthdate3,
[Link]([Link](birthdate3)));

Comparación de fechas antes de Java 8


Antes de Java 8, las fechas podían compararse utilizando las clases [Link] y
[Link] . La clase de fecha ofrece 4 métodos para comparar fechas:

• después (fecha en que)


• antes (fecha en que)
• compareTo (fecha de otra fecha)
• es igual a (objeto obj)

after, before , compareTo y equals métodos comparan los valores devueltos por getTime () método
para cada fecha.

compareTo método compareTo devuelve un entero positivo.

• Valor mayor que 0: cuando la fecha es posterior al argumento de fecha


• Valor mayor que 0: cuando la fecha es anterior al argumento de fecha
• El valor es igual a 0: cuando la fecha es igual al argumento de la fecha

equals resultados equals pueden ser sorprendentes como se muestra en el ejemplo porque los
valores, como los milisegundos, no se inicializan con el mismo valor si no se dan explícitamente.

Desde Java 8
Con Java 8, está disponible un nuevo Objeto para trabajar con Fecha [Link] .
LocalDate implementa ChronoLocalDate , la representación abstracta de una fecha donde la
cronología, o sistema de calendario, es conectable.

Para tener la precisión de fecha y hora, se debe usar el objeto [Link] .


LocalDate y LocalDateTime usan el mismo nombre de método para comparar.

La comparación de fechas con LocalDate es diferente de usar ChronoLocalDate porque la cronología


o el sistema de calendario no se tienen en cuenta en la primera.

Debido a que la mayoría de las aplicaciones deben usar LocalDate , ChronoLocalDate no se incluye
en los ejemplos. Lectura adicional aquí .

La mayoría de las aplicaciones deben declarar firmas de métodos, campos y variables


como LocalDate, no esta interfaz [ChronoLocalDate].

LocalDate tiene 5 métodos para comparar fechas:

[Link] 168
• isAfter (ChronoLocalDate other)
• isBefore (ChronoLocalDate other)
• isEqual (ChronoLocalDate otro)
• compareTo (ChronoLocalDate otro)
• es igual a (objeto obj)

En el caso del parámetro LocalDate , isAfter , isBefore , isEqual , equals y compareTo ahora use este
método:

int compareTo0(LocalDate otherDate) {


int cmp = (year - [Link]);
if (cmp == 0) {
cmp = (month - [Link]);
if (cmp == 0) {
cmp = (day - [Link]);
}
}
return cmp;
}

equalsverificación de método si la referencia del parámetro es igual a la fecha primero, mientras


que isEqual llama directamente a compareTo0 .

En el caso de una instancia de otra clase de ChronoLocalDate las fechas se comparan utilizando el
Epoch Day la Epoch Day . El recuento del día de la época es un recuento incremental simple de días
donde el día 0 es 1970-01-01 (ISO).

Convertir la fecha a un determinado formato de cadena

format()de la clase SimpleDateFormat ayuda a convertir un objeto Date en cierto objeto String
formato utilizando la cadena de patrón suministrada.

Date today = new Date();

SimpleDateFormat dateFormat = new SimpleDateFormat("dd-MMM-yy"); //pattern is specified here


[Link]([Link](today)); //25-Feb-16

Los patrones se pueden aplicar de nuevo utilizando applyPattern()

[Link]("dd-MM-yyyy");
[Link]([Link](today)); //25-02-2016

[Link]("dd-MM-yyyy HH:mm:ss E");


[Link]([Link](today)); //25-02-2016 [Link] Thu

Nota: Aquí mm (letra minúscula m) denota minutos y MM (mayúscula M) denota mes. Preste mucha
atención al formatear los años: el capital "Y" ( Y ) indica la "semana del año", mientras que la
minúscula "y" ( y ) indica el año.

Convertir cadena en fecha

[Link] 169
parse() de la clase SimpleDateFormat ayuda a convertir un patrón de String en un objeto Date .

DateFormat dateFormat = [Link]([Link], [Link]);


String dateStr = "02/25/2016"; // input String
Date date = [Link](dateStr);
[Link]([Link]()); // 116

Hay 4 estilos diferentes para el formato de texto, SHORT , MEDIUM (este es el valor predeterminado),
LONG y FULL , todos los cuales dependen de la configuración regional. Si no se especifica una
configuración regional, se utiliza la configuración regional predeterminada del sistema.

Estilo [Link] [Link]

CORTO 30/6/09 30/06/09

MEDIO Jun 30, 2009 30 juin 2009

LARGO 30 de junio de 2009 30 juin 2009

COMPLETO Martes 30 de junio de 2009 mardi 30 juin 2009

Una fecha básica de salida.

Usando el siguiente código con la cadena de formato yyyy/MM/dd hh:[Link] , recibiremos la


siguiente salida

2016/04/19 11: 45.36

// define the format to use


String formatString = "yyyy/MM/dd hh:[Link]";

// get a current date object


Date date = [Link]().getTime();

// create the formatter


SimpleDateFormat simpleDateFormat = new SimpleDateFormat(formatString);

// format the date


String formattedDate = [Link](date);

// print it
[Link](formattedDate);

// single-line version of all above code


[Link](new SimpleDateFormat("yyyy/MM/dd
hh:[Link]").format([Link]().getTime()));

Convertir la representación de cadena formateada de la fecha en el objeto


Fecha

Este método se puede usar para convertir una representación de cadena formateada de una

[Link] 170
fecha en un objeto Date .

/**
* Parses the date using the given format.
*
* @param formattedDate the formatted date string
* @param dateFormat the date format which was used to create the string.
* @return the date
*/
public static Date parseDate(String formattedDate, String dateFormat) {
Date date = null;
SimpleDateFormat objDf = new SimpleDateFormat(dateFormat);
try {
date = [Link](formattedDate);
} catch (ParseException e) {
// Do what ever needs to be done with exception.
}
return date;
}

Creando una fecha específica

Si bien la clase de fecha de Java tiene varios constructores, notará que la mayoría está en
desuso. La única forma aceptable de crear una instancia de Fecha directamente es usando el
constructor vacío o pasando un largo (número de milisegundos desde el tiempo base estándar).
Tampoco son útiles a menos que esté buscando la fecha actual o tenga otra instancia de Date ya
disponible.

Para crear una nueva fecha, necesitará una instancia de Calendario. Desde allí puede establecer
la instancia de Calendario en la fecha que necesite.

Calendar c = [Link]();

Esto devuelve un nuevo conjunto de instancias de Calendario a la hora actual. El calendario tiene
muchos métodos para mutar su fecha y hora o establecerlo de forma absoluta. En este caso, lo
estableceremos en una fecha específica.

[Link](1974, 6, 2, 8, 0, 0);
Date d = [Link]();

El método getTime devuelve la instancia de fecha que necesitamos. Tenga en cuenta que los
métodos de configuración del calendario solo establecen uno o más campos, no los configuran
todos. Es decir, si establece el año, los otros campos permanecerán sin cambios.

TRAMPA

En muchos casos, este fragmento de código cumple su propósito, pero tenga en cuenta que dos
partes importantes de la fecha / hora no están definidas.

• los parámetros (1974, 6, 2, 8, 0, 0) se interpretan dentro de la zona horaria


predeterminada, definida en otro lugar,

[Link] 171
• los milisegundos no se establecen en cero, pero se llenan desde el reloj del sistema en el
momento en que se crea la instancia de Calendario.

Objetos Java 8 LocalDate y LocalDateTime

Los objetos Date y LocalDate no se pueden convertir exactamente entre sí ya que un objeto Date
representa un día y una hora específicos, mientras que un objeto LocalDate no contiene
información de hora o zona horaria. Sin embargo, puede ser útil convertir entre los dos si solo te
importa la información de la fecha real y no la información de la hora.

Crea una fecha local

// Create a default date


LocalDate lDate = [Link]();

// Creates a date from values


lDate = [Link](2017, 12, 15);

// create a date from string


lDate = [Link]("2017-12-15");

// creates a date from zone


[Link]([Link]());

Crea un LocalDateTime

// Create a default date time


LocalDateTime lDateTime = [Link]();

// Creates a date time from values


lDateTime = [Link](2017, 12, 15, 11, 30);

// create a date time from string


lDateTime = [Link]("2017-12-05T[Link]");

// create a date time from zone


[Link]([Link]());

Fecha local hasta la fecha y viceversa

Date date = [Link]([Link]());


ZoneId defaultZoneId = [Link]();

// Date to LocalDate
LocalDate localDate = [Link]().atZone(defaultZoneId).toLocalDate();

// LocalDate to Date
[Link]([Link](defaultZoneId).toInstant());

LocalDateTime to Date y viceversa

Date date = [Link]([Link]());


ZoneId defaultZoneId = [Link]();

[Link] 172
// Date to LocalDateTime
LocalDateTime localDateTime = [Link]().atZone(defaultZoneId).toLocalDateTime();

// LocalDateTime to Date
Date out = [Link]([Link](defaultZoneId).toInstant());

Zonas horarias y [Link]

Un objeto [Link] no tiene un concepto de zona horaria.

• No hay manera de establecer una zona horaria para una fecha


• No hay forma de cambiar la zona horaria de un objeto Date
• Un objeto Date creado con el new Date() constructor predeterminado new Date() se
inicializará con la hora actual en la zona horaria predeterminada del sistema

Sin embargo, es posible mostrar la fecha representada por el punto en el tiempo descrito por el
objeto Date en una zona horaria diferente utilizando, por ejemplo, [Link] :

Date date = new Date();


//print default time zone
[Link]([Link]().getDisplayName());
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //note: time zone not in
format!
//print date in the original time zone
[Link]([Link](date));
//current time in London
[Link]([Link]("Europe/London"));
[Link]([Link](date));

Salida:

Central European Time


2016-07-21 [Link]
2016-07-21 [Link]

Convertir [Link] a [Link]

[Link] to [Link] conversión suele ser necesaria cuando un objeto Date debe
escribirse en una base de datos.

[Link] es un envoltorio alrededor de un valor de milisegundos y JDBC utiliza para identificar


un tipo de SQL DATE

En el siguiente ejemplo, usamos el constructor [Link]() , que crea un objeto Date y lo


inicializa para representar el tiempo en el milisegundo más cercano. Esta fecha se utiliza en el
método convert([Link] utilDate) para devolver un objeto [Link]

Ejemplo

public class UtilToSqlConversion {

[Link] 173
public static void main(String args[])
{
[Link] utilDate = new [Link]();
[Link]("[Link] is : " + utilDate);
[Link] sqlDate = convert(utilDate);
[Link]("[Link] is : " + sqlDate);
DateFormat df = new SimpleDateFormat("dd/MM/YYYY - hh:mm:ss");
[Link]("dateFormated date is : " + [Link](utilDate));
}

private static [Link] convert([Link] uDate) {


[Link] sDate = new [Link]([Link]());
return sDate;
}

Salida

[Link] is : Fri Jul 22 [Link] IST 2016


[Link] is : 2016-07-22
dateFormated date is : 22/07/2016 - [Link]

[Link] información de fecha y hora, mientras que [Link] solo tiene


información de fecha

Hora local

Para usar solo la parte de tiempo de una fecha use LocalTime. Puede crear una instancia de un
objeto LocalTime en un par de maneras

1. LocalTime time = [Link]();


2. time = [Link];
3. time = [Link];
4. time = [Link](12, 12, 45);

LocalTime también tiene un método toString incorporado que muestra el formato muy bien.

[Link](time);

También puede obtener, sumar y restar horas, minutos, segundos y nanosegundos del objeto
LocalTime, es decir,

[Link](1);
[Link]();
[Link](1);

Puedes convertirlo en un objeto Date con el siguiente código:

LocalTime lTime = [Link]();


Instant instant = [Link]([Link](A_YEAR, A_MONTH, A_DAY)).
atZone([Link]()).toInstant();
Date time = [Link](instant);

[Link] 174
esta clase funciona muy bien dentro de una clase de temporizador para simular un reloj de
alarma.

Lea Clase de fecha en línea: [Link]

[Link] 175
Capítulo 29: Clase de objetos Métodos y
constructor
Introducción
Esta página de documentación sirve para mostrar detalles con ejemplos sobre constructores de
clases Java y sobre Métodos de clases de objetos que se heredan automáticamente de la
Superclase Object de cualquier clase recién creada.

Sintaxis
• Clase nativa final pública <?> getClass ()
• pública final vacío nativo notificar ()
• vacío nativo final público notificar a todos ()
• la espera de final nativa pública pública (tiempo de espera largo) lanza InterruptedException
• pública final void wait () lanza InterruptedException
• la espera de final público (tiempo de espera largo, int nanos) lanza la excepción
interrumpida
• código nativo int local ()
• booleanos públicos iguales (objeto obj)
• Cadena pública a la cadena ()
• El objeto nativo protegido clone () lanza la excepción CloneNotSupportedException
• vacío vacío finalizado () lanza Throwable

Examples
método toString ()

El método toString() se usa para crear una representación de String de un objeto utilizando el
contenido del objeto. Este método debe ser anulado al escribir su clase. toString() se llama
implícitamente cuando un objeto se concatena a una cadena como en "hello " + anObject .

Considera lo siguiente:

public class User {


private String firstName;
private String lastName;

public User(String firstName, String lastName) {


[Link] = firstName;
[Link] = lastName;
}

@Override
public String toString() {
return firstName + " " + lastName;

[Link] 176
}

public static void main(String[] args) {


User user = new User("John", "Doe");
[Link]([Link]()); // Prints "John Doe"
}
}

Aquí toString() de la clase Object se reemplaza en la clase User para proporcionar datos
significativos sobre el objeto al imprimirlo.

Cuando se utiliza println() , el método toString() del objeto se llama implícitamente. Por lo tanto,
estas declaraciones hacen lo mismo:

[Link](user); // toString() is implicitly called on `user`


[Link]([Link]());

Si el toString() no se reemplaza en la clase de User mencionada anteriormente,


[Link](user) puede devolver User@659e0bfd o una cadena similar casi sin información
útil, excepto el nombre de la clase. Esto se debe a que la llamada usará la implementación
toString() de la clase de Object Java base que no sabe nada sobre la estructura de la clase de
User o las reglas de negocios. Si desea cambiar esta funcionalidad en su clase, simplemente
anule el método.

método igual ()

TL; DR

== pruebas de igualdad de referencia (si son el mismo objeto )

.equals() comprueba la igualdad de valores (si son lógicamente "iguales" )

equals() es un método usado para comparar dos objetos para la igualdad. La implementación
predeterminada del método equals() en la clase Object devuelve true si y solo si ambas
referencias apuntan a la misma instancia. Por lo tanto, se comporta igual que la comparación por
== .

public class Foo {


int field1, field2;
String field3;

public Foo(int i, int j, String k) {


field1 = i;
field2 = j;
field3 = k;
}

public static void main(String[] args) {


Foo foo1 = new Foo(0, 0, "bar");
Foo foo2 = new Foo(0, 0, "bar");

[Link]([Link](foo2)); // prints false

[Link] 177
}
}

Aunque foo1 y foo2 se crean con los mismos campos, apuntan a dos objetos diferentes en la
memoria. La implementación por defecto de equals() por lo tanto, se evalúa como false .

Para comparar el contenido de un objeto para la igualdad, se debe anular equals() .

public class Foo {


int field1, field2;
String field3;

public Foo(int i, int j, String k) {


field1 = i;
field2 = j;
field3 = k;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}

Foo f = (Foo) obj;


return field1 == f.field1 &&
field2 == f.field2 &&
(field3 == null ? f.field3 == null : [Link](f.field3));
}

@Override
public int hashCode() {
int hash = 1;
hash = 31 * hash + this.field1;
hash = 31 * hash + this.field2;
hash = 31 * hash + (field3 == null ? 0 : [Link]());
return hash;
}

public static void main(String[] args) {


Foo foo1 = new Foo(0, 0, "bar");
Foo foo2 = new Foo(0, 0, "bar");

[Link]([Link](foo2)); // prints true


}
}

Aquí el método equals() anulado decide que los objetos son iguales si sus campos son iguales.

Observe que el método hashCode() también se sobrescribió. El contrato para ese método
establece que cuando dos objetos son iguales, sus valores hash también deben ser iguales. Es
por eso que uno casi siempre debe reemplazar hashCode() y equals() juntos.

Preste especial atención al tipo de argumento del método equals . Es el Object obj , no Foo obj . Si

[Link] 178
coloca este último en su método, eso no es una anulación del método equals .

Al escribir su propia clase, tendrá que escribir una lógica similar cuando se reemplaza a equals() y
hashCode() . La mayoría de los IDE pueden generar esto automáticamente por ti.

Se puede encontrar un ejemplo de una implementación equals() en la clase String , que forma
parte de la API de Java central. En lugar de comparar punteros, la clase String compara el
contenido de String .

Java SE 7

Java 1.7 introdujo la clase [Link] que proporciona un método conveniente, equals , que
compara dos referencias potencialmente null , por lo que puede usarse para simplificar
implementaciones del método equals .

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}

Foo f = (Foo) obj;


return field1 == f.field1 && field2 == f.field2 && [Link](field3, f.field3);
}

Comparación de clases
Dado que el método equals puede ejecutarse contra cualquier objeto, una de las primeras cosas
que el método hace a menudo (después de verificar si es null ) es verificar si la clase del objeto
que se está comparando coincide con la clase actual.

@Override
public boolean equals(Object obj) {
//...check for null
if (getClass() != [Link]()) {
return false;
}
//...compare fields
}

Esto se hace normalmente como se muestra arriba comparando los objetos de clase. Sin
embargo, eso puede fallar en algunos casos especiales que pueden no ser obvios. Por ejemplo,
algunos marcos generan proxies dinámicos de clases y estos proxies dinámicos son en realidad
una clase diferente. Aquí hay un ejemplo usando JPA.

Foo detachedInstance = ...


Foo mergedInstance = [Link](detachedInstance);
if ([Link](detachedInstance)) {
//Can never get here if equality is tested with getClass()

[Link] 179
//as mergedInstance is a proxy (subclass) of Foo
}

Un mecanismo para evitar esa limitación es comparar clases usando instanceof

@Override
public final boolean equals(Object obj) {
if (!(obj instanceof Foo)) {
return false;
}
//...compare fields
}

Sin embargo, hay algunos escollos que se deben evitar al usar instanceof . Como Foo podría
tener otras subclases y esas subclases podrían reemplazar a equals() , podría entrar en un caso
en el que un Foo es igual a una FooSubclass pero la FooSubclass Foo no es igual a Foo .

Foo foo = new Foo(7);


FooSubclass fooSubclass = new FooSubclass(7, false);
[Link](fooSubclass) //true
[Link](foo) //false

Esto viola las propiedades de simetría y transitividad y, por lo tanto, es una implementación no
válida del método equals() . Como resultado, cuando se utiliza instanceof , una buena práctica es
hacer que el método equals() final (como en el ejemplo anterior). Esto asegurará que ninguna
anulación de subclase sea equals() y viole las suposiciones clave.

método hashCode ()

Cuando una clase de Java anula el método equals , también debería anular el método hashCode .
Como se define en el contrato del método :

• Cada vez que se invoca en el mismo objeto más de una vez durante una
ejecución de una aplicación Java, el método hashCode debe devolver
constantemente el mismo número entero, siempre que no se modifique la
información utilizada en comparaciones iguales en el objeto. No es necesario
que este número entero permanezca consistente de una ejecución de una
aplicación a otra ejecución de la misma aplicación.
• Si dos objetos son iguales según el método equals(Object) , entonces llamar al
método hashCode en cada uno de los dos objetos debe producir el mismo
resultado entero.
• No es necesario que si dos objetos son desiguales según el método
equals(Object) , llamar al método hashCode en cada uno de los dos objetos debe
producir resultados enteros distintos. Sin embargo, el programador debe tener en
cuenta que producir resultados enteros distintos para objetos desiguales puede
mejorar el rendimiento de las tablas hash.

Los códigos hash se utilizan en implementaciones de hash como HashMap , HashTable y HashSet . El
resultado de la función hashCode determina el grupo en el que se colocará un objeto. Estas

[Link] 180
implementaciones de hash son más eficientes si la implementación de hashCode proporcionada es
buena. Una propiedad importante de una buena implementación de hashCode es que la distribución
de los valores de hashCode es uniforme. En otras palabras, existe una pequeña probabilidad de
que numerosas instancias se almacenen en el mismo cubo.

Un algoritmo para calcular un valor de código hash puede ser similar al siguiente:

public class Foo {


private int field1, field2;
private String field3;

public Foo(int field1, int field2, String field3) {


this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}

Foo f = (Foo) obj;


return field1 == f.field1 &&
field2 == f.field2 &&
(field3 == null ? f.field3 == null : [Link](f.field3);
}

@Override
public int hashCode() {
int hash = 1;
hash = 31 * hash + field1;
hash = 31 * hash + field2;
hash = 31 * hash + (field3 == null ? 0 : [Link]());
return hash;
}
}

Usando [Link] () como un atajo


Java SE 1.2

En Java 1.2 y superior, en lugar de desarrollar un algoritmo para calcular un código hash, se
puede generar uno utilizando [Link]#hashCode proporcionando un objeto o una matriz de
primitivas que contiene los valores de campo:

@Override
public int hashCode() {
return [Link](new Object[] {field1, field2, field3});
}

Java SE 7

[Link] 181
Java 1.7 introdujo la clase [Link] que proporciona un método conveniente,
hash(Object... objects) , que calcula un código hash basado en los valores de los objetos que se
le suministran. Este método funciona igual que [Link]#hashCode .

@Override
public int hashCode() {
return [Link](field1, field2, field3);
}

Nota: este enfoque es ineficiente y produce objetos de basura cada vez que se llama a su método
hashCode() personalizado:

• Se crea un Object[] temporal Object[] . (En la versión [Link]() , la matriz se crea


mediante el mecanismo "varargs").
• Si alguno de los campos son tipos primitivos, deben estar recuadrados y eso puede crear
más objetos temporales.
• La matriz debe estar poblada.
• La matriz debe [Link] [Link] método [Link] o [Link] .
• Las llamadas a [Link]() que [Link] o [Link] tiene que hacer
(probablemente) no se pueden insertar.

Caché interno de códigos hash


Dado que el cálculo del código hash de un objeto puede ser costoso, puede ser atractivo
almacenar el valor del código hash en el objeto la primera vez que se calcula. Por ejemplo

public final class ImmutableArray {


private int[] array;
private volatile int hash = 0;

public ImmutableArray(int[] initial) {


array = [Link]();
}

// Other methods

@Override
public boolean equals(Object obj) {
// ...
}

@Override
public int hashCode() {
int h = hash;
if (h == 0) {
h = [Link](array);
hash = h;
}
return h;
}
}

Este enfoque intercambia el costo de (repetidamente) calcular el código hash contra la

[Link] 182
sobrecarga de un campo adicional para almacenar en caché el código hash. Si esto se amortiza
como una optimización del rendimiento dependerá de la frecuencia con la que se halle (busque)
un objeto determinado y otros factores.

También notará que si el verdadero código hash de un ImmutableArray es cero (una posibilidad en
2 32 ), el caché no es efectivo.

Finalmente, este enfoque es mucho más difícil de implementar correctamente si el objeto que
estamos haciendo hash es mutable. Sin embargo, hay mayores preocupaciones si los códigos
hash cambian; Consulte el contrato anterior.

Métodos de esperar () y notificar ()

wait() y notify() trabajan en tándem: cuando un subproceso llama a wait() en un objeto, ese
subproceso se bloqueará hasta que otro subproceso llame a notify() o notifyAll() en ese mismo
objeto.

(Ver también: esperar () / notificar () )

package [Link];

import [Link];

public class WaitAndNotify {

public static void main(String[] args) throws InterruptedException {


final Object obj = new Object();
AtomicBoolean aHasFinishedWaiting = new AtomicBoolean(false);

Thread threadA = new Thread("Thread A") {


public void run() {
[Link]("A1: Could print before or after B1");
[Link]("A2: Thread A is about to start waiting...");
try {
synchronized (obj) { // wait() must be in a synchronized block
// execution of thread A stops until [Link]() is called
[Link]();
}
[Link]("A3: Thread A has finished waiting. "
+ "Guaranteed to happen after B3");
} catch (InterruptedException e) {
[Link]("Thread A was interrupted while waiting");
} finally {
[Link](true);
}
}
};

Thread threadB = new Thread("Thread B") {


public void run() {
[Link]("B1: Could print before or after A1");

[Link]("B2: Thread B is about to wait for 10 seconds");


for (int i = 0; i < 10; i++) {
try {
[Link](1000); // sleep for 1 second

[Link] 183
} catch (InterruptedException e) {
[Link]("Thread B was interrupted from waiting");
}
}

[Link]("B3: Will ALWAYS print before A3 since "


+ "A3 can only happen after [Link]() is called.");

while (![Link]()) {
synchronized (obj) {
// notify ONE thread which has called [Link]()
[Link]();
}
}
}
};

[Link]();
[Link]();

[Link]();
[Link]();

[Link]("Finished!");
}
}

Algunos ejemplos de salida:

A1: Could print before or after B1


B1: Could print before or after A1
A2: Thread A is about to start waiting...
B2: Thread B is about to wait for 10 seconds
B3: Will ALWAYS print before A3 since A3 can only happen after [Link]() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

B1: Could print before or after A1


B2: Thread B is about to wait for 10 seconds
A1: Could print before or after B1
A2: Thread A is about to start waiting...
B3: Will ALWAYS print before A3 since A3 can only happen after [Link]() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

A1: Could print before or after B1


A2: Thread A is about to start waiting...
B1: Could print before or after A1
B2: Thread B is about to wait for 10 seconds
B3: Will ALWAYS print before A3 since A3 can only happen after [Link]() is called.
A3: Thread A has finished waiting. Guaranteed to happen after B3
Finished!

método getClass ()

El método getClass() se puede usar para encontrar el tipo de clase de tiempo de ejecución de un
objeto. Vea el ejemplo a continuación:

[Link] 184
public class User {

private long userID;


private String name;

public User(long userID, String name) {


[Link] = userID;
[Link] = name;
}
}

public class SpecificUser extends User {


private String specificUserID;

public SpecificUser(String specificUserID, long userID, String name) {


super(userID, name);
[Link] = specificUserID;
}
}

public static void main(String[] args){


User user = new User(879745, "John");
SpecificUser specificUser = new SpecificUser("1AAAA", 877777, "Jim");
User anotherSpecificUser = new SpecificUser("1BBBB", 812345, "Jenny");

[Link]([Link]()); //Prints "class User"


[Link]([Link]()); //Prints "class SpecificUser"
[Link]([Link]()); //Prints "class SpecificUser"
}

El método getClass() devolverá el tipo de clase más específico, por lo que cuando se llama a
getClass() en anotherSpecificUser , el valor devuelto es la class SpecificUser porque es más bajo
en el árbol de herencia que el User .

Es de destacar que, mientras que el método getClass se declara como:

public final native Class<?> getClass();

El tipo estático real devuelto por una llamada a getClass es Class<? extends T> donde T es el tipo
estático del objeto en el que se llama a getClass .

Es decir, lo siguiente compilará:

Class<? extends String> cls = "".getClass();

método clone ()

El método clone() se utiliza para crear y devolver una copia de un objeto. Este método discutible
debe evitarse ya que es problemático y se debe utilizar un constructor de copia o algún otro
método para copiar en favor de clone() .

Para que el método se use, todas las clases que llaman al método deben implementar la interfaz
Cloneable .

[Link] 185
La interfaz Cloneable en sí misma es solo una interfaz de etiqueta utilizada para cambiar el
comportamiento del método native clone() que verifica si la clase de objetos llamantes
implementa Cloneable . Si la persona que llama no implementa esta interfaz, se
CloneNotSupportedException una CloneNotSupportedException .

La clase Object sí no implementa esta interfaz, por lo que se CloneNotSupportedException una


CloneNotSupportedException si el objeto que llama es de la clase Object .

Para que un clon sea correcto, debe ser independiente del objeto desde el cual se está clonando,
por lo tanto, puede ser necesario modificar el objeto antes de que se devuelva. Esto significa
crear esencialmente una "copia profunda" copiando también cualquiera de los objetos mutables
que conforman la estructura interna del objeto que se está clonando. Si esto no se implementa
correctamente, el objeto clonado no será independiente y tendrá las mismas referencias a los
objetos mutables que el objeto desde el que se clonó. Esto resultaría en un comportamiento
inconsistente ya que cualquier cambio en aquellos en uno afectaría al otro.

class Foo implements Cloneable {


int w;
String x;
float[] y;
Date z;

public Foo clone() {


try {
Foo result = new Foo();
// copy primitives by value
result.w = this.w;
// immutable objects like String can be copied by reference
result.x = this.x;

// The fields y and z refer to a mutable objects; clone them recursively.


if (this.y != null) {
result.y = [Link]();
}
if (this.z != null) {
result.z = [Link]();
}

// Done, return the new object


return result;

} catch (CloneNotSupportedException e) {
// in case any of the cloned mutable fields do not implement Cloneable
throw new AssertionError(e);
}
}
}

finalizar () método

Este es un método protegido y no estático de la clase Object . Este método se utiliza para realizar
algunas operaciones finales o limpiar operaciones en un objeto antes de que se elimine de la
memoria.

[Link] 186
Según el documento, este método es llamado por el recolector de basura en un objeto
cuando la recolección de basura determina que no hay más referencias al objeto.

Pero no hay garantías de que se llame al método finalize() si el objeto aún es accesible o si no
se ejecuta ningún recolector de basura cuando el objeto es elegible. Es por eso que es mejor no
confiar en este método.

En las bibliotecas principales de Java, se pueden encontrar algunos ejemplos de uso, por
ejemplo, en [Link] :

protected void finalize() throws IOException {


if ((fd != null) && (fd != [Link])) {
/* if fd is shared, the references in FileDescriptor
* will ensure that finalizer is only called when
* safe to do so. All references using the fd have
* become unreachable. We can call close()
*/
close();
}
}

En este caso, es la última oportunidad de cerrar el recurso si ese recurso no se ha cerrado antes.

En general, se considera una mala práctica utilizar el método finalize() en aplicaciones de


cualquier tipo y debe evitarse.

Los finalizadores no están destinados a liberar recursos (por ejemplo, cerrar archivos). Se llama al
recolector de basura cuando (si!) El sistema se queda con poco espacio de almacenamiento. No
se puede confiar en que se llame cuando el sistema se esté quedando sin los manejadores de
archivos o, por cualquier otro motivo.

El caso de uso previsto para los finalizadores es para un objeto que está a punto de ser
reclamado para notificar a otro objeto sobre su inminente destino. Ahora existe un mejor
mecanismo para ese propósito: la clase [Link]<T> . Si crees que necesitas
escribir un método finalize() , entonces deberías investigar si puedes resolver el mismo
problema usando WeakReference . Si eso no resuelve su problema, es posible que deba volver a
pensar su diseño en un nivel más profundo.

Para leer más aquí, hay un artículo sobre el método finalize() del libro "Effective Java" de
Joshua Bloch.

Constructor de objetos

Todos los constructores en Java deben hacer una llamada al constructor de Object . Esto se hace
con la llamada super() . Esta tiene que ser la primera línea en un constructor. La razón de esto es
para que el objeto se pueda crear realmente en el montón antes de que se realice una
inicialización adicional.

Si no especifica la llamada a super() en un constructor, el compilador la colocará por usted.

Así que los tres de estos ejemplos son funcionalmente idénticos

[Link] 187
con llamada explícita a super() constructor

public class MyClass {

public MyClass() {
super();
}
}

con llamada implícita a super() constructor

public class MyClass {

public MyClass() {
// empty
}
}

con constructor implícito

public class MyClass {

¿Qué pasa con el encadenamiento de constructores?

Es posible llamar a otros constructores como la primera instrucción de un constructor. Como tanto
la llamada explícita a un súper constructor como la llamada a otro constructor tienen que ser las
dos primeras instrucciones, se excluyen mutuamente.

public class MyClass {

public MyClass(int size) {

doSomethingWith(size);

public MyClass(Collection<?> initialValues) {

this([Link]());
addInitialValues(initialValues);
}
}

Llamar a la nueva MyClass([Link]("a", "b", "c")) llamará al segundo constructor con el


argumento Lista, que a su vez delegará al primer constructor (que delegará implícitamente a
super() ) y luego llame a addInitialValues(int size) con el segundo tamaño de la lista. Esto se
usa para reducir la duplicación de código donde varios constructores necesitan hacer el mismo
trabajo.

¿Cómo llamo a un constructor específico?

[Link] 188
Dado el ejemplo anterior, uno puede llamar a new MyClass("argument") o new MyClass("argument", 0)
. En otras palabras, al igual que la sobrecarga de métodos , simplemente llame al constructor con
los parámetros que son necesarios para su constructor elegido.

¿Qué pasará en el constructor de la clase Object?

Nada más de lo que sucedería en una subclase que tiene un constructor vacío predeterminado
(menos la llamada a super() ).

El constructor vacío predeterminado se puede definir explícitamente, pero si no, el compilador lo


incluirá siempre que no haya otros constructores definidos.

¿Cómo se crea un Objeto a partir del constructor en Objeto?

La creación real de objetos se reduce a la JVM. Cada constructor en Java aparece como un
método especial llamado <init> que es responsable de la inicialización de la instancia. El
compilador suministra este método <init> y debido a que <init> no es un identificador válido en
Java, no se puede usar directamente en el lenguaje.

¿Cómo invoca la JVM este método <init> ?

La JVM invocará el método <init> utilizando la instrucción especial invokespecial y solo puede
invocarse en instancias de clase sin inicializar.

Para obtener más información, consulte la especificación JVM y la especificación del lenguaje
Java:

• Métodos especiales (JVM) - JVMS - 2.9


• Constructores - JLS - 8.8

Lea Clase de objetos Métodos y constructor en línea:


[Link]

[Link] 189
Capítulo 30: Clase de propiedades
Introducción
El objeto de propiedades contiene un par de clave y valor tanto como una cadena. La clase
[Link] es la subclase de Hashtable.

Se puede utilizar para obtener el valor de la propiedad en función de la clave de propiedad. La


clase de propiedades proporciona métodos para obtener datos del archivo de propiedades y
almacenar datos en el archivo de propiedades. Por otra parte, se puede utilizar para obtener
propiedades del sistema.

Ventaja del archivo de propiedades

No se requiere la compilación, si la información se cambia desde el archivo de propiedades: si se


cambia alguna información de

Sintaxis
• En un archivo de propiedades:
• clave = valor
• #comentario

Observaciones
Un objeto de propiedades es un mapa cuyas claves y valores son cadenas por convención.
Aunque los métodos de Map se pueden usar para acceder a los datos, los métodos getProperty ,
setProperty y stringPropertyNames más seguros para el uso de tipos se usan en su lugar.

Las propiedades se almacenan con frecuencia en archivos de propiedades Java, que son
archivos de texto simples. Su formato está documentado a fondo en el método [Link] .
En resumen:

• Cada par clave / valor es una línea de texto con espacios en blanco, es igual a ( = ), o colon
( : ) entre la llave y el valor. Los iguales o dos puntos pueden tener cualquier cantidad de
espacios en blanco antes y después, que se ignora.
• Los espacios en blanco iniciales siempre se ignoran, los espacios en blanco finales se
incluyen siempre.
• Se puede usar una barra invertida para escapar de cualquier carácter (excepto en
minúsculas u ).
• Una barra invertida al final de la línea indica que la siguiente línea es una continuación de la
línea actual. Sin embargo, al igual que con todas las líneas, los espacios en blanco iniciales
en la línea de continuación se ignoran.
• Al igual que en el código fuente de Java, \u seguido de cuatro dígitos hexadecimales
representa un carácter UTF-16.

[Link] 190
La mayoría de los marcos, incluidas las instalaciones propias de Java SE como
[Link], cargan archivos de propiedades como InputStreams. Al cargar un
archivo de propiedades desde un InputStream, ese archivo solo puede contener caracteres ISO
8859-1 (es decir, caracteres en el rango de 0 a 255). Cualquier otro personaje debe ser
representado como \u escapa. Sin embargo, puede escribir un archivo de texto en cualquier
codificación y usar la herramienta native2ascii (que viene con cada JDK) para hacer ese escape
por usted.

Si va a cargar un archivo de propiedades con su propio código, que puede ser en cualquier
codificación, siempre y cuando se crea un lector (como un InputStreamReader ) basado en el
correspondiente conjunto de caracteres . Luego puede cargar el archivo usando load (Reader) en
lugar del método de carga heredado (InputStream).

También puede almacenar propiedades en un archivo XML simple, lo que permite que el propio
archivo defina la codificación. Dicho archivo se puede cargar con el método loadFromXML . La
DTD que describe la estructura de dichos archivos XML se encuentra en
[Link] .

Examples
Cargando propiedades

Para cargar un archivo de propiedades empaquetado con su aplicación:

public class Defaults {

public static Properties loadDefaults() {


try (InputStream bundledResource =
[Link]("[Link]")) {

Properties defaults = new Properties();


[Link](bundledResource);
return defaults;
} catch (IOException e) {
// Since the resource is bundled with the application,
// we should never get here.
throw new UncheckedIOException(
"[Link] not properly packaged"
+ " with application", e);
}
}

Los archivos de propiedades advierten: espacios en blanco al final

Eche un vistazo de cerca a estos dos archivos de propiedades que parecen ser completamente
idénticos:

[Link] 191
excepto que en realidad no son idénticos:

(las capturas de pantalla son de Notepad ++)

Dado que el espacio en blanco se conserva, el valor de lastName sería "Smith" en el primer caso y
"Smith " en el segundo.

Muy raramente, esto es lo que los usuarios esperan y uno y solo puede especular por qué este es
el comportamiento predeterminado de la clase Properties . Sin embargo, es fácil crear una versión
mejorada de Properties que solucione este problema. La siguiente clase, TrimmedProperties ,
hace justamente eso. Es un reemplazo directo para la clase de propiedades estándar.

import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];

/**
* Properties class where values are trimmed for trailing whitespace if the
* properties are loaded from a file.
*
* <p>
* In the standard {@link [Link] Properties} class trailing
* whitespace is always preserved. When loading properties from a file such
* trailing whitespace is almost always <i>unintentional</i>. This class fixes
* this problem. The trimming of trailing whitespace only takes place if the
* source of input is a file and only where the input is line oriented (meaning
* that for example loading from XML file is <i>not</i> changed by this class).
* For this reason this class is almost in all cases a safe drop-in replacement
* for the standard <tt>Properties</tt>
* class.
*
* <p>
* Whitespace is defined here as any of space (U+0020) or tab (U+0009).
* *
*/
public class TrimmedProperties extends Properties {

/**
* Reads a property list (key and element pairs) from the input byte stream.
*
* <p>Behaves exactly as {@link [Link]#load([Link]) }
* with the exception that trailing whitespace is trimmed from property values

[Link] 192
* if <tt>inStream</tt> is an instance of <tt>FileInputStream</tt>.
*
* @see [Link]#load([Link])
* @param inStream the input stream.
* @throws IOException if an error occurred when reading from the input stream.
*/
@Override
public void load(InputStream inStream) throws IOException {
if (inStream instanceof FileInputStream) {
// First read into temporary props using the standard way
Properties tempProps = new Properties();
[Link](inStream);
// Now trim and put into target
trimAndLoad(tempProps);
} else {
[Link](inStream);
}
}

/**
* Reads a property list (key and element pairs) from the input character stream in a
simple line-oriented format.
*
* <p>Behaves exactly as {@link [Link]#load([Link])}
* with the exception that trailing whitespace is trimmed on property values
* if <tt>reader</tt> is an instance of <tt>FileReader</tt>.
*
* @see [Link]#load([Link]) }
* @param reader the input character stream.
* @throws IOException if an error occurred when reading from the input stream.
*/
@Override
public void load(Reader reader) throws IOException {
if (reader instanceof FileReader) {
// First read into temporary props using the standard way
Properties tempProps = new Properties();
[Link](reader);
// Now trim and put into target
trimAndLoad(tempProps);
} else {
[Link](reader);
}
}

private void trimAndLoad(Properties p) {


for (Entry<Object, Object> entry : [Link]()) {
if ([Link]() instanceof String) {
put([Link](), trimTrailing((String) [Link]()));
} else {
put([Link](), [Link]());
}
}
}

/**
* Trims trailing space or tabs from a string.
*
* @param str
* @return
*/
public static String trimTrailing(String str) {

[Link] 193
if (str != null) {
// read str from tail until char is no longer whitespace
for (int i = [Link]() - 1; i >= 0; i--) {
if (([Link](i) != ' ') && ([Link](i) != '\t')) {
return [Link](0, i + 1);
}
}
}
return str;
}
}

Guardar propiedades como XML

Almacenamiento de propiedades en un archivo XML

La forma en que almacena los archivos de propiedades como archivos XML es muy similar a la
forma en que los almacenaría como archivos .properties . Solo en lugar de usar store()
storeToXML() .

public void saveProperties(String location) throws IOException{


// make new instance of properties
Properties prop = new Properties();

// set the property values


[Link]("name", "Steve");
[Link]("color", "green");
[Link]("age", "23");

// check to see if the file already exists


File file = new File(location);
if (![Link]()){
[Link]();
}

// save the properties


[Link](new FileOutputStream(file), "testing properties with xml");
}

Cuando abres el archivo se verá así.

Cargar propiedades desde un archivo XML

[Link] 194
Ahora, para cargar este archivo como una properties , debe llamar a loadFromXML() lugar de a
load() que usaría con los archivos .propeties normales.

public static void loadProperties(String location) throws FileNotFoundException, IOException{


// make new properties instance to load the file into
Properties prop = new Properties();

// check to make sure the file exists


File file = new File(location);
if ([Link]()){
// load the file
[Link](new FileInputStream(file));

// print out all the properties


for (String name : [Link]()){
[Link](name + "=" + [Link](name));
}
} else {
[Link]("Error: No file found at: " + location);
}
}

Cuando ejecute este código obtendrá lo siguiente en la consola:

age=23
color=green
name=Steve

Lea Clase de propiedades en línea: [Link]

[Link] 195
Capítulo 31: Clase EnumSet
Introducción
La clase Java EnumSet es la implementación especializada de conjuntos para usar con tipos de
enumeración. Hereda la clase AbstractSet e implementa la interfaz Set.

Examples
Ejemplo de conjunto de enumeración

import [Link].*;
enum days {
SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY
}
public class EnumSetExample {
public static void main(String[] args) {
Set<days> set = [Link]([Link], [Link]);
// Traversing elements
Iterator<days> iter = [Link]();
while ([Link]())
[Link]([Link]());
}
}

Lea Clase EnumSet en línea: [Link]

[Link] 196
Capítulo 32: Clase inmutable
Introducción
Los objetos inmutables son instancias cuyo estado no cambia después de que se haya
inicializado. Por ejemplo, String es una clase inmutable y, una vez instanciada, su valor nunca
cambia.

Observaciones
Algunas clases inmutables en Java:

1. [Link]
2. Las clases de envoltorio para los tipos primitivos: [Link], [Link],
[Link], [Link], [Link], [Link], [Link],
[Link]
3. La mayoría de las clases de enumeración son inmutables, pero esto, de hecho, depende del
caso concreto.
4. [Link] y [Link] (al menos objetos de esas clases en sí)
5. [Link]. Tenga en cuenta que esto representa un objeto externo a la VM (un archivo en
el sistema local), que puede o no existir, y tiene algunos métodos para modificar y consultar
el estado de este objeto externo. Pero el objeto File en sí permanece inmutable.

Examples
Reglas para definir clases inmutables.

Las siguientes reglas definen una estrategia simple para crear objetos inmutables.

1. No proporcione métodos de "establecimiento": métodos que modifican campos u objetos a


los que se hace referencia por campos.
2. Hacer todos los campos finales y privados.
3. No permitir que las subclases anulen los métodos. La forma más sencilla de hacer esto es
declarar la clase como final. Un enfoque más sofisticado es hacer que el constructor sea
privado y construir instancias en métodos de fábrica.
4. Si los campos de la instancia incluyen referencias a objetos mutables, no permita que se
cambien esos objetos:
5. No proporcione métodos que modifiquen los objetos mutables.
6. No comparta referencias a los objetos mutables. Nunca almacene referencias a objetos
mutables externos pasados al constructor; Si es necesario, cree copias y almacene
referencias a las copias. Del mismo modo, cree copias de sus objetos mutables internos
cuando sea necesario para evitar devolver los originales en sus métodos.

Ejemplo sin referencias mutables.

[Link] 197
public final class Color {
final private int red;
final private int green;
final private int blue;

private void check(int red, int green, int blue) {


if (red < 0 || red > 255 || green < 0 || green > 255 || blue < 0 || blue > 255) {
throw new IllegalArgumentException();
}
}

public Color(int red, int green, int blue) {


check(red, green, blue);
[Link] = red;
[Link] = green;
[Link] = blue;
}

public Color invert() {


return new Color(255 - red, 255 - green, 255 - blue);
}
}

Ejemplo con referencias mutables

En este caso, la clase Point es mutable y algunos usuarios pueden modificar el estado del objeto
de esta clase.

class Point {
private int x, y;

public Point(int x, int y) {


this.x = x;
this.y = y;
}

public int getX() {


return x;
}

public void setX(int x) {


this.x = x;
}

public int getY() {


return y;
}

public void setY(int y) {


this.y = y;
}
}

//...

public final class ImmutableCircle {


private final Point center;
private final double radius;

[Link] 198
public ImmutableCircle(Point center, double radius) {
// we create new object here because it shouldn't be changed
[Link] = new Point([Link](), [Link]());
[Link] = radius;
}

¿Cuál es la ventaja de la inmutabilidad?

La ventaja de la inmutabilidad viene con la concurrencia. Es difícil mantener la corrección en


objetos mutables, ya que varios subprocesos podrían estar intentando cambiar el estado del
mismo objeto, lo que lleva a que algunos subprocesos vean un estado diferente del mismo objeto,
dependiendo de la sincronización de las lecturas y escrituras a dicho objeto.

Al tener un objeto inmutable, uno puede asegurarse de que todos los subprocesos que miran el
objeto verán el mismo estado, ya que el estado de un objeto inmutable no cambiará.

Lea Clase inmutable en línea: [Link]

[Link] 199
Capítulo 33: Clase interna local
Introducción
Una clase, es decir, creada dentro de un método, se llama clase interna local en java. Si desea
invocar los métodos de la clase interna local, debe crear una instancia de esta clase dentro del
método.

Examples
Clase interna local

public class localInner1{


private int data=30;//instance variable
void display(){
class Local{
void msg(){[Link](data);}
}
Local l=new Local();
[Link]();
}
public static void main(String args[]){
localInner1 obj=new localInner1();
[Link]();
}
}

Lea Clase interna local en línea: [Link]

[Link] 200
Capítulo 34: Clases anidadas e internas
Introducción
Usando Java, los desarrolladores tienen la capacidad de definir una clase dentro de otra clase.
Tal clase se llama una clase anidada . Las clases anidadas se denominan clases internas si se
declararon como no estáticas; de lo contrario, simplemente se denominan clases anidadas
estáticas. Esta página es para documentar y proporcionar detalles con ejemplos sobre cómo usar
clases anidadas e internas de Java.

Sintaxis
• clase pública OuterClass {clase pública InnerClass {}} // las clases internas también pueden
ser privadas
• clase pública OuterClass {clase estática pública StaticNestedClass {}} // Las clases anidadas
estáticas también pueden ser privadas
• método de anulación público () {clase privada LocalClass {}} // Las clases locales son
siempre privadas
• SomeClass anonymousClassInstance = new SomeClass () {}; // Las clases internas
anónimas no pueden ser nombradas, por lo tanto el acceso es discutible. Si 'SomeClass ()'
es abstracto, el cuerpo debe implementar todos los métodos abstractos.
• SomeInterface anonymousClassInstance = new SomeInterface () {}; // El cuerpo debe
implementar todos los métodos de interfaz.

Observaciones

Terminologia y clasificacion
La especificación de lenguaje Java (JLS) clasifica los diferentes tipos de clases de Java de la
siguiente manera:

Una clase de nivel superior es una clase que no es una clase anidada.

Una clase anidada es cualquier clase cuya declaración ocurre dentro del cuerpo de
otra clase o interfaz.

Una clase interna es una clase anidada que no se declara explícita o implícitamente
como estática.

Una clase interna puede ser una clase miembro no estática , una clase local o una
clase anónima . Una clase miembro de una interfaz es implícitamente estática, por lo
que nunca se considera una clase interna.

En la práctica, los programadores se refieren a una clase de nivel superior que contiene una clase
interna como la "clase externa". Además, hay una tendencia a usar "clase anidada" para referirse

[Link] 201
solo a clases anidadas estáticas (explícita o implícitamente).

Tenga en cuenta que existe una relación estrecha entre las clases internas anónimas y las
lambdas, pero las lambdas son clases.

Diferencias semanticas
• Las clases de nivel superior son el "caso base". Son visibles a otras partes de un programa
sujeto a reglas de visibilidad normales basadas en la semántica del modificador de acceso.
Si no son abstractos, se pueden crear instancias de cualquier código en el que los
constructores relevantes sean visibles según los modificadores de acceso.

• Las clases anidadas estáticas siguen las mismas reglas de acceso e instanciación que las
clases de nivel superior, con dos excepciones:

○ Una clase anidada se puede declarar como private , lo que la hace inaccesible fuera
de su clase de nivel superior.
○ Una clase anidada tiene acceso a los miembros private de la clase adjunta de nivel
superior y toda su clase probada.

Esto hace que las clases anidadas estáticas sean útiles cuando necesita representar
múltiples "tipos de entidades" dentro de un límite de abstracción estricto; por ejemplo,
cuando las clases anidadas se utilizan para ocultar "detalles de implementación".

• Las clases internas agregan la capacidad de acceder a variables no estáticas declaradas en


los ámbitos adjuntos:

○ Una clase miembro no estática puede referirse a variables de instancia.


○ Una clase local (declarada dentro de un método) también puede referirse a las
variables locales del método, siempre que sean final . (Para Java 8 y versiones
posteriores, pueden ser efectivamente definitivas ).
○ Una clase interna anónima se puede declarar dentro de una clase o un método, y
puede acceder a las variables de acuerdo con las mismas reglas.

El hecho de que una instancia de clase interna pueda referirse a variables en una instancia
de clase adjunta tiene implicaciones para la creación de instancias. Específicamente, se
debe proporcionar una instancia adjunta, ya sea implícita o explícitamente, cuando se crea
una instancia de una clase interna.

Examples
Una pila simple usando una clase anidada

public class IntStack {

private IntStackNode head;

// IntStackNode is the inner class of the class IntStack

[Link] 202
// Each instance of this inner class functions as one link in the
// Overall stack that it helps to represent
private static class IntStackNode {

private int val;


private IntStackNode next;

private IntStackNode(int v, IntStackNode n) {


val = v;
next = n;
}
}

public IntStack push(int v) {


head = new IntStackNode(v, head);
return this;
}

public int pop() {


int x = [Link];
head = [Link];
return x;
}
}

Y su uso, que (en particular) no reconoce en absoluto la existencia de la clase anidada.

public class Main {


public static void main(String[] args) {

IntStack s = new IntStack();


[Link](4).push(3).push(2).push(1).push(0);

//prints: 0, 1, 2, 3, 4,
for(int i = 0; i < 5; i++) {
[Link]([Link]() + ", ");
}
}
}

Clases anidadas estáticas y no estáticas

Al crear una clase anidada, tiene la opción de tener esa clase estática anidada:

public class OuterClass1 {

private static class StaticNestedClass {

O no estático:

public class OuterClass2 {

[Link] 203
private class NestedClass {

En su núcleo, las clases anidadas estáticas no tienen una instancia circundante de la clase
externa, mientras que las clases anidadas no estáticas sí las tienen. Esto afecta a dónde y
cuándo se permite a una instancia crear una clase anidada, y a qué instancias de esas clases
anidadas se les permite acceder. Añadiendo al ejemplo anterior:

public class OuterClass1 {

private int aField;


public void aMethod(){}

private static class StaticNestedClass {


private int innerField;

private StaticNestedClass() {
innerField = aField; //Illegal, can't access aField from static context
aMethod(); //Illegal, can't call aMethod from static context
}

private StaticNestedClass(OuterClass1 instance) {


innerField = [Link]; //Legal
}

public static void aStaticMethod() {


StaticNestedClass s = new StaticNestedClass(); //Legal, able to construct in static
context
//Do stuff involving s...
}

public class OuterClass2 {

private int aField;

public void aMethod() {}

private class NestedClass {


private int innerField;

private NestedClass() {
innerField = aField; //Legal
aMethod(); //Legal
}
}

public void aNonStaticMethod() {


NestedClass s = new NestedClass(); //Legal
}

public static void aStaticMethod() {


NestedClass s = new NestedClass(); //Illegal. Can't construct without surrounding

[Link] 204
OuterClass2 instance.
//As this is a static context, there is no
surrounding OuterClass2 instance
}
}

Por lo tanto, su decisión de estática frente a no estática depende principalmente de si necesita


poder acceder directamente a los campos y métodos de la clase externa, aunque también tiene
consecuencias sobre cuándo y dónde puede construir la clase anidada.

Como regla general, haga que sus clases anidadas sean estáticas a menos que necesite acceder
a los campos y métodos de la clase externa. Al igual que hacer que sus campos sean privados, a
menos que los necesite, esto disminuye la visibilidad disponible para la clase anidada (al no
permitir el acceso a una instancia externa), lo que reduce la posibilidad de error.

Modificadores de Acceso para Clases Internas

Una explicación completa de los modificadores de acceso en Java se puede encontrar aquí .
¿Pero cómo interactúan con las clases internas?

public , como de costumbre, da acceso sin restricciones a cualquier ámbito capaz de acceder al
tipo.

public class OuterClass {

public class InnerClass {

public int x = 5;

public InnerClass createInner() {


return new InnerClass();
}
}

public class SomeOtherClass {

public static void main(String[] args) {


int x = new OuterClass().createInner().x; //Direct field access is legal
}
}

tanto protected como el modificador predeterminado (de nada) se comportan como se espera
también, de la misma manera que lo hacen para las clases no anidadas.

private , curiosamente, no se limita a la clase a la que pertenece. Más bien, se restringe a la


unidad de compilación: el archivo .java. Esto significa que las clases externas tienen acceso total
a los campos y métodos de la clase interna, incluso si están marcados como private .

public class OuterClass {

public class InnerClass {

[Link] 205
private int x;
private void anInnerMethod() {}
}

public InnerClass aMethod() {


InnerClass a = new InnerClass();
a.x = 5; //Legal
[Link](); //Legal
return a;
}
}

La Clase Interna en sí misma puede tener una visibilidad que no sea public . Al marcarlo como
private u otro modificador de acceso restringido, otras clases (externas) no podrán importar y
asignar el tipo. Sin embargo, aún pueden obtener referencias a objetos de ese tipo.

public class OuterClass {

private class InnerClass{}

public InnerClass makeInnerClass() {


return new InnerClass();
}
}

public class AnotherClass {

public static void main(String[] args) {


OuterClass o = new OuterClass();

InnerClass x = [Link](); //Illegal, can't find type


[Link] x = [Link](); //Illegal, InnerClass has visibility
private
Object x = [Link](); //Legal
}
}

Clases internas anónimas

Una clase interna anónima es una forma de clase interna que se declara y crea una instancia con
una sola declaración. Como consecuencia, no hay un nombre para la clase que pueda usarse en
otra parte del programa; Es decir, es anónimo.

Las clases anónimas se utilizan normalmente en situaciones en las que es necesario poder crear
una clase de peso ligero que se pase como parámetro. Esto normalmente se hace con una
interfaz. Por ejemplo:

public static Comparator<String> CASE_INSENSITIVE =


new Comparator<String>() {
@Override
public int compare(String string1, String string2) {
return [Link]().compareTo([Link]());
}
};

[Link] 206
Esta clase anónima define un objeto Comparator<String> ( CASE_INSENSITIVE ) que compara dos
cadenas ignorando las diferencias en el caso.

Otras interfaces que se implementan e Runnable frecuencia usando clases anónimas son Runnable
y Callable . Por ejemplo:

// An anonymous Runnable class is used to provide an instance that the Thread


// will run when started.
Thread t = new Thread(new Runnable() {
@Override
public void run() {
[Link]("Hello world");
}
});
[Link](); // Prints "Hello world"

Las clases internas anónimas también pueden basarse en clases. En este caso, la clase anónima
extends implícitamente la clase existente. Si la clase que se está extendiendo es abstracta,
entonces la clase anónima debe implementar todos los métodos abstractos. También puede
anular métodos no abstractos.

Constructores
Una clase anónima no puede tener un constructor explícito. En su lugar, se define un constructor
implícito que usa super(...) para pasar cualquier parámetro a un constructor en la clase que se
está extendiendo. Por ejemplo:

SomeClass anon = new SomeClass(1, "happiness") {


@Override
public int someMethod(int arg) {
// do something
}
};

El constructor implícito para nuestra subclase anónima de SomeClass llamará a un constructor de


SomeClass que coincida con la firma de llamada SomeClass(int, String) . Si no hay ningún
constructor disponible, obtendrá un error de compilación. Cualquier excepción lanzada por el
constructor emparejado también es lanzada por el constructor implícito.

Naturalmente, esto no funciona cuando se extiende una interfaz. Cuando creas una clase
anónima desde una interfaz, la clase superclase es [Link] que solo tiene un constructor
sin argumentos.

Método de clases internas locales

Una clase escrita dentro de un método llamado método clase interna local . En ese caso, el
alcance de la clase interna está restringido dentro del método.

Una clase interna de método local puede instanciarse solo dentro del método donde se define la
clase interna.

[Link] 207
El ejemplo de usar el método local de clase interna:

public class OuterClass {


private void outerMethod() {
final int outerInt = 1;
// Method Local Inner Class
class MethodLocalInnerClass {
private void print() {
[Link]("Method local inner class " + outerInt);
}
}
// Accessing the inner class
MethodLocalInnerClass inner = new MethodLocalInnerClass();
[Link]();
}

public static void main(String args[]) {


OuterClass outer = new OuterClass();
[Link]();
}
}

La ejecución dará una salida: Method local inner class 1 .

Acceso a la clase externa desde una clase interna no estática

La referencia a la clase externa usa el nombre de la clase y this

public class OuterClass {


public class InnerClass {
public void method() {
[Link]("I can access my enclosing class: " + [Link]);
}
}
}

Puede acceder a los campos y métodos de la clase externa directamente.

public class OuterClass {


private int counter;

public class InnerClass {


public void method() {
[Link]("I can access " + counter);
}
}
}

Pero en caso de colisión de nombres, puede utilizar la referencia de clase externa.

public class OuterClass {


private int counter;

public class InnerClass {


private int counter;

[Link] 208
public void method() {
[Link]("My counter: " + counter);
[Link]("Outer counter: " + [Link]);

// updating my counter
counter = [Link];
}
}
}

Crear instancia de clase interna no estática desde el exterior.

También se puede crear una clase interna que sea visible para cualquier clase externa a partir de
esta clase.

La clase interna depende de la clase externa y requiere una referencia a una instancia de ella.
Para crear una instancia de la clase interna, el new operador solo necesita ser llamado en una
instancia de la clase externa.

class OuterClass {

class InnerClass {
}
}

class OutsideClass {

OuterClass outer = new OuterClass();

[Link] createInner() {
return [Link] InnerClass();
}
}

Tenga en cuenta el uso como [Link] .

Lea Clases anidadas e internas en línea: [Link]


anidadas-e-internas

[Link] 209
Capítulo 35: Clases y objetos
Introducción
Los objetos tienen estados y comportamientos. Ejemplo: Un perro tiene estados (color, nombre,
raza y comportamientos): menear la cola, ladrar, comer. Un objeto es una instancia de una clase.

Clase: una clase se puede definir como una plantilla / modelo que describe el comportamiento /
estado que admite el objeto de su tipo.

Sintaxis
• clase Ejemplo {} // clase palabra clave, nombre, cuerpo

Examples
Clase posible más simple

class TrivialClass {}

Una clase consta de un mínimo de la palabra clave de class , un nombre y un cuerpo, que pueden
estar vacíos.

Se crea una instancia de una clase con el new operador.

TrivialClass tc = new TrivialClass();

Miembro Objeto vs Miembro Estático

Con esta clase:

class ObjectMemberVsStaticMember {

static int staticCounter = 0;


int memberCounter = 0;

void increment() {
staticCounter ++;
memberCounter++;
}
}

el siguiente fragmento de código:

final ObjectMemberVsStaticMember o1 = new ObjectMemberVsStaticMember();


final ObjectMemberVsStaticMember o2 = new ObjectMemberVsStaticMember();

[Link] 210
[Link]();

[Link]();
[Link]();

[Link]("o1 static counter " + [Link]);


[Link]("o1 member counter " + [Link]);
[Link]();

[Link]("o2 static counter " + [Link]);


[Link]("o2 member counter " + [Link]);
[Link]();

[Link]("[Link] = " +
[Link]);

// the following line does not compile. You need an object


// to access its members
//[Link]("[Link] = " +
[Link]);

produce esta salida:

o1 static counter 3
o1 member counter 1

o2 static counter 3
o2 member counter 2

[Link] = 3

Nota: No debe llamar a miembros static en objetos, sino en clases. Si bien no hace una
diferencia para la JVM, los lectores humanos lo apreciarán.

static miembros static son parte de la clase y existen solo una vez por clase. Los miembros no
static existen en las instancias, hay una copia independiente para cada instancia. Esto también
significa que necesita acceder a un objeto de esa clase para acceder a sus miembros.

Métodos de sobrecarga

A veces, se debe escribir la misma funcionalidad para diferentes tipos de entradas. En ese
momento, uno puede usar el mismo nombre de método con un conjunto diferente de parámetros.
Cada conjunto diferente de parámetros se conoce como una firma de método. Como se ve en el
ejemplo, un solo método puede tener varias firmas.

public class Displayer {

public void displayName(String firstName) {


[Link]("Name is: " + firstName);
}

public void displayName(String firstName, String lastName) {


[Link]("Name is: " + firstName + " " + lastName);
}

[Link] 211
public static void main(String[] args) {
Displayer displayer = new Displayer();
[Link]("Ram"); //prints "Name is: Ram"
[Link]("Jon", "Skeet"); //prints "Name is: Jon Skeet"
}
}

La ventaja es que se llama a la misma funcionalidad con dos números diferentes de entradas. Al
invocar el método de acuerdo con la entrada que estamos pasando, (en este caso, un valor de
cadena o dos valores de cadena) se ejecuta el método correspondiente.

Los métodos pueden ser sobrecargados:

1. Basado en el número de parámetros pasados.

Ejemplo: method(String s) y method(String s1, String s2) .

2. Basado en el orden de los parámetros .

Ejemplo: method(int i, float f) y method(float f, int i)) .

Nota: los métodos no pueden sobrecargarse cambiando solo el tipo de retorno ( int method() se
considera el mismo que String method() y lanzará una RuntimeException si se intenta). Si cambia el
tipo de retorno, también debe cambiar los parámetros para sobrecargar.

Construcción y uso de objetos básicos

Los objetos vienen en su propia clase, por lo que un ejemplo simple sería un automóvil
(explicaciones detalladas a continuación):

public class Car {

//Variables describing the characteristics of an individual car, varies per object


private int milesPerGallon;
private String name;
private String color;
public int numGallonsInTank;

public Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}

//this is where an individual object is created


public Car(int mpg, int, gallonsInTank, String carName, String carColor){
milesPerGallon = mpg;
name = carName;
color = carColor;
numGallonsInTank = gallonsInTank;
}

//methods to make the object more usable

[Link] 212
//Cars need to drive
public void drive(int distanceInMiles){
//get miles left in car
int miles = numGallonsInTank * milesPerGallon;

//check that car has enough gas to drive distanceInMiles


if (miles <= distanceInMiles){
numGallonsInTank = numGallonsInTank - (distanceInMiles / milesPerGallon)
[Link]("Drove " + numGallonsInTank + " miles!");
} else {
[Link]("Could not drive!");
}
}

public void paintCar(String newColor){


color = newColor;
}
//set new Miles Per Gallon
public void setMPG(int newMPG){
milesPerGallon = newMPG;
}

//set new number of Gallon In Tank


public void setGallonsInTank(int numGallons){
numGallonsInTank = numGallons;
}

public void nameCar(String newName){


name = newName;
}

//Get the Car color


public String getColor(){
return color;
}

//Get the Car name


public String getName(){
return name;
}

//Get the number of Gallons


public String getGallons(){
return numGallonsInTank;
}

Los objetos son instancias de su clase. Entonces, la forma en que crearía un objeto sería
llamando a la clase Car de una de las dos formas en su clase principal (método principal en
Java u onCreate en Android).

Opción 1

`Car newCar = new Car(30, 10, "Ferrari", "Red");

La opción 1 es donde esencialmente le dice al programa todo sobre el Coche al crear el objeto.

[Link] 213
Cambiar cualquier propiedad del automóvil requeriría llamar a uno de los métodos, como el
método repaintCar . Ejemplo:

[Link]("Blue");

Nota: asegúrese de pasar el tipo de datos correcto al método. En el ejemplo anterior, también
puede pasar una variable al método repaintCar siempre que el tipo de datos sea correcto .

Ese fue un ejemplo de cambio de propiedades de un objeto, recibir propiedades de un objeto


requeriría el uso de un método de la clase Car que tenga un valor de retorno (es decir, un método
que no sea void ). Ejemplo:

String myCarName = [Link](); //returns string "Ferrari"

La opción 1 es la mejor opción cuando tiene todos los datos del objeto en el momento de la
creación.

opcion 2

`Car newCar = new Car();

La opción 2 obtiene el mismo efecto pero requiere más trabajo para crear un objeto
correctamente. Quiero recordar a este Constructor en la clase de Automóviles:

public void Car(){


milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}

Tenga en cuenta que no tiene que pasar ningún parámetro al objeto para crearlo. Esto es muy útil
para cuando no tiene todos los aspectos del objeto pero necesita usar las partes que tiene. Esto
establece datos genéricos en cada una de las variables de instancia del objeto, de modo que, si
solicita un dato que no existe, no se generan errores.

Nota: No olvide que debe configurar las partes del objeto más adelante con las que no lo haya
inicializado. Por ejemplo,

Car myCar = new Car();


String color = [Link](); //returns empty string

Este es un error común entre los objetos que no están inicializados con todos sus datos. Se
evitaron los errores porque hay un Constructor que permite que se cree un objeto de Coche vacío
con variables de apoyo ( public Car(){} ), pero ninguna parte de myCar fue realmente
personalizada. Ejemplo correcto de crear un objeto de coche:

Car myCar = new Car();


[Link]("Ferrari");

[Link] 214
[Link]("Purple");
[Link](10);
[Link](30);

Y, como recordatorio, obtenga las propiedades de un objeto llamando a un método en su clase


principal. Ejemplo:

String myCarName = [Link](); //returns string "Ferrari"

Constructores

Los constructores son métodos especiales nombrados después de la clase y sin un tipo de
retorno, y se utilizan para construir objetos. Los constructores, como los métodos, pueden tomar
parámetros de entrada. Los constructores se utilizan para inicializar objetos. Las clases
abstractas también pueden tener constructores.

public class Hello{


// constructor
public Hello(String wordToPrint){
printHello(wordToPrint);
}
public void printHello(String word){
[Link](word);
}
}
// instantiates the object during creating and prints out the content
// of wordToPrint

Es importante entender que los constructores son diferentes de los métodos de varias maneras:

1. Los constructores solo pueden tomar los modificadores public , private y protected , y no
pueden ser declarados abstract , final , static o synchronized .

2. Los constructores no tienen un tipo de retorno.

3. Los constructores DEBEN tener el mismo nombre que el nombre de la clase. En el ejemplo
de Hello , el nombre del constructor del objeto Hello es el mismo que el nombre de la clase.

4. La palabra clave this tiene un uso adicional dentro de los constructores. [Link](...)
llama a un método en la instancia actual, mientras que this(...) refiere a otro constructor en
la clase actual con diferentes firmas.

A los constructores también se les puede llamar por herencia usando la palabra clave super .

public class SuperManClass{

public SuperManClass(){
// some implementation
}

// ... methods
}

[Link] 215
public class BatmanClass extends SupermanClass{
public BatmanClass(){
super();
}
//... methods...
}

Ver la especificación del lenguaje Java # 8.8 y # 15.9

Inicializando campos finales estáticos usando un inicializador estático

Para inicializar campos static final que requieren el uso de más de una expresión, se puede
usar un inicializador static para asignar el valor. El siguiente ejemplo inicializa un conjunto no
modificable de String s:

public class MyClass {

public static final Set<String> WORDS;

static {
Set<String> set = new HashSet<>();
[Link]("Hello");
[Link]("World");
[Link]("foo");
[Link]("bar");
[Link]("42");
WORDS = [Link](set);
}
}

Explicando qué es el método de sobrecarga y anulación.

El método de anulación y sobrecarga son dos formas de polimorfismo soportado por Java.

Método de sobrecarga

La sobrecarga de métodos (también conocida como Polimorfismo estático) es una forma en que
puede tener dos (o más) métodos (funciones) con el mismo nombre en una sola clase. Sí, es tan
simple como eso.

public class Shape{


//It could be a circle or rectangle or square
private String type;

//To calculate area of rectangle


public Double area(Long length, Long breadth){
return (Double) length * breadth;
}

//To calculate area of a circle


public Double area(Long radius){
return (Double) 3.14 * r * r;

[Link] 216
}
}

De esta manera, el usuario puede llamar al mismo método para el área dependiendo del tipo de
forma que tenga.

Pero la pregunta real ahora es, ¿cómo distinguirá el compilador Java qué cuerpo del método se
ejecutará?

Bueno, Java ha dejado claro que aunque los nombres de los métodos ( area() en nuestro caso)
pueden ser iguales, el método de los argumentos debe ser diferente.

Los métodos sobrecargados deben tener diferentes listas de argumentos (cantidad y


tipos).

Dicho esto, no podemos agregar otro método para calcular el área de un cuadrado como este:
public Double area(Long side) porque, en este caso, entrará en conflicto con el método del círculo
del área y causará ambigüedad para el compilador Java.

Gracias a Dios, hay algunas relajaciones al escribir métodos sobrecargados como

Puede tener diferentes tipos de retorno.

Puede tener diferentes modificadores de acceso.

Puede lanzar diferentes excepciones.

¿Por qué se llama esto polimorfismo estático?

Bueno, eso se debe a que los métodos sobrecargados que se van a invocar se deciden en el
momento de la compilación, según el número real de argumentos y los tipos de tiempo de
compilación de los argumentos.

Una de las razones más comunes para usar la sobrecarga de métodos es la


simplicidad del código que proporciona. Por ejemplo, recuerde [Link]() que
toma casi cualquier tipo de argumento? Lo que está escrito detrás de la escena es
probablemente algo como esto:

static String valueOf(boolean b)


static String valueOf(char c)
static String valueOf(char[] data)
static String valueOf(char[] data, int offset, int count)
static String valueOf(double d)
static String valueOf(float f)
static String valueOf(int i)
static String valueOf(long l)
static String valueOf(Object obj)

Método Anulando

Bueno, el método de anulación (sí, supongo que es correcto, también se conoce como

[Link] 217
polimorfismo dinámico) es un tema algo más interesante y complejo.

En la sustitución de métodos, sobrescribimos el cuerpo del método proporcionado por la clase


padre. ¿Lo tengo? ¿No? Veamos un ejemplo.

public abstract class Shape{

public abstract Double area(){


return 0.0;
}
}

Así que tenemos una clase llamada Forma y tiene un método llamado área que probablemente
devolverá el área de la forma.

Digamos que ahora tenemos dos clases llamadas Círculo y Rectángulo.

public class Circle extends Shape {


private Double radius = 5.0;

// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return 3.14 * radius * radius;
}
}

De forma similar clase de rectángulo:

public class Rectangle extends Shape {


private Double length = 5.0;
private Double breadth= 10.0;

// See this annotation @Override, it is telling that this method is from parent
// class Shape and is overridden here
@Override
public Double area(){
return length * breadth;
}
}

Entonces, ahora las dos clases de sus hijos tienen el cuerpo del método actualizado
proporcionado por la clase principal ( Shape ). Ahora la pregunta es ¿cómo ver el resultado?
Bueno, psvm la vieja psvm .

public class AreaFinder{

public static void main(String[] args){

//This will create an object of circle class


Shape circle = new Circle();
//This will create an object of Rectangle class
Shape rectangle = new Rectangle();

[Link] 218
// Drumbeats ......
//This should print 78.5
[Link]("Shape of circle : "+[Link]());

//This should print 50.0


[Link]("Shape of rectangle: "+[Link]());

}
}

¡Guauu! no es genial? Dos objetos del mismo tipo que llaman a los mismos métodos y devuelven
valores diferentes. Mi amigo, ese es el poder del polimorfismo dinámico.

Aquí hay una tabla para comparar mejor las diferencias entre estos dos:

Método de sobrecarga Método Anulando

La anulación del método se utiliza


El método de sobrecarga se utiliza para aumentar la para proporcionar la implementación
legibilidad del programa. específica del método que ya está
provisto por su superclase.

La anulación del método se produce


La sobrecarga de métodos se realiza dentro de la
en dos clases que tienen una relación
clase.
IS-A (herencia).

En caso de sobrecarga del método, el parámetro En caso de anulación del método, el


debe ser diferente. parámetro debe ser el mismo.

La anulación del método es el


La sobrecarga de métodos es el ejemplo del
ejemplo del polimorfismo de tiempo
polimorfismo de tiempo de compilación.
de ejecución.

En java, la sobrecarga de métodos no se puede


realizar cambiando solo el tipo de retorno del El tipo de devolución debe ser igual o
método. El tipo de retorno puede ser igual o covariante en la invalidación del
diferente en la sobrecarga de métodos. Pero debes método.
tener que cambiar el parámetro.

Lea Clases y objetos en línea: [Link]

[Link] 219
Capítulo 36: Clonación de objetos
Observaciones
La clonación puede ser complicada, especialmente cuando los campos del objeto contienen otros
objetos. Hay situaciones en las que desea realizar una copia profunda , en lugar de copiar solo
los valores de campo (es decir, referencias a los otros objetos).

La conclusión es que la copia está rota , y debe pensarlo do