# Programación en Java/Versión Para Imprimir

* Si imprimes esta página, o eliges la opción de Vista preliminar de impresión de tu navegador, verás que desaparecen este cuadro y los elementos de navegación de arriba y de la izquierda, pues no son útiles en una versión impresa.
* Pulsando antes en Refrescar esta página te asegurarás de obtener los últimos cambios del libro antes de imprimirlo.
* Para más información, puedes ver Wikilibros:Versión para imprimir.

# Características del lenguaje

Es un lenguaje sencillo de aprender. Su sintaxis es la de C++ “simplificada”. Los creadores de Java partieron de la sintaxis de C++ y trataron de eliminar de este todo lo que resultase complicado o fuente de errores en este lenguaje.
Java es un lenguaje orientado a objetos, aunque no de los denominados puros; en Java todos los tipos, a excepción de los tipos fundamentales de variables (int, char, long...) son clases. Sin embargo, en los lenguajes orientados a objetos puros incluso estos tipos fundamentales son clases, por ejemplo en Smalltalk.
El código generado por el compilador Java es independiente de la arquitectura: podría ejecutarse en un entorno UNIX, Mac o Windows. El motivo de esto es que el que realmente ejecuta el código generado por el compilador no es el procesador del ordenador directamente, sino que este se ejecuta mediante una máquina virtual. Esto permite que los Applets de una web pueda ejecutarlos cualquier máquina que se conecte a ella independientemente de qué sistema operativo emplee (siempre y cuando el ordenador en cuestión tenga instalada una máquina virtual de Java).

## bytecodes

    una especie de código máquina.

## applets

    programas embebidos en páginas Web.

## Máquina Virtual

    software que emula a un ordenador.

## Características

