De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda
Un fragmento de código Java con palabras clave resaltadas en negrita azul

La sintaxis de Java se refiere al conjunto de reglas que definen cómo se escribe e interpreta un programa Java.

La sintaxis se deriva principalmente de C y C ++ . A diferencia de C ++, en Java no hay funciones o variables globales, pero hay miembros de datos que también se consideran variables globales. Todo el código pertenece a clases y todos los valores son objetos . La única excepción son los tipos primitivos , que no están representados por una instancia de clase por razones de rendimiento (aunque se pueden convertir automáticamente en objetos y viceversa mediante autoboxing ). Algunas características como la sobrecarga de operadores o los tipos de enteros sin signo se omiten para simplificar el lenguaje y evitar posibles errores de programación.

La sintaxis de Java se ha ampliado gradualmente en el transcurso de numerosas versiones importantes de JDK y ahora admite capacidades como programación genérica y literales de función (llamadas expresiones lambda en Java). Desde 2017, se lanza una nueva versión de JDK dos veces al año, y cada lanzamiento trae mejoras incrementales al lenguaje.

Conceptos básicos [ editar ]

Identificador [ editar ]

Un identificador es el nombre de un elemento en el código . Hay ciertas convenciones de nomenclatura estándar que se deben seguir al seleccionar nombres para elementos. Los identificadores en Java distinguen entre mayúsculas y minúsculas .

Un identificador puede contener:

  • Cualquier carácter Unicode que sea una letra (incluidas letras numéricas como números romanos ) o un dígito.
  • Signo de moneda (como ¥).
  • Conectando caracteres de puntuación (como _ ).

Un identificador no puede:

  • Empiece con un dígito.
  • Ser igual a una palabra clave reservada, literal nulo o literal booleano.

Palabras clave [ editar ]

Literales [ editar ]

Los literales enteros son de inttipo por defecto a menos que el longtipo se especifique agregando Lo lsufijo al literal, por ejemplo 367L. Desde Java SE 7, es posible incluir guiones bajos entre los dígitos de un número para aumentar la legibilidad; por ejemplo, un número 145608987 se puede escribir como 145_608_987 .

Variables [ editar ]

Las variables son identificadores asociados con valores. Se declaran escribiendo el tipo y el nombre de la variable y, opcionalmente, se inicializan en la misma instrucción asignando un valor.

int  count ;  // Declarando una variable no inicializada llamada 'count', de tipo 'int' count  =  35 ;  // Inicializando la variable int  count  =  35 ;  // Declarando e inicializando la variable al mismo tiempo

Se pueden declarar e inicializar varias variables del mismo tipo en una declaración utilizando una coma como delimitador.

int  a ,  b ;  // Declarando múltiples variables del mismo tipo int  a  =  2 ,  b  =  3 ;  // Declarar e inicializar múltiples variables del mismo tipo

Desde Java 10, es posible inferir tipos para las variables automáticamente usando var.

// la secuencia tendrá el tipo FileOutputStream como se infiere de su inicializador var  stream  =  new  FileOutputStream ( "file.txt" );// Una declaración equivalente con un tipo explícito FileOutputStream  stream  =  new  FileOutputStream ( "file.txt" );

Bloques de código [ editar ]

Los separadores { y} significa un bloque de código y un nuevo alcance. Los miembros de la clase y el cuerpo de un método son ejemplos de lo que puede vivir dentro de estas llaves en varios contextos.

Dentro de los cuerpos del método, se pueden usar llaves para crear nuevos ámbitos, como se indica a continuación:

