Tema 3: Características básicas del lenguaje Java

D.I.G

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 Objective­C 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 (just­in­time ) 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 envoltorios, los tipos enumerados, etc.

D.I.G

6.0 (2007) Es la versión actual.

Como ya se ha mencionado, Ja va 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 cada fichero .java  pueden definirse varias clases, pero sólo una puede ser pública.

D.I.G

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 pseudo­aleatorios (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 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:

D.I.G

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 La orden para compilar el programa HolaMundo.java es: javac HolaMundo.java

D.I.G

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 estudiando con algo más de detalle sus componentes básicos: variables, literales y operadores.

D.I.G

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át cas están definidas sobre estos tipos. Por  i 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  long  56 , 0123 , 0xaf 8456l , 33456L

10

Tema 3: Características básicas del lenguaje Java double  float  char  boolean  4.66 , 23.7e3 , 35.213d , 23.2D 67.345f , 34.122F , 21.34e2f ’a’ , ’$’ , ’ t ’  , ’u0061’ true , false

D.I.G

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 Conversiones implícitas

D.I.G

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 float n = ( float ) 432.5;

D.I.G

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 sigu iente: int contador = 0 , máximo ; Una variable se puede declarar como constante precediendo su declaración  on la etiqueta  c 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 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).

en todo el bloque 1);

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 pseudo­variable 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 def ecto son las siguiente:                                              tipo    Valor inicial por defecto     boolean  char  byte, short, int, long  float  double  referencia a objeto  false ’\0’ 0 +0.0f +0.0 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 conocid os, 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  3 * 5 + x += 7.3  ’a’ <= 45 y *= x += 7.3 Las expresiones simples se pueden combinar dando lugar a expresiones compuestas.

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 suf icientes 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 comu nes.

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 System.out.println( ”Hoy comemos judías . ” ) ; break ; case Viernes : System.out.println( ”Hoy comemos puchero . ” ) ; break ; default : System.out.println( ”Hoy no comemos. ” ) ; }

D.I.G

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 cues tiones 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 muestra en pantalla Lunes Martes Miércoles Jueves Viernes Sábado Domingo

D.I.G

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 La siguiente tabla muestra los métodos para la lectura de distintos tipo de datos: Tipo byte short int long float double boolean Método a invocar teclado.nextByte(); teclado.nextShort(); teclado.nextInt(); teclado.nextLong(); teclado.nextFloat(); teclado.nextDouble(); teclado.nextBoolean();

D.I.G

23

Sign up to vote on this title
UsefulNot useful