Documente Academic
Documente Profesional
Documente Cultură
TEMA 3: CARACTERÍSTICAS BÁSICAS DEL LENGUAJE JAVA
1. INTRODUCCIÓN
El lenguaje de programación Java fue fruto de un proyecto de la compañía Sun Microsystems a
finales de 1990, y promovido por el ingeniero Patrick Naughton como consecuencia de los problemas
que algunos ingenieros de la empresa encontraban en las APIs (Application Programming Interfaces )
del lenguaje C++. El proyecto comenzó denominándose Stealth (cautela), pero enseguida pasó a
llamarse Green Project (Proyecto Verde), uniéndose al mismo James Gosling y Mike Sheridan, entre
otros ingenieros.
Inicialmente, el proyecto se concibió con el objetivo de desarrollar una nueva tecnología para
programar la siguiente generación de electrodomésticos inteligentes (microondas, lavadoras, . . . ),
considerada por Sun un importante campo de aplicación tecnológica en el futuro. Aunque el equipo de
desarrollo consideró al principio utilizar C++ para estos propósitos, muchos de sus componentes
encontraban el lenguaje y los recursos de programación (bibliotecas de clases) disponibles
problemáticos por varias razones: lenguaje demasiado complejo, propensión a errores, ausencia de
recolección automática de basura, inexistencia de facilidades portables para seguridad, programación
distribuida y concurrencia. El objetivo pasó a ser la construcción de una plataforma que pudiese ser
portada fácilmente a todo tipo de dispositivos.
El director científico de Sun en esos momentos, Bill Joy, propuso la definición de un lenguaje
que combinase los aspectos positivos de C++ y Mesa1. Aunque en un principio Gosling intentó
modificar y extender C++, pronto abandonó esa idea en favor de crear un lenguaje completamente
nuevo que denominó Oak, por un roble plantado fuera de su oficina. En verano de 1992 el equipo ya
había desarrollado algunas partes de la nueva plataforma incluyendo el sistema operativo Green, el
lenguaje Oak, las librerías y el hardware. Sus primeros pasos estuvieron orientados a la construcción
de un dispositivo similar a una agenda electrónica (PDA) denominado Star7. En noviembre de 1992 el
equipo del proyecto Green se constituyó en una empresa subsidiaria de Sun Microsystems,
denominada FirstPerson, que dirigió su estrategia comercial a la construcción de dispositivos
altamente interactivos. Después de varios intentos fallidos por generar interés en su plataforma en la
industria de la televisión, la empresa volvió a depender totalmente de Sun. Fue en 1994 cuando el
equipo del proyecto volvió a retomar el objetivo original, pero en esta ocasión enfocando el uso de la
tecnología a la web.
Fue en ese mismo año cuando el lenguaje pasó a llamarse Java, pues una empresa de tarjetas
adaptadoras de vídeo ya había utilizado comercialmente la marca Oak. El nuevo nombre fue elegido
en una cafetería frecuentada por algunos de los miembros del equipo de desarrollo del proyecto,
aunque no está claro si el nombre responde también a algún acrónimo. Lo que sí parece evidente es la
relación del nombre con el café, pues los ocho primeros bytes de los ficheros que almacenan clases
Java en hexadecimal se leen como CAFE BABE.
El diseño de Java ha sido influenciado por diferentes lenguajes. Aunque la coincidencia de
Java con las construcciones sintácticas de C++ es evidente, desde un punto de vista semántico las
1 El lenguaje Mesa fue desarrollado por Xerox para programar una máquina basada en 16 bits; es un lenguaje
fuertemente tipado con una sintaxis tipo Algol68 y con algunas influencias de Lisp y Smalltalk, como la recolección
automática de basura.
1
Tema 3: Características básicas del lenguaje Java D.I.G
diferencias son muy grandes, siendo otros los lenguajes a los que Java debe sus características. En
efecto, el paso de Patrick Naughton por la empresa NeXT hizo que ObjectiveC se cuente entre estos
lenguajes; del mismo modo, la experiencia previa de James Gosling con lenguajes como Smalltalk o
Simula68 permitió aportar nuevas ideas al desarrollo de Java.
La primera distribución pública de Java se realizó el 23 de Mayo de 1995 en el congreso
mundial de Sun, coincidiendo con el anuncio de que Netscape soportaría Java en sus navegadores. En
enero de 1996, Sun creó una línea de negocio, JavaSoft, para desarrollar la tecnología.
Después de varios años de popularidad, el uso de Java en los navegadores de internet ha ido
perdiendo presencia, hasta que su uso para implementar animaciones interactivas simples ha sido
sustituido en gran medida por Macromedia Flash, y actualmente tiende a ser utilizado para
aplicaciones más complejas. Por el contrario, para aplicaciones que se ejecutan en el lado del servidor,
Java es más popular que nunca. Al margen de su uso en aplicaciones sobre la web, Java se ha
desaconsejado tradicionalmente para programar otro tipo de aplicaciones. Sin embargo, los grandes
avances durante la última década en la potencia de los ordenadores, las mejoras de la máquina virtual
y la calidad que van alcanzando los compiladores actuales, han hecho de Java un lenguaje de
propósito general ampliamente extendido.
En el siguientes puntos veremos evolución histórica de Java. También veremos los pasos a
seguir en la realización de un programa, así como los elementos que aporta Java (caracteres,
secuencias de escape, tipos de datos, etc.) para escribir dicho programa.
2. EVOLUCIÓN DE JAVA
Desde su presentación en sociedad, el lenguaje Java ha ido evolucionando en las distintas
versiones y revisiones que se han ido definiendo:
● 1.0 (1996) Primera versión del lenguaje.
● 1.1 (1997) Se incorporan importantes mejoras, fundamentalmente en el modelo de eventos, y
se introducen las clases internas.
● 1.2 (1998) La API (Application Programming Interface ) sufre importantes modificaciones: se
introducen las capacidades de reflexión y se integra la biblioteca gráfica Swing entre las
clases básicas del lenguaje. También se modifica la máquina virtual de Java, que es equipado
con un compilador JIT (justintime ) que mejora las prestaciones del proceso de traducción a
bytecodes . Con esta versión se empieza a hablar de Java 2
● 1.3 (2000) Entre los cambios más notables se puede mencionar que la API para la invocación
remota de procedimientos (RMI —Remote Method Invocation ) es sustituida por una basada
en CORBA.
● 1.4 (2002) Es la versión más extendida y utilizada hasta el momento, e incluyó los siguientes
cambios, entre otros, frente a las versiones previas: la palabra reservada assert para comprobar
asertos, encadenamiento de excepciones, nueva biblioteca de entrada y salida no bloqueante,
analizador sintáctico de XML integrado, etc.
● 5.0 (2004) Inicialmente denominada 1.5, añade características sustanciales al lenguaje que
suponen un cambio drástico en las bases del mismo. Por ejemplo, se introduce la genericidad
mediante clases parametrizadas, la conversión automática entre tipos primitivos y tipos
2
Tema 3: Características básicas del lenguaje Java D.I.G
envoltorios, los tipos enumerados, etc.
● 6.0 (2007) Es la versión actual.
Como ya se ha mencionado, Java preserva gran parte de la sintaxis de C++, pero presenta
cambios sustanciales en las características como lenguaje orientado a objetos, entre los que destacan:
1. eliminación de definiciones de tipos de valores y macros,
2. eliminación de punteros y de la aritmética de punteros,
3. recolección automática de basura,
4. herencia simple,
5. noción de interfaz,
6. noción de paquete para organizar clases,
7. vinculación dinámica por defecto, . . .
3. LA TECNOLOGÍA JAVA
Como vimos en el tema anterior, la mayoría de los lenguajes son compilados o interpretados,
de forma que sus programas puedan ejecutarse en una computadora. Java es un poco especial ya que
es compilado e interpretado a la vez. Primero el programa es compilado a código intermedio llamado
Java bytecodes, que son independientes de la plataforma o máquina. Después, estos bytecodes son
ejecutados por un intérprete sobre la computadora. La compilación ocurre una sola vez; la
interpretación se produce cada vez que el programa se ejecuta.
El intérprete de los bytecodes se le conoce como Máquina Virtual de Java (Java VM, Java
Virtual Machine). Los Java bytecodes se pueden ejecutar sobre cualquier implementación de la Java
VM, por lo tanto, si el sistema operativo dispone de una Java VM, podemos ejecutar cualquier
programa Java compilado.
Si accedemos a java.sun.com podemos encontrar las siguientes versiones de plataformas Java
con sus implementaciones:
● Java EE (Enterprise Edition): Para el desarrollo de aplicaciones empresariales, servicios web,
aplicaciones web...
● Java SE (Standard Edition): Para el desarrollo de aplicaciones, applets, programación en
lenguaje Java.
● Java ME (Micro Edition): Entorno altamente optimizado para la utilización de Java en una
gran cantidad de artículos de consumo como móviles, tarjetas, agendas electrónicas, etc.
4. REALIZACIÓN DE UN PROGRAMA EN JAVA
Para poder escribir programas en Java se necesita un entorno de desarrollo Java. Sun
Microsystems, propietario de Java, proporciona uno de forma gratuita, Java Development Kit (JDK).
Dependiendo del sistema operativo que se vaya a utilizar, los pasos a seguir en la instalación serán
diferentes. Las instrucciones a seguir las podemos encontrar en en la página web, junto al material
que deseemos descargar.
3
Tema 3: Características básicas del lenguaje Java D.I.G
una vez finalizada la instalación, se crea en el disco duro una estructura de directorios entre los
que se encuentran:
● La carpeta bin: contiene las herramientas de desarrollo como:
○ javac: programa para compilar.
○ java: programa para ejecutar.
○ jdb: programa para depurar.
○ javadoc: programa para documentar.
● La carpeta jre: es el entorno de ejecución de Java. Este fichero se puede obtener también por
separado.
● La carpeta lib: contiene bibliotecas de clases.
● Las carpetas demo y sample: contiene ejemplo.
● La carpeta include: Contiene los ficheros de cabecera que dan soporte para añadir a un
programa Java código nativo (código escrito en un lenguaje distinto de Java, pro ejemplo Ada
o C++)
Para editar el código fuente Java es suficiente con un editor de texto sin formato; por ejemplo
el bloc de notas de Windows o gedit de Linux. No obstante, todo el trabajo de edición, compilación,
ejecución y depuración, se hace mucho más fácil si se utiliza un entorno de desarrollo con interfaz
gráfica de usuario que integre las herramientas mencionadas, en lugar de tener que utilizar la interfaz
de línea de órdenes del JDK.
Existen multitud de fabricantes que disponen de entornos de desarrollo para Java. Entre los
entornos que podemos obtener de forma gratuita están:
● NetBeans (java.sun.com o www.netbeans.org). es el entorno de libre distribución patrocinado
por Sun MicroSystems.
● Eclipse (www.eclipse.org). Es un proyecto de creación de un entorno genérico de desarrollo
patrocinado principalmente por IBM. Su objetivo es crear un marco de trabajo para distintos
tareas y lenguajes de programación.
● BlueJ (www.bluej.org). Entorno de desarrollo de la Universidad e Kent. Es un entorno muy
sencillo.
4.1. Programas y paquetes en Java
Un programa en Java es una colección de clases diseñadas para colaborar en una tarea, con una clase
(pública) distinguida que, al menos, ha de contener un método de clase (estático) con la siguiente
signatura o cabecera:
public static void main ( String [ ] args )
Este método es el que desencadena la ejecución del programa. Las demás clases pueden estar
definidas ad hoc o pertenecer a una biblioteca de clases.
Cada clase declarada como pública (mediante la palabra reservada public , cuyo significado se
detallará más adelante) debe almacenarse en un fichero con extensión .java con su mismo nombre; en
4
Tema 3: Características básicas del lenguaje Java D.I.G
cada fichero .java pueden definirse varias clases, pero sólo una puede ser pública.
Para ejecutar una aplicación Java, todos los ficheros que contienen las clases que componen la
misma deben ser precompilados, generándose un fichero con extensión .class por cada clase. La
ejecución se consigue interpretando el fichero .class de la clase distinguida antes mencionada en la
máquina virtual de Java. En cualquier distribución de Java la compilación se realiza mediante el
compilador javac.exe y la interpretación mediante java.exe . En la figura 3.1 se ilustra gráficamente el
proceso de compilación e interpretación de una aplicación Java.
Figura 3.1: Proceso de ejecución de un programa Java.
Cuando varias clases están estrechamente relacionadas entre sí se pueden organizar en
paquetes (packages ). Todas las clases pertenecientes a un paquete deben estar localizadas en el
mismo directorio. La forma de organizar un grupo de clases en un paquete consiste en especificar el
nombre del mismo al comienzo de los ficheros que definen el código fuente de las clases. Para ello se
utiliza la palabra reservada package seguida del nombre del paquete:
package <nombre−del−paquete>;
Existe una gran variedad de paquetes ya definidos en la biblioteca de clases de Java como
subpaquetes de los paquetes java y javax . Para poder utilizar paquetes distintos a éstos, su ubicación
(ruta) debe estar incluida en la variable de entorno CLASSPATH . Entre los paquetes básicos de Java,
atendiendo al uso que se hará de ellos en este texto, se pueden destacar los siguientes:
● java.lang: Incluye clases que son fundamentales para el diseño del propio lenguaje de
programación Java, como la que define las funciones matemáticas (la clase Math ), las
5
Tema 3: Características básicas del lenguaje Java D.I.G
diversas variantes de las clases que representan las cadenas de caracteres (String ,
StringBuffer, StringBuilder ), las que permiten una representación de los tipos básicos
(Integer , Boolean , Character , . . . ) como objetos, o clases especiales con funcionalidad
diversa (por ejemplo, las clases Object y System ).
● java.util: Contiene clases de utilidad como las que conforman el marco de las colecciones, el
modelo de eventos o las facilidades de hora y fecha; también proporciona una clase para
generar números pseudoaleatorios (Random ).
● java.io Proporciona las posibilidades de entrada y salida a través de flujos de información,
serialización2 y la conexión con el sistema de ficheros.
● java.awt: Contiene clases para confeccionar interfaces gráficas de usuario y dibujar gráficos e
imágenes.
● javax.swing: Incluye diversas componentes para la construcción de interfaces gráficas de
usuario, que permiten independizar las aplicaciones de la plataforma sobre la que se ejecutan.
Todos estos paquetes serán estudiados en temas posteriores, y cualquier detalle de éstos y otros
paquetes puede consultarse en la documentación proporcionada como complemento al JDK (Java
Development Kit ), localizada usualmente en el subdirectorio “. . . /docs/api/index.html”. (También se
puede encontrar la documentación en la dirección http://java.sun.com/javase/6/docs/api/
El nombre de cada paquete debe coincidir con el camino que va desde algún directorio
contenido en la variable CLASSPATH al subdirectorio donde está ubicado el paquete. Las clases
definidas dentro de un paquete pueden ser accedidas directamente sólo desde otras clases dentro del
mismo paquete. Desde fuera del paquete es necesario utilizar el nombre de la clase precedido por el
nombre del paquete. Por ejemplo, si deseamos calcular la media de un millón de números generados
aleatoriamente, deberíamos definir la clase siguiente:
Este requisito no es necesario en el caso de las clases del paquete java.lang , que son accesibles
utilizando tan solo su nombre. Éste es el caso de la clase System como se puede ver en el ejemplo.
Obsérvese que cualquier referencia a la clase Random se realiza mediante la expresión java.
util .Random , precediendo el nombre de la clase con la del paquete en la que está definida (el
subpaquete util del paquete java ). Cuando se hace referencia a una clase externa en muchas ocasiones
puede resultar tedioso tener que precederla con el nombre del paquete cada vez se utiliza; en estos
2Este término se corresponde con el inglés serialization, y se refiere a la posibilidad de empaquetar como un flujo de
datos secuencial la información almacenada en los objetos.
6
Tema 3: Características básicas del lenguaje Java D.I.G
casos, es conveniente utilizar la palabra reservada import antes de la definición de la clase (al
principio del fichero). El ejemplo anterior quedaría entonces:
Incluso es posible importar paquetes completos mediante cláusulas de importación como:
import java.util.* ;
Esto permitiría hacer referencia a cualquier clase (no sólo Random ) del paquete java.util sin
necesidad de precederla con el nombre del mismo.
4.2 Cómo crear un programa
Vamos a empezar con el clásico ejemplo de mostrar un mensaje de saludo. La aplicación la
realizaremos desde dos puntos de vista: utilizando la interfaz de línea de órdenes del JDK y utilizando
un entorno de desarrollo integrado.
Interfaz de línea de órdenes
1. Visualizar el editor de texto que vayamos a utilizar para editar el fichero fuente Java.
2. Escribir el texto correspondiente al programa fuente. cada sentencia Java finaliza con ; y cada
línea del programa se finaliza pulsando la tecla Intro.
class HolaMundo{
/*
*args: matriz de parámetros pasados a la aplicación mediante la línea de órdenes. puede estar vacía.
*/
public static void main (String[] args) {
System.out.println(“Hola Mundo”);
}
}
3. Guardar el programa escrito en el disco. El nombre del programa fuente debe ser el mismo
que el de la clase que contiene, respectando mayúsculas y minúsculas. La extensión del
fichero fuente es java. En nuestro caso será HolaMundo.java
4. Compilar y ejecutar el programa.
7
Tema 3: Características básicas del lenguaje Java D.I.G
La orden para compilar el programa HolaMundo.java es:
javac HolaMundo.java
Previamente, para que el sistema operativo encuentre la utilidad javac, hay que añadir a la
variable de entorno PATH la ruta de la carpeta donde se encuentra esta utilidad y otras que
utilizaremos a continuación.
Por ejemplo, en Linux:
PATH=$PATH:/home/usuario/jdk1.6.0_02/bin
export PATH
En Windows:
path=%path%;C:\java\jdk1.6.0_02\bin
El resultado de la compilación será un fichero HolaMundo.class que contiene el código de
bytes que ejecutará la máquina virtual de Java.
La ejecución del programa se realiza mediante el comando java, seguido del nombre del
fichero obtenido en la compilación. La extensión class no es necesaria.
java HolaMundo
5. Depurar el programa. Una vez ejecutado el programa, la solución puede ser incorrecta. Para
depurar un programa desde el compilador se pone la orden:
javac g HolaMundo.java
¿Qué hace el programa?
1. Declara la clase de objetos HolaMundo
2. Se describe el cuerpo de la clase encerrado entre los caracteres { y }.
3. Las líneas encerradas entre /* */ son comentarios.
4. El método principal main contiene la sentencia que se ejecutará. En este caso el método
println del objeto out miembro de la clase System de la biblioteca Java, escribe como
resultado la expresión que aparece especificadaentre comillas.
Entorno de desarrollo integrado
Ver manual de NetBeans
5. CONCEPTOS BÁSICOS DEL LENGUAJE: DE VARIABLES Y OPERADORES
A INSTRUCCIONES
Como hemos visto en los ejemplos presentados hasta ahora, las expresiones son las unidades
básicas de nuestros programas, entendiendo por expresiones fragmentos de código que pueden ser
evaluados, realizar algún cómputo y devolver algún valor. Algunas expresiones pueden ser utilizadas
como instrucciones por sí solas, o ser utilizadas dentro de otras instrucciones, las cuales pueden a su
vez ser agrupadas en bloques. Pero primero consideremos las expresiones, y para ello empecemos
8
Tema 3: Características básicas del lenguaje Java D.I.G
estudiando con algo más de detalle sus componentes básicos: variables, literales y operadores.
5.1 Identificadores
En primer lugar, alguna puntualización sobre los identificadores , los cuales dan nombre a
variables, métodos, clases e interfaces. Un identificador es una secuencia arbitraria de caracteres
Unicode —letras, dígitos, subrayado o símbolos de monedas—, el cual no debe comenzar por un
dígito ni coincidir con alguna palabra reservada. Podemos por tanto denominar por ejemplo máximo
a una de nuestras variables, cuando no es posible utilizar letras acentuadas en los identificadores de la
mayoría de los lenguajes de programación; en Java sí es posible, y nombres como tamaño , número o
αβασ son identificadores válidos.
Cuando se trabaja con el lenguaje Java hay que tener en cuenta que se distingue entre
mayúsculas y minúsculas3 ,y es habitual seguir las siguientes convenciones para los identificadores
que se utilizan en los programas:
● Los nombres de variables y métodos se escriben en minúsculas. Si son compuestos, las
palabras no se separan y comienzan con mayúscula. Por ejemplo, margenDeError , contador
,valorMáximo , etc.
● Los nombres de clase igual, pero comenzando con mayúscula. Por ejemplo, PilaDeNaturales ,
String , FileChooser , StringIndexOutOfBoundsException , etc.
● Los nombres de constantes se escriben todo en mayúsculas, y si son compuestos, las palabras
se separan con subrayados. Por ejemplo, CTE_DE_GRAVITACIÓN_UNIVERSAL ,
KM_POR HORA , PI , etc.
Ya nos hemos encontrado en las secciones anteriores comentarios en nuestros programas; todo
lo que va tras // en una línea es ignorado por el compilador —por supuesto, salvo si // va dentro de
una cadena de caracteres—. Es también posible introducir comentarios de varias líneas; para ello
ponemos /* al principio del texto a comentar y */ al final. Todo lo que queda entre un /* y el
siguiente */ es ignorado por el compilador. La utilidad JavaDoc , muy útil para documentar
programas, utiliza comentarios de la forma /** ... / .
5.2 Tipos y valores
En los lenguajes de programación, los tipos de datos y sus operadores juegan un papel
fundamental: definen la forma en que se representa la información y cómo podemos utilizarla. Ya que
las clases definen tipos de objetos, podemos pensar que definir una clase es similar a definir un tipo
de datos.
En la mayoría de las ocasiones, un programa Java trabaja con objetos, pero hay varios tipos de
datos básicos que no son clases, y a los cuales nos referimos como tipos primitivos . En concreto,
tenemos ocho tipos primitivos para representar valores numéricos (como 3 ó 54.32), caracteres
(como ’K’ o ’(’) y valores lógicos (true y false ). La razón por la que estos tipos primitivos no son
orientados a objetos es la eficiencia; son tipos muy utilizados y representarlos y manipularlos a bajo
nivel supone una mejora considerable en la eficiencia de nuestros programas. Sin embargo, como
3Esta distinción también afecta al nombre de los ficheros y directorios que se manipulen desde Java. De este modo, incluso en Windows es necesario
tenerlo en cuenta.
9
Tema 3: Características básicas del lenguaje Java D.I.G
veremos en otro tema, Java también proporciona clases que se corresponden con los tipos de datos
primitivos por razones que estudiaremos en ese mismo tema; p.ej., tenemos una clase Integer que
define objetos que encapsulan enteros.
Una característica importante de los valores de los tipos de datos primitivos es que se utiliza
siempre la misma cantidad de memoria para almacenarlos, es decir, que los rangos de valores de cada
uno de ellos es siempre el mismo, independientemente de la máquina que usemos. Como
consecuencia de esto, y a diferencia de lo que ocurre con otros lenguajes de programación, la
ejecución de los programas Java será la misma sea cual sea el ordenador utilizado. El cuadro 3.2
muestra los tipos de datos primitivos disponibles en Java y la cantidad de memoria utilizada para
representarlos.
De entre los tipos numéricos los más habituales son int , salvo que necesitemos números de un
rango mayor, y double . Esto es debido a que, aunque hay tipos que requieren menos espacio de
almacenamiento, la mayor parte de las operaciones matemáticas están definidas sobre estos tipos. Por
ejemplo, el método sqrt de la clase Math que calcula la raíz cuadrada de un número toma un double
como argumento y devuelve un double .
Java utiliza el formato Unicode para representar los caracteres —65.536 caracteres— por lo
que necesita 2 bytes para almacenar valores del tipo char .
Los valores de los tipos primitivos también se pueden manipular directamente, usando sus
representaciones literales. Los literales son valores fijos, valores que no pueden cambiar durante la
ejecución de nuestro programa. En la siguiente tabla podemos ver ejemplos de literales de los
distintos tipos de datos primitivos.
int 56 , 0123 , 0xaf
long 8456l , 33456L
10
Tema 3: Características básicas del lenguaje Java D.I.G
double 4.66 , 23.7e3 , 35.213d , 23.2D
float 67.345f , 34.122F , 21.34e2f
char ’a’ , ’$’ , ’ t ’ , ’u0061’
boolean true , false
Es importante hacer varias aclaraciones sobre los literales de los tipos primitivos:
● Los literales enteros son secuencias de dígitos octales, decimales o hexadecimales. La base del
número se considera decimal (base 10) a no ser que la cadena empiece con 0 , en cuyo caso se
considera un número octal (base 8), o con 0x ó 0X , en cuyo caso se considera un número
hexadecimal (base 16). Los literales enteros se consideran de tipo long si terminan en L ó l ,
como p.ej. 3L ; si no terminan de esta forma se supone que los literales enteros son de tipo int
. Para ser representados como byte o short es preciso asignar un entero de rango válido a una
variable declarada de estos tipos.
● Los literales en punto flotante pueden ir seguidos de f ó F , para indicar que es de simple
precisión, o de d ó D , para doble precisión. Un número con coma flotante será considerado
de tipo double si no se indica nada.
● Los literales del tipo char se representan entre comillas simples. Es posible expresar
cualquier carácter Unicode como \uxxxx ; ciertos caracteres especiales pueden representarse
utilizando también secuencias de escape . Mostramos en la figura 3.3 los caracteres de escape
más habituales.
También es posible expresar literales de tipo cadena de caracteres, y lo haremos encerrándolos
entre comillas dobles. Por ejemplo, ”hola” y ”\”¡Hola !\”, dijo Juan” son cadenas de caracteres. Los
literales de tipo cadena de caracteres están asociados al tipo String , del cual hablaremos en un tema
posterior.
Los valores, al igual que los objetos, se pueden manipular mediante variables. Y de la misma
forma que podemos declarar variables de tipo referencia a objetos, también podemos declarar
variables de los tipos de datos primitivos.
11
Tema 3: Características básicas del lenguaje Java D.I.G
Conversiones implícitas
Aunque Java es un lenguaje fuertemente tipado, es posible por ejemplo asignar un valor de
tipo int a una variable de tipo long. Son lo que se conocen como conversiones implícitas: es posible
asignar un valor numérico a cualquier variable numérica cuyo tipo admita un intervalo de valores
mayor. Las conversiones implícitas son las que se muestran en la figura 3.4.
Figura 3.4: Conversiones implícitas
Obsérvese que conservar el rango no es lo mismo que conservar la precisión. Por ejemplo, al ir
de un valor entero a uno en coma flotante no perderemos rango, pero podemos perder precisión. La
asignación del valor de tipo long 9223372036854775807 a una variable de tipo float es legal, pero el
valor almacenado será 9,2233720E18.
La conversión implícita se produce en los siguientes contextos:
● Asignaciones (el tipo de la expresión se promociona al tipo de la variable de destino).
● Invocaciones de métodos (los tipos de los parámetros actuales se promocionan a los tipos de
los parámetros formales).
● Evaluación de expresiones aritméticas (los tipos de los operandos se promocionan al del
operando con el tipo más general, y como mínimo se promocionan a int).
● Concatenación de cadenas (los valores de los argumentos se convierten en cadenas).
Como indica este último punto, hay un tipo especial de conversión implícita que ocurre al
utilizar el operador + de concatenación de cadenas con al menos un valor de tipo String. Si los dos
operandos son de tipo String éstos se concatenan normalmente, pero si el uno de ellos no es un String,
éste es convertido implícitamente en un String. Estas conversiones están definidas para todos los tipos
primitivos (y para cualquier objeto invocando al método toString). Por ejemplo, el resultado de
evaluar la expresión (’¡’ + ”hola ”+ ’!’) es de tipo String. Estudiaremos las cadenas de caracteres y el
método toString () en detalle más adelante.
Conversiones explícitas
A veces, en nuestros programas, será necesario convertir un valor de un tipo a otro de rango
menor, por ejemplo, al asignar un valor de tipo double a una variable de tipo float. Una asignación
como ésta no podría hacerse con una conversión implícita, aunque en muchas ocasiones es posible
hacer conversiones explícitas para convertir un valor de un tipo a un valor en un tipo de rango menor.
A veces nos referimos a las conversiones explícitas como castings explícitos, y de hecho la sintaxis
utilizada es la misma que la del casting para objetos.
12
Tema 3: Características básicas del lenguaje Java D.I.G
float n = ( float ) 432.5;
La realización de una conversión de este tipo consiste en la creación de un nuevo valor que sea
la mejor representación de dicho valor en el nuevo tipo. Toda conversión no estará permitida; p.ej., no
será posible convertir un valor lógico en un valor de tipo long.
Es posible por tanto convertir un valor de un tipo primitivo en un valor de un tipo primitivo de
menor rango, pero tenemos que tener en cuenta que podemos estar perdiendo precisión al hacerlo.
Evidentemente, la conversión de un valor de tipo long a un valor de tipo int, o de un valor de tipo
double a un valor de tipo byte, puede conllevar una pérdida de información.
Como se mencionó anteriormente, las constantes de tipo int se pueden asignar a variables de
tipos byte o short sin necesidad de conversión explícita, siempre que el valor asignado esté dentro del
rango de valores válidos.
Variables
Las variables se utilizan tanto para referirse a objetos como a valores. Según el tipo de datos
de la variable se podrán realizar distintas operaciones sobre la misma.
Antes de usar una variable se requiere una declaración:
<tipo> <identificador>
Podemos declarar por ejemplo una variable contador de tipo int de la siguiente forma:
int contador ;
Y una variable margenDeError de tipo double como:
double margenDeError ;
Es posible asignarle un valor a una variable mediante una instrucción de asignación. La
declaración de una variable y su inicialización explícita pueden aparecer en la misma línea:
int contador = 1;
También es posible declarar varias variables del mismo tipo en una misma declaración.
int contador , máximo;
Y combinarlas a nuestro antojo, por ejemplo, podemos declarar variables contador y máximo y
asignarle un valor inicial a la primera en una declaración como la siguiente:
int contador = 0 , máximo ;
Una variable se puede declarar como constante precediendo su declaración con la etiqueta
final; por ejemplo, podemos declarar una constante MÁXIMO con valor 0 como sigue:
final int MÁXIMO = 0;
La inicialización de una variable final se puede hacer en cualquier momento posterior a su
declaración. Cualquier intento de cambiar el valor de una variable final después de su inicialización
produce un error en tiempo de compilación.
13
Tema 3: Características básicas del lenguaje Java D.I.G
Ámbito de una variable
Como en la mayoría de los lenguajes de programación, en Java tenemos unas reglas de ámbito
que rigen la accesibilidad de las variables de nuestros programas; en el caso de los lenguajes
orientados a objetos, y por tanto de Java, reglas similares son aplicadas a la accesibilidad de las
variables locales y los miembros de las clases (variables de instancia y de clase y métodos).
Nos centramos en el estudio del ámbito de las variables locales, el ámbito de las variables de
instancia y de clase y los métodos se estudiarán más tarde. En primer lugar diremos que las
declaraciones e instrucciones pueden agruparse en bloques usando llaves (’{’ y ’}’). Tendremos por
tanto que el cuerpo de un método será un bloque, pero también es posible definir unos bloques dentro
de otros (bloques anidados), y las reglas de ámbito habituales son aplicables a este contexto.
Una variable puede ser declarada en cualquier lugar dentro de un bloque, y puede ser utilizada
en cualquier lugar dentro de ese bloque (su ámbito), pero no será accesible fuera de dicho ámbito.
Podemos decir por tanto que el ámbito de una variable es la zona de código donde se puede usar su
identificador sin calificar. El ámbito de una variable determina cuándo se crea y cuándo se destruye el
espacio de memoria utilizado para almacenar el valor de dicha variable. Por ejemplo, cuando se
invoca un método se crea espacio para almacenar sus parámetros y las variables locales que en él se
declaren.
Todo identificador debe ser único dentro de su ámbito, no es posible declarar una variable si
ya existe una variable local con el mismo nombre en el mismo ámbito.
Las variables, según su ámbito, se clasifican en las siguientes categorías:
● variables de clase, accesibles en toda la clase en la que se declaran (en la figura 3.5, visibles
en todo el bloque 1);
● variables de instancia, accesibles en toda la clase en la que se declaran menos en los métodos
de clase (en la figura 3.5, visibles en todo el bloque 1 menos en el bloque 2);
● variables locales a un bloque, su ámbito es el bloque en que es declarada (en la figura 3.5, por
ejemplo, una variable declarada en el bloque 3 tiene como ámbito todo ese bloque 3, incluido
el bloque 4; si se declarara una variable con el mismo nombre en el bloque 4 la variable
visible en ese bloque sería la declarada en él, quedando oculta la del 3);
● parámetros de métodos, igual que las variables locales (en la figura 3.5, por ejemplo, un
parámetro del método método1 tiene como ámbito todo el bloque 2), y parámetros de gestor
de excepciones, tienen un tratamiento similar a los parámetros de métodos (en la figura 3.5, un
parámetro del catch que aparece en el método método1 tendría como ámbito todo el bloque 5).
Si se declarara una variable local, un parámetro de método o un parámetro de gestor de
excepciones con el mismo nombre que una variable de instancia o de clase siempre es posible
referirse a esta última mediante la pseudovariable this.
14
Tema 3: Características básicas del lenguaje Java D.I.G
Figura 3.5: Ámbito de las variables
15
Tema 3: Características básicas del lenguaje Java D.I.G
Inicialización de variables
Toda variable ha de ser inicializada antes de poder ser utilizada. Si intentamos utilizar una
variable local antes de haberle asignado un valor el compilador generará un error; sin embargo, el
sistema inicializa las variables de clase y de instancia (no finales) de forma automática cuando no se
les asigna un valor explícitamente en su declaración:
● Las variables de clase se inicializan automáticamente al cargar la clase.
● Las variables de instancia se inicializan automáticamente cada vez que se crea una instancia.
Los valores que se utilizan para las inicializaciones por defecto son las siguiente:
tipo
Valor inicial por defecto
boolean false
char ’\0’
byte, short, int, long 0
float +0.0f
double +0.0
referencia a objeto null
5.3 Operadores y expresiones
Las expresiones son la parte fundamental de cualquier programa, ya que son ellas las que
realizan el trabajo. Una expresión es una combinación de literales, variables, operadores y mensajes,
acorde con la sintaxis del lenguaje, que se evalúa a un valor simple o a una referencia a un objeto y
devuelve el resultado obtenido.
Junto con literales, variables y mensajes, los operadores son por tanto los elementos que se
combinan para construir expresiones. Los operadores son de hecho una pieza fundamental, ya que
todo operador devuelve un valor resultado, y los operadores sólo se usan dentro de expresiones.
Un operador es una función de uno, dos o tres argumentos. Existen operadores
aritméticos (+ ++ * / % )
de relación/comparación ( > >= < <= == != )
lógicos (&& || ! & | ˆ )
de asignación (= += = *= /= %= &= |= ˆ= )
para la manipulación de bits
otros operadores ( ? : )
Aunque suponemos que la mayoría de estos operadores son conocidos, merece la pena hacer
algunas puntualizaciones:
● Los operadores aritméticos se pueden usar tanto con números enteros como con números
16
Tema 3: Características básicas del lenguaje Java D.I.G
reales, y también a valores de tipo char . La división entre dos enteros devuelve un entero, es
decir, posiblemente un valor truncado. Se puede obtener el valor del resto con el operador % .
Si se intenta dividir por cero se produce una excepción.
● Los operadores de incremento y decremento se pueden utilizar como prefijo y como sufijo. Si
el operador aparece como prefijo (delante de su operando) se realiza el incremento de la
variable antes de evaluar el resto de la expresión. Si el operador aparece como sufijo (detrás de
su operando) se evalúa la expresión en primer lugar y después se realiza el incremento o
decremento.
● Todos los operadores relacionales pueden utilizarse con operandos de tipo numérico y char .
Es posible comprobar si dos valores booleanos son iguales o distintos, pero no tienen definida
una relación de orden.
● El operador new es un operador de creación de instancias, y se utiliza para crear instancias de
clases o de arrays. El resultado de la expresión es una referencia al objeto creado.
● El operador instanceof toma como primer argumento una referencia a un objeto y como
segundo argumento el nombre de una clase o interfaz, y comprueba si dicho objeto es una
instancia de dicha clase o interfaz.
● El operador condicional ?: devuelve el resultado de evaluar la expresión dada como segundo o
tercer argumentos dependiendo de si su primer argumento —una expresión booleana— evalú
a true o false . Las expresiones dadas como segundo y tercer argumentos han de tener tipos
compatibles, y el tipo de la expresión global será el mayor de los dos tipos.
Con un operador y sus argumentos se construyen expresiones simples.
3 * 5 x += 7.3 ’a’ <= 45
Las expresiones simples se pueden combinar dando lugar a expresiones compuestas.
3 * 5 + x += 7.3 y *= x += 7.3
El orden de evaluación de las expresiones compuestas depende de la precedencia y de la
asociatividad de los operadores que aparezcan. Hay expresiones en las que el orden en que se se
evalúe la expresión no cambia el resultado (p.ej. 3 * 2 * 5 ó 7 + 3 1); en cambio, hay otras en las que
el orden que se considere es fundamental (p.ej. 3 + 4 * 2 ó 8 / 2 2). La figura 3.6 muestra la
precedencias de los operadores más frecuentes ordenadas de mayor a menor. El orden de las
operaciones en una expresión siempre se puede modificar mediante el uso de paréntesis.
Las precedencias no son suficientes para resolver todos los posibles casos ambiguos.
Expresiones con varios operadores de la misma precedencia pueden dar lugar a situaciones ambiguas.
Por ejemplo, aunque expresiones como 4 + 5 − 2 no crea problemas, es necesario resolver sin
ambigüedad una expresión como 4 / 2 / 2 ó x = y = 3 . Los operadores de asignación son evaluados
de derecha a izquierda; todos los demás operadores binarios son evaluados de izquierda a derecha.
17
Tema 3: Características básicas del lenguaje Java D.I.G
Figura 3.6: Precedencia de los operadores más comunes.
6. TIPOS ENUMERADOS
Los tipos enumerados nos dan la posibilidad de definir nuevos tipos de datos simplemente
enumerando sus posibles valores. Podemos crear tipos enumerados utilizando la palabra reservada
enum . Por ejemplo, podemos definir un tipo enumerado Semana simplemente enumerando los días
de la semana:
enum Semana {Lunes , Martes , Miércoles , Jueves , Viernes , Sábado , Domingo };
Los identificadores Lunes , Martes , Miércoles , Jueves , Viernes , Sábado y Domingo se
denominan constantes de enumerado . Una vez creado el tipo de datos se utiliza el programa como
cualquier otro tipo de datos. Por ejemplo, podemos declarar variables de tipo enumerado y asignarles
valores.
Semana s ;
. . .
s = Semana.Lunes ;
Como la variable s ha sido declarada de tipo Semana sólo puede tomar los valores definidos
en el enumerado. Obsérvese que utilizamos los valores del enumerado calificándolos con el nombre
del tipo, es decir, Lunes va precedido por Semana .
Es posible comparar la igualdad de dos valores enumerados utilizando el operador == , por
ejemplo, podemos tener una expresión s == Semana.Miércoles . También es posible utilizar un valor
enumerado en una sentencia switch , por ejemplo:
switch ( s ) {
case Lunes :
System.out.println( ”Hoy comemos arroz. ” ) ;
break ;
case Miércoles :
18
Tema 3: Características básicas del lenguaje Java D.I.G
System.out.println( ”Hoy comemos judías . ” ) ;
break ;
case Viernes :
System.out.println( ”Hoy comemos puchero . ” ) ;
break ;
default :
System.out.println( ”Hoy no comemos. ” ) ;
}
Obsérvese que las constantes de enumerado no se califican en los casos de una instrucción
switch .
Aunque el uso de los enumerados es bastante parecido al que haríamos con los tipos
primitivos, la sintaxis para la definición de tipos enumerados no es más que azúcar sintáctico, e
internamente Java construye objetos pertenecientes a la clase java.lang.Enum . En realidad funcionan
de una forma bastante parecida a como ocurre con los arrays. Entender algunas cuestiones puede
sernos útil:
● Los valores de un tipo enumerado se definen como objetos, y por tanto pueden ser
comparados utilizando equals. Sin embargo, se definen como constantes (utilizando final ) y
por tanto pueden también compararse con == , lo que permite abstraerse de su representación
interna y usarlos como tipos enumerados.
● Los enumerados tienen disponibles varios métodos predefinidos, entre los cuales destacamos
los siguientes:
○ el método ordinal(), que devuelve la posición (int) de cada valor del tipo enumerado según
éste fue declarado —la primera posición es el 0 —,
○ el método values() , que devuelve todos los valores de un tipo como un array deobjetos, lo
que permite iterar sobre los elementos de un tipo enumerado, y
○ el método valueOf(String str ) , que devuelve la constante de enumerado cuyo valor
corresponde a la cadena pasada como argumento.
Cuando se convierte una constante de enumerado a cadena de caracteres, como ocurre en una
instrucción println , se obtiene su nombre. Por ejemplo, el programa
class DíasDeLaSemana {
public static void main ( String [ ] args ) {
for (Semana se : Semana.values ( ) ) {
System.out.print ( se + ” ” ) ;
}
}
}
19
Tema 3: Características básicas del lenguaje Java D.I.G
muestra en pantalla
Lunes Martes Miércoles Jueves Viernes Sábado Domingo
Obsérvese que podemos utilizar el bucle for each debido a que values() devuelve un array
sobre el que podemos iterar.
El listado 3.7 muestra el código de la clase Fecha , la cual se define con tres variables de
instancia que definen su estado: día y año de tipo int , y mes de tipo Mes , donde Mes es un tipo
enumerado con los meses del año como posibles valores. El tipo enumerado se ha definido aquí como
una clase más, en este caso con visibilidad dentro del paquete, aunque podría haberse declarado
pública, y podría haberse declarado también dentro de la clase Fecha.
La clase Fecha tiene tres constructores, los tres con tres argumentos, aunque a cada uno de ellos,
además de un día y un año, se le pasa un mes en formato int , String o Mes , respectivamente.
Obsérvese el uso de los métodos values() y valueOf para convertir un entero y una cadena de
caracteres en un valor del tipo Mes . El método ordinal () es utilizado en númeroMes() para obtener
el número del mes. Obsérvese finalmente la forma en que se construye una cadena de caracteres que
representa una fecha en el método toString () ; al utilizar el operador de concatenación de cadenas de
caracteres el sistema convierte automáticamente un valor de tipo Mes en una cadena de caracteres.
Consideremos para ver el uso de esta clase y sus diferentes constructores la siguiente
aplicación.
public class PruebaFecha {
public static void main ( String [ ] args ) {
Fecha hoy = new Fecha (27 , 1 , 2006) ;
System.out.println( hoy ) ;
Fecha sanJosé = new Fecha (19 , ”Marzo ” , 2006) ;
System.out.println( sanJosé ) ;
System.out.println( ”Número de mes sanJosé : ” +
sanJose.númeroMes ( ) ) ;
Fecha inicioVac = new Fecha (1 , Mes . Agosto , 2006) ;
System.out.println ( ” Inicio de las vacaciones : ” + inicioVac ) ;
}
}
Obsérvese cómo nos referimos al mes de agosto como Mes.Agosto . Dada la visibilidad del
enumerado Mes esto se permite porque Fecha y PruebaFecha pertenecen al mismo paquete. El
resultado de la ejecución de la clase PruebaFecha es el siguiente:
27 de Enero de 2006
19 de Marzo de 2006
Número de mes sanJosé : 3
Inicio de las vacaciones : 1 de Agosto de 2006
20
Tema 3: Características básicas del lenguaje Java D.I.G
21
Tema 3: Características básicas del lenguaje Java D.I.G
7. PETICIÓN DE VALORES PRIMITIVOS AL USUARIO
En Java la entrada (lectura) de datos se realiza mediante un flujo de entrada. Para la lectura de
datos desde teclado, dispone (desde la versión 5.0) de la clase Scanner.
Java proporciona un flujo para la entrada predeterminada llamado System.in que el sistema
abre al empezar la ejecución del programa. Este flujo lee, por defecto, del teclado.
En el ejemplo 3.8 se muestra un programa en Java que pide al usuario los datos del radio y la altura de
un cilindro, y calcula su volumen.
import java.util.Scanner;
public class PedirDatos{
public static void main (String[] args){
//El valor del número pi
final double PI= 3,1415923536;
double radio;
double altura;
Scanner teclado = new Scanner (System.in);
System.out.println(“Introduzca los datos del cilindro: “);
System.out.println(“Radio: “);
/* Espera a que el usuario escriba algo en el teclado y pulse la tecla de reotrno.
En ese momento convierte lo leído en un valor del tipo double y lo guarda en la
variable radio */
radio = teclado.nextDouble();
System.out.println(“Altura: “);
altura = teclado.netDouble();
System.out.println(“El área del cilindro es: “);
System.out.println(PI*radio*radio*altura);
}
}
Ejemplo 3.8: Cálculo del área de un cilindro solicitando los datos al usuario
22
Tema 3: Características básicas del lenguaje Java D.I.G
La siguiente tabla muestra los métodos para la lectura de distintos tipo de datos:
Tipo Método a invocar
byte teclado.nextByte();
short teclado.nextShort();
int teclado.nextInt();
long teclado.nextLong();
float teclado.nextFloat();
double teclado.nextDouble();
boolean teclado.nextBoolean();
23