* Lenguaje totalmente orientado a Objetos. Todos los conceptos en los que se apoya esta técnica, encapsulación, herencia, polimorfismo, etc., están presentes en Java.
* Disponibilidad de un amplio conjunto de bibliotecas. Como ya se mencionó anteriormente, Java es algo más que un lenguaje. La programación de aplicaciones con Java se basa no solo en el empleo del juego de instrucciones que componen el lenguaje, sino, fundamentalmente, en la posibilidad de utilizar el amplísimo conjunto de clases que Sun pone a disposición del programador y con las cuales es posible realizar prácticamente cualquier tipo de aplicación.
* Lenguaje simple. Java posee una curva de aprendizaje muy rápida. Resulta relativamente sencillo escribir applets interesantes desde el principio. Todos aquellos familiarizados con C++ encontrarán que Java es más sencillo, ya que se han eliminado ciertas características, como los punteros. Debido a su semejanza con C y C++, y dado que la mayoría de la gente los conoce aunque sea de forma elemental, resulta muy fácil aprender Java. Los programadores experimentados en C++ pueden migrar muy rápidamente a Java y ser productivos en poco tiempo.
* Distribuido. Java proporciona una colección de clases para su uso en aplicaciones de red, que permiten abrir sockets y establecer y aceptar conexiones con servidores o clientes remotos, facilitando así la creación de aplicaciones distribuidas.
* Interpretado y compilado a la vez. Java es compilado, en la medida en que su código fuente se transforma en una especie de código máquina, los bytecodes, semejantes a las instrucciones de ensamblador. Por otra parte, es interpretado, ya que los bytecodes se pueden ejecutar directamente sobre cualquier máquina a la cual se hayan portado el intérprete y el sistema de ejecución en tiempo real (run-time).
* Robusto. Java fue diseñado para crear software altamente fiable. Para ello proporciona numerosas comprobaciones en compilación y en tiempo de ejecución. Sus características de memoria liberan a los programadores de una familia entera de errores (la aritmética de punteros), ya que se ha prescindido por completo de los punteros, y la recolección de basura elimina la necesidad de liberación explícita de memoria.
* Seguro (?). Dada la naturaleza distribuida de Java, donde las applets se bajan desde cualquier punto de la Red, la seguridad se impuso como una necesidad de vital importancia. A nadie le gustaría ejecutar en su ordenador programas con acceso total a su sistema, procedentes de fuentes desconocidas. Así que se implementaron barreras de seguridad en el lenguaje y en el sistema de ejecución en tiempo real.
* Indiferente a la arquitectura. Java está diseñado para soportar aplicaciones que serán ejecutadas en los más variados entornos de red, desde Unix a Windows Nt, pasando por Mac y estaciones de trabajo, sobre arquitecturas distintas y con sistemas operativos diversos. Para acomodar requisitos de ejecución tan diversos o variopintos, el compilador de Java genera bytecodes: un formato intermedio indiferente a la arquitectura diseñado para transportar el código eficientemente a múltiples plataformas hardware y software. El resto de problemas los soluciona el intérprete de Java.
* Portable. La indiferencia a la arquitectura representa sólo una parte de su portabilidad. Además, Java especifica los tamaños de sus tipos de datos básicos y el comportamiento de sus operadores aritméticos, de manera que los programas son iguales en todas las plataformas. Estas dos últimas características se conocen como la Máquina Virtual Java (JVM).
* Alto rendimiento.
* Multihebra. Hoy en día ya se ven como terriblemente limitadas las aplicaciones que sólo pueden ejecutar una acción a la vez. Java soporta sincronización de múltiples hilos de ejecución (multithreading) a nivel de lenguaje, especialmente útiles en la creación de aplicaciones de red distribuidas. Así, mientras un hilo se encarga de la comunicación, otro puede interactuar con el usuario mientras otro presenta una animación en pantalla y otro realiza cálculos.
* Dinámico. El lenguaje Java y su sistema de ejecución en tiempo real son dinámicos en la fase de enlazado. Las clases sólo se enlazan a medida que son necesitadas. Se pueden enlazar nuevos módulos de código bajo demanda, procedente de fuentes muy variadas, incluso desde la Red.
* Produce applets. Java puede ser usado para crear dos tipos de programas: aplicaciones independientes y applets. Las aplicaciones independientes se comportan como cualquier otro programa escrito en cualquier lenguaje, como por ejemplo el navegador de Web HotJava, escrito íntegramente en Java. Por su parte, las applets son pequeños programas que aparecen embebidos en las páginas Web, como aparecen los gráficos o el texto, pero con la capacidad de ejecutar acciones muy complejas, como animar imágenes, establecer conexiones de red, presentar menús y cuadros de diálogo para luego emprender acciones, etc.
* Lenguaje totalmente orientado a Objetos. Todos los conceptos en los que se apoya esta técnica, encapsulación, herencia, polimorfismo, etc., están presentes en Java.
* Disponibilidad de un amplio conjunto de librerías. Como ya se mencionó anterirmente, Java es algo mas que un lenguaje. La programación de aplicaciones con Java se basa no solo en el empleo del juego de instrucciones que componen el lenguaje, sino, fundamentalmente, en la posibilidad de utilizar el amplísimo conjunto de clases que Sun pone a disposición del programador y con las cuales es posible realizar prácticamente cualquier tipo de aplicación.
* Lenguaje simple. Java posee una curva de aprendizaje muy rápida. Resulta relativamente sencillo escribir applets interesantes desde el principio. Todos aquellos familiarizados con C++ encontrarán que Java es más sencillo, ya que se han eliminado ciertas características, como los punteros. Debido a su semejanza con C y C++, y dado que la mayoría de la gente los conoce aunque sea de forma elemental, resulta muy fácil aprender Java. Los programadores experimentados en C++ pueden migrar muy rápidamente a Java y ser productivos en poco tiempo.
* Distribuido Java proporciona una colección de clases para su uso en aplicaciones de red, que permiten abrir sockets y establecer y aceptar conexiones con servidores o clientes remotos, facilitando así la creación de aplicaciones distribuidas.
* Interpretado y compilado a la vez Java es compilado, en la medida en que su código fuente se transforma en una especie de código máquina, los bytecodes, semejantes a las instrucciones de ensamblador. Por otra parte, es interpretado, ya que los bytecodes se pueden ejecutar directamente sobre cualquier máquina a la cual se hayan portado el intérprete y el sistema de ejecución en tiempo real (run-time).
* Robusto Java fue diseñado para crear software altamente fiable. Para ello proporciona numerosas comprobaciones en compilación y en tiempo de ejecución. Sus características de memoria liberan a los programadores de una familia entera de errores (la aritmética de punteros), ya que se ha prescindido por completo los punteros, y la recolección de basura elimina la necesidad de liberación explícita de memoria.
* Seguro (?) Dada la naturaleza distribuida de Java, donde las applets se bajan desde cualquier punto de la Red, la seguridad se impuso como una necesidad de vital importancia. A nadie le gustaría ejecutar en su ordenador programas con acceso total a su sistema, procedentes de fuentes desconocidas. Así que se implementaron barreras de seguridad en el lenguaje y en el sistema de ejecución en tiempo real.
* Indiferente a la arquitectura Java está diseñado para soportar aplicaciones que serán ejecutadas en los más variados entornos de red, desde Unix a Windows Nt, pasando por Mac y estaciones de trabajo, sobre arquitecturas distintas y con sistemas operativos diversos. Para acomodar requisitos de ejecución tan variopintos, el compilador de Java genera bytecodes: un formato intermedio indiferente a la arquitectura diseñado para transportar el código eficientemente a múltiples plataformas hardware y software. El resto de problemas los soluciona el intérprete de Java.
* Portable La indiferencia a la arquitectura representa sólo una parte de su portabilidad. Además, Java especifica los tamaños de sus tipos de datos básicos y el comportamiento de sus operadores aritméticos, de manera que los programas son iguales en todas las plataformas. Estas dos últimas características se conocen como la Máquina Virtual Java (JVM).
Alto rendimiento
* Multihebra Hoy en día ya se ven como terriblemente limitadas las aplicaciones que sólo pueden ejecutar una acción a la vez. Java soporta sincronización de múltiples hilos de ejecución (multithreading) a nivel de lenguaje, especialmente útiles en la creación de aplicaciones de red distribuidas. Así, mientras un hilo se encarga de la comunicación, otro puede interactuar con el usuario mientras otro presenta una animación en pantalla y otro realiza cálculos.
* Dinámico El lenguaje Java y su sistema de ejecución en tiempo real son dinámicos en la fase de enlazado. Las clases sólo se enlazan a medida que son necesitadas. Se pueden enlazar nuevos módulos de código bajo demanda, procedente de fuentes muy variadas, incluso desde la Red.
* Produce applets Java puede ser usado para crear dos tipos de programas: aplicaciones independientes y applets. Las aplicaciones independientes se comportan como cualquier otro programa escrito en cualquier lenguaje, como por ejemplo el navegador de Web HotJava, escrito íntegramente en Java. Por su parte, las applets son pequeños programas que aparecen embebidos en las páginas Web, como aparecen los gráficos o el texto, pero con la capacidad de ejecutar acciones muy complejas, como animar imágenes, establecer conexiones de red, presentar menús y cuadros de diálogo para luego emprender acciones, etc.

# Primer programa

