Java Language Es
Java Language Es
#java
Tabla de contenido
Acerca de 1
Observaciones 2
Instalando Java 3
¿Que sigue? 3
Pruebas 3
Otro 3
Versiones 4
Examples 4
Examples 11
Introducción a JNA 11
¿Qué es JNA? 11
¿A dónde ir ahora? 12
Capítulo 3: Afirmando 13
Sintaxis 13
Parámetros 13
Observaciones 13
Examples 13
Examples 14
Examples 17
Enfoque general 17
Observaciones 20
Examples 21
Capítulo 7: Anotaciones 25
Introducción 25
Sintaxis 25
Observaciones 25
Tipos de parametros 25
Examples 25
Anotaciones incorporadas 25
Valores predeterminados 30
Meta-Anotaciones 30
@Objetivo 30
Valores disponibles 30
@Retencion 31
Valores disponibles 32
@Documentado 32
@Heredado 32
@Repeable 33
Repetir anotaciones 34
Anotaciones heredadas 35
Ejemplo 35
La anotacion 36
El procesador de anotaciones. 36
embalaje 38
Integración IDE 39
Netbeans 39
Resultado 40
Examples 43
Introducción 46
Examples 46
Introducción 49
Observaciones 49
Actuación 49
Examples 49
Introducción 49
Invocando un método 51
Constructor de llamadas 53
Proxies dinámicos 57
Capítulo 11: AppDynamics y TIBCO BusinessWorks Instrumentation para una fácil integración 61
Introducción 61
Examples 61
Introducción 63
Observaciones 63
Examples 63
Applet mínimo 63
Examples 68
Apuntar a un camino 72
Cierre 76
Agregando Directorios 81
Introducción 84
Examples 84
Introducción 87
Sintaxis 87
Parámetros 87
Examples 87
Casos basicos 87
Introducción 88
Es posible que las matrices no se puedan reinicializar con la sintaxis de acceso directo d 95
en bucle 107
[Link] () 107
[Link] () 108
[Link] () 108
[Link] () 108
Observaciones 117
Examples 117
Reproducir un archivo de audio en bucle 117
Introducción 121
Observaciones 121
Examples 121
Observaciones 126
Examples 126
-XXaggresivo 126
-XXallocClearChunks 126
-XXallocClearChunkSize 127
-XXcallProfiling 127
-XXdisableFatSpin 127
-XXdumpSize 128
-XXexitOnOutOfMemory 128
Introducción 130
Examples 130
[Link]ón 130
[Link] 131
[Link] 131
[Link] 131
6. Poder 132
[Link] 133
[Link] 133
[Link] () 135
Introducción 136
Sintaxis 136
Observaciones 136
Examples 137
Inicialización 137
Introducción 144
Sintaxis 144
Examples 144
Observaciones 147
Examples 147
Creando objetos de calendario 147
Encontrando AM / PM 148
Introducción 149
Observaciones 149
Examples 149
Introducción 153
Observaciones 153
Examples 153
Observaciones 155
Examples 155
Examples 158
Un ejemplo que utiliza un sistema criptográfico híbrido que consiste en OAEP y GCM 158
Introducción 163
Examples 163
Sintaxis 164
Parámetros 164
Observaciones 164
Examples 165
Introducción 176
Sintaxis 176
Examples 176
Introducción 190
Sintaxis 190
Observaciones 190
Examples 191
Introducción 196
Examples 196
Introducción 197
Observaciones 197
Examples 197
Introducción 200
Examples 200
Introducción 201
Sintaxis 201
Observaciones 201
Examples 202
Constructores 207
Introducción 210
Sintaxis 210
Examples 210
Constructores 215
Observaciones 220
Examples 220
Introducción 226
Observaciones 226
Examples 226
Variables 227
Constantes 227
Modificadores 230
Sangría 231
Anotaciones 234
Literales 236
Tirantes 236
Examples 238
Pilas 239
Ejemplo 239
BlockingQueue 240
Deque 242
Introducción 244
Observaciones 244
Examples 245
INCORRECTO 248
CORRECTO 249
Creando su propia estructura de Iterable para usar con Iterator o para cada bucle. 256
Observaciones 261
Examples 261
Introducción 272
Examples 272
Examples 276
Sintaxis 277
Observaciones 277
Examples 277
Introducción 285
Observaciones 285
C ++ 285
Java 285
C ++ 286
Java 286
C ++ 286
Java 286
Polimorfismo 287
Examples 290
Ejemplo de C ++ 290
Ejemplo de Java 291
C ++ 291
Java 291
C ++ 292
Java 292
C ++ 292
Java 292
Ejemplo de C ++ 294
C ++ 294
Java 295
C ++ 295
Java 295
Interfaz 295
C ++ 295
Java 295
Observaciones 296
Examples 296
Referencias 299
Introducción 302
Examples 302
Examples 304
Inicialización 305
Introducción 309
Observaciones 309
Examples 309
Examples 313
Introducción 319
Sintaxis 319
Examples 319
h21 327
Uso de flujos de [Link] para conservar los valores iniciales después del mapeo 339
Observaciones 346
Examples 346
Parámetros 353
Examples 354
Introducción 361
Observaciones 361
Examples 361
Prerrequisitos 364
Observaciones 369
Examples 369
Introducción 370
Sintaxis 370
Observaciones 371
Examples 371
Examples 378
Examples 383
Java SE 385
Java EE 385
Java ME 386
Java FX 386
Introducción 389
Observaciones 389
Examples 389
ThreadPoolExecutor 390
Programar tareas para que se ejecuten a una hora determinada, después de un retraso o repe 392
Introducción 403
Observaciones 403
Examples 403
Sintaxis 409
Observaciones 409
Examples 409
Introducción 419
Observaciones 419
Examples 419
Introducción 422
Examples 422
Introducción 423
Examples 423
Introducción 424
Sintaxis 424
Observaciones 424
Restricciones 424
Examples 425
Introducción 443
Examples 443
Pitfall: utilizando == para comparar objetos de envoltorios primitivos, como Integer 443
Observaciones 455
Examples 455
Pitfall - Usar nulo para representar una matriz o colección vacía 456
En resumen 459
Introducción 462
Observaciones 462
Examples 462
Solución 462
Pitfall: el uso de 'nuevo' para crear instancias de contenedor primitivas es ineficiente 464
Pitfall: el uso de size () para comprobar si una colección está vacía es ineficiente. 468
Pitfall - Interning Strings para que puedas usar == es una mala idea 472
Fragilidad 472
Pitfall - Las lecturas / escrituras pequeñas en flujos no almacenados en búfer son inefici 474
Observaciones 477
Examples 477
Trampa: omitir llaves: los problemas de "colgar si" y "colgar de otra manera" 480
Pitfall - Declarar clases con los mismos nombres que las clases estándar 483
Pitfall: las importaciones de comodines pueden hacer que su código sea frágil 485
Introducción 488
Examples 488
Sintaxis 497
Parámetros 497
Observaciones 497
Examples 497
Introducción 503
Examples 503
Sintaxis 504
Observaciones 504
Examples 504
Observaciones 506
Examples 506
Si / Else 510
Descanso 512
Observaciones 515
Examples 515
Evaluando un NodeList en un documento XML 515
Introducción 518
Observaciones 518
Examples 518
Introducción 522
Sintaxis 522
Examples 522
Introducción 539
Intento-finalmente 545
prueba-captura-finalmente 545
Introducción 548
Observaciones 548
Examples 548
Introducción 555
Sintaxis 555
Examples 555
Introducción 572
Sintaxis 572
Observaciones 572
Importaciones 572
Escollos 572
Examples 573
Usando expresiones regulares con comportamiento personalizado compilando el patrón con ban 574
Examples 578
Instante 579
Introducción 583
Examples 583
Examples 586
Sintaxis 587
Parámetros 587
Examples 587
Observaciones 593
Examples 593
Examples 598
Introducción 599
Sintaxis 599
Observaciones 599
Examples 599
El diamante 603
Nota: 609
Soluciones 609
Diferentes formas de implementar una interfaz genérica (o extender una clase genérica) 613
Obtenga una clase que satisfaga el parámetro genérico en tiempo de ejecución 615
Examples 617
Manifestación 625
Observaciones 627
Examples 627
Finalización 627
Introducción 635
Examples 635
Introducción 638
Examples 638
Introducción 642
Sintaxis 642
Observaciones 642
Examples 642
Herencia 647
Sintaxis 659
Parámetros 659
Observaciones 659
Examples 659
Introducción 661
Observaciones 663
Examples 663
Explicación: 666
Ejemplo: 666
Observaciones 667
Examples 667
Sintaxis 672
Observaciones 672
Examples 672
Introducción 677
Examples 677
Suposiciones 677
Introducción 690
Observaciones 690
Examples 691
Subcadenas 698
Regex 707
Introducción 712
Sintaxis 712
Examples 712
Variables 722
Métodos 722
Introducción 725
Examples 725
Lista de interfaces funcionales estándar de Java Runtime Library por firma 725
Observaciones 728
Examples 728
Introducción 732
Observaciones 732
Examples 732
Observaciones 734
Examples 734
Parámetros 737
Observaciones 737
Examples 737
Código C ++ 738
Salida 739
Código C ++ 740
Salida 740
Observaciones 743
Examples 743
Introducción 753
Observaciones 753
Examples 753
Introducción 757
Sintaxis 757
Observaciones 757
Examples 758
Introducción 759
Sintaxis 759
Parámetros 759
Observaciones 759
Examples 759
Especificando una instancia de XmlAdapter para (re) usar datos existentes 764
Ejemplo 765
Adaptador 765
Examples 769
Introducción 770
Examples 770
Examples 775
Introducción 780
Sintaxis 780
Observaciones 780
Examples 781
Expresiones 781
Variables 781
Introducción 784
Observaciones 784
Examples 784
Detalles 787
Deserialización: 787
[Link] 789
Detalles 791
Nota 792
Observaciones 793
Historia 793
Examples 793
Examples 796
Examples 797
Pitfall - Demasiados hilos hace que una aplicación sea más lenta. 799
Introducción 806
Examples 806
BufferedReader 806
Introducción 806
Introducción 809
Examples 809
Introducción 811
Examples 811
Introducción 812
Examples 812
Introducción 821
Sintaxis 821
Observaciones 821
Examples 822
CopyOnWriteArrayList 833
RoleUnresolvedList 834
Apilar 834
Vector 834
Observaciones 835
Examples 835
Lugar 837
Idioma 837
Introducción 839
Sintaxis 839
Observaciones 839
Examples 840
Introducción 846
Observaciones 846
Examples 846
Sintaxis 855
Los operadores de asignación (=, + =, - =, * =, / =,% =, << =, >> =, >>> =, & =, | = y ^ = 859
Observaciones 866
Examples 866
Introducción 872
Examples 872
Introducción 874
Examples 874
Introducción 875
Observaciones 875
Examples 875
Componiendo el Mapa <X, Y> y el Mapa <Y, Z> para obtener el Mapa <X, Z> 882
Introducción 887
Examples 890
Introducción 891
Observaciones 891
Examples 891
Introducción 894
Sintaxis 894
Parámetros 894
Examples 895
Introducción 896
Sintaxis 896
Observaciones 896
Referencias: 897
Examples 897
Observaciones 903
Examples 903
Comportamiento 906
Examples 912
Introducción 919
Examples 919
final 919
volátil 920
estático 921
resumen 922
sincronizado 923
transitorio 924
strictfp 924
Sintaxis 925
Observaciones 925
Examples 925
Introducción 928
Sintaxis 928
Observaciones 928
Examples 928
Observaciones 933
Examples 933
Sintaxis 935
Examples 935
Observaciones 939
Examples 939
Fallas típicas de diseño que evitan que una clase sea inmutable. 941
Sintaxis 945
Examples 945
Introducción 947
Sintaxis 947
Examples 947
Mapa 948
Filtrar 949
Introducción 952
Examples 952
Introducción 958
Observaciones 958
Examples 958
Introducción 960
Observaciones 960
Examples 960
Examples 970
PreferenceChangeEvent 970
NodeChangeEvent 970
Sintaxis 977
Parámetros 977
Observaciones 977
Examples 977
Observaciones 980
Examples 980
[Link] 981
Introducción 985
Observaciones 985
Examples 985
Productor-consumidor 986
CountDownLatch 988
Sincronización 989
Semáforo 1003
Obtenga el estado de todas las hebras iniciadas por su programa, excluyendo las hebras del 1004
Examples 1009
Introducción 1011
Examples 1011
Introducción 1021
Examples 1021
Introducción 1024
Observaciones 1024
Salida 1024
Eliminación de Java y Tail-Call 1024
Examples 1024
Ejemplo 1028
Solución 1028
Ejemplo 1028
Por qué la eliminación de la llamada de cola no está implementada en Java (todavía) 1031
Introducción 1032
Observaciones 1032
Examples 1033
Cargando recursos del mismo nombre desde múltiples archivos JAR 1034
Sintaxis 1036
Examples 1036
Ejemplo de socket: leer una página web utilizando un socket simple 1039
Multidifusión 1041
Notas 1044
Observaciones 1045
Examples 1045
Examples 1048
Examples 1052
Introducción 1055
Observaciones 1055
Examples 1055
La jce 1055
Aleatoriedad y tu 1055
Observaciones 1057
Examples 1057
Servicio 1057
Uso 1058
Introducción 1061
Examples 1061
Introducción 1066
Examples 1066
Inicialización perezosa segura para subprocesos utilizando la clase de soporte | Implement 1067
Introducción 1071
Observaciones 1071
Examples 1071
Introducción 1075
Examples 1075
Introducción 1076
Examples 1076
Introducción 1078
Sintaxis 1078
Observaciones 1078
Examples 1078
Observaciones 1081
Examples 1081
Examples 1084
Introducción 1087
Examples 1087
Observaciones 1088
Examples 1088
Sintaxis 1092
Examples 1092
Introducción 1094
Parámetros 1094
Observaciones 1094
Examples 1094
Examples 1098
Creando un tipo de referencia 1098
Desreferenciación 1098
Introducción 1099
Sintaxis 1099
Observaciones 1099
Examples 1100
Examples 1110
Introducción 1112
Examples 1112
Introducción 1113
Examples 1113
Sintaxis 1118
Examples 1118
Introducción 1121
Observaciones 1121
Examples 1121
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
Observaciones 1130
Examples 1130
Capítulo 183: Visibilidad (control de acceso a los miembros de una clase) 1132
Sintaxis 1132
Observaciones 1132
Examples 1132
Introducción 1136
Sintaxis 1136
Parámetros 1136
Observaciones 1136
Examples 1136
[Link] 1138
Examples 1139
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.
• 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)".
• 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) .
¿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.
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:
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
Java SE 9 (acceso
Ninguna futuro 2017-07-27
temprano)
Patio de
Java SE 1.2 antes del 2009-11-04 1998-12-08
recreo
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:
[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 ( $ ).
cd /path/to/containing/folder/
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.
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
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.
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
¡Hola Mundo!
Nota: Para que los comandos de Java ( java , javac , etc.) sean reconocidos, deberá asegurarse
de que:
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 ).
[Link] 6
HelloWorld , un método main y una declaración dentro del método main .
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 ).
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]() ).
• 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 )
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 .
[Link]("Hello, World!");
Elemento Propósito
[Link] 7
Elemento Propósito
este es el nombre del campo estático del tipo PrintStream dentro de la clase
out
System contiene la funcionalidad de salida estándar.
"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.
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.
[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
¿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:
class Member {
private String name;
private String type;
private int level;
private int rank;
[Link] 9
return [Link]; // my type 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 .
[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 ...)
[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]);
[Link]
package [Link];
[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 .
[Link] 12
Capítulo 3: Afirmando
Sintaxis
• afirmar expresión1 ;
• afirmar expresión1 : expresión2 ;
Parámetros
Parámetro Detalles
Observaciones
Por defecto, las aserciones están deshabilitadas en tiempo de ejecución.
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);
return a;
[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:
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.
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;
}
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:
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].
import [Link];
Cuando esté compilado en un archivo jar, abra el Manifiesto y asegúrese de que tenga el atributo
de clase principal.
Premain-Class: PremainExample
[Link] 15
Para usar el agente con otro programa java "myProgram", debe definir el agente en los
argumentos de JVM:
[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:
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.
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.
myString += "foo";
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 :
[Link] 17
Si crea cadenas largas con frecuencia (por ejemplo, SQL), use una API de construcción de
cadenas.
fuente
Teniendo en cuenta este sabio consejo, este es el procedimiento recomendado para optimizar
programas:
2. Llegue a un estado de trabajo y (idealmente) desarrolle pruebas unitarias para las partes
clave del código base.
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.)
[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.
11. Vuelva a ejecutar el punto de referencia para ver si el cambio de código ha mejorado el
rendimiento:
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:
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.
[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:
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.
[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.
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
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];
[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];
[Link](bookTitlesById);
}
Esto produce:
[Link] 23
Found start of element: book
Found start of element: notABook
{1=Effective Java, 2=Java Concurrency In Practice}
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.
[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
Clase abstracta
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
}
}
• 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 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
}
@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:
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
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);
}
@interface MyDefaultAnnotation {
@Retention([Link])
@interface MyRuntimeVisibleAnnotation {
@MyDefaultAnnotation
static class RuntimeCheck1 {
}
@MyRuntimeVisibleAnnotation
static class RuntimeCheck2 {
}
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
}
Valores disponibles
@Retention([Link])
ANNOTATION_TYPE tipos de anotaciones @interface MyAnnotation
@MyAnnotation
CONSTRUCTOR constructores public MyClass() {}
[Link] 30
ejemplo de uso en el elemento de
Tipo de elemento objetivo
destino
@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) {
...
}
Java SE 8
ejemplo de uso en el elemento de
Tipo de elemento objetivo
destino
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
@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.
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);
[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 {
}
@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]));
null
@InheritedAnnotationType()
@InheritedAnnotationType()
_________________________________
@UninheritedAnnotationType()
null
null
Tenga en cuenta que las anotaciones solo pueden heredarse de las clases, no de las interfaces.
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 {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)
{
// get elements annotated with the @Setter annotation
Set<? extends Element> annotatedElements =
[Link]([Link]);
[Link] 37
// check, if setter is public
if (![Link]().contains([Link])) {
printError(method, "setter must be public");
}
@Override
public void init(ProcessingEnvironment processingEnvironment) {
[Link](processingEnvironment);
embalaje
Para ser aplicado por el compilador, el procesador de anotaciones debe estar disponible para el
SPI (ver ServiceLoader ).
[Link]
import [Link];
@Setter
[Link] 38
private void setValue(String value) {}
@Setter
public void setString(String value) {}
@Setter
public static void main(String[] args) {}
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:
[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
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:
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 siguiente ejemplo ilustra la sintaxis para ambos tipos de parámetros del receptor:
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:
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:
[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í:
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"})
@SuppressWarnings("unused")
[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 .
@Override
public boolean equals(Object obj) {
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.
@Override
public boolean equals(Object obj) {
return [Link](this, obj, "field1", "field2");
}
Para implementar hashCode método hashCode de un objeto, puede usar la clase HashCodeBuilder .
@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);
}
@Override
public int hashCode() {
return [Link](this, "field1", "field2");
}
Para implementar fácilmente el método toString de un objeto, puede usar la clase ToStringBuilder
.
@Override
public String toString() {
return [Link]();
}
Resultado de ejemplo:
[Link]@dd7123[<null>,0,false]
@Override
public String toString() {
[Link] 44
[Link]("field1",field1);
[Link]("field2",field2);
[Link]("field3",field3);
return [Link]();
}
Resultado de ejemplo:
[Link]@dd7404[field1=<null>,field2=0,field3=false]
@Override
public String toString() {
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);
}
@Override
public String toString() {
return [Link](this, ToStringStyle.JSON_STYLE);
}
[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.
Examples
Imprimir todos los marcos de pila de la secuencia 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
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.
class FooHelper {
protected static void foo() {
[Link]();
}
}
class BarHelper {
protected static void bar() {
[Link]([Link](Option.RETAIN_CLASS_REFERENCE).getCallerClass());
}
}
Salida:
class [Link]
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 {
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.
[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.
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];
[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.
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];
[Link]("Method parameter:");
final Type parameterType = [Link]()[0];
displayGenericType(parameterType, "\t");
[Link]("Field type:");
final Type fieldType = [Link]();
displayGenericType(fieldType, "\t");
[Link] 50
}
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
import [Link];
import [Link];
Para hacerlo, deberá usar el método Clase # getField () de una manera como la que se muestra a
continuación:
[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");
// Set the value of the modifiers field under an object for non-static fields
[Link](nameField, newModifiersOnNameField);
// 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:
Cuando use Class # getDeclaredField , utilícelo para obtener un campo en la clase en sí:
class Hacked {
public String someState;
}
[Link] 52
Constructor de llamadas
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:
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]();
recuperando valores
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]());
}
Dada una String contiene el nombre de una clase, se puede acceder a su objeto de Class usando
[Link] :
[Link] 54
throw new IllegalStateException(ex);
}
Java SE 1.2
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:
[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.
import [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:
rompe ambas barreras se puede utilizar para cambiar las variables privadas y finales
Reflection
como se explicó anteriormente.
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 .
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.
[Link] 57
public void someMethod1();
public int someMethod2(String s);
}
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;
}
};
[Link] 58
Parameter: stackoverflow
anotherMethod was invoked!
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
for(Field f : [Link]())
[Link](f);
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 .
[Link] 59
Así que este código imprimirá "apestas!"
1 = 42
Todo es verdad
Y de acuerdo con este post de stackoverflow podemos usar la reflexión para hacer algo realmente
malo.
Tenga en cuenta que lo que estamos haciendo aquí hará que la JVM se comporte de forma
inexplicable. Esto es muy peligroso.
[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
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
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.
nombre del
descripción
método
stop() se llama cada vez que el applet se superpone con otras ventanas
Examples
Applet mínimo
[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);
}
}
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>
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 .
@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);
}
}
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 .
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.
@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);
}
}
@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]();
}
}
[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 */ }
}
}
[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 SE 7
import [Link];
import [Link];
import [Link];
try {
byte[] data = [Link](path);
} catch(IOException e) {
[Link]();
}
import [Link];
import [Link];
...
try {
Image img = [Link](new File("~/Desktop/[Link]"));
} catch (IOException e) {
[Link]();
}
Java SE 7
[Link] 68
} catch (IOException ioe) {
// Handle I/O Exception
[Link]();
}
Java SE 7
La mayoría de las API de archivos [Link] aceptan tanto String como File como argumentos, por
lo que también podría usar
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 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.
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:
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:
[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.
[Link] 71
}
}
}
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]");
// -> NIO
Path directory = [Link]("C:/");
Path pathInDirectory = [Link]("[Link]");
// -> 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);
// -> 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));
}
}
[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];
}
});
// -> 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];
}
});
[Link] 74
[Link](([Link]() ? "d" : "f") + " " +
[Link]());
if ([Link]()) {
// Note: Symbolic links are followed
recurseFolder(selectedFile);
}
}
}
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:
[Link] 75
} catch (FileNotFoundException e) {
[Link]();
} catch (IOException e) {
[Link]();
}
Puede leer un archivo binario utilizando este fragmento de código en todas las versiones
recientes de Java:
Java SE 1.4
Si está utilizando Java 7 o posterior, hay una forma más sencilla de usar la nio API :
Java SE 7
Cierre
Un archivo puede ser bloqueado usando la API FileChannel que se puede adquirir de los streams y
readers de Input Input.
[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]();
}
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.
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:
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
if (![Link]()) {
[Link]("The input file doesn't exit.");
return;
}
try {
FileInputStream fis = new FileInputStream(inputFile);
FileChannel fileChannel = [Link]();
ByteBuffer buffer = [Link](1024);
[Link]();
} catch (IOException e) {
[Link]();
[Link] 78
}
}
}
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];
import [Link];
import [Link];
import [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]();
}
}
}
Para escribir datos en un archivo usando Channel necesitamos los siguientes pasos:
import [Link].*;
import [Link].*;
public class FileChannelWrite {
try {
FileOutputStream fos = new FileOutputStream(outputFile);
FileChannel fileChannel = [Link]();
byte[] bytes = [Link]();
ByteBuffer buffer = [Link](bytes);
[Link](buffer);
[Link]();
} catch ([Link] e) {
[Link]();
}
}
}
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]";
[Link]();
} catch (FileNotFoundException e) {
[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 )
// assume that neither "A New Folder" or "A New Folder 2" exist
[Link] 81
[Link](); // will make the directory
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.
En un sistema UNIX, Linux o MacOSX se puede hacer desde el shell usando > redirección. Por
ejemplo:
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).
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:
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] 82
de comandos.
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.
[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.
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 .
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:
[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];
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 :
[Link] 85
La ejecución de la clase Main muestra que SampleClass se carga desde el directorio versionado:
jar root
- demo
- [Link]
- META-INF
- versions
- 9
- demo
- [Link]
package demo;
import [Link];
[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.).
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
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
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:
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 :
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 .
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.
Sin embargo, como se trata de una matriz vacía, no se pueden leer ni asignar elementos de ella:
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 .
El tamaño de la matriz se puede determinar utilizando un campo final público llamado length :
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.
[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:
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.
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:
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 :
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 .
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)
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.
[Link] 93
public MyGenericClass(Class<T> clazz) {
a = (T[]) [Link](clazz, 5);
}
[Link]() se puede usar para llenar una matriz con el mismo valor después de la
inicialización:
Vivir en Ideone
fill() también puede asignar un valor a cada elemento del rango especificado de la matriz:
Vivir en Ideone
Java SE 8
El siguiente ejemplo crea una matriz de enteros y establece todos sus elementos en su valor de
índice respectivo:
Vivir en Ideone
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:
Vivir en Ideone
[Link] 95
• Object[] toArray()
Java SE 5
Java SE 5
// 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]);
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
):
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] .
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, 6},
{7, 8, 9}
};
[Link]([Link](arr)); // [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
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:
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.
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
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]()
// Using [Link]()
// Using [Link]()
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
[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 :
• 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:
• 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[] ).
Ver demostración
Integer[] arr = {1, 2, 3}; // object array of Integer (wrapper for int)
[Link]([Link](arr).contains(1));
Ver demostración
[Link]([Link](1,2,3).contains(1));
Ver demostración
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 .
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];
[Link] 100
Fuente de la imagen: [Link]
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:
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 .
Salida:
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]);
}
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.
[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.
Resultado:
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
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.
Java SE 8
Puede iterar sobre matrices usando un bucle mejorado para (también conocido como foreach) o
usando índices de matrices:
[Link] 104
Java SE 5
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 matrices primitivas (usando java 8) use flujos (específicamente en este ejemplo -
[Link] -> IntStream ):
Si no puede usar secuencias (no java 8), puede elegir usar la biblioteca de guayabas de google:
En arreglos bidimensionales o más, ambas técnicas pueden usarse de una manera un poco más
compleja.
Ejemplo:
Java SE 5
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:
// 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:
// DON'T DO THIS :
int doubleLength = [Link] * 2;
for (int i = 0; i < doubleLength; i += 2) {
array[i / 2] = i;
}
}
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);
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
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:
Tenga en cuenta que [Link] también proporciona una sobrecarga que le permite cambiar
el tipo de la matriz:
[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.
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;
}
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:
// Creates a new array with the same size as the list and copies the list
// elements to it.
array = [Link](new String[[Link]()]);
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:
[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]
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:
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:
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[] 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.
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.
Supongamos (por ejemplo) que es necesario agregar un nuevo elemento a la matriz listOfCities
definida como se listOfCities anteriormente. Para hacer esto, necesitarás:
Hay varias formas de hacer lo anterior. Antes de Java 6, la forma más concisa era:
Desde Java 6 en adelante, los métodos [Link] y [Link] pueden hacer esto de
manera más simple:
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
[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.
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:
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.
[Link] 112
Usando una Stream
Java SE 8
Nota: Usar una búsqueda lineal directa es más eficiente que envolver en una lista.
Java SE 8
[Link] 113
}
Ordenando matrices
import [Link];
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
Salida:
Orden decreciente
Salida:
String array after sorting in descending order : [Steve, Shane, John, Ben, Adam]
[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.
[Link](courses);
[Link]("Object array after sorting in natural order : " +
[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 ]
Java SE 8
[Link] 115
Con versiones inferiores, puede ser iterando la matriz primitiva y copiándola explícitamente a la
matriz en caja:
Java SE 8
De manera similar, una matriz en caja se puede convertir en una matriz de su contraparte
primitiva:
Java SE 8
Java SE 8
[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];
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.
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
import [Link];
[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]();
}
}
}
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];
// ...
[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);
[Link]();
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.
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].*;
// 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]();
}
}
[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.
Java SE 7
Afortunadamente, las expresiones que evalúan a int pueden usarse en lugar de un Integer
cuando sea necesario.
[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:
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
[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.
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.
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 .
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();
}
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é.
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
}
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
Ejemplo:
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.
[Link] 125
Capítulo 18: Banderas JVM
Observaciones
Se recomienda encarecidamente que utilice estas opciones solamente:
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
-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>
-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:
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
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
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
[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:
Comparando BigDecimals
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:
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.
//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.
//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:
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 .
Resultado: 0.7142857143
//Equivalent to result = a % b
BigDecimal result = [Link](b);
[Link](result);
Resultado: 5
6. Poder
[Link] 132
BigDecimal a = new BigDecimal("5");
Resultado: 9765625
[Link]
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
Resultado: 7
[Link]
BigDecimal a = new BigDecimal("5");
BigDecimal b = new BigDecimal("7");
Resultado: 5
Resultado: 52.3449843776
[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.
import [Link];
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 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];
[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.
sum = [Link]([Link](i));
Java SE 8
[Link] 136
BigInteger puede tener más de 2 mil millones de bits!
Examples
Inicialización
o, para enteros:
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.
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:
Esto generará una instancia de BigInteger con valor -128 ya que el primer bit se interpreta como
el bit de signo.
[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.
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:
if([Link](two)){
[Link]("Equal");
}
else{
[Link]("Not Equal");
}
Salida:
Not Equal
Nota:
if (firstBigInteger == secondBigInteger) {
// Only checks for reference equality, not content equality!
}
[Link] 138
También puede comparar su BigInteger con valores constantes como 0,1,10.
por ejemplo:
También puede comparar dos BigIntegers usando el compareTo() , como sigue: compareTo()
devuelve 3 valores.
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.
}
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
salida: 20
Sustracción: 10 - 9 = 1
salida: 1
[Link] 139
División: 10/5 = 2
salida: 2
División: 17/4 = 4
salida: 4
Multiplicación: 10 * 5 = 50
salida: 50
Potencia: 10 ^ 3 = 1000
salida: 1000
Resto: 10% 6 = 4
salida: 4
[Link] 140
[Link]([Link](value2));
Salida: 6
[Link]([Link](value2));
Salida: 11
[Link]([Link](value2));
Salida: 10
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
[Link](val2);
Binario y
[Link](val2);
Xor binario:
[Link] 141
[Link](val2);
Giro a la derecha:
Shift izquierdo:
[Link]();
Salida: 5
NAND (y no): *
[Link](val2);
Salida: 7
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:
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:
Si está dispuesto a renunciar a la velocidad para obtener números aleatorios de mayor calidad,
puede usar un new SecureRandom () lugar:
import [Link];
¡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.
@Override
protected int next(int bits) {
seed = ((22695477 * seed) + 1) & 2147483647; // Values shamelessly stolen from
Wikipedia
return seed;
}
});
[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.
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:
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.
[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 .
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.
[Link](); // true
[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 .
[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.
Nota : utilice siempre las constantes del mes: la representación numérica es engañosa , por
ejemplo, [Link] tiene el valor 0
add() y roll() se pueden usar para aumentar / disminuir los campos del Calendar .
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
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] 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;
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:
El siguiente ejemplo muestra otras formas en que puede usar el guión bajo en literales numéricos:
Puede colocar guiones bajos solo entre dígitos; No puedes colocar guiones bajos en los
siguientes lugares:
[Link] 150
• En posiciones donde se espera una cadena de dígitos
Puedes usar
en lugar de
[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.
[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.
[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.
[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.
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:
[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:
@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 .
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.
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] .
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]();
}
[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.
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.
/**
* 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 {
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);
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]();
byte[] wrappedKey;
try {
wrappedKey = [Link](aesKey);
} catch (IllegalBlockSizeException e) {
throw new RuntimeException(
"AES key should always fit OAEP with normal sized RSA key", e);
}
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 ---
// - element 1: make sure that we know the size of the wrapped key
[Link]((short) [Link]);
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 {
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);
// 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");
}
[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 ---
return [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.
Donde se usa
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();
[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)
Observaciones
Representación
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];
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:
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
Aquí, este objeto Date contiene la fecha y hora actuales en que se creó este objeto.
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] 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.
//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]()));
Java SE 8
//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)));
after, before , compareTo y equals métodos comparan los valores devueltos por getTime () método
para cada 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.
Debido a que la mayoría de las aplicaciones deben usar LocalDate , ChronoLocalDate no se incluye
en los ejemplos. Lectura adicional aquí .
[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:
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).
format()de la clase SimpleDateFormat ayuda a convertir un objeto Date en cierto objeto String
formato utilizando la cadena de patrón suministrada.
[Link]("dd-MM-yyyy");
[Link]([Link](today)); //25-02-2016
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.
[Link] 169
parse() de la clase SimpleDateFormat ayuda a convertir un patrón de String en un objeto Date .
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.
// print it
[Link](formattedDate);
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;
}
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.
[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.
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 un LocalDateTime
// Date to LocalDate
LocalDate localDate = [Link]().atZone(defaultZoneId).toLocalDate();
// LocalDate to Date
[Link]([Link](defaultZoneId).toInstant());
[Link] 172
// Date to LocalDateTime
LocalDateTime localDateTime = [Link]().atZone(defaultZoneId).toLocalDateTime();
// LocalDateTime to Date
Date out = [Link]([Link](defaultZoneId).toInstant());
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] :
Salida:
[Link] to [Link] conversión suele ser necesaria cuando un objeto Date debe
escribirse en una base de datos.
Ejemplo
[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));
}
Salida
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
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);
[Link] 174
esta clase funciona muy bien dentro de una clase de temporizador para simular un reloj de
alarma.
[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:
@Override
public String toString() {
return firstName + " " + lastName;
[Link] 176
}
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:
método igual ()
TL; DR
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
== .
[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 .
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}
@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;
}
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;
}
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.
[Link] 179
//as mergedInstance is a proxy (subclass) of Foo
}
@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 .
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:
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != [Link]()) {
return false;
}
@Override
public int hashCode() {
int hash = 1;
hash = 31 * hash + field1;
hash = 31 * hash + field2;
hash = 31 * hash + (field3 == null ? 0 : [Link]());
return hash;
}
}
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:
// 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;
}
}
[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.
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.
package [Link];
import [Link];
[Link] 183
} catch (InterruptedException e) {
[Link]("Thread B was interrupted from waiting");
}
}
while (![Link]()) {
synchronized (obj) {
// notify ONE thread which has called [Link]()
[Link]();
}
}
}
};
[Link]();
[Link]();
[Link]();
[Link]();
[Link]("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 {
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 .
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 .
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 .
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.
} 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] :
En este caso, es la última oportunidad de cerrar el recurso si ese recurso no se ha cerrado antes.
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.
[Link] 187
con llamada explícita a super() constructor
public MyClass() {
super();
}
}
public MyClass() {
// empty
}
}
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.
doSomethingWith(size);
this([Link]());
addInitialValues(initialValues);
}
}
[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.
Nada más de lo que sucedería en una subclase que tiene un constructor vacío predeterminado
(menos la llamada a super() ).
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.
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:
[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.
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
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:
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);
}
}
/**
* 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;
}
}
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() .
[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.
age=23
color=green
name=Steve
[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]());
}
}
[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.
[Link] 197
public final class Color {
final private int red;
final private int green;
final private int blue;
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;
//...
[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;
}
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á.
[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
[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".
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
[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 {
//prints: 0, 1, 2, 3, 4,
for(int i = 0; i < 5; i++) {
[Link]([Link]() + ", ");
}
}
}
Al crear una clase anidada, tiene la opción de tener esa clase estática anidada:
O no estático:
[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:
private StaticNestedClass() {
innerField = aField; //Illegal, can't access aField from static context
aMethod(); //Illegal, can't call aMethod from static context
}
private NestedClass() {
innerField = aField; //Legal
aMethod(); //Legal
}
}
[Link] 204
OuterClass2 instance.
//As this is a static context, there is no
surrounding OuterClass2 instance
}
}
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.
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 int x = 5;
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.
[Link] 205
private int x;
private void anInnerMethod() {}
}
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.
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:
[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:
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:
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.
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:
[Link] 208
public void method() {
[Link]("My counter: " + counter);
[Link]("Outer counter: " + [Link]);
// updating my counter
counter = [Link];
}
}
}
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 {
[Link] createInner() {
return [Link] InnerClass();
}
}
[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.
class ObjectMemberVsStaticMember {
void increment() {
staticCounter ++;
memberCounter++;
}
}
[Link] 210
[Link]();
[Link]();
[Link]();
[Link]("[Link] = " +
[Link]);
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.
[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.
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.
Los objetos vienen en su propia clase, por lo que un ejemplo simple sería un automóvil
(explicaciones detalladas a continuación):
public Car(){
milesPerGallon = 0;
name = "";
color = "";
numGallonsInTank = 0;
}
[Link] 212
//Cars need to drive
public void drive(int distanceInMiles){
//get miles left in car
int miles = numGallonsInTank * milesPerGallon;
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
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 .
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
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:
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,
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:
[Link] 214
[Link]("Purple");
[Link](10);
[Link](30);
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.
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 .
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 SuperManClass(){
// some implementation
}
// ... methods
}
[Link] 215
public class BatmanClass extends SupermanClass{
public BatmanClass(){
super();
}
//... methods...
}
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:
static {
Set<String> set = new HashSet<>();
[Link]("Hello");
[Link]("World");
[Link]("foo");
[Link]("bar");
[Link]("42");
WORDS = [Link](set);
}
}
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.
[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.
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.
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.
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.
Así que tenemos una clase llamada Forma y tiene un método llamado área que probablemente
devolverá el área de la forma.
// 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;
}
}
// 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 .
[Link] 218
// Drumbeats ......
//This should print 78.5
[Link]("Shape of circle : "+[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:
[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