HLC Java Tema1 Apuntes
HLC Java Tema1 Apuntes
Apuntes
Página 1 de 25
Sumario
1. Introducción y sintaxis de Java_________________________________________________3
1.1. Introducción 3
1.2. Descripción del lenguaje 3
1.3. Identificadores 5
1.4. Palabras clave 6
1.5. Literales 6
1.6. Tipos de datos 7
1.7. Operadores 9
1.8. Separadores 10
1.9. Comentarios 10
1.10. Arrays 11
1.11. Empaquetar tipos primitivos 12
1.12. Conversión de tipos de datos 13
1.13. Bloques y ámbitos 14
1.14. Expresiones 14
1.15. Clasificación de operadores 15
1.16. Precedencia de los operadores 19
1.17. Control de flujo 19
Página 2 de 25
1. Introducción y sintaxis de Java
1.1. Introducción
Los orígenes de Java se remontan al año 1990, cuando un equipo de la compañía Sun
Microsystems investigaba, bajo la dirección del ingeniero James Gosling, en el diseño y
elaboración de software para pequeños dispositivos electrónicos de consumo.
Se hace patente la necesidad de introducir un nuevo lenguaje de programación, que permita
desarrollar programas independientes del tipo de plataforma. Los dispositivos que se
pretenden fabricar son calculadoras, relojes, equipos de música, cafeteras, etc...., que no
tienen una gran capacidad computacional, por lo que el nuevo lenguaje debe ser capaz de
generar programas pequeños y rápidos, además de ser fiables y robustos.
El equipo de James Gosling se planteó como objetivo la utilización de Java como lenguaje
en el que escribir aplicaciones que pudiesen funcionar a través de Internet. Como resultado
de su trabajo se desarrolló un nuevo navegador completamente escrito en Java, llamado
HotJava. Este navegador permitía la integración de pequeñas aplicaciones en el interior de
las páginas Web. El desarrollo de HotJava hizo patente que las características de Java se
adaptan perfectamente a las peculiaridades de Internet. A partir de su primera y sencilla
versión Java ha ido creciendo progresiva y espectacularmente para pasar a ofrecer un
potente y complejo lenguaje con el que se pueden abarcar una gran cantidad de campos.
Página 3 de 25
Un interfaz es una colección de nombres de métodos sin definiciones reales que indican que
una clase tiene un conjunto de comportamientos, además de los que la clase hereda de sus
superclases.
Por lo tanto un interfaz es una lista de métodos sin ninguna implementación, la palabra
reservada implements es utilizada en la declaración de una clase para indicar que
implementa los métodos de un interfaz determinado.
La unidad básica dentro de la programación en Java va a ser la clase y el objeto. Java está
compuesto por un gran número de clases que se agrupan y clasifican en paquetes.
Pero a pesar de estar compuesto de clases, en Java nos encontramos también con una
serie de tipos de datos predefinidos ,estos tipos, denominados tipos primitivos son:
boolean, char, byte, short, int, long, float y double. Por lo tanto en Java podremos
definir variables de estos tipos de datos, en este caso se empleará la denominación variable
en lugar de objeto, ya que los tipos primitivos no son clases.
Se puede considerar que por un lado tenemos el lenguaje Java, que es con el que
escribimos nuestras clases y compilamos, y por otro se encuentra la Máquina Virtual de
Java, JVM (Java Virtual Machine). El compilador compila no a una plataforma determinada,
sino a una plataforma abstracta llamada Máquina Virtual de Java.
El código para la Máquina Virtual de Java se almacena en ficheros .class, cada uno de los
cuales contiene al menos el código de una clase pública.
Los archivos binarios Java, que se obtienen al compilar el código fuente, son independientes
de la plataforma y pueden ejecutarse en múltiples plataformas sin necesidad de volver a
compilar el fuente.
Los archivos binarios Java se encuentran en una forma especial llamada bytecode, que son
un conjunto de instrucciones muy parecidas al código máquina, pero que no son específicas
para ningún procesador. Para ejecutar un programa Java, se debe ejecutar un programa
llamado intérprete de bytecode, el cual a su vez ejecuta el programa Java deseado. En el
caso de los applets el intérprete se encuentra integrado en el navegador Web con capacidad
para Java y es ejecutado automáticamente.
Página 4 de 25
El concepto de independencia de la plataforma es ilustrado en la siguiente figura:
Figura 1
La desventaja de utilizar los bytecodes es la velocidad, estos programas tienen una menor
velocidad de ejecución, ya que previamente a ejecutarse sobre el sistema, deben ser
procesados por el intérprete.
El recolector de basura (garbage collector) es otro de los aciertos del lenguaje Java, se
trata de un hilo de ejecución (thread) que se encarga de rastrear en tiempo de ejecución
cada objeto que se ha creado, advierte cuándo desaparece la última referencia a él y libera
el objeto por el programador.
1.3. Identificadores
Los identificadores son literales que representan nombres únicos para ser asignados a
objetos, variables, clases y métodos, de este modo el compilador puede identificarlos
unívocamente.
Los identificadores tienen que comenzar por una letra, un subrayado o un símbolo de dólar,
tras este carácter, se pueden utilizar combinaciones de los ya mencionados y números del 0
al 9. No pueden utilizarse, como es lógico, las palabras clave del lenguaje como
identificadores (que mostraremos más adelante). Aunque estos identificadores pueden ser
cualquier longitud, para el compilador sólo son significativos los primeros 32 caracteres.
Se debe tener cuidado al escribir los identificadores, porque Java distingue entre
mayúsculas y minúsculas, de este modo, Nombre y nombre son dos variables diferentes.
Página 5 de 25
Java permite el uso de cualquier carácter del código Unicode para definir identificadores, de
esta forma, el identificador Año es totalmente válido en Java.
En Java se utiliza el word-mixing (EsteEsUnEjemploDeWordMixing), la primera letra se
escribe en mayúscula para las clases (ManejadorDeClientes, por ejemplo), y no se
utilizan los signos subrayado ni dólar como primer carácter de un identificador.
1.5. Literales
Llamamos literales a aquellos elementos de un programa que no pueden variar. Se les llama
también constantes.
Los literales pueden ser: números, caracteres y cadenas. Los literales numéricos se dividen
en: enteros, coma flotante y booleanos (álgebra de Boole). Los literales dan en Java lugar a
cada uno de los tipos básicos, anteponiéndoles la palabra reservada correspondiente a la
hora de declararlos.
El literal null
El literal null se corresponde con el tipo null, quien tiene un solo valor: la referencia nula.
Página 6 de 25
1.6. Tipos de datos
Cada uno de ellos se refiere a un tipo básico de datos, aunque en Java hay algunos tipos de
datos que no tienen representación como literales. Estos son los arrays (o matrices) y las
clases.
Una clase se podía asemejar a un tipo de datos y un objeto de la clase a una variable de ese
tipo de datos.
La sintaxis de la sentencia de declaración es (las sentencias finalizan con un punto y coma)
tipoidetificador1 = valor1]
,identificadorN [= valorN ]];
Enteros
Los enteros, dependiendo de la precisión que el número pueda tener se dividen en los
siguientes tipos primarios:
• byte: 8 bits complemento a dos
• short: 16 bits complemento a dos
• int: 32 bits complemento a dos
• long: 64 bits complemento a dos
Los enteros se almacenan por defecto internamente como tipo int, que es un valor de 32 bits
con signo.
byte edad;
short alturaEdificio = 614;
int miCantidad = 3456740, tuCantidad = 645780;
long distanciaInical, distanciaFinal = 86868688;
Coma flotante
Pueden ser de dos tipos: float y double. Los primeros se almacenan en 32 bits, mientras que
los segundos se almacenan en 64 bits. La única diferencia, es su capacidad de precisión,
debida la mayor cantidad de información que necesitan para representarlos.
Por defecto, los literales en coma flotante son del tipo double. Ambos (float y double) pueden
representarse en notación estándar (3,14159) o científica (3,14159e-5).
• float: 32 bits IEEE 754
• double: 64 bits IEEE 754
Página 7 de 25
float presión;
double distanciaEstelar;
Booleanos
El tipo booleano (boolean) se ha implementado en Java para representar los valores de
verdadero y falso, que en C se representan con un literal entero (0 falso y 1 o cualquier cosa
que no sea 0, verdadero). Se utiliza para ello dos palabras reservadas: true (verdadero) y
false (false).
Caracteres
Los caracteres, que se refieran un único carácter Unicode, se representan al igual que en C,
entre comillas simples. También pueden incluirse caracteres de control no imprimibles. En la
siguiente tabla se ofrecen estos caracteres.
Descripción Representación
Continuación \
Barra invertida \\
Retroceso \b
Retorno de carro \r
Alimentación formularios \f
Tabulador horizontal \t
Línea nueva \n
Comillas simples \’
Página 8 de 25
char inicial;
char milnicial = 'F';
Cadenas
Un literal de cadena es un conjunto de caracteres agrupados. Se representan entre comillas
dobles. Java, cada vez que encuentra un literal de tipo cadena, crea una nueva instancia de
la clase String.
1.7. Operadores
Operadores (según tipo)
Aritméticos unarios ++ -- - ~
Aritméticos binarios + - * / %
Lógicos && || !
Condicional ternario ?:
Cadenas +
Asignación = += -= *= /= %= &= |= ^=
Página 9 de 25
1.8. Separadores
Sólo hay un par de secuencias con otros caracteres que pueden aparecer en el código Java;
son los separadores simples, que van a definir la forma y función del código. Los
separadores admitidos en Java son los que se detallan a continuación:
[] corchetes Para declarar tipos matriz así como para referenciar los valores de
la matriz.
1.9. Comentarios
Los comentarios pueden ser considerados como un caso especial dentro de los elementos
de la sintaxis del lenguaje, ya que aunque estos sean reconocidos por el compilador, éste los
ignora. Las razones son tan obvias, que no vamos a entrar en detalles.
En Java existen tres tipos de comentarios (los dos del C y uno distinto).
Tipos de Comentarios
// comentario de línea
/*
comentario de bloque
*/
Página 10 de 25
/**
comentario de documentación
*/
1.10. Arrays
En Java, los arrays son objetos, son creados dinámicamente y pueden ser asignados a
variables de tipo Object, por lo que todos los métodos de la clase pueden ser invocados
desde un array.
Un array tiene un número entero de elementos que lo componen, y nos referimos a ellos por
su índice, que obviamente es un entero. Si un array tiene n elementos, el índice varía
entre 0 y n-1 ambos inclusive.
Un array puede tener 0 elementos, decimos entonces que el array está vacío. Del mismo
modo, un array puede tener una o más dimensiones. En cualquier caso, una vez creado el
array éste no puede cambiar de tamaño, es estático (existe en Java la clase Vector,
que permite trabajar con "arrays" dinámicos).
Todos los elementos de un array tienen que ser del mismo tipo, aunque estos
pueden ser arrays, en tal caso, debe llegar un momento en que los elementos de estos
elementos sean datos de otro tipo.
Un array se "fabrica" en dos tiempos: el de declaración y el de creación. En el primero sólo
se indican el tipo y las dimensiones de éste, esta información es procesada por el
compilador. En el segundo tiempo se crea el array en memoria, para lo que se utiliza el
operador new (este operador lo veremos en siguiente capítulo para la creación de objetos),
es entonces cuando indicamos el número de elementos que va a contener.
La declaración de arrays en Java es:
Página 11 de 25
// Declara y construye in array de 27 elementos
char cAlfabeto []= new char[27];
int iPrimos[];
iPrimos = new int[4];
iPrimos[0] = 1;
iPrimos[1] = 3;
iPrimos[2] = 5;
iPrimos[3] = 7;
Ahora se permite inicializar los contenidos de un array al utilizar el operador new. Lo que
flexibiliza la creación de arrays. El siguiente código fuente es ahora correcto:
Integer int
Long long
Página 12 de 25
Float float
Double double
Boolean boolean
char c;
c = (char) System.in.read();
float double
Página 13 de 25
1.13. Bloques y ámbitos
Bloques
Al igual que C, Java utiliza las llaves ({} la primera de inicio y la otra de fin de bloque) para
determinar los bloques dentro de un programa. Todo lo que se encuentra entre estas dos
llaves se considera un bloque. Los bloques son parte de la sintaxis del lenguaje.
Los bloques pueden y suelen anidarse; utilizándose la sangría para clarificar el contenido de
un bloque. De este modo, el bloque más externo se sitúa al margen izquierdo del fichero de
código fuente, y cada vez que se anida un bloque se indenta (sangra) el texto que lo
contienen un número determinado de columnas, normalmente tres o cuatro.
El sangrado no tiene ninguna utilidad para el compilador, pero sin ella la lectura del código
por parte del programador es casi imposible.
Ámbitos
Los bloques además, definen los ámbitos de las variables. El ámbito se refiere a la
longevidad de las variables.
Una variable existe sólo dentro del bloque donde ha sido declarada, eliminándola el
compilador una vez que se sale de dicho bloque. Cuando una variable sale de ámbito, es
eliminada y la memoria que ésta ocupaba es liberada por el recolector de basura (garbage
collector).
1.14. Expresiones
Una expresión no es más que una secuencia de elementos que puede ser evaluada por el
compilador.
Una llamada a una función, una asignación, un cálculo aritmético o lógico son algunos
ejemplos de expresiones.
Las expresiones suelen dividirse según su tipo, es decir según el tipo del valor que
devuelven al ser resueltas, en: aritméticas y lógicas. Dentro de cada una de ellas existen
subdivisiones.
El compilador las analiza y, si está bien construido, las simplifica todo lo posible,
evaluándose en tiempo de ejecución.
Algunos ejemplos de expresiones aparecen en el código fuente siguiente:
System.out.println( "Hola" + c );
a = 21 ;
b = a + b + C + 15 ;
c = (a + b) * (y-7);
d = 2 / 3 + 4 * 5
d = a && b;
e = (a && b) | c;
Página 14 de 25
Las expresiones se analizan de izquierda a derecha, salvo que existan paréntesis, en tal, los
fragmentos de la expresión encerrados entre paréntesis son evaluados antes. Si no hubiese
paréntesis, hay algunos fragmentos que son evaluados antes que otros, dependiendo de la
precedencia (importancia) de los operadores que se encuentran entre los operandos, pero a
igual nivel de precedencia, se mantiene la evaluación de izquierda a derecha.
En el caso de la expresión de ejemplo cuyo resultado se asigna a la variable d, podemos
interpretarla de varias maneras, ya que de no saber en qué sentido se evalúan las
expresiones y cual es la precedencia de los operadores, el resultado es imprevisible. De
todos modos, adelantamos que esta expresión en Java equivale a lo que muestra a
continuación:
d = (2/3) + (4*5)
Unarios
++ Incremento. Añade una unidad al valor actual de la variable. (1)
– Decremento. Sustrae una unidad al valor actual de la variable. (1)
- Negación. Equivale a multiplicar por -1 el valor de la variable.
~ Complemento a nivel de bits. (2)
Binarios
+ Adición
- Sustracción
Página 15 de 25
* Multiplicación
/ División (Cociente de la división)
% División (Resto entero de la división)
<< Desplazamiento a la izquierda. (3)
>> Desplazamiento a la derecha. (3)
>>> Desplazamiento a la derecha con relleno de ceros. (3)
& AND a nivel de bits.
| OR a nivel de bits.
^ XOR a nivel de bits.
Relacionales
< Menor que
> Mayor que
<= Menor o igual que
>= Mayor o igual que
== Igual que
!= Distinto que
Tanto los operadores unarios como los binarios, independientemente del tipo de los
operandos sobre los que se realice la operación, devuelven un int para todos los casos,
excepto que uno de los operandos sea un long, en cuyo caso el valor devuelto es de tipo
long.
(1) Estos operadores pueden utilizarse en forma de prefijo (++variable) o forma de sufijo
(variable++). En el primer caso el incremento (o decremento) de la variable se realiza
antes de evaluar la expresión, y en segundo se realiza tras evaluar la expresión.
(2) Este operador conmuta el número a nivel de bits, es decir, todos los bits que estaban
a 0 pasan a ser 1, y todos los bits que estaban a 1 pasan a 0.
(3) Estos operadores desplazan los bits a la derecha o izquierda el número de posiciones
especificado como segundo operando.
Página 16 de 25
Unarios
++ Incremento. Añade una unidad al valor actual de la variable.
-- Decremento. Sustrae una unidad al valor actual de la variable.
Binarios
+ Adición
- Sustracción
* Multiplicación
/ División (Cociente de la división)
% Módulo (Resto entero de la división)
Relacionales
< Menor que
> Mayor que
<= Menor o igual que
>= Mayor o igual que
== Igual que
!= Distinto que
Página 17 de 25
Operadores sobre cadenas
En Java existe un solo operador que utilice cadenas como operandos, este es el operador
binario +, este operador concatena cadenas. En el código fuente siguiente vemos un
ejemplo.
Operadores de asignación
Estos operadores, salvo el operador de asignación simple (=) se utilizan para escribir
menos, y por lo tanto, su forma simplificada es exactamente equivalente a su forma
extendida.
Página 18 de 25
1.16. Precedencia de los operadores
A continuación se presenta todos los operadores que hemos visto, según su orden de
precedencia de mayor a menor, es decir, según su importancia a la hora de ser evaluados.
Esto quiere decir, que salvo que se agrupen expresiones mediante el uso de paréntesis,
aquellos operadores que tengan mayor orden de precedencia, serán evaluados primero.
• [] ()
• ++ -- ~
• ! ~ instanceof
• */%
• +-
• << >> >>>
• < > <= >= == !=
• & | ^
• && ||
• = += -= *= /= %= &= |= ^=
if-else
La sintaxis de esta estructura es la siguiente:
if ( ExprBooleana )
// sentencia1;
[ else [if ( ExprBooleana ) ]
Página 19 de 25
// sentencia2; ]
Aunque también pueden utilizarse bloques en lugar de sentencias, del siguiente modo:
if ( ExprBooleana ) {
// sentencias;
}
[ else [if ( ExprBooleana ) ] {
// sentencias;
} ]
ExprBooleana puede ser cualquier expresión que, al ser evaluada, devuelva un resultado de
tipo Booleano.
switch
La sintaxis de esta estructura es la siguiente:
switch( Expresión ) {
case Constantel:
sentencias;
[break;]
[case Constante2:
sentencias;
[break;] ]
[default:
sentencias;
[break;] ]
}
Página 20 de 25
switch( iDíaSemana ) {
case 1:
sDia = "lunes";
break;
case 2:
sDia = "martes";
break;
case 3:
sDia = "miércoles";
break;
case 4:
sDia = "jueves";
break;
case 5:
sDia = "viernes";
break;
case 6:
sDia = "sábado";
break;
case 7:
sDia = "domingo";
break;
default:
sDia = "No se qué día es";
}
A continuación vemos otro ejemplo en el que no utilizamos una sentencia break tras cada
case.
int iMes;
int iDías;
long nAño;
switch (iMes) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
iDías = 31;
break;
case 4:
case 6:
case 9:
case 11:
iDías = 30;
break;
case 2:
if ( (( nAño % 4 == 0) && !( nAño % 100 ==0)) || ( nAño % 400 == 0) )
iDías = 29;
else
iDías = 28;
break;
Página 21 de 25
default:
iDias = 0;
}
for
La sintaxis del bucle for es la siguiente:
O bien:
Aunque estas tres expresiones pueden utilizarse para el propósito que se desee,
normalmente se utilizan para los siguientes fines:
• Exprlnidaliza, en esta expresión se inicializa la variable(s) que va a controlar el bucle.
• ExprCondición, esta expresión controla cuando finalizan las iteraciones del bucle.
• Exprlteración, esta expresión indica cómo cambia la variable de control del bucle.
Se debe señalar que las expresiones son todas optativas, y aunque se pueda escribir un
bucle sin ninguna de ellas, no tiene mucho sentido hacerlo. Si así se hiciera, se tendría que
mantener los puntos y comas que separan las tres expresiones.
Cada una de estas expresiones que se definen en la cabecera del bucle pueden ser simples
o expresiones compuestas separadas por comas. Veamos un ejemplo de cada una de ellas:
Vemos, a continuación, expresiones simples.
La cabecera de este bucle for puede leerse del siguiente modo: "Para x igual a uno, y
mientras que x sea menor o igual que diez, incrementa x en una unidad".
El código fuente siguiente, nos muestra expresiones compuestas.
Página 22 de 25
for (x = 1, t = 30; x <= 10 && (x - t) != 20; x++, t -= 2 ) { ... }
La cabecera de este bucle for puede leerse del siguiente modo: "Para x igual a uno, y t igual
a treinta, mientras que x sea menor o igual que diez y mientras x menos t sea distinto de 20,
incrementa x en una unidad y disminuye t en dos unidades".
while
Las principales diferencias entre el bucle for y el bucle while son que en éste no se inicializan
los valores de control ni se dispone de la expresión de iteración.
La sintaxis de este bucle es la siguiente:
while (CondBooleana)
// sentencia;
O bien:
while (CondBooleana){
// sentencias;
}
do-while:
La sintaxis de este bucle es la siguiente:
do
// sentencia;
while (CondBooleana);
O bien
do {
Página 23 de 25
// sentencias;
} while (CondBooleana);
Como puede verse, este bucle es casi idéntico al bucle while, salvo que en este caso, la
expresión booleana se evalúa tras haberse realizado la primera iteración del bucle.
Este bucle pinta solamente los números del 1 al 4. Ya que break se ejecuta cuando i == 5, lo
que hace que el flujo de la aplicación pase control instrucción que se encuentra
inmediatamente tras el bucle.
La sentencia continue es similar a break, pero en lugar de transferir el flujo de la aplicación
fuera del bucle, continue lo lleva a la cabecera del bucle. Por lo tanto, y como es lógico, esta
instrucción sólo puede utilizarse dentro de bucles.
A continuación podemos ver un ejemplo del uso de esta sentencia.
Este bucle muestra todos los números del 1 al 10 excepto el número 5. Ya que continue se
ejecuta cuando i == 5, lo que hace que se salten todas las sentencias por debajo de continue
y que el flujo de la aplicación vuelva a la cabecera del bucle.
Aunque goto es una palabra reservada, en Java los saltos no están permitidos.
Sin embargo, Java permite asociar una etiqueta cuando se va a realizar un salto, para de
este modo clarificar el código. La etiqueta se asocia con las instrucciones break y continue,
que son las únicas sentencias de salto que Java contempla.
Veamos un ejemplo del uso de las etiquetas en el entorno para el que fueron pensadas.
Página 24 de 25
uno: for( ){
dos: for( ){
continue; // seguiría en el bucle interno
break; // se saldría del bucle interno
continue uno; // seguiría en el bucle principal
break uno; // se saldría del bucle principal
}
return
Esta instrucción es un caso especial, ya que aunque permite realizar un salto, no es una
instrucción de salto propiamente dicha.
Esta sentencia tiene la siguiente sintaxis:
return valor;
Cuando return es encontrado en el programa, el flujo salta fuera del método donde fue
encontrado, no ejecutándose ninguna otra instrucción por debajo de esta y devuelve el
control al método que lo invocó. Si el método donde se encuentra return es el principal, la
aplicación termina.
Esta sentencia permite devolver un valor al método que llama a otro tras la ejecución de un
proceso determinado. Lo que en Java es muy importante, porque los métodos, si se
especifica que tienen que devolver un dato de un tipo determinado (cualquiera excepto void),
tienen que contener una instrucción return que devuelva un valor coincidente con la
declaración del tipo del método.
Página 25 de 25