Nuestro primer programa será sencillo y mostrará el saludo "Hola Mundo" en la pantalla. Para crear el programa necesitaremos realizar los siguientes pasos:
* Crear el código fuente. Un archivo de código fuente contiene texto escrito en el lenguaje de programación Java. Se puede utilizar un simple editor de texto para crear y editar el código.
* Compilar el código fuente. El compilador translada el código fuente en instrucciones que la máquina virtual de Java pueda entender. El compilador crea esas instrucciones en un archivo bytecode.
* Ejecutar el programa. El intérprete Java, instalado en el sistema operativo, implementa la máquina virtual de Java. Este intérprete transforma el bytecode en instrucciones que pueda entender el sistema operativo.
* Este programa escribe el texto "Hola Mundo" en la consola
* utilizando el método System.out.println
public class HolaMundo { public static void main (String args) { System.out.println("Hola Mundo");

## Compilar el código

Una vez guardado el código fuente, abrimos el MS-DOS o Command Prompt. Nos situamos en el directorio en donde se encuentra el archivo y luego ejecutamos la siguiente orden:
javac HolaMundo.java
Si todo sale bien, el compilador genera un archivo bytecode , HolaMundo.class en el mismo directorio en donde está el programa. De lo contrario muestra los errores que contiene el código.

## Ejecutar el Código

En el mismo directorio en donde estamos trabajando escribir la siguiente orden:
java HolaMundo
Esta vez escribimos el nombre del programa, pero sin la extensión. Si hemos realizado bien los pasos y tenemos instalado correctamente el JDK , tendremos en la pantalla el saludo:

## Para saber más

* Máquina virtual de Java
* Bytecode
Ejemplo de un clasico de la programación: en lenguaje Java:

# Variables

Las variables son una de las características fundamentales de los lenguajes de programación, permiten acceder a la memoria para almacenar y recuperar los datos con los que nuestros programas van a trabajar. Son por tanto el mecanismo que los lenguajes de programación ponen a nuestra disposición para acceder a la memoria.
Se trata de un mecanismo de lo más sencillo, sólo tenemos que dar un nombre a nuestras variables, a partir de ese momento el compilador traducirá de forma automática ese nombre en un acceso a memoria. Por ejemplo:
Java es un lenguaje tipado y nos obliga a declarar nuestras variables antes de poder hacer uso de ellas, con esta declaración le indicamos al compilador el espacio en memoria que debe de reservar para almacenar la información. Por ejemplo:
Aquí estamos reservando memoria para una variable de tipo String y la identificamos con el nombre “cliente”. De ahora en adelante si en el programa hablamos de cliente, estamos haciendo referencia a esa porción de memoria y al valor que contiene.
Podemos asignarle algún valor en el momento de declarar una variable. Por ejemplo:
Aquí reservamos memoria para una cadena de caracteres y le asignamos el valor "Isaac Newton". También podemos declararla y en otro lugar del programa fijarle un valor :
La sentencia para declarar una variable se resume como:
Definimos el tipo de dato, el nombre y opcionalmente su valor inicial.
Para ver como se utilizan las variables, podemos modificar el primer programa. Agregaremos una variable que contenga el texto que se mostrará en pantalla:
Definimos una variable de tipo String con el nombre "saludo". En la declaración de la variable también la iniciamos con el valor "¡Hola mundo!". Luego llamamos al método que imprimirá el texto en la pantalla haciendo referencia a la variable. En el programa original, explícitamente introducíamos el texto que se mostraría, ahora solo escribimos el nombre de la variable. Cuando el intérprete se encuentre con el nombre de esta variable, tendrá que buscar el valor que almacene en la memoria para mostrarlo por pantalla.
Un variable puede cambiar su valor en el transcurso del programa (salvo que se preceda su definición con la palabra: final)
Siempre debemos inicializar una variable. Al compilar el programa, el compilador de Java leerá el contenido de la variable y siempre verificará que tenga un valor. De lo contrario el programa no compilará y mostrará un error. Un ejemplo de este caso:
En este caso el compilador mostrará un mensaje de error indicando que la variable x no se ha iniciado con ningún valor. Como se puede observar esta variable solo se inicia cuando se cumple una condición, sin embargo se indica que va a ser utilizada siempre. El compilador detecta este posible error. Un ejemplo de solución posible sería:
Agregando estas líneas al final del código de la clase UsoVariables nos mostraría lo siguiente a la salida:

## Nombre de la variable

El nombre debe ser único en el contexto del programa. Además debe seguir las siguientes reglas:
* No puede ser una palabra reservada del lenguaje o un literal booleano (true o false)
* Puede contener cualquier carácter Unicode, pero no puede comenzar con un número
* No debe contener los símbolos que se utilicen como operadores ( + , - , ?, etc )
    Por convención, los nombres de variables comienzan con una letra en minúscula. Si un nombre consiste en más de una palabra, se escribirá sin espacios entre ellas y cada palabra (salvo la primera) comenzará con una letra mayúscula (por ejemplo : estaBienEsteNombre )

## Tipo de variable

Cada variable debe tener un tipo de dato predefinido. Esto determina el rango de valores que puede almacenar y qué operaciones se pueden realizar así como el resultado que te dará. Por ejemplo, una variable de tipo entero puede almacenar números sin decimales y puede realizar operaciones aritméticas, pero no puede contener palabras.
Existen dos categorías de variables: las de tipo primitivo y las referenciadas. Una variable de tipo primitivo accede al valor asignado directamente. Las referenciadas acceden a través de un puntero, es decir, no almacenan un valor sino una dirección de memoria. Estas últimas son utilizadas por las matrices, las clases y las interfaces.
Tipos de datos primitivos :
| Tipo | Tamaño y formato | Rango |
| | enteros | |
| byte | 8 bits - complemento a 2 | $-2^{7}\ al\ 2^{7}-1$ |
| short | 16 bits - complemento a 2 | $-2^{15}\ al\ 2^{15}-1$ |
| int | 32 bits - complemento a 2 | $-2^{31}\ al\ 2^{31}-1$ |
| long | 64 bits - complemento a 2 | $-2^{63}\ al\ 2^{63}-1$ |
| | números reales | |
| float | 32 bits - IEEE 754 | |
| double | 64 bits - IEEE 754 | |
| | otros | |
| char | 16 bits - caracteres UNICODE | '\u0000' al '\uffff' |
| boolean | 1 bit | true o false |
En otros lenguajes de programación, el formato o el tamaño de los tipos primitivos dependen del microprocesador o del sistema operativo en el que se están ejecutando. En cambio, Java pretende ser independiente de la plataforma y mantiene los formatos sin cambios. Para los caracteres alfanuméricos utiliza la codificación UNICODE de 16 bits, para permitir la inclusión de varios alfabetos.

## Para saber más

* Variables
* Tipos de datos

## Literales

Pueden existir varias formas de representar un valor. Por ejemplo al tener el número 100, significa exactamente 100 en una base decimal, pero hablamos de 4 en una base binaria o 256 en hexadecimal. Para evitar ambigüedades, en Java se establecieron algunas normas.

## Literales enteros

Existen 3 maneras de representar el valor de un número entero. Si se escribe el número solamente, éste representa un número en base decimal. Si tiene un cero delante estamos escribiendo octales y si tiene el prefijo "0x" el valor está representado en base hexadecimal. Por ejemplo:
| Base de numeración | valor | valor decimal |
| Decimal | 100 | 100 |
| Octal | 0100 | 64 |
| Hexadecimal | 0x100 | 256 |
Para indicarle al compilador que un valor dado es de tipo long debemos incluir el sufijo L:

## Literales de números reales

Al tratar con números reales introducimos el punto decimal o utilizamos la notación científica. Por ejemplo:
En el ejemplo el valor 3.0e+5 significa $3.0*10^{5}$. La letra e denota la mantisa, y da igual si la escribimos en mayúscula o minúscula.
Para determinar si estamos hablando de float o double, al número se le agrega un sufijo: F o f para float y D o d para double. Si no colocamos un sufijo el compilador lo toma como double.

## Literales char

Una variable de tipo char almacena un carácter Unicode. Este sistema de codificación amplía la escasez de opciones que tiene la codificación ASCII para incluir otros alfabetos. Podemos escribir en griego, hebreo o en vietnamita sin que el compilador proteste. Un literal de tipo char se expresa encerrando el carácter entre comillas simples:
Otra forma de representar un carácter es indicando el código Unicode en hexadecimal, anteponiendo los símbolos \u, todo entre comillas simples. De esta manera el símbolo arroba ( @ ) se escribe:
El primer byte de la codificación Unicode es la misma que el viejo y querido ASCII

## Literales boolean

Sencillamente true o false (verdadero o falso) sin comillas y en minúscula. No tienen correlación con ningún número como ocurre en el lenguaje C que teníamos al 0 como false y al 1 como true.

## Literales String

El tipo String no es un tipo de dato primitivo. Pero se comporta como si lo fuera. Para indicar una cadena de caracteres se encierran entre comillas dobles.

## Ejemplos de valores literales

| Literal | Tipo de dato |
| "Gato" | String |
| "G" | String |
| 'G' | char |
| 123 | int |
| 8000L | long |
| 3.14 | double |
| 3.14D | double |
| 3.14f | float |
| 26.45e-45 | double |
| '\u00ff' | char |
| 'c' | char |
| "true" | String |
| true | boolean |
En los sufijos que tenemos para identificar el tipo de dato no importa si son en minúscula o mayúscula. Pero por convención se utilizan en mayúscula, pues se puede confundir al leer el código una ele minúscula ( l ) con un uno ( 1 ).
Hay que tener cuidado de no olvidarnos los sufijos cuando sean necesarios. El siguiente código da un error en tiempo de compilación:
El compilador nos dará el error de "possible loss of precision" (posible pérdida de precisión). Esto se debe a que sin la F atrás, estamos indicando un valor de tipo double. El compilador se niega a comprimir un double de 64 bits en un float de tan solo 32 bits. Lo solucionamos de esta manera:
Y le alegramos la vida a un compilador gruñón.

## La palabra reservada final

En una aplicación posiblemente nos encontremos con algún valor que permanece constante durante la ejecución. Podemos definirla como una variable común pero perderíamos el control. Por allí, en algún descuido, se cambiaría de valor pero no nos enteraríamos. Podemos agregar a la definición de la variable el modificador final, que indica que a esa variable solo se le puede asignar un valor u objeto una única vez. La sintaxis es la siguiente:
Por ejemplo :
Si tratamos de modificar el valor de una variable con el modificador final, el compilador indicará un error. Una vez definido el valor no se puede modificar.
Realmente, lo que permanece constante es la asignación de un objeto a esa variable, no los atributos internos que pueda tener ese objeto. Por ejemplo, en el siguiente caso:
habríamos creado al ciudadano 'juan' y ya nunca más se le podrá asignar a 'juan' otra instancia de Ciudadano. Sin embargo, es posible cambiar los datos internos de ese ciudadano:
el objeto 'juan' ha cambiado internamente.
Con el modificador final evitaremos lo siguiente:
La última línea no compilaría pues 'juan' fue declarado con final, así que no se le puede asignar nada nuevo.

## Secuencias de Escape

Las secuencias de escape son pequeñas constantes que nos brindan una gran utilidad; para comprenderlo mejor este ejemplo (en consola):
Este ejemplo presenta una linea de texto, pero, ¿qué pasa si queremos este texto en tres lineas?, tendríamos que escribir :
Es algo más tedioso, menos mal que existen las secuencias de escape en Java, las cuales nos ahorrarán el trabajo de la siguiente manera:
Pero este es solo un ejemplo. ¿Qué pasa si queremos una pequeña tabulacion? Tendríamos que teclear la barra espaciadora hasta la medida del espacio que queremos, java también soluciona esto de la siguiente manera:
A continuación hay una lista de secuencias de escape:
* \n -----> Nueva línea.
* \t -----> Tabulador.
* \r -----> Retorno de carro.
* \f -----> Comienzo de página.
* \b -----> Borrado a la izquierda.
* \\ -----> El carácter barra inversa ( \ ).
* \' -----> El carácter comilla simple ( ' ).
* \" -----> El carácter comillas dobles ( " ).