void  doSomething ()  {  int  una ; {  int  b ;  a  =  1 ;  } a  =  2 ;  b  =  3 ;  // Ilegal porque la variable b está declarada en un ámbito interno .. }

Comentarios [ editar ]

Java tiene tres tipos de comentarios: comentarios tradicionales , comentarios de final de línea y comentarios de documentación .

Los comentarios tradicionales, también conocidos como comentarios de bloque, comienzan con /*y terminan con */, pueden extenderse a lo largo de varias líneas. Este tipo de comentario se derivó de C y C ++.

/ * Este es un comentario de varias líneas. Puede ocupar más de una línea. * /

Los comentarios de final de línea comienzan //y se extienden hasta el final de la línea actual. Este tipo de comentario también está presente en C ++ y en C.

// Este es un comentario de final de línea

Los comentarios de documentación en los archivos fuente son procesados ​​por la herramienta Javadoc para generar documentación. Este tipo de comentario es idéntico a los comentarios tradicionales, excepto que comienza /**y sigue las convenciones definidas por la herramienta Javadoc. Técnicamente, estos comentarios son un tipo especial de comentario tradicional y no se definen específicamente en la especificación del lenguaje.

/ ** * Este es un comentario de documentación. * * @ autor John Doe * /

Tipos universales [ editar ]

Las clases del paquete java.lang se importan implícitamente en cada programa, siempre que ningún tipo importado explícitamente tenga los mismos nombres. Los importantes incluyen:

java.lang.Object
El tipo superior de Java . Superclase de todas las clases que no declaran una clase padre. Todos los valores se pueden convertir a este tipo, aunque para los valores primitivos esto implica el autoboxing .
java.lang.String
Tipo de cadena básico de Java. Inmutable . Algunos métodos tratan cada unidad de código UTF-16 como un "carácter", pero también están disponibles métodos para convertir a uno int[]que sea efectivamente UTF-32 .
java.lang.Throwable
supertipo de todo lo que se puede lanzar o capturar con declaraciones throwy de Java catch.

Estructura del programa [ editar ]

Las aplicaciones Java constan de colecciones de clases. Las clases existen en paquetes, pero también se pueden anidar dentro de otras clases.

mainmétodo [ editar ]

Cada aplicación Java debe tener un punto de entrada. Esto es cierto tanto para las aplicaciones de interfaz gráfica como para las aplicaciones de consola. El punto de entrada es el mainmétodo. Puede haber más de una clase con un mainmétodo, pero la clase principal siempre se define externamente (por ejemplo, en un archivo de manifiesto ). El método debe ser staticy se pasa argumentos de línea de comandos como una matriz de cadenas. A diferencia de C ++ o C # , nunca devuelve un valor y debe devolverlo void.

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

Paquetes [ editar ]

Los paquetes son parte de un nombre de clase y se utilizan para agrupar y / o distinguir entidades nombradas de otras. Otro propósito de los paquetes es gobernar el acceso al código junto con los modificadores de acceso. Por ejemplo, java.io.InputStreames un nombre de clase completamente calificado para la clase InputStreamque se encuentra en el paquete java.io.

Un paquete se declara al comienzo del archivo con la packagedeclaración:

paquete  myapplication.mylibrary ; clase  pública MyClass  { }

Las clases con el publicmodificador deben colocarse en los archivos con el mismo nombre y extensión java y colocarse en carpetas anidadas correspondientes al nombre del paquete. La clase anterior tendrá la siguiente ruta: .myapplication.mylibrary.MyClassmyapplication/mylibrary/MyClass.java

Declaración de importación [ editar ]

Escriba la declaración de importación [ editar ]

Una declaración de importación de tipo permite hacer referencia a un tipo con nombre mediante un nombre simple en lugar del nombre completo que incluye el paquete. Las declaraciones de importación pueden ser declaraciones de importación de un solo tipo o declaraciones de importación bajo demanda . Las declaraciones de importación deben colocarse en la parte superior de un archivo de código después de la declaración del paquete.

paquete  myPackage ;import  java.util.Random ;  // Declaración de tipo únicopublic  class  ImportsTest  {  public  static  void  main ( String []  args )  {  / * La siguiente línea es equivalente a  * java.util.Random random = new java.util.Random ();  * Hubiera sido incorrecto sin la importación.  * /  Aleatorio  aleatorio  =  nuevo  Aleatorio ();  } }

Las declaraciones de importación bajo demanda se mencionan en el código. Una "importación de tipo" importa todos los tipos de paquete. Una "importación estática" importa miembros del paquete.

importar  java.util. * ;  / * Esta forma de importar clases hace que todas las clases  en el paquete java.util estén disponibles por nombre, podría usarse en lugar de la  declaración de importación en el ejemplo anterior. * / importar  java. * ;  / * Esta declaración es legal, pero no hace nada, ya que no  hay clases directamente en el paquete java. Todos ellos están en paquetes  dentro del paquete java. Esto no importa todas las clases disponibles. * /

Declaración de importación estática [ editar ]

Este tipo de declaración está disponible desde J2SE 5.0 . Las declaraciones de importación estáticas permiten el acceso a miembros estáticos definidos en otra clase, interfaz, anotación o enumeración; sin especificar el nombre de la clase:

import static  java.lang.System.out ;  // 'out' es un campo estático en java.lang.Systempublic  class  HelloWorld  {  public  static  void  main ( String []  args )  {  / * La siguiente línea es equivalente a:  System.out.println ("¡Hola mundo!"); y habría sido incorrecto sin la declaración de importación. * /  fuera . println ( "¡Hola mundo!" );  } }

Las declaraciones de importación bajo demanda permiten importar todos los campos del tipo:

importar static  java.lang.System. * ;  / * Esta forma de declaración hace que todos los  campos de la clase java.lang.System estén disponibles por nombre, y puede usarse en lugar  de la declaración de importación en el ejemplo anterior. * /

Las constantes de enumeración también se pueden usar con la importación estática. Por ejemplo, esta enumeración está en el paquete llamado screen:

 enumeración  pública ColorName  {  ROJO ,  AZUL ,  VERDE };

Es posible usar declaraciones de importación estáticas en otra clase para recuperar las constantes de enumeración:

import  screen.ColorName ; importar  pantalla estática.ColorName . * ;public  class  Dots  {  / * La siguiente línea es equivalente a 'ColorName foo = ColorName.RED',  y habría sido incorrecta sin la importación estática. * /  ColorName  foo  =  ROJO ; void  shift ()  {  / * La siguiente línea es equivalente a: if (foo == ColorName.RED) foo = ColorName.BLUE; * /  if  ( foo  ==  ROJO )  foo  =  AZUL ;  } }

Operadores [ editar ]

Los operadores en Java son similares a los de C ++ . Sin embargo, no existe un deleteoperador debido a los mecanismos de recolección de basura en Java, y no hay operaciones en los punteros ya que Java no los admite. Otra diferencia es que Java tiene un operador de desplazamiento a la derecha sin firmar ( >>>), mientras que el signo del operador de desplazamiento a la derecha de C depende del tipo. Los operadores en Java no se pueden sobrecargar .

Estructuras de control [ editar ]

Declaraciones condicionales [ editar ]

ifdeclaración [ editar ]

si las declaraciones en Java son similares a las de C y usan la misma sintaxis:

si  ( i  ==  3 ) hacer  Algo ();

ifLa declaración puede incluir un elsebloque opcional , en cuyo caso se convierte en una declaración if-then-else:

if  ( i  ==  2 )  {hacer  Algo (); }  else  {  doSomethingElse (); }

Al igual que C, la construcción else-if no implica ninguna palabra clave especial, se forma como una secuencia de declaraciones if-then-else independientes:

if  ( i  ==  3 )  {hacer  Algo (); }  más  si  ( i  ==  2 )  {  hacerAlgoElse (); }  else  {  hacerAlgoDiferente (); }

Además, tenga en cuenta que el operador ?: Se puede utilizar en lugar de una declaración if simple, por ejemplo

int  a  =  1 ; int  b  =  2 ; int  minVal  =  ( a  <  b )  ?  a  :  b ;

switchdeclaración [ editar ]

Sentencias switch en Java pueden utilizar byte, short, char, y int(nota: no long) tipos de datos primitivos o sus correspondientes tipos de envoltura. A partir de J2SE 5.0, es posible utilizar tipos de enumeración . A partir de Java SE 7, es posible utilizar Strings. No se pueden utilizar otros tipos de referencia en switchdeclaraciones.

Los valores posibles se enumeran mediante caseetiquetas. Estas etiquetas en Java pueden contener solo constantes (incluidas las constantes de enumeración y las constantes de cadena). La ejecución comenzará después de la etiqueta correspondiente a la expresión dentro de los corchetes. defaultPuede estar presente una etiqueta opcional para declarar que el código siguiente se ejecutará si ninguna de las etiquetas de caso corresponde a la expresión.

El código de cada etiqueta termina con la breakpalabra clave. Es posible omitirlo haciendo que la ejecución pase a la siguiente etiqueta, sin embargo, normalmente se informará una advertencia durante la compilación.

cambiar  ( ch )  {  caso  'A' : hacer  Algo ();  // Se activa si ch == 'A' se  rompe ;  case  'B' :  case  'C' :  doSomethingElse ();  // Se activa si ch == 'B' o ch == 'C' se  rompen ;  predeterminado :  doSomethingDifferent ();  // Activado en cualquier otro caso  break ; }
switchexpresiones [ editar ]

Desde Java 14 es posible utilizar expresiones de cambio, que utilizan la nueva sintaxis de flechas:

var  result  =  switch  ( ch )  {  caso  'A'  ->  Resultado . GRANDE ;  caso  'B' ,  'C'  ->  Resultado . FINO ;  predeterminado  ->  lanzar  nueva  ThisIsNoGoodException (); };

Alternativamente, existe la posibilidad de expresar lo mismo con la yielddeclaración, aunque se recomienda preferir la sintaxis de flecha porque evita el problema de caídas accidentales.

var  result  =  switch  ( ch )  {  case  'A' :  rendimiento del  resultado . GRANDE ;  caso  'B' :  caso  'C' :  rendimiento de  resultado . FINO ;  predeterminado :  lanza una  nueva  ThisIsNoGoodException (); };

Declaraciones de iteración [ editar ]

Las declaraciones de iteración son declaraciones que se ejecutan repetidamente cuando una condición determinada se evalúa como verdadera. Desde J2SE 5.0 , Java tiene cuatro formas de tales declaraciones.

whilebucle [ editar ]

En el whileciclo, la prueba se realiza antes de cada iteración.

while  ( i  <  10 )  {hacer  Algo (); }

do ... whilebucle [ editar ]

En el do ... whileciclo, la prueba se realiza después de cada iteración. En consecuencia, el código siempre se ejecuta al menos una vez.

// doSomething () se llama al menos una vez do  {  doSomething (); }  mientras  ( i  <  10 );

forbucle [ editar ]

forLos bucles en Java incluyen un inicializador, una condición y una contraexpresión. Es posible incluir varias expresiones del mismo tipo utilizando una coma como delimitador (excepto en la condición). Sin embargo, a diferencia de C, la coma es solo un delimitador y no un operador.

para  ( int  i  =  0 ;  i  <  10 ;  i ++ )  {hacer  Algo (); } // Un ciclo más complejo usando dos variables para  ( int  i  =  0 ,  j  =  9 ;  i  <  10 ;  i ++ ,  j  - =  3 )  {  doSomething (); }

Como C, las tres expresiones son opcionales. El siguiente ciclo es infinito:

para  (;;)  {hacer  Algo (); }

forBucle mejorado [ editar ]

Los forbucles mejorados están disponibles desde J2SE 5.0 . Este tipo de bucle utiliza iteradores integrados sobre matrices y colecciones para devolver cada elemento de la colección dada. Cada elemento es devuelto y accesible en el contexto del bloque de código. Cuando se ejecuta el bloqueo, se devuelve el siguiente elemento hasta que no queden elementos. A diferencia de C # , este tipo de bucle no implica una palabra clave especial, sino que utiliza un estilo de notación diferente.

para  ( int  i  :  intArray )  {  doSomething ( i ); }

Saltar declaraciones [ editar ]

Etiquetas [ editar ]

A las etiquetas se les asignan puntos en el código que utilizan las declaraciones breaky continue. Tenga en cuenta que la gotopalabra clave Java no se puede utilizar para saltar a puntos específicos del código.

inicio: algún método ();

breakdeclaración [ editar ]

La breakdeclaración sale del bucle o switchdeclaración más cercana . La ejecución continúa en la declaración después de la declaración terminada, si la hubiera.

for  ( int  i  =  0 ;  i  <  10 ;  i ++ )  {  while  ( true )  {  break ;  }  // Romperá hasta este punto }

Es posible salir del bucle externo usando etiquetas:

exterior: for  ( int  i  =  0 ;  i  <  10 ;  i ++ )  {  while  ( verdadero )  {  romper  exterior ;  } } // Romperá hasta este punto

continuedeclaración [ editar ]

La continuedeclaración interrumpe la iteración actual de la declaración de control actual y comienza la siguiente iteración. El siguiente whilebucle en el código a continuación lee caracteres llamando getChar(), omitiendo las declaraciones en el cuerpo del bucle si los caracteres son espacios:

int  ch ; while  ( ch  ==  getChar ())  {  if  ( ch  ==  '' )  {  continuar ;  // Omite el resto del ciclo while  } // El resto del ciclo while, no se alcanzará si ch == ''  doSomething (); }

Las etiquetas se pueden especificar en continuedeclaraciones y breakdeclaraciones:

externo: para  ( String  str  :  stringsArr )  {  char []  strChars  =  str . toCharArray ();  para  ( carbón  ch  :  strChars )  {  Si  ( CH  ==  '' )  {  / * Continúa el ciclo externo y la siguiente  secuencia se recupera del stringsArr * /  siguen  exterior ;  }  DoSomething ( CH );  } }

returndeclaración [ editar ]

La returndeclaración se utiliza para finalizar la ejecución del método y devolver un valor. Un valor devuelto por el método se escribe después de la returnpalabra clave. Si el método devuelve algo menos void, debe usar la returndeclaración para devolver algún valor.

void  doSomething ( boolean  streamClosed )  {  // Si streamClosed es verdadero, la ejecución se detiene  if  ( streamClosed )  {  return ;  }  readFromStream (); }int  calcularSuma ( int  a ,  int  b )  {  int  resultado  =  a  +  b ;  devolver  resultado ; }

returninstrucción finaliza la ejecución inmediatamente, excepto en un caso: si la instrucción se encuentra dentro de un trybloque y se complementa con un finally, el control se pasa al finallybloque.

vacío  doSomething ( booleano  streamClosed )  {  try  {  si  ( streamClosed )  {  retorno ;  }  readFromStream ();  }  finalmente  {  / * Se llamará en último lugar incluso si  no se llamó a  readFromStream ()  * / freeResources (); } }

Declaraciones de manejo de excepciones [ editar ]

try-catch-finallydeclaraciones [ editar ]

Las excepciones se gestionan dentro de try... catchbloques.

try  {  // Declaraciones que pueden  generar excepciones methodThrowingExceptions (); }  catch  ( Exception  ex )  {  // Excepción capturada y manejada aquí  reportException ( ex ); }  finalmente  {  // Las sentencias siempre se ejecutan después de los bloques try / catch  freeResources (); }

Las instrucciones dentro del trybloque se ejecutan y, si alguna de ellas genera una excepción, la ejecución del bloque se interrumpe y el catchbloque maneja la excepción . Puede haber varios catchbloques, en cuyo caso se ejecuta el primer bloque con una variable de excepción cuyo tipo coincide con el tipo de la excepción lanzada.

Java SE 7 también introdujo cláusulas de captura múltiple además de cláusulas de captura única. Este tipo de cláusulas catch permite a Java manejar diferentes tipos de excepciones en un solo bloque, siempre que no sean subclases entre sí.

try  {  methodThrowingExceptions (); }  catch  ( IOException  |  IllegalArgumentException  ex )  {  // Tanto IOException como IllegalArgumentException serán capturados y manejados aquí  reportException ( ex ); }

Si ningún catchbloque coincide con el tipo de la excepción lanzada, la ejecución del bloque externo (o método) que contiene la declaración try... catchse interrumpe y la excepción se pasa hacia arriba y fuera del bloque contenedor (o método). La excepción se propaga hacia arriba a través de la pila de llamadas hasta que se encuentra un catchbloque coincidente dentro de uno de los métodos actualmente activos. Si la excepción se propaga hasta el mainmétodo superior sin que se encuentre un catchbloque coincidente , se escribe una descripción textual de la excepción en el flujo de salida estándar.

Las sentencias dentro del finallybloque siempre se ejecutan después de los bloques tryy catch, tanto si se lanzó una excepción como si no e incluso si returnse alcanzó una sentencia. Estos bloques son útiles para proporcionar código de limpieza que se garantiza que siempre se ejecutará.

Los bloques catchy finallyson opcionales, pero al menos uno u otro debe estar presente después del trybloque.

try-con-declaraciones de recursos [ editar ]

tryLas sentencias -with-resources son un tipo especial de try-catch-finallysentencias introducidas como una implementación del patrón dispose en Java SE 7. En una trysentencia -with-resources, la trypalabra clave es seguida por la inicialización de uno o más recursos que se liberan automáticamente cuando se tryejecuta el bloque. Está terminado. Los recursos deben implementar java.lang.AutoCloseable. tryNo se requiere que las sentencias -with-resources tengan un catcho un finallybloque a diferencia de las try-catch-finallysentencias normales .

try  ( FileOutputStream  fos  =  new  FileOutputStream ( "nombre de archivo" );  XMLEncoder  xEnc  =  nuevo  XMLEncoder ( fos ))  {  xEnc . writeObject ( objeto ); }  catch  ( IOException  ex )  {  Logger . getLogger ( Serializador . clase . getName ()). log ( Nivel . SEVERE ,  nulo , ex ); }

Desde Java 9 es posible utilizar variables ya declaradas:

FileOutputStream  fos  =  new  FileOutputStream ( "nombre de archivo" ); XMLEncoder  xEnc  =  nuevo  XMLEncoder ( fos ); intente  ( fos ;  xEnc )  {  xEnc . writeObject ( objeto ); }  catch  ( IOException  ex )  {  Logger . getLogger ( Serializador . clase . getName ()). log ( Nivel .SEVERO ,  nulo ,  ex ); }

throwdeclaración [ editar ]

La throwdeclaración se usa para lanzar una excepción y finalizar la ejecución del bloque o método. La instancia de excepción lanzada se escribe después de la throwinstrucción.

void  methodThrowingExceptions ( Object  obj )  {  if  ( obj  ==  null )  {  // Lanza una excepción del tipo NullPointerException  throw  new  NullPointerException ();  }  // No se llamará, si el objeto es nulo  doSomethingWithObject ( obj ); }

Control de concurrencia de subprocesos [ editar ]

Java tiene herramientas integradas para la programación de subprocesos múltiples . A los efectos de la sincronización de subprocesos, la synchronizeddeclaración se incluye en lenguaje Java.

Para sincronizar un bloque de código, está precedido por la synchronizedpalabra clave seguida por el objeto de bloqueo dentro de los corchetes. Cuando el hilo en ejecución alcanza el bloque sincronizado, adquiere un bloqueo de exclusión mutua , ejecuta el bloque y luego lo libera. Ningún hilo puede entrar en este bloque hasta que se libere el bloqueo. Se puede utilizar como bloqueo cualquier tipo de referencia no nulo.

/ * Adquiere bloqueo en someObject. Debe ser de un tipo de referencia y no debe ser nulo * / sincronizado  ( someObject )  {  // Declaraciones sincronizadas }

assertdeclaración [ editar ]

assertLas declaraciones han estado disponibles desde J2SE 1.4 . Estos tipos de declaraciones se utilizan para hacer afirmaciones en el código fuente, que se pueden activar y desactivar durante la ejecución de clases o paquetes específicos. Para declarar una aserción, assertse usa la palabra clave seguida de una expresión condicional. Si evalúa falsecuando se ejecuta la instrucción, se lanza una excepción. Esta declaración puede incluir dos puntos seguidos de otra expresión, que actuará como mensaje de detalle de la excepción.

// Si n es igual a 0, se lanza AssertionError assert  n  ! =  0 ; / * Si n es igual a 0, AssertionError se lanzará con el mensaje después de los dos puntos * / assert  n  ! =  0  :  "n era igual a cero" ;

Tipos primitivos [ editar ]

Los tipos primitivos en Java incluyen tipos enteros, números de punto flotante, unidades de código UTF-16 y un tipo booleano. No hay tipos sin firmar en Java, excepto chartype, que se utiliza para representar unidades de código UTF-16. La falta de tipos sin firmar se compensa con la introducción de la operación de desplazamiento a la derecha sin firmar ( >>>), que no está presente en C ++. No obstante, se han recibido críticas sobre la falta de compatibilidad con C y C ++ que esto provoca. [2]

charno corresponde necesariamente a un solo carácter. Puede representar una parte de un par sustituto , en cuyo caso el punto de código Unicode está representado por una secuencia de dos charvalores.

Boxeo y unboxing [ editar ]

Esta función de idioma se introdujo en J2SE 5.0 . El boxing es la operación de convertir un valor de un tipo primitivo en un valor de un tipo de referencia correspondiente, que sirve como envoltorio para este tipo primitivo en particular. Unboxing es la operación inversa de convertir un valor de un tipo de referencia (previamente encuadrado) en un valor de un tipo primitivo correspondiente. Ninguna operación requiere una conversión explícita.

Ejemplo:

int  foo  =  42 ;  // Tipo primitivo Integer  bar  =  foo ;  / * foo está encajado en bar, bar es de tipo Integer,  que sirve como envoltorio para int * / int  foo2  =  bar ;  // Desempaquetado de nuevo al tipo primitivo

Tipos de referencia [ editar ]

Los tipos de referencia incluyen tipos de clase, tipos de interfaz y tipos de matriz. Cuando se llama al constructor, se crea un objeto en el montón y se asigna una referencia a la variable. Cuando una variable de un objeto sale del alcance, la referencia se rompe y cuando no quedan referencias, el objeto se marca como basura. El recolector de basura luego lo recolecta y lo destruye algún tiempo después.

Una variable de referencia es nullcuando no hace referencia a ningún objeto.

Matrices [ editar ]

Las matrices en Java se crean en tiempo de ejecución, al igual que las instancias de clase. La longitud de la matriz se define en el momento de la creación y no se puede cambiar.

int []  números  =  nuevo  int [ 5 ] ; números [ 0 ]  =  2 ; números [ 1 ]  =  5 ; int  x  =  números [ 0 ] ;

Inicializadores [ editar ]

// Sintaxis larga int []  números  =  new  int []  { 20 ,  1 ,  42 ,  15 ,  34 }; // Sintaxis corta int []  numbers2  =  { 20 ,  1 ,  42 ,  15 ,  34 };

Matrices multidimensionales [ editar ]

En Java, las matrices multidimensionales se representan como matrices de matrices. Técnicamente, están representados por matrices de referencias a otras matrices.

int [] []  números  =  nuevo  int [ 3 ] [ 3 ] ; números [ 1 ] [ 2 ]  =  2 ;int [] []  números2  =  {{ 2 ,  3 ,  2 },  { 1 ,  2 ,  6 },  { 2 ,  4 ,  5 }};

Debido a la naturaleza de las matrices multidimensionales, las submatrices pueden variar en longitud, por lo que las matrices multidimensionales no están obligadas a ser rectangulares a diferencia de C:

int [] []  números  =  nuevo  int [ 2 ] [] ;  // Inicialización de la primera dimensión solamentenúmeros [ 0 ]  =  nuevo  int [ 3 ] ; números [ 1 ]  =  nuevo  int [ 2 ] ;

Clases [ editar ]

Las clases son los fundamentos de un lenguaje orientado a objetos como Java. Contienen miembros que almacenan y manipulan datos. Las clases se dividen en nivel superior y anidadas . Las clases anidadas son clases ubicadas dentro de otra clase que pueden acceder a los miembros privados de la clase adjunta. Las clases anidadas incluyen clases miembro (que pueden definirse con el modificador estático para anidamiento simple o sin él para clases internas), clases locales y clases anónimas .

Declaración [ editar ]

Instanciación [ editar ]

Los miembros no estáticos de una clase definen los tipos de variables y métodos de instancia, que están relacionados con los objetos creados a partir de esa clase. Para crear estos objetos, se debe crear una instancia de la clase utilizando el newoperador y llamando al constructor de la clase.

Foo  foo  =  nuevo  Foo ();

Accediendo a miembros [ editar ]

Se accede a los miembros de las instancias y clases estáticas con el .operador (punto).

Acceso a un miembro de la
instancia Se puede acceder a los miembros de la instancia a través del nombre de una variable.

String  foo  =  "Hola" ; Barra de cadena  = foo . toUpperCase ();  

Acceso a un miembro de clase
estática Se accede a los miembros estáticos mediante el nombre de la clase o cualquier otro tipo. Esto no requiere la creación de una instancia de clase. Los miembros estáticos se declaran mediante el staticmodificador.

public  class  Foo  {  public  static  void  doSomething ()  {  } }// Llamando al método estático Foo . hacer algo ();

Modificadores [ editar ]

Los modificadores son palabras clave que se utilizan para modificar declaraciones de tipos y miembros de tipos. En particular, hay un subgrupo que contiene los modificadores de acceso.

  • abstract - Especifica que una clase solo sirve como clase base y no se puede crear una instancia.
  • static - Usado solo para clases miembro, especifica que la clase miembro no pertenece a una instancia específica de la clase contenedora.
  • final- Las clases marcadas como finalno pueden extenderse y no pueden tener subclases.
  • strictfp- Especifica que todas las operaciones de punto flotante deben realizarse de acuerdo con IEEE 754 y prohíbe el uso de precisión mejorada para almacenar resultados intermedios.
Modificadores de acceso [ editar ]

Los modificadores de acceso , o modificadores de herencia , establecen la accesibilidad de clases, métodos y otros miembros. Los miembros marcados como publicpueden ser contactados desde cualquier lugar. Si una clase o su miembro no tiene modificadores, se asume el acceso predeterminado.

public  class  Foo  {  int  go ()  {  return  0 ;  }  Bar de clases  privadas { } }  

La siguiente tabla muestra si el código dentro de una clase tiene acceso a la clase o al método dependiendo de la ubicación de la clase de acceso y el modificador para la clase o miembro de clase accedido:

Esta imagen describe el alcance del miembro de clase dentro de clases y paquetes.

Constructores e inicializadores [ editar ]

Un constructor es un método especial que se llama cuando se inicializa un objeto. Su propósito es inicializar los miembros del objeto. Las principales diferencias entre los constructores y los métodos ordinarios son que los constructores se llaman solo cuando se crea una instancia de la clase y nunca devuelven nada. Los constructores se declaran como métodos comunes, pero reciben el nombre de la clase y no se especifica ningún tipo de retorno:

class  Foo  {  String  str ; Foo ()  {  // Constructor sin argumentos // Inicialización  } Foo ( String  str )  {  // Constructor con un argumento  this . str  =  str ;  } }

Los inicializadores son bloques de código que se ejecutan cuando se crea una clase o instancia de una clase. Hay dos tipos de inicializadores, inicializadores estáticos e inicializadores de instancia .

Los inicializadores estáticos inicializan los campos estáticos cuando se crea la clase. Se declaran utilizando la staticpalabra clave:

class  Foo  {  static  {  // Inicialización  } }

Una clase se crea solo una vez. Por lo tanto, los inicializadores estáticos no se llaman más de una vez. Por el contrario, los inicializadores de instancia se llaman automáticamente antes de la llamada a un constructor cada vez que se crea una instancia de la clase. A diferencia de los constructores, los inicializadores de instancias no pueden aceptar ningún argumento y, por lo general, no pueden generar ninguna excepción marcada (excepto en varios casos especiales). Los inicializadores de instancia se declaran en un bloque sin palabras clave:

clase  Foo  {  {  // Inicialización  } }

Dado que Java tiene un mecanismo de recolección de basura, no hay destructores . Sin embargo, cada objeto tiene un finalize()método llamado antes de la recolección de basura, que se puede anular para implementar la finalización.

Métodos [ editar ]

Todas las declaraciones en Java deben residir dentro de métodos. Los métodos son similares a las funciones excepto que pertenecen a clases. Un método tiene un valor de retorno, un nombre y, por lo general, algunos parámetros se inicializan cuando se llama con algunos argumentos. Al igual que en C ++, los métodos que no devuelven nada tienen el tipo de retorno declarado como void. A diferencia de C ++, los métodos en Java no pueden tener valores de argumento predeterminados y los métodos suelen estar sobrecargados.

class  Foo  {  int  bar ( int  a ,  int  b )  {  return  ( a * 2 )  +  b ;  } / * Método sobrecargado con el mismo nombre pero diferente conjunto de argumentos * /  int  bar ( int  a )  {  return  a * 2 ;  } }

Un método se llama usando .notación en un objeto, o en el caso de un método estático, también en el nombre de una clase.

Foo  foo  =  nuevo  Foo (); int  resultado  =  foo . barra ( 7 ,  2 );  // Se llama al método no estático en fooint  finalResult  =  Math . abs ( resultado );  // Llamada al método estático

La throwspalabra clave indica que un método lanza una excepción. Todas las excepciones marcadas deben aparecer en una lista separada por comas.

void  openStream ()  lanza  IOException ,  myException  {  // Indica que se puede lanzar IOException }
Modificadores [ editar ]
  • abstract- Los métodos abstractos solo pueden estar presentes en clases abstractas , tales métodos no tienen cuerpo y deben anularse en una subclase a menos que sea abstracto en sí mismo.
  • static- Hace que el método sea estático y accesible sin la creación de una instancia de clase. Sin embargo, los métodos estáticos no pueden acceder a miembros no estáticos de la misma clase.
  • final - Declara que el método no se puede invalidar en una subclase.
  • native- Indica que este método se implementa a través de JNI en código dependiente de la plataforma. La implementación real ocurre fuera del código Java, y tales métodos no tienen cuerpo.
  • strictfp- Declara conformidad estricta con IEEE 754 en la realización de operaciones de punto flotante.
  • synchronized- Declara que un hilo que ejecuta este método debe adquirir monitor. Para los synchronizedmétodos, el monitor es la instancia de la clase o java.lang.Classsi el método es estático.
  • Modificadores de acceso: idénticos a los que se utilizan con las clases.
Varargs [ editar ]

Esta función de idioma se introdujo en J2SE 5.0 . El último argumento del método puede declararse como un parámetro de aridad variable, en cuyo caso el método se convierte en un método de aridad variable (a diferencia de los métodos de aridad fija) o simplemente un método varargs . Esto permite pasar un número variable de valores, del tipo declarado, al método como parámetros, sin incluir parámetros. Estos valores estarán disponibles dentro del método como una matriz.

vacío  PrintReport ( Cadena  de cabecera ,  int ...  números )  {  // número representa varargs  sistema . fuera . println ( encabezado );  para  ( int  num  :  números )  {  System . fuera . println ( num );  } }// Llamando al método varargs printReport ( "Datos de informe" ,  74 ,  83 ,  25 ,  96 );

Campos [ editar ]

Los campos, o variables de clase, se pueden declarar dentro del cuerpo de la clase para almacenar datos.

clase  Foo  {  doble  barra ; }

Los campos se pueden inicializar directamente cuando se declaran.

clase  Foo  {  barra doble  = 2.3 ; }  
Modificadores [ editar ]
  • static - Hace que el campo sea un miembro estático.
  • final - Permite que el campo se inicialice solo una vez en un constructor o dentro del bloque de inicialización o durante su declaración, lo que ocurra primero.
  • transient- Indica que este campo no se almacenará durante la serialización .
  • volatile- Si se declara un campo volatile, se garantiza que todos los subprocesos vean un valor coherente para la variable.

Herencia [ editar ]

Las clases en Java solo pueden heredar de una clase. Una clase puede derivarse de cualquier clase que no esté marcada como final. La herencia se declara mediante la extendspalabra clave. Una clase puede hacer referencia a sí misma usando la thispalabra clave y su superclase directa usando la superpalabra clave.

class  Foo  {}clase  Foobar  extiende  Foo  {}

Si una clase no especifica su superclase, hereda implícitamente de la java.lang.Objectclase. Por tanto, todas las clases en Java son subclases de Objectclase.

Si la superclase no tiene un constructor sin parámetros, la subclase debe especificar en sus constructores qué constructor de la superclase usar. Por ejemplo:

class  Foo  {  public  Foo ( int  n )  {  // Haz algo con n  } }la clase  Foobar  extiende  Foo  {  número int privado  ; // La superclase no tiene constructor sin parámetros // así que tenemos que especificar qué constructor de nuestra superclase usar y cómo    public  Foobar ( int  número )  {  super ( número );  esto . número  =  número ;  } }
Métodos anuladores [ editar ]

A diferencia de C ++, todos los finalmétodos que no son métodos en Java son virtuales y pueden ser anulados por las clases heredadas.

 Operación de  clase {  public  int  doSomething ()  {  return  0 ;  } }la clase  NewOperation  extiende la  operación  {  @Override  public  int  doSomething ()  {  return  1 ;  } }
Clases abstractas [ editar ]

Una clase abstracta es una clase que está incompleta o que se considera incompleta. Las clases normales pueden tener métodos abstractos, es decir, métodos que están declarados pero aún no implementados, solo si son clases abstractas. Una clase C tiene métodos abstractos si se cumple alguna de las siguientes condiciones:

  • C contiene explícitamente una declaración de un método abstracto.
  • Cualquiera de las superclases de C tiene un método abstracto y C no declara ni hereda un método que lo implemente.
  • Una superinterfaz directa de C declara o hereda un método (que por lo tanto es necesariamente abstracto) y C ni declara ni hereda un método que lo implemente.
  • Se puede instanciar una subclase de una clase abstracta que no es abstracta en sí misma, lo que da como resultado la ejecución de un constructor para la clase abstracta y, por lo tanto, la ejecución de los inicializadores de campo para las variables de ejemplo de esa clase.
paquete  org.dwwwp.test ;/ ** * @author jcrypto * / public  class  AbstractClass  {  saludo de cadena final estático privado  ;    static  {  System . fuera . println ( AbstractClass . class . getName ()  +  ": tiempo de ejecución del bloque estático" );  hola  =  "hola de"  +  AbstractClass . clase . getName ();  } {  System . fuera . println ( AbstractClass . class . getName ()  +  ": tiempo de ejecución del bloque de instancia" );  } public  AbstractClass ()  {  System . fuera . println ( AbstractClass . class . getName ()  +  ": tiempo de ejecución del constructor" );  } public  static  void  hola ()  {  System . fuera . println ( hola );  } }
paquete  org.dwwwp.test ;/ ** * @author jcrypto * / public  class  CustomClass  extiende  AbstractClass  { static  {  System . fuera . println ( CustomClass . class . getName ()  +  ": tiempo de ejecución del bloque estático" );  } {  System . fuera . println ( CustomClass . class . getName ()  +  ": tiempo de ejecución del bloque de instancia" );  } public  CustomClass ()  {  System . fuera . println ( CustomClass . class . getName ()  +  ": tiempo de ejecución del constructor" );  } public  static  void  main ( String []  args )  {  CustomClass  nc  =  new  CustomClass ();  hola ();  //AbstractClass.hello();// también válido  } }

Producción:

org.dwwwp.test.AbstractClass: tiempo de ejecución de bloque estáticoorg.dwwwp.test.CustomClass: tiempo de ejecución de bloque estáticoorg.dwwwp.test.AbstractClass: tiempo de ejecución del bloque de instanciaorg.dwwwp.test.AbstractClass: tiempo de ejecución del constructororg.dwwwp.test.CustomClass: tiempo de ejecución del bloque de instanciasorg.dwwwp.test.CustomClass: tiempo de ejecución del constructorhola desde org.dwwwp.test.AbstractClass

Enumeraciones [ editar ]

Esta función de idioma se introdujo en J2SE 5.0 . Técnicamente, las enumeraciones son un tipo de clase que contiene constantes enum en su cuerpo. Cada constante de enumeración define una instancia del tipo de enumeración. Las clases de enumeración no se pueden instanciar en ningún lugar excepto en la propia clase de enumeración.

enum  Temporada  {  INVIERNO ,  PRIMAVERA ,  VERANO ,  OTOÑO }

Se permite que las constantes de enumeración tengan constructores, que se llaman cuando se carga la clase:

 enumeración  pública Temporada  {  INVIERNO ( "Frío" ),  PRIMAVERA ( "Más cálido" ),  VERANO ( "Calor" ),  OTOÑO ( "Más frío" ); Temporada ( descripción de la cadena  ) { esto . descripción = descripción ; }       descripción de cadena final  privada ;  public  String  getDescription ()  {  descripción de retorno  ; } } 

Las enumeraciones pueden tener cuerpos de clase, en cuyo caso se tratan como clases anónimas extendiendo la clase enum:

public  enum  Season  {  INVIERNO  {  String  getDescription ()  { return  "cold" ;}  },  PRIMAVERA  {  String  getDescription ()  { return  "warmer" ;}  },  VERANO  {  String  getDescription ()  { return  "hot" ;}  },  OTOÑO  {  String  getDescription ()  { return  "más fresco" ;}  }; }

Interfaces [ editar ]

Las interfaces son tipos que no contienen campos y generalmente definen varios métodos sin una implementación real. Son útiles para definir un contrato con cualquier número de implementaciones diferentes. Cada interfaz es implícitamente abstracta. Los métodos de interfaz pueden tener un subconjunto de modificadores de acceso según la versión del idioma strictfp, lo que tiene el mismo efecto que para las clases, y también staticdesde Java SE 8.

interfaz  ActionListener  {  int  ACTION_ADD  =  0 ;  int  ACTION_REMOVE  =  1 ;  void  actionSelected ( int  acción ); }

Implementando una interfaz [ editar ]

Una interfaz es implementada por una clase usando la implementspalabra clave. Se permite implementar más de una interfaz, en cuyo caso se escriben después de la implementspalabra clave en una lista separada por comas. La clase que implementa una interfaz debe anular todos sus métodos; de lo contrario, debe declararse como abstracta.

interfaz  RequestListener  {  int  requestReceived (); }class  ActionHandler  implementa  ActionListener ,  RequestListener  {  public  void  actionSelected ( int  action )  {  } public  int  requestReceived ()  {  } }// Método de llamada definido por la interfaz RequestListener  listener  =  new  ActionHandler ();  / * ActionHandler se puede  representar como RequestListener ... * / listener . requestReceived ();  /*... y por lo tanto se sabe que implementa el  método requestReceived () * /

Interfaces funcionales y expresiones lambda [ editar ]

Estas características se introdujeron con el lanzamiento de Java SE 8. Una interfaz se convierte automáticamente en una interfaz funcional si define solo un método. En este caso, una implementación se puede representar como una expresión lambda en lugar de implementarla en una nueva clase, lo que simplifica enormemente la escritura de código en el estilo funcional . Las interfaces funcionales se pueden anotar opcionalmente con la @FunctionalInterfaceanotación, que le indicará al compilador que verifique si la interfaz realmente se ajusta a una definición de interfaz funcional.

// Una interfaz funcional @FunctionalInterface interface  Calculation  {  int  calcular ( int  someNumber ,  int  someOtherNumber ); }// Un método que acepta esta interfaz como parámetro int  runCalculation ( cálculo de  cálculo )  {  cálculo de retorno  . calcular ( 1 , 2 ); } // Usando una lambda para llamar al método runCalculation (( number ,  otherNumber )  ->  number  +  otherNumber );// Código equivalente que usa una clase anónima en su lugar runCalculation ( new  Calculation ()  {  @Override  public  int  calculate ( int  someNumber ,  int  someOtherNumber )  {  return  someNumber  +  someOtherNumber ;  } })

Los tipos de parámetros de Lambda no tienen que estar completamente especificados y se pueden inferir de la interfaz que implementa. El cuerpo de Lambda se puede escribir sin un bloque de cuerpo y una returndeclaración si es solo una expresión. Además, para aquellas interfaces que solo tienen un único parámetro en el método, se pueden omitir los corchetes.

// Misma llamada que la anterior, pero con tipos completamente especificados y un bloque de cuerpo runCalculation (( int  número ,  int  otherNumber )  ->  {  return  number  +  otherNumber ; });// Una interfaz funcional con un método que tiene solo una interfaz de  un solo parámetro StringExtender  {  String  extendString ( String  input ); }// Inicializando una variable de este tipo usando un lambda StringExtender  extender  =  input  ->  input  +  "Extended" ;

Referencias de métodos [ editar ]

No es necesario utilizar lambdas cuando ya existe un método con nombre compatible con la interfaz. Este método se puede pasar en lugar de un lambda utilizando una referencia de método. Hay varios tipos de referencias a métodos:

El código arriba del cual las llamadas runCalculationpodrían reemplazarse con lo siguiente usando las referencias del método:

runCalculation ( Integer :: sum );

Herencia [ editar ]

Las interfaces pueden heredar de otras interfaces al igual que las clases. A diferencia de las clases, se permite heredar de múltiples interfaces. Sin embargo, es posible que varias interfaces tengan un campo con el mismo nombre, en cuyo caso se convierte en un único miembro ambiguo, al que no se puede acceder.

/ * La clase que implementa esta interfaz debe implementar métodos de ActionListener y RequestListener * / interface  EventListener  extiende  ActionListener ,  RequestListener  {  }

Métodos predeterminados [ editar ]

Java SE 8 introdujo métodos predeterminados para las interfaces, lo que permite a los desarrolladores agregar nuevos métodos a las interfaces existentes sin romper la compatibilidad con las clases que ya implementan la interfaz. A diferencia de los métodos de interfaz normales, los métodos predeterminados tienen un cuerpo que se llamará en el caso si la clase de implementación no lo anula.

interfaz  StringManipulator  {  String  extendString ( entrada de cadena  );  // Un método que es opcional para implementar  String shortenString predeterminado  ( String input ) { return input . subcadena ( 1 ); } }      // Esta es una clase válida a pesar de no implementar todos los métodos. Clase  PartialStringManipulator  implementa  StringManipulator  {  @Override  public  String  extendString ( String  input )  {  return  input  +  "Extended" ;  } }

Métodos estáticos [ editar ]

Los métodos estáticos son otra característica del lenguaje introducida en Java SE 8. Se comportan exactamente de la misma manera que en las clases.

interfaz  StringUtils  {  cadena estática  shortenByOneSymbol ( cadena de entrada ) { entrada de retorno . subcadena ( 1 ); } }      StringUtils . shortenByOneSymbol ( "Prueba" );

Métodos privados [ editar ]

Los métodos privados se agregaron en la versión de Java 9. Una interfaz puede tener un método con un cuerpo marcado como privado, en cuyo caso no será visible para las clases heredadas. Se puede llamar desde métodos predeterminados con el propósito de reutilizar el código.

interfaz  Logger  {  default  void  logError ()  {  log ( Level . ERROR );  } por defecto  void  logInfo ()  {  log ( Nivel . INFO );  }  registro de anulación  privado ( nivel de nivel ) { SystemLogger . log ( nivel . id ); } }    

Anotaciones [ editar ]

Las anotaciones en Java son una forma de incrustar metadatos en el código. Esta función de idioma se introdujo en J2SE 5.0 .

Tipos de anotaciones [ editar ]

Java tiene un conjunto de tipos de anotaciones predefinidos, pero se le permite definir otros nuevos. Una declaración de tipo de anotación es un tipo especial de declaración de interfaz. Se declaran de la misma forma que las interfaces, excepto que la interfacepalabra clave está precedida por el @signo. Todas las anotaciones se amplían implícitamente java.lang.annotation.Annotationy no se pueden ampliar desde ninguna otra cosa.

@interface  BlockingOperations  { }

Las anotaciones pueden tener las mismas declaraciones en el cuerpo que las interfaces comunes, además se les permite incluir enumeraciones y anotaciones. La principal diferencia es que las declaraciones de métodos abstractos no deben tener parámetros ni generar excepciones. También pueden tener un valor predeterminado, que se declara usando la defaultpalabra clave después del nombre del método:

@interface  BlockingOperations  {  fileSystemOperations booleano  (); boolean networkOperations () predeterminado false ; }    
Uso de anotaciones [ editar ]

Las anotaciones se pueden usar en cualquier tipo de declaración, ya sea paquete, clase (incluidas las enumeraciones), interfaz (incluidas las anotaciones), campo, método, parámetro, constructor o variable local. También se pueden usar con constantes enum. Las anotaciones se declaran utilizando el @signo que precede al nombre del tipo de anotación, después del cual los pares elemento-valor se escriben entre corchetes. A todos los elementos sin valor predeterminado se les debe asignar un valor.

@BlockingOperations ( / * obligatorio * /  fileSystemOperations , / * opcional * /  networkOperations  =  true ) void  openOutputStream ()  {  // Método anotado }

Además de la forma genérica, existen otras dos formas de declarar una anotación, que son abreviaturas. La anotación de marcador es una forma corta, se usa cuando no se asignan valores a los elementos:

@Unused  // Abreviatura de @Unused () void  travelToJupiter ()  { }

La otra forma corta se llama anotación de elemento único . Se utiliza con tipos de anotaciones que contienen solo un elemento o en el caso de que haya varios elementos, pero solo uno de ellos carece de un valor predeterminado. En la forma de anotación de un solo elemento, el nombre del elemento se omite y en su lugar solo se escribe el valor:

/ * Equivalente a @BlockingOperations (fileSystemOperations = true). networkOperations tiene un valor predeterminado y no es necesario asignar un valor * /@BlockingOperations ( verdadero ) void  openOutputStream ()  { }

Genéricos [ editar ]

Genéricos , o tipos parametrizados, o polimorfismo paramétrico es una de las principales características introducidas en J2SE 5.0 . Antes de que se introdujeran los genéricos, se requería declarar todos los tipos explícitamente. Con los genéricos fue posible trabajar de manera similar con diferentes tipos sin declarar los tipos exactos. El objetivo principal de los genéricos es garantizar la seguridad de los tipos y detectar errores de tiempo de ejecución durante la compilación. A diferencia de C #, la información sobre los parámetros utilizados no está disponible en tiempo de ejecución debido al borrado de tipo . [4]

Clases genéricas [ editar ]

Las clases se pueden parametrizar agregando una variable de tipo entre paréntesis angulares ( <y >) después del nombre de la clase. Hace posible el uso de esta variable de tipo en miembros de clase en lugar de tipos reales. Puede haber más de una variable de tipo, en cuyo caso se declaran en una lista separada por comas.

Es posible limitar una variable de tipo a un subtipo de alguna clase específica o declarar una interfaz que debe ser implementada por el tipo. En este caso, la variable de tipo se agrega con la extendspalabra clave seguida del nombre de la clase o la interfaz. Si la variable está restringida tanto por la clase como por la interfaz o si hay varias interfaces, el nombre de la clase se escribe primero, seguido de los nombres de las interfaces con el & signo utilizado como delimitador.

/ * Esta clase tiene dos variables de tipo, T y V. T debe ser un subtipo de ArrayList e implementar una interfaz formateable * / public  class  Mapper < T  extiende  ArrayList  &  Formattable ,  V >  {  public  void  add ( T  array ,  V  item )  {  // la matriz tiene el método add porque es una  matriz de subclase ArrayList . agregar ( elemento );  } }

Cuando se declara una variable de un tipo parametrizado o se crea una instancia, su tipo se escribe exactamente en el mismo formato que en el encabezado de la clase, excepto que el tipo real se escribe en lugar de la declaración de variable de tipo.

/ * Mapper se crea con CustomList como T y Integer como V. CustomList debe ser una subclase de ArrayList e implementar Formattable * / Mapper < CustomList ,  Integer >  mapper  =  new  Mapper < CustomList ,  Integer > ();

Desde Java SE 7, es posible usar un diamante ( <>) en lugar de argumentos de tipo, en cuyo caso se inferirá este último. El siguiente código en Java SE 7 es equivalente al código del ejemplo anterior:

Mapper < CustomList ,  Integer >  mapper  =  new  Mapper <> ();

Al declarar una variable para un tipo parametrizado, es posible utilizar comodines en lugar de nombres de tipos explícitos. Los comodines se expresan escribiendo un ?signo en lugar del tipo real. Es posible limitar los tipos posibles a las subclases o superclases de alguna clase específica escribiendo la extendspalabra clave o la superpalabra clave seguida correspondientemente por el nombre de la clase.

/ * Cualquier Mapper ejemplo con CustomList como el primer parámetro se puede utilizar independientemente de la segunda uno * /. Mapper < CustomList ,  ?>  Mapper ; mapper  =  new  Mapper < CustomList ,  Boolean > (); mapper  =  new  Mapper < CustomList ,  Integer > ();/ * No aceptará tipos que usen nada más que una subclase de Number como segundo parámetro * / void  addMapper ( Mapper <? ,  ?  Extiende  Number >  mapper )  { }

Métodos y constructores genéricos [ editar ]

El uso de genéricos puede estar limitado a algunos métodos particulares, este concepto también se aplica a los constructores. Para declarar un método parametrizado, las variables de tipo se escriben antes del tipo de retorno del método en el mismo formato que para las clases genéricas. En el caso del constructor, las variables de tipo se declaran antes del nombre del constructor.

class  Mapper  {  // La clase en sí no es genérica, el constructor es  < T ,  V >  Mapper ( matriz T  , elemento V ) { } }    / * Este método aceptará solo matrices del mismo tipo que el tipo de elemento buscado o su subtipo * / static  < T ,  V  extiende  T >  booleano  contiene ( T  elemento ,  V []  arr )  {  para  ( T  currentItem  :  arr )  {  if  ( item . es igual a ( currentItem ))  {  devuelve  verdadero ;  }  }  devuelve  falso ; }

Interfaces genéricas [ editar ]

Las interfaces se pueden parametrizar de manera similar a las clases.

interfaz  Expandible < T  extiende  Número >  {  void  addItem ( elemento T  ); }// Esta clase está parametrizada class  Array < T  amplía  Número >  implementa  Expandable < T >  {  void  addItem ( T  item )  {  } }// Y esto no es y usa un tipo explícito en su lugar class  IntegerArray  implementa  Expandable < Integer >  {  void  addItem ( Integer  item )  {  } }

Ver también [ editar ]

  • Plataforma Java, edición estándar

Referencias [ editar ]

  1. ^ "Operadores (Tutoriales de Java ™> Aprendizaje del lenguaje Java> Conceptos básicos del lenguaje)" . docs.oracle.com . Oracle y / o sus afiliados . Consultado el 16 de junio de 2015 .
  2. ^ Owens, Sean. "Java y unsigned int, unsigned short, unsigned byte, unsigned long, etc. (O más bien, la falta de ellos)" .
  3. ^ "Tipos de datos primitivos" .
  4. ^ Genéricos en el tiempo de ejecución (Guía de programación de C #)
  • Patrick Naughton , Herbert Schildt . Java 2: The Complete Reference , tercera edición. The McGraw-Hill Companies, 1999. ISBN 0-07-211976-4 
  • Vermeulen; Caballo amblador; Bumgardner; Metz; Misfeldt; Shur; Thompson (2000). Los elementos del estilo Java . Prensa de la Universidad de Cambridge. ISBN 0-521-77768-2.
  • Gosling, James ; Joy, Bill ; Steele, Guy ; Bracha, Gillad (2005). Especificación del lenguaje Java (3ª ed.). Addison-Wesley Professional . Consultado el 3 de diciembre de 2008 .

Enlaces externos [ editar ]

  • Especificación del lenguaje Java, tercera edición Descripción autorizada del lenguaje Java
  • Javadocs de la API de Java SE 10