## Arrays

En Java, un Array o (en español arreglo) es un grupo de variables llamadas elementos o componentes que contienen variables las cuales son de un mismo tipo. En java, a diferencia del lenguaje C, existe un tipo de variable “especial”, el Array o matriz. Este tipo de variables no es más que un conjunto secuencial de memoria a las que se accede a través de un índice de posición.
Las matrices en Java son objetos, por lo que cuentan con propiedades y métodos para manipularlos. Se pueden declarar matrices de tipos de datos primitivos y de objetos.
Para hacer referencia a un elemento en especial en un arreglo, se debe especificar el nombre que llevará la referencia al arreglo y el número de la posición del elemento en el arreglo. El número de la posición del elemen- to se conoce como el índice o subíndice del elemento.
Existen varias maneras de declarar un array, por ejemplo:
Sintaxis:
Como puedes observar puedes inicializar un array al momento de declararlo o postergar esta operación para cuando sea necesario.
Para inicializar un array existen 2 maneras:
* int matriz=new int[4] o
* int matriz={100,200,302,400}
Como podrás concluir, en la primera declaras el array nada más, diciéndole la cantidad de memoria secuencial que se debe reservar, en el segundo ejemplo se inicializa el array dándole los valores que va a contener (obviamente la cantidad de memoria secuencial reservada será igual a la cantidad de elementos insertados).
Al momento de inicializar una matriz de la manera :
* int matriz=new int[4]
cada posición de la matriz sera inicializada con el valor predeterminado del tipo de variable. Por ejemplo si la matriz es de tipo boolean, todas las posiciones de la matriz serán inicializadas con el valor false (ya que este es valor predeterminado de este tipo de dato), por el contrario si la matriz fuese de un tipo no primitivo, el valor que contendrá cada casilla sera null.
A continuación tienes una lista de los valores predeterminados de cada tipo de dato:
Tipo de Dato-->Valor byte-->0 short-->0 int-->0 long-->0 float-->0.0 double-->0.0 char-->/u0000 boolean-->false Object (Cualquier tipo de Objeto)-->null
Para obtener el tamaño de un array de manera dinámica se utiliza la propiedad .length. Esta propiedad es común para todos los arrays. También es importante saber que las matrices se empiezan a enumerar desde el número cero (0), por tanto para acceder al valor almacenado en la última posición deberás colocar el tamaño de la matriz menos 1 unidad.
Al momento de tratar de acceder a una posición fuera del rango de la matriz se lanzará un excepción de tipo java.lang.ArrayIndexOutOfBoundsException (esta excepción es una excepción no chequeada, por lo que no es necesario colocar un bloque try/catch en el código)
Pasaremos con un ejemplo:
Programación en Java/arrays secuencias finales/inluye un programa como ejemplo

# Operadores

Un operador realiza una función, toma uno o más argumentos y devuelve un resultado. Cuando vimos las variables, definimos un tipo de dato con un conjunto de operaciones asociadas. Es de esperar que podamos realizar operaciones aritméticas con números y lógicas con los booleanos. Estas operaciones se representan mediante operadores.
Los operadores, al igual que los métodos, se pueden sobrecargar, es decir se puede redefinir su funcionalidad dependiendo de los tipos de datos de los operandos que reciba. Así, podemos indicar que el operador (+) realice una suma aritmética si los operandos que recibe son dos enteros y una concatenación si recibe una cadena y otro objeto.

# Operadores aritméticos

Realizan las operaciones aritméticas básicas: suma (+), resta (-), multiplicación (*) ,división (/) y módulo (%) para datos de tipo numérico, tanto enteros como reales. Estas son operaciones binarias porque admiten dos operandos.
Ejemplo de utilización de estos operadores:
El resultado de estas operaciones no puede quedar almacenado en una variable de tipo short o byte, por más pequeño que sea. Si tramos de compilar esto:
Tendremos un "possible lost of precision" como respuesta, por más que el pequeñito 2 entre holgadamente en una variable short. El compilador evita que al utilizar estos tipos de datos no nos pasemos de largo. Pero de todas formas me voy a vengar. Analicemos el siguiente código:
El valor 2147483647 (es decir 2^31 - 1 ) es el más grande que puede tolerar un int. Pero veamos que pasa al sumarle uno más. El compilador se queda mudo y cae en nuestra trampa. Ejecutamos el programa y obtenemos:
Desastroso, ¿Verdad? Veamos lo que pasó: Teníamos el valor máximo para los int:
Esta anomalía se la conoce como “overflow” (desbordamiento). El procesador puede identificar un resultado con este problema comparando los signos. Es de esperar que si sumamos dos números positivos, no nos dé como resultado un número negativo. Pero el intérprete de Java no nos avisa, por lo tanto tenemos que cuidarnos al trabajar cerca de los extremos.
Sigamos metiéndonos en embrollos. Veamos ahora que ocurre si tratamos de dividir cualquier número por cero. Para la verificación escribimos este programa:
No tenemos noticias al compilar. Pero al ejecutar el programa, el intérprete nos manda a pasear con la siguiente nota:
Veremos mas adelante cómo controlar el ánimo del interprete cuando ocurren estos errores, aquí conocidos como excepciones. La moraleja es que no se puede dividir un entero por cero.
Sigamos dando pelea, no nos dejemos intimidar. Probemos que ocurre con los números reales:
Compilamos y no escuchamos nada. Ejecutamos el programa...
Ni error ni cosas raras, el float se aguantó los malos tratos. Esto ocurre porque los números reales en su representación binaria soportan el valor infinito.

## Operadores aritméticos unarios

Dentro de los operadores aritméticos tenemos los unarios + y – que simplemente operan con el signo de un valor dado. Por ejemplo:
El operador – se encarga de cambiar el signo, y el + sencillamente deja el signo como está. Nuevamente no podemos almacenar el resultado en enteros cortos, los tipos byte y short los transforma en int. Dentro del catálogo de operadores tenemos algunos unarios más. Se trata del auto incremental ++ y del auto decremental --. Respectivamente, suma y resta una unidad al valor. Ambos operadores pueden ser sufijos, es decir se coloca antes del operando o posfijo que se sitúa detrás. Veamos algunos ejemplos:
En este ejemplo estamos incrementado y decrementando el valor de i. A priori parece que los operadores funcionan igual, tanto como posfijo como sufijo, pero su comportamiento es diferente. Observemos lo que ocurre en este ejemplo:
todo es practico. Partiendo del mismo valor, vemos que j se incrementó, mientras que la variable i se mostró sin cambios. Si colocamos el operador como sufijo, primero se evalúa la variable y luego se realiza la operación. En el caso de la variable i, antes de incrementar su valor se mostró por pantalla. Para la variable j el procedimiento fue inverso. Antes de mostrar su valor se incrementó.

# Operadores relacionales

Revisando algunas definiciones matemáticas, nos enteramos que los números conforman un conjunto ordenado. Cada uno tiene una posición relativa. Sabemos que el 2 "es menor que" el 4 y que el 6 "es más grande que" el 1. Al comparar dos números, realizamos una función de relación.
En java disponemos de los operadores relacionales para verificar si se cumple una relación. Por ejemplo el operador de equivalencia ( == ) nos devuelve un valor de verdadero si los operandos son iguales. Estas operaciones comparan dos valores numéricos y devuelven un valor booleano.
Operadores relacionales :
| Operador | Utilización | Resultado |
| > | A > B | verdadero si A es mayor que B |
| >= | A >= B | verdadero si A es mayor o igual que B |
| < | A < B | verdadero si A es menor que B |
| <= | A <= B | verdadero si A es menor o igual que B |
| == | A == B | verdadero si A es igual a B |
| != | A != B | verdadero si A es distinto de B |
Aquí tenemos un programa para ver el funcionamiento de estos operadores :
No nos olvidemos de los char, que también participan. Podemos comparar caracteres, pues internamente están almacenados como números.
Entre los booleanos solo se permiten los operadores de equivalencia, es igual (==) o es distinto (!= )

# Operadores booleanos

Como deben suponer, trabajan con operandos booleanos. Realizan las operaciones lógicas de conjunción (AND), disyunción (OR), negación (NOT) y la disyunción exclusiva (XOR).
Operadores booleanos :
| Nombre | Operador | Utilización | Resultado |
| AND | && | A && B | verdadero cuando A y B son verdaderos. Evaluación condicional. |
| OR | || | A || B | verdadero cuando A o B son verdaderos. Evaluación condicional. |
| NOT | ! | !A | verdadero si A es falso. |
| AND | & | A & B | verdadero cuando A y B son verdaderos. Siempre evalúa ambos operandos. |
| OR | | | A | B | verdadero cuando A o B son verdaderos. Siempre evalúa ambos operandos. |
| XOR | ^ | A ^ B | verdadero cuando A y B son diferentes |
Cada una de estas operaciones tiene asociada una tabla de verdad. Esto nos permite ver el resultado de un operador aplicado a las distintas combinaciones de valores que pueden tener los operandos. A continuación mostraremos como se comporta el operador AND mediante su tabla de verdad.
Si probamos a quitar un ampersand ( & ) del operador, vemos que obtenemos los mismos resultados. Existen dos operadores AND, uno con dos símbolos & y el otro con uno solo. También tenemos dos operadores OR.
Parece extraño, sobre todo porque tienen la misma tabla de verdad. Pero internamente tienen un comportamiento diferente.
Cuando estamos en presencia de un operador con un solo símbolo, siempre se evalúan ambos operandos. En cambio para el operador con el símbolo repetido, su evaluación cambia según el valor del primer operando. Por ejemplo tenemos la siguiente operación.
El resultado es falso, pero el intérprete tiene que mirar el segundo operando para saberlo.
Aquí ni se molesta en mirar el último operando, porque la operación AND es verdadera solamente cuando ambos operandos son verdaderos.
En el caso del operador OR, se evalúa el segundo operador si el primero es falso. Cuando es verdadero, no tiene en cuenta el otro operando. El resultado es verdadero sin importar el valor del segundo.
Veamos un caso extremo para mostrar como funciona la evaluación condicional. Tenemos el siguiente programa en donde pretendemos hacer saltar al intérprete con un error.
Sin ningún tipo de emoción, aburridamente el intérprete nos avisa que el resultado es "false". Ahora verá. Quitemos un símbolo & y quedémonos con uno solo. El resultado es otro :
La primera vez verificó que x!=0 era falso, entonces dio por terminada la operación con el resultado falso. Cuando cambiamos de operador, evaluó los dos operandos y cayó en nuestra trampa. Tuvo que calcular cuanto es y / x dando luego un error de división por cero.
Los operadores booleanos son muy amigos de los relacionales. Se llevan bien porque los últimos dan resultados booleanos. Entre ambos tipos de operadores se pueden construir instrucciones mas complejas.
Por ejemplo, queremos saber si un número está dentro de un rango. Solo tenemos que compararlo con los extremos:
Ahora deseamos saber si una variable tiene el valor "a" no importando si es mayúscula o minúscula.
No olviden que el operador de equivalencia (==) tiene dos símbolos igual (=), si colocan uno solo les dará un error de asignación.

# Operadores de bits

Como sabrán, los datos en una computadora internamente se representan en código binario. El microprocesador solo entiende de ceros y unos. Luego, mediante una serie de procesos, nosotros vemos a este código ya transformado en números, caracteres, imágenes y sonido. Pero en realidad en la trastienda todo sigue siendo binario.

## Los Bits

El método más sencillo de representación son los números naturales. Por ejemplo, si tengo el número 85 en decimal, solo tengo que llevarlo a binario y obtengo una serie de unos y ceros:
Cada dígito (un cero o un uno) de este número se llama bit. Java tiene una serie de operadores capaces de manipular estos dígitos, son los operadores de bits.
Operadores de bits :
| Operador | Utilización | Resultado |
| << | A << B | Desplazamiento de A a la izquierda en B posiciones |
| >> | A >> B | Desplazamiento de A a la derecha en B posiciones, tiene en cuenta el signo. |
| >>> | A >>> B | Desplazamiento de A a la derecha en B posiciones, no tiene en cuenta el signo. |
| & | A & B | Operación AND a nivel de bits |
| | | A | B | Operación OR a nivel de bits |
| ^ | A ^ B | Operación XOR a nivel de bits |
| ~ | ~A | Complemento de A a nivel de bits |
Para operar a nivel de bit es necesario tomar toda la longitud predefinida para el tipo de dato. Estamos acostumbrados a desechar los ceros a la izquierda en nuestra representación de números. Pero aquí es importante. Si trabajamos una variable de tipo short con un valor de 3, está representada de la siguiente manera :
Aquí los 16 bits de un short se tienen en cuenta.

## Desplazamientos

Los operadores de desplazamiento, mueven los bits a la izquierda o a la derecha. El primer operando será la victima a sacudir. El segundo indicará cuantas posiciones.

### Desplazamiento a la izquierda

Deseamos correr el número 33 dos posiciones a la izquierda. Entonces realizamos :
Este es el resultado:
Cada "hueco" que queda a la derecha tras correr este número se rellena con ceros. Los bits a la izquierda se pierden, no es una operación de rotación. Si prestamos atención, observaremos que esta operación multiplicó a j por 2 tantas veces como posiciones se ha desplazado. En este caso se multiplicó por 4 ( 2 x 2 ). Hay que notar que el signo del número puede cambiar tras la operación (por ejemplo 1 << 31 = -2147483648).

### Desplazamiento a la derecha con signo

Volvamos a colocar como estaban los bits del caso anterior. Queremos obtener nuevamente el número 33. Para esto desplazamos el número 132 dos posiciones a la derecha.
Como resultado obtenemos el número original.
Podemos ver que el corrimiento a la derecha realiza una división de enteros. Divide por 2, tantas veces como posiciones desplazadas.
Veamos que ocurre si pretendemos realizar un desplazamiento a la derecha con un número negativo. Tengan en cuenta que la representación de números es de complemento a 2. Si tengo una variable de tipo int con el valor –1 , internamente está almacenada de la siguiente forma :
Ahora realicemos un programa para ver que ocurre con el desplazamiento.
La salida del programa nos indica que:
Quedó exactamente igual. Prueben de correr el número tantas posiciones como tengan ganas y obtendrán el mismo resultado. Esto ocurre porque en el desplazamiento, los "huecos" que quedan a la izquierda se rellenan con el bit uno (1), quedando inalterable.
Este operador desplaza el conjunto de bit a la derecha y agrega a la izquierda los bits que faltan según el bit de signo, o sea el más significativo. Si se encuentra con un número positivo, el bit de signo vale 0, entonces agrega ceros, en cambio si son negativos el bit de signo vale 1, entonces agrega unos. Este proceso, denominado extensión de signo mantiene el signo del número como si se tratara de una división. Por esto se lo conoce como desplazamiento con signo.

### Desplazamiento a la derecha sin signo

Modifiquemos ligeramente el programa anterior agregándole al operador un símbolo >. Nos queda de esta manera :
Si ejecutamos el programa nos dice lo siguiente :
Veamos de donde salió este número raro. Si lo llevamos a binario tenemos :
Ahora nos damos cuenta que se han agregado dos ceros a la izquierda. Este operador desplaza a la derecha, pero no tiene en cuenta el signo. Siempre agrega bit con el valor cero, por lo que se llama desplazamiento sin signo. Este operador suele ser más adecuado que el >> cuando queremos manipular los bits mismos, no su representación numérica.

## Operadores lógicos de bits

Estos operadores extienden las operaciones booleanas a los enteros. Para comprender como trabajan debemos descomponer los enteros en un conjunto de bits. El operador aplicará una operación lógica bit por bit, tomando el valor de uno como verdadero y el valor de cero como falso. De un operando toma un bit y aplica la operación al bit que tiene la misma posición del segundo operando. Como resultado obtenemos otro entero.

### Operador AND de Bits

Si ambos bits comparados son 1, establece el resultado en 1. De lo contrario da como resultado 0.

### Operador OR de Bits

Si por lo menos uno de los dos bits comparados es 1, establece el resultado en 1. De lo contrario da como resultado 0.

### Operador XOR de Bits

Si uno de los bits comparados es 0 y el otro 1, el resultado es 1. Si ambos bits comparados son iguales, el resultado es 0.

### Operador NOT de Bits

Sólo invierte los bits, es decir, convierte los ceros en unos y viceversa. Observemos que es el único de esta familia que tiene un solo operando.
Como los enteros negativos en Java se representan con el método del complemento a dos, podemos realizar un sencillo experimento de cambiarle el signo a un número. Para realizarlo debemos aplicar a un entero el operador NOT y sumarle uno.

## Para saber más

* Bit
* Lógica binaria

# Operadores de asignación

Prácticamente lo hemos utilizado en todos los ejemplos de variables y operadores. Es el operador de asignación. Este aparece con un signo igual (=). Cambia el valor de la variable que está a la izquierda por un literal o el resultado de la expresión que se encuentra a la derecha.
En el ejemplo vemos la variable par toma el valor de 2 y perímetro el resultado de una expresión.
Veamos un ejemplo de una instrucción tonta, que en realidad no hace nada.
La variable algo toma el valor de algo; todo queda como antes. Ahora aumentemos el valor de la variable en 3 unidades.
Aquí la variable toma el valor que tenía mas 3 unidades. Existe una forma de simplificar la notación anterior. Es la siguiente:
Se juntaron el operador de suma con el de asignación. Este atajo se puede realizar para otras operaciones además de la suma. Es útil cuando la operación contiene como primer operando al valor de la misma variable en la que se almacena el resultado.
Operadores de asignación :
| Operación | Operador | Utilización | Operación equivalente |
| Suma | += | A += B | A = A + B |
| Resta | -= | A -= B | A = A - B |
| Multiplicación | *= | A *= B | A = A * B |
| División | /= | A /= B | A = A / B |
| Resto de división | %= | A %= B | A = A % B |
| Desplazamiento a la izquierda | <<= | A <<= B | A = A << B |
| Desplazamiento a la derecha | >>= | A >>= B | A = A >> B |
| Desplazamiento a la derecha sin signo | >>>= | A >>>= B | A = A >>> B |
| AND de bits | &= | A &= B | A = A & B |
| OR de bits | |= | A |= B | A = A | B |
| XOR de bits | ^= | A ^= B | A = A ^ B |

# Operador cast

Cada vez que realizamos una operación obtenemos un resultado. Este resultado podrá tener un tipo de dato diferente de los operandos. Veamos esto:
Nos da un error en la compilación. Se debe a que se produjo un cambio de tipo en el resultado, en vez de un byte se nos apareció un int. Este es un cambio de tipo implícito.
Pero no queremos que quede así. Podemos forzar al compilador que nos entregue un byte. Lo haremos de la siguiente forma :
Estamos realizando un cambio explícito de tipo, realizado con un operador cast. Este operador aparece como el nombre del tipo a obtener entre paréntesis; siempre antepuesto al resultado que se debe modificar.
Nos encontraremos ahora con un viejo conocido que nos ha molestado antes, es el literal descarriado:
Sabemos ya que nos dará un error debido a que es un literal double que trata de disfrazarse de float. Pero le daremos un cast así lo transformamos en float.
De esta manera el compilador no protestará porque colocamos peras con manzanas. El operador cast se ocupó de convertir un double en un float.
Existe un cierto peligro en la utilización indiscriminada de este operador. Observemos el siguiente programa :
Aquí intentamos meter a empujones un valor en un byte, cuyo valor es más grande de lo soportado. Pero en este caso Java tomas las cosas con indiferencia. Si ejecutamos el programa nos indicará :
El resultado dista mucho del valor original. El operador cast se comportó como una picadora de bits. Si miramos con lupa ambos valores, nos damos cuenta de qué ocurrió:
Resulta que al aplicar el cast "cortamos" la variable int en los primeros 8 bits que corresponden al tamaño del byte.

# Precedencia de operadores

Ya que conocimos a los operadores, vamos a tratar de colocarlos todos juntos en una sola expresión. Vamos a ver como se organizan para trabajar:
Civilizadamente se organizan de acuerdo al nivel del precedencia de cada uno. Primeramente proceden los unarios, luego los aritméticos, después los de bits, posteriormente los relacionales, detrás vienen los booleanos y por último el operador de asignación. La regla de precedencia establece que los operadores de mayor nivel se ejecuten primero.
Precedencia de operadores :
| Descripción | Operadores |
| operadores posfijos | op++ op-- |
| operadores unarios | ++op --op +op -op ~ ! |
| multiplicación y división | * / % |
| suma y resta | + - |
| desplazamiento | << >> >>> |
| operadores relacionales | < > <= => |
| equivalencia | == != |
| operador AND | & |
| operador XOR | ^ |
| operador OR | | |
| AND booleano | && |
| OR booleano | || |
| condicional | ?: |
| operadores de asignación | = += -= *= /= %= &= ^= |= <<= >>= >>>= |
En la tabla se muestra el nivel de precedencia de los operadores. Los de mayor nivel se encuentran arriba. Podemos ver que los últimos son los de asignación. Esto es lógico, ya que se debe calcular primeramente la expresión antes de asignar un resultado a una variable.
Veamos unos ejemplos de cómo actúa esta regla.
Desde que aprendimos aritmética básica, conocemos la regla que nos obliga a calcular la multiplicación antes de una suma. Esto también se cumple en Java.
Si todos los operadores tienen un nivel idéntico de precedencia se evalua la expresión de izquierda a derecha.

## Utilización de paréntesis

Se utilizan para aislar una porción de la expresión de forma que el cálculo se ejecute de forma independiente. Puede forzar a una expresión a ignorar las reglas de precedencia.
Tomando el primer ejemplo, forzamos al compilador a realizar la suma antes que la multiplicación.
En este ejemplo es imprescindible la utilización de paréntesis :
Si quitamos los paréntesis el compilador protestará. Porque al establecer un nivel muy bajo para la asignación, procede primero la suma. Pero estamos sumando con una variable sin valor.
Como en matemáticas, podemos anidar los paréntesis. Se comenzara a evaluar los internos hasta llegar a los externos.
Cabe agregar que los paréntesis no disminuyen el rendimiento de los programas. Por lo tanto, agregar paréntesis no afecta negativamente al programa.
* Estructuras de control
** Estructuras de selección
*** Sentencia if-else
*** Sentencia switch
*** Operador if-else
** Estructuras de iteración
*** Sentencia while
*** Sentencia do-while
*** entencia for
** Saltos
*** Sentencia break
*** Sentencia continue
* Funciones
** Parámetros de una función
** Cláusula return
** Funciones recursivas
* Programación Orientada a Objetos
** Clases
*** Ejemplos de Implementación
*** Ejercicios Prácticos
** Objetos
** Ciclo de vida de un objeto
** Paquetes
** Encapsulamiento
** Herencia
** Interfaces
** Polimorfismo
** Excepciones
* Almacenamiento en Java
** La clase String
** La clase StringBuffer
** La clase StringTokenizer
** Vectores (Arreglos)
** Colecciones (JFC)
*** La clase ArrayList
*** La clase Vector
*** La clase Stack
*** La clase Hashtable
*** La clase HashSet
*** La clase LinkedList
*** La clase TreeMap
*** La clase StringTokenizer
* Entrada y Salida
** Imprimir en Pantalla
** Lectura del Teclado
* Interfaz Gráfica
** Componentes Swing
** Eventos
** Applets
* Threads
** ¿Qué es un thread?
* Apéndices
** Palabras reservadas
** Ejemplos prácticos
*** Crear un PDF en Java