0% encontró este documento útil (0 votos)
15 vistas105 páginas

1DAM PROG U02 Primeros Pasos en Java

Cargado por

Grace
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
15 vistas105 páginas

1DAM PROG U02 Primeros Pasos en Java

Cargado por

Grace
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 105

UNIDAD 2

PRIMEROS PASOS
EN
JAVA

PROGRAMACIÓN
IES Serra Perenxisa
1DAM
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

UNIDAD 2: TABLA DE CONTENIDOS


1. VERSIONES DE JAVA.
2. INSTALAR EL ENTORNO DE DESARROLLO.
3. PRIMEROS PROGRAMAS EN JAVA.
3.1. Cosas A Tener En Cuenta.
3.2. Analizar un Programa Sencillo.
3.3. Compilar y Ejecutar Desde la Línea de Comandos.
3.4. Herramienta JavaDoc.
3.5. Paquetes y Sentencia import.
4. ELEMENTOS DE UN PROGRAMA.
4.1. Identificadores.
4.2. Datos: Variables y constantes.
4.3. Tipos de Datos: primitivos y objetos.
4.4. Conversión de Tipos (casting).
4.5. Operadores y precedencia.
5. CLASES Y OBJETOS DE FÁBRICA.
5.1. Algunas clases y objetos de uso Habitual.
5.2. Introducción a las enumeraciones.
6. ENTRADA Y SALIDA DE DATOS.
7. SENTENCIAS DE DECISIÓN.
7.1. Decisión Simple (if-else).
7.2. Decisión Múltiple (switch).
8. EJERCICIOS.

BIBLIOGRAFÍA:
- Java, Cómo Programar (10ª Ed.).
Pearson. Paul Deitel (2016).
- Introduction to Programming Using Java (7ªEd).
David J. Eck (2014)
- Documentación oficial de Java, Oracle.

2/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

2.1. VERSIONES DE JAVA.


Recuerda que para "crear" programas en Java necesitamos el programa
que realiza la traducción a bytecodes (el compilador) y para ejecutarlos
necesitamos el que realiza la interpretación (la JVM).
Hay entornos (kits de desarrollo) que permiten la creación de los
bytecodes y que incluyen herramientas con capacidad de desarrollar y
ejecutar aplicaciones Java. El más popular (además es gratuito y libre de
usar hasta la versión 17) es el Java Developer Kit (JDK) (antes de Sun,
ahora de Oracle), que se encuentra disponible en este enlace. Se le llama
SDK (Software Developer Kit) y al descargarlo de Internet hay que elegir
la plataforma deseada (SE, EE o ME, ...).
Si solamente quieres ejecutar programas Java pero no desarrollarlos
solamente necesitas el entorno de ejecución (JRE: Java Run Environment).
Para poder crear los bytecodes de un programa Java, hace falta el SDK.
Sin embargo este kit va evolucionando: se actualiza el lenguaje Java, el
compilador y las herramientas de apoyo como las máquinas virtuales, etc.
De ahí que se hable de Java 1.1, Java 1.2, etc. Los nombres de los distintos
SDK y del lenguaje correspondiente.

Figura 1: Dukes con enlaces a JDK SE.


(izq.) Versiones de Oracle. (der.) Versiones de OpenJDK.

Las primeras versiones de Java han cumplido más de 20 años. Hemos


pasado de la versión 1.0 a la 1.19. Cada nueva versión incluye mejoras o
ampliaciones de:

3/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• El lengaje java: se añaden elementos.


• Las herramientas: compilador, intérprete, generadores de
documentación, etc.
• Las librerías de clases (las API): se añaden nuevas o se mejoran
las existentes, se eliminan otras, etc.

OpenJDK es una versión de Java gratuita y distribuible sin licencia,


mantenida por la comunidad, con dos sabores: Licencia GNU y licencia
GAL (Oracle) (https://jdk.java.net/).

2.2. INSTALAR EL ENTORNO DE DESARROLLO.


El JDK puede descargarse e instalarse en muchos sistemas operativos de
ordenadores y dispositivos. Veremos como hacerlo en los dos sistemas
operativos (SO) más usados para PC. Puedes descargar los instalables del
JDK SE desde la página Java Downloads | Oracle

Figura 2: Página de descarga del SDK de Oracle.

EN MICROSOFT WINDOWS
Desde la página de descarga, se elige la versión deseada del JDK. Una vez
descargado el programa de instalación basta con ejecutarlo.
Hay que prestar atención al directorio en el que se ha instalado. La razón
es que a veces debemos modificar 3 variables del sistema (variables que

4/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

utiliza Windows) para ejecutar desde el sistema (al margen de un IDE) los
programas. Aunque algunas veces los instalables utilizan el registro de
Windows en lugar de las variables de entorno, no está mal dejarlas
configuradas. Estas 3 variables son:
PATH
Contiene rutas por defecto donde el SO busca programas que se piden
ejecutar. Hay que incluir donde están los programas del JDK porque si
queremos usar por ejemplo javac (el compilador de java) debe estar
disponible desde cualquier carpeta. Ese programa y el resto de programas
del JDK están en la carpeta bin, dentro de la carpeta donde se haya
instalado el JDK.
Si por ejemplo, al instalar el JDK SE 12, decido
instalarlo en d:\java\jdk12, debo añadir a lo
que tenía antes en la variable PATH la ruta: d:\
java\jdk12\bin. Ejemplo de cambio del
contenido de la variable path:
(1) Escribir en la caja de búsqueda variables
de entorno, aparece una opción en el
menú Editar las variables de entorno del
sistema. Al hacer clic aparece la ventana
siguiente.
(1)
(2) Pulsar el botón Variables de entorno.

(2)

5/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

(3) En el diálogo aparecen dos listas, la primera afecta solo al usuario


actual. La segunda afecta a todos los usuarios (al sistema). En la
segunda lista (la del sistema), marcas la variable a cambiar (Path
en este caso) y se pulsa el botón Editar.

(3)

(4)
(4) Ahora creas/modificas la entrada y si hay una anterior la subes o
borras para que tenga efecto la última.

(4) (4)

(4)

6/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Nota: Hasta que no reinicies, los cambios no tienen efecto.


Nota: Puedes comprobar el valor ejecutando desde cmd: echo %PATH%
Nota: Puedes modificar temporalmente (el cambio desaparece al cerrar la
ventana) el valor de PATH si no quieres reiniciar el sistema, para
añadirle una nueva ruta, ejecutando en una ventana de comandos:
set PATH=%PATH%;nueva_ruta

JAVA_HOME
Variable utilizada por la mayoría de aplicaciones basadas en Java que
contiene la ruta a la carpeta en la que se instaló el SDK. Por ejemplo,
debería contener el valor d:\java\jdk12\ en este ejemplo.

CLASSPATH
Es una variable similar al PATH que sirve para indicar rutas a las carpetas
en las que debe buscar clases que use un programa Java. Debería contener
como mínimo la carpeta raíz del SDK y la carpeta actual que se expresa
mediante el carácter punto (.).

7/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

EN GNU/LINUX
Para conocer si hay una versión instalada habría que ejecutar el comando
java –-version. Si deseamos instalar Java o actualizarlo, hay varias
opciones.
• La primera es utilizar el gestor de paquetes para descargar la
última versión del paquete jdk. O también podemos instalar desde
la línea de comandos, sería algo como:
sudo apt-get update
sudo apt-get install default-jdk
sudo apt-get install default-jre
# Si queremos una versión concreta, por ejemplo la 19:
sudo apt-get install openjdk-19-jdk

• Otra opción es acudir a una página de descargas de los JDK y


descargarnos el instalable del SDK que queramos
(.deb, .rpm, .tar.gz). El archivo hay que descomprimirlo (si es
un .tar.gz) o ejecutarlo (si es rpm o .deb). Se crea un directorio con
todo el SDK de Java.

Nota: lo que instalas suele quedarse dentro del directorio


/usr/lib/jvm/nombre_del_SDK.

• Otra opción es dar de alta los repositorios donde se cuelgan los


instalables y descargarlos desde ahí. También podemos tener
varias versiones de JDK instaladas a la vez, o si queremos instalar
una versión oficial de Oracle (necesita que aceptes la licencia de
uso) ejecutar el instalable no será suficiente, así que te indico como
hacerlo en el ejemplo 1.
EJEMPLO 1: Instalar varios JDK o SDK desde repositorios en
GNU/Linux (solo hasta JDK 17 LTS): Imagina que tenemos el OpenJDK 11
instalado y queremos tener también el JDK 17 de Oracle. Si descargas y ejecutas
el bin de Oracle lo mejor que puede pasar es que se copien los ficheros a la
carpeta /usr/lib pero no podrás usarlo, por eso os paso esta pequeña guía.
PASO 1. Abrimos un terminal y ejecutamos:

8/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

sudo add-apt-repository ppa:linuxuprising/java

PASO 2: instalamos descargando el paquete desde el repositorio.


sudo apt-get update
sudo apt-get install oracle-java17-installer-local

Debemos aceptar las condiciones de uso de Oracle.


CAMBIAR EL JDK QUE QUEREMOS USAR
Para ver los JDK que disponemos en el sistema:
update-java-alternatives --list

Para cambiar al que queremos usar actualmente desde el sistema:


sudo update-java-alternatives --set /path/to/java/version
Donde /path/to/java/version es la ruta a uno de los que tenemos
instalados como pe. /usr/lib/jvm/java-1.11.0-openjdk-amd64
En todo caso, sea cual sea la forma de instalar el SDK, si vas a usar los
programas desde la línea de comandos habrá que modificar las 3 variables
de entorno si el instalador no lo hace (lo sabrás porque no te encontrará
programas o clases). Para conseguirlo puedes modificar el fichero
/etc/bash.bashrc y al final añadir las siguientes entradas:
• export JAVA_HOME="ruta al SDK de Java" La ruta podría ser algo
como /usr/lib/jvm/jdk-19.0.1
• export PATH="$PATH:$JAVA_HOME/bin" para definir la variable que
indica al sistema donde debe buscar ejecutables.
• export CLASSPATH="rutas a los directorios en los que se
almacenarán programas en Java" . Es conveniente incluir el directorio
raíz del SDK que quieras usar y el directorio actual. Así que por
ejemplo, una posible opción sería usar este comando: export
CLASSPATH="$JAVA_HOME:."

Para probar que todo ha ido bien, tanto en Windows (ejecutar cmd) como
en GNU/Linux (ejecutar teminal) puedes abrir una consola (ventana de

9/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

comandos) y usar los comandos java -version y javac

Figura 3: Comprobando la versión de java.

DOCUMENTACIÓN DEL JDK


En la página de Oracle puedes acceder a la documentación oficial de
varios SDK. Lo más interesante es la documentación del API de Java
(clases estándar de Java) para consultar dudas específicas. También podéis
aprovecharos de tutoriales disponibles porque los hay de distintos niveles:
básicos, intermedios y específicos. La única pega es que no hay
documentación en castellano. Otra posibilidad es descargarse la
documentación en un archivo zip. De esta forma no dependes de la
conexión a Internet para consultarla.

2.3. PRIMEROS PROGRAMAS EN JAVA.


Con el SDK ya instalando y funcionando, ya tenemos todo lo necesario
para hacer programas usando el lenguaje Java.
2.3.1. COSAS A TENER EN CUENTA.
El código fuente de un programa Java se escribe en documentos de texto
con extensión .java. Para escribirlo basta cualquier editor de texto como el
bloc de notas de Windows o nano o gedit de Linux.
Nota: si usas el bloc de notas de Windows, recuerda que al guardar debes
quitar la opción Documentos de texto (*.txt) o si no, añade .txt al final
del fichero. En la figura el fichero se llamará ejemplo.java.txt y eso te
puede confundirte.

10/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Figura 4: Error al dar nombre en el bloc de notas.

Nota: En el caso de Windows es prefereible que uses otros editores más


enfocados a programar como por ejemplo: notepad++, sublime, etc. Y lo
ideal es usar un IDE como visual studio code, NetBeans, Eclipse, Intellij
Idea, etc. En el caso de Linux, sus editores de serie son bastante potables
para hacer pequeños programas de la mayoría de lenguajes.
Al ser Java un lenguaje multiplataforma y pensado para su integración en
redes, la codificación de texto utiliza UTF-8, lo que implica que los
programadores de lenguas romances (castellano, valenciano, francés, etc.)
podemos utilizar símbolos de nuestra lengua como la eñe o las vocales con
tildes o diéresis o la c trencada cuando damos nombre a los
identificadores de un programa. Pero no es aconsejable hacerlo.
Otros detalles importantes que debes recordar:
• Java es case sensitive: al igual que otros lenguajes como C, C++ y
C#, en Java se diferencia entre mayúsculas y minúsculas y por
tanto las palabras if o porCentaje no son las mismas que If y
porcentaje.
• Sentencias acaban en punto y coma. Cada sentencia del lenguaje
termina con un carácter punto y coma (;). No son obligatorias
detrás de un final de bloque: }
• Escritura libre: Una instrucción puede extenderse más de una
línea. Además se pueden dejar espacios y tabuladores a la
izquierda e incluso en el interior de la instrucción para separar los
elementos de la misma. Pese a que la escritura es libre, siempre
hay unos hábitos o convenciones que se han demostrado

11/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

ventajosos y que los programadores de cada lenguaje se esfuerzan


en respetar. Con idendependencia del lenguaje, estos hábitos son
muy recomendables:
◦ Indentar código.
◦ Comentarlo.
◦ No apelotonar elementos de cada sentencia (espaciar).
El motivo es que se escriben programas fuente más fáciles de leer,
entender y cambiar si es necesario.
• Los comentarios en Java: en Java hay comentarios de una línea y
de varias líneas. Si son de una línea deben comenzar con doble
barra (//) y todo lo que sigue hasta el final de la línea es ignorado
por el traductor. Si ocupan más de una línea deben comenzar con
/* y terminar con */. Ejemplo de comentarios:
/* Comentario
de varias líneas */

// Comentario de una línea

• Java usa bloques de sentencias: En Java hay sentencias simples y


sentencias compuestas (formadas por una o más sentencias
simples). La forma de indicar donde comienza y acaba un grupo
de sentencias es mediante las llaves quebradas:
◦ Comienza un grupo: {
◦ Acaba un grupo: }
EJEMPLO 2: Un bloque de sentencias:
sentencias antes del bloque
{
sentencias dentro del bloque
}
sentencias después del bloque

2.3.2. ANALIZAR UN PRIMER PROGRAMA.


Cuando un usuario pide a la máquina virtual de Java que ejecute un
programa, le indica el nombre de la clase que quiere ejecutar (desde línea

12/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

de comandos por ejemplo: java PrimerPrograma.java) y la JVM busca en la


clase un método (subprograma) exactamente igual a este:
public static void main(String[] args) {
// Aquí van las sentencias que compila y ejecuta...
}

La JVM ejecuta las sentencias que tenga este método en el orden en que
estén escritas. Una clase para poder ejecutarse (ser una aplicación) debe
ser pública y contener este método main() que sirve para saber por donde
comenzar a ejecutar.

ANATOMÍA DE UNA CLASE EN JAVA


Vamos a comentar brevemente qué cosas podemos encontrar dentro de
una clase (no forzosamente, pero podrían aparecer):
• Comentarios.
• Declaración de datos globales: de la clase o de cada objeto.
• Código: sentencias encerradas en llaves {}
• Declaración de métodos: de la clase o de sus objetos. Como por
ejemplo el método main: public static void main(String[]args){}
• Declaración de otras clases: clases internas o anidadas.
EJEMPLO 3: Un primer programa. Este código escrito en Java, sirve para
escribir el texto ¡Hola Mundo! en la pantalla. No te preocupes si no
entiendes las cosas, precisamente lo vemos para empezar a entenderlo:
public class PrimerPrograma {
public static void main(String[] args) {
System.out.println("¡Hola Mundo!");
}
}

EJERCICIO 1: escribe el código en un editor de texto. Lo guardas con el


nombre PrimerPrograma.java y lo ejecutas de dos formas:
◦ Primera forma, llamando al intérprete (programa java): la
JVM lo compila al vuelo (pide al compilador que genere sus
bytecodes que no guarda en ningún lugar, sino que los usa
para ejecutarlos) y una vez ejecutado el programa ya no se

13/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

pueden reutilizar una siguiente vez.


◦ Segunda forma, llamar al compilador (programa javac):
compila el fichero .java y genera sus bytecodes que se guardan
en un fichero .class. Luego hay que pedir al intérprete que
ejecute los bytecodes del .class.
Ahora se explican elementos de este primer programa para ir
descubriendo características de Java:
• Java es totalmente orientado a objetos. Eso significa que no puede
haber ni código ni datos fuera de una clase. Un programa fuente
debe crear la clase que contenga el programa. Así que la primera
línea (public class PrimerPrograma) declara el nombre de la clase.
Cuando declaramos una clase, lo primero que ponemos es su cabecera y
luego indicamos donde comienza y acaba con un bloque, por ejemplo:

public class Ejemplo { /* cuerpo de la clase... */ }

La primera palabra (public) es un modificador y nos proporciona la


posibilidad de dar permisos de acceso a la clase. Los permisos a nivel de
clase son los siguientes:
• Modificador public: Una clase "public" es accesible (visible o
utilizable) desde cualquier otra clase, no obstante, para que esto
suceda, debe ser primero accesible el package donde se almacena.
Un package es "una carpeta donde está almacenada la clase" si se
usa la sentencia package nombre; o cualquiera (default package) si no
se usa. Para que un "package" sea accesible, debe de estar dentro del
directorio que señala la variable "CLASSPATH" que definimos al
instalar nuestro entorno Java y claro está, tener permisos de lectura
en ese directorio/carpeta. También podemos aportar esas
indicaciones cuando llamamos al intérprete o al compilador desde
la línea de comandos pasándoles parámetros.
• Modificador package: Usar este modificador en la cabecera de una
clase es opcional, pues es la opción por defecto, es decir, si no
escribes public, es como indicar package. Ejemplo:

14/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

class Ejemplo { /* cuerpo de la clase... */ }

Es lo mismo que escribir:


package class Ejemplo { /* cuerpo de la clase... */ }

Las clases "package" (las que no son "public") son accesibles solo al
usarlas desde su propio package, no desde fuera.
También hay otras implicaciones: si la clase es public, el fichero debe
llamarse como ella (por tanto, como consecuencia, solo puede haber una
clase pública en cada fichero .java).
Nota: el nombre de la clase pública del programa y el nombre del fichero
donde se almacena deben coincidir, de lo contrario, dará error al compilar
cuando tengamos aplicaciones formadas por más de una clase.
Resumiendo: haz coincidir el nombre del archivo .java y el nombre de la
clase pública que contiene, tanto en mayúsculas como en minúsculas.

Figura 5: Nombre de clase public y del fichero .java deben coincidir.

Nota: por convención, a las clases se les da nombres que comienzan


en mayúscula. Si el nombre lo forman varias palabras, la inicial de cada
palabra comienza también en mayúscula. Ej: MiPrimerPrograma

• La línea public static void main(String args[]), es la definición o


cabecera de un método (un método es como se conoce a un

15/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

subalgoritmo en orientación a objetos) y se utiliza para indicar


donde debe comenzar a ejecutar sentencias el programa, lo indica
el inicio del método main(). Este método contiene las instrucciones
que se ejecutan cuando el programa arranque. Es decir, lo que está
dentro de las llaves del main(), es lo que comienza a ejecutar el
programa.
• La instrucción System.out.println() es una llamada al método
println() de un objeto que está dentro de la clase System y que se
llama out. La clase System contiene elementos que permiten a un
programa interactuar con el sistema operativo (por ejemplo leer
datos con su objeto in y escribirlos con su objeto out). El método
println(dato) de out sirve para escribir dato en forma de texto (por
defecto en pantalla) y luego saltar de línea. Como le pasamos un
texto, se encierra entre comillas dobles.
ERRORES EN LOS PROGRAMAS.
Durante la creación de un programa, su codificación, su prueba o su
explotación, pueden detectarse errores. Los errores pueden ser:
• Errores en tiempo de compilación (léxicos, sintácticos, ...):
aparecen al utilizar mal las reglas del lenguaje, por ejemplo usar
letras que no son del lenguaje, palabras reservadas mal escritas,
instrucciones incompletas, mal formadas, etc. Estos errores se
detectan durante la fase de compilación, cuando el programa se
traduce del lenguaje de programación de alto nivel a código
máquina o bytecodes en el caso de Java. La herramienta de
traducción nos avisa del error (línea y posible causa), por tanto son
fáciles de detectar y corregir en la mayoría de ocasiones.
• Errores en tiempo de ejecución: Se producen durante la ejecución
del programa porque se realiza una operación no permitida o
porque se da una situación imprevista de la que el programa no se
puede recuperar. Ejemplos: se agota la memoria, se intenta acceder
a un fichero de disco que no existe o no se tienen permisos, no
queda espacio de disco para escribir, cierta operación con el valor
actual de un dato es errónea, se pide hacer un trabajo a un objeto

16/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

inexistente, etc. El compilador no detecta este tipo de errores al


traducir y en general, son más difíciles de detectar (no aparecen
siempre) y corregir (aunque los lenguajes modernos implementan
mecanismos de autoprotección que se llaman excepciones y que
permiten controlarlos cuando aparecen).
• Errores lógicos: El programa no produce error, ni durante la
compilación ni durante su ejecución. Simplemente, bajo ciertas
condiciones no produce el resultado correcto que se espera. Son los
más complicados de solucionar porque debes investigar la causa
que hace que se produzcan, y muchas veces no es trivial. Los IDES
y el propio lenguaje nos dan herramientas como depuradores
(debuggers), registradores (loggers), sistemas de prueba
sistemática (como JUnit) etc. para automatizar la realización de
trazas y rastrear, encontrar y solucionar los fallos.
2.3.3. COMPILAR Y EJECUTAR EN LÍNEA DE COMANDOS.
La compilación del código java se realiza mediante el programa javac
incluido en el SDK. La forma básica de compilar es (desde la línea de
comandos):
javac Archivo.java
El resultado de esto es un archivo con el mismo nombre que el archivo
java pero con la extensión .class. Esto ya es el archivo de bytecodes. Es
decir, el código precompilado.
El programa es ejecutable si contiene el método main() y el código se puede
interpretar usando el programa java del kit de desarrollo (que se
encuentra en el mismo sitio que javac) o el JRE. Sintaxis:
java Archivo.class // El intérprete usa el .class
java Archivo.java // java llama a javac que genera los bytecodes
java Archivo // Si el .class ya está generado

Estos comandos hay que escribirlos desde la línea de comandos en la


carpeta en la que se encuentre el programa. Pero antes hay que asegurarse
de que los programas del JDK son accesibles desde cualquier carpeta del
sistema (configurar las variables del sistema).

17/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

En el caso de GNU/Linux hay que ser especialmente cuidadoso con la


variable de sistema CLASSPATH y asegurarnos de que contiene en sus
rutas raíces de Java el símbolo "." (punto) que representa a la carpeta
actual. De otro modo la ejecución del comando java podría fallar.
Nota: Para cada nuevo programa que hagamos, es conveniente crear una
carpeta nueva y dejar sus ficheros dentro. Esta carpeta hará de package de
las clases.
EJEMPLO 4: En
Windows, crea el
siguiente programa
en un editor y lo
guardas en la carpeta
ejemplo201. Luego lo
compilas, miras los
ficheros generados y
lo ejecutas.

18/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

EJEMPLO 5: Haz lo mismo en GNU/Linux pero crea la carpeta


~/java/ejemplo202.

2.3.4. HERRAMIENTA JAVADOC.


Javadoc es una herramienta muy interesante del SDK para generar
automáticamente documentación de los programas Java. Genera
documentación para paquetes completos o para archivos java. Su sintaxis
básica es:
javadoc Archivo.java
javadoc paquete

El funcionamiento es el siguiente: Los comentarios que comienzan con las


letras /** se llaman comentarios de documento y serán utilizados por
javadoc. Terminan con */ y por visualizarlos mejor cada línea suele tener
un * alineado.
Cada línea javadoc se suele iniciar con el símbolo de asterisco para
mejorar su legibilidad. Dentro se puede incluir cualquier texto; incluso se

19/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

pueden utilizar etiquetas HTML para generar la documentación en este


formato. En el código javadoc se pueden usar etiquetas especiales, las
cuales comienzan con el símbolo @. Algunas de ellas:
• @author. Tras esa palabra se indica el autor del código. Para que
aparezca hay que indicarlo en la llamada a la herramienta, igual
que la versión: javadoc -author -version fichero.java
• @version. Le sigue el número de versión para documentar cuando
se hizo checkout del sistema de control de versiones.
• @see. Tras esta palabra se indica una referencia o enlace a otro
código o clase Java relacionado con éste.
• @since. Indica desde cuándo esta disponible este código.
• @deprecated. Palabra a la que no sigue ningún otro texto en la
línea y que indica que esta clase/método es obsoleta/obsoleto.
• @throws y @Exception Indican cada excepción que puede lanzar
el método.
• @param. Describe a los parámetros que requiere un método para su
utilización. Cada parámetro tiene su propia anotación @param.
• @return. Tras esta palabra se describe los valores que devuelve el
código (el código en este caso es un método de clase)
• {@code} incluye en el comentario un trozo de código que se
formatea de forma especial.
• {@docRoot}: incluye una ruta relativa al directorio raíz donde se
genera la documentación.
• {@inheritDoc}: hereda el comentario Javadoc de la clase o método
superior en la jerarquía de clases.
• {@link} y {@linkplain}: incluye un enlace a otra sección de la
documentación, método o clase. En @linkplain el enlace es texto
plano.
• {@literal}: muestra texto sin interpretarlo como HTML.
• @serial, @serialData, @serialField : describe un campo.

20/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• {@value}: muestra el valor de un campo estático.

Los comentarios javadoc hay que colocarlos en tres sitios distintos dentro
del código java de la aplicación:
• Al principio de una clase/interface. En esta zona se colocan
comentarios que describen la clase o interface. Se suelen utilizar las
etiquetas: @author, @version, @see, @since y @deprecated
• Delante de cada método. Los métodos describen las cosas que
puede realizar una clase. Delante de cada método los comentarios
se usan para describir al método en concreto. Además de los
comentarios, en esta zona se pueden incluir las etiquetas: @see,
@param, @exception, @return, @since y @deprecated
• Delante de cada atributo/dato global. Se describe para qué sirve
cada dato en cada clase. Pueden contener las etiquetas: @serial,
@serialData, @serialfield, @value, @deprecated

EJEMPLO 4: Añade al
programa Ejemplo203 los
comentarios javadoc
resaltados en amarillo y
luego usa la herramienta
para generar la
documentación. Luego abre
el documento index.html
generado.
Aparece como resultado la
página web de la página
siguiente.

Figura 2.11: Página de


documentación generada por
javadoc.

21/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

/** <h2>Esto es un comentario para probar javadoc</h2>


* <p>Este texto aparece en el archivo HTML generado.
* <strong>Realizado en agosto 2019</strong></p>
*
* @author José RR
* @version 1.0
*/
public class Ejemplo203 {
// Este comentario no aparece en javadoc
/** <p>Este método contiene el código ejecutable</p>
*
* @param args Lista de argumentos de la línea de comandos
* @return void
*/
public static void main(String[] args){
System.out.println("¡Hola Mundo! ");
}
}

2.3.5. PAQUETES Y SENTENCIA IMPORT.


En cualquier lenguaje de programación existen librerías que contienen
código ya escrito con tareas comunes que agilizan la creación de nuevos
programas. En Java no se llaman librerías sino paquetes.
Los paquetes son carpetas que contienen clases ya preparadas y más
paquetes. Cuando se instala el JDK, además de los programas necesarios
para compilar y ejecutar código Java, se incluyen miles de clases dentro de
cientos de paquetes ya preparados, que facilitan la generación de
programas.
Algunos paquetes sirven para utilizar funciones matemáticas, otros nos
dan utilidades de lectura y escritura, comunicación en red, programación
de gráficos y muchas otras cosas. Por ejemplo la clase System está dentro
del paquete java.lang (paquete básico) y contiene entre otros, el método
out.println() que necesitamos para escribir por pantalla.

Si necesitamos trabajar con fechas, podemos utilizar la clase Date que está
definida en el paquete java.util. Es necesario escribir una instrucción que
permita incorporar el código de la clase Date cuando compilemos nuestro

22/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

programa. Para eso sirve la instrucción import. La sintaxis de esta


instrucción es:
import paquete.subpaquete.subsubpaquete. … .Clase;
import paquete.*;

Las instrucciones import se colocan tras la sentencia package (si la hay) en


la parte de arriba del código fuente. Para la clase Date sería:
import java.util.Date;

Lo que significa: importar en el código la clase Date que se encuentra


dentro del paquete util que a su vez está dentro del paquete java.
También se puede utilizar el asterisco de esta forma:
import java.util.*;

Esto significa que se va a incluir en el código todas las clases que están
dentro del paquete java.util. En realidad no es obligatorio escribir la
palabra import para utilizar una clase, pero sin ella hay que escribir el
nombre completo de la clase. Es decir, no podríamos utilizar el nombre
Date, sino java.util.Date cada vez que queramos usar una fecha.

Nota: si en java.util (donde está Date) hubiese otros subpaquetes dentro


(pe. paquete1), usar * solo importa todas las clases de java.util, no las
clases de java.util.paquete1.

2.4. ELEMENTOS BÁSICOS DE UN PROGRAMA.


2.4.1. IDENTIFICADORES.
Los nombres son fundamentales a la hora de escribir programas. En un
programa, cuando quieres usar una sentencia del lenguaje, debes saber el
nombre que tiene. Además, cuando quieres dar nombre a un dato (una
variable o una constante) o a un método (un trozo de código) o a una
clase, debes usar nombres. Por tanto debes conocer bien las reglas que se
aceptan a la hora de dar nombre a elementos de tus programas.

23/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

A los nombres se les conoce como Identificadores. Un identificador en


Java es una secuencia de uno o más caracteres donde el primer carácter
debe ser una letra o un carácter de subrayado (_) y el resto de caracteres
pueden ser letras, dígitos o más subrayados.
Algunos identificadores están reservados para el lenguaje y no los puedes
usar para otra cosa. Estos identificadores se conocen como palabras
reservadas o palabras clave. En Java hay unas 57 y son las siguientes:
• abstract • final • public
• assert • finally • return
• boolean • float • short
• break • for • static
• byte • goto • strictfp
• case • if • super
• catch • implements • switch
• char • import • synchronized
• class • instanceof • this
• const • int • throw
• continue • interface • throws
• default • long • transient
• do • native • try
• double • new • void
• else • package • volatile
• enum • private • while
• extends • protected
El resto de identificadores puedes usarlos para dar nombre a tus clases,
datos y métodos. Ejemplos de identificadores legales en Java:
N n ratio x15 poco a largo nombre nombreCompleto

No se permiten espacios en blanco, por ejemplo holaMundo es un


identificador legal, pero hola Mundo es ilegal.
Como Java es case sensitive, los identificadores holamundo, holaMundo,
holaMUNDO y HOLAmundo se consideran diferentes.
Java es permisivo en cuanto a las letras que quieras usar porque utiliza
UTF-8, lo que te permite usar letras propias de tu idioma (eñes, c

24/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

trencadas, letras acentuadas, etc.) en tus identificadores. Sin embargo, hay


que intentar evitarlos en las sentencias del programa (no en los mensajes
que ven los usuarios) y ceñirnos a las letras del alfabeto inglés (sustituye
eñes, acentos, c trencadas, etc.).
Además hay convenciones que deberías seguir a la hora de dar nombres a
los elementos que utilices en tus programas. Por ejemplo:
• Usa nombres representativos: si tu programa usa veinte variables
y las llamas v1, v2, v3, v4, .... v19 y v20, cuando pasen 3 días sin
verlo, ni tu mismo, que has escrito el programa, lo comprendes. Si
vas a dar un nombre a un dato, que el nombre permita deducir el
valor que contiene. Si das nombre a un método (que representa
una acción) normalmente el nombre será un verbo que describa lo
que hace o varias palabras. Por ejemplo: doy nombre al método
que me calcula la mitad del número que le paso y lo llamo
mahonesa() ¿Es legal? Sí ¿Es representativo de lo que hace? No. Lo
más práctico es definirlo así: double mitad(int n){...}.
• Primera letra de Clases e Interfaces en mayúscula: cuando des
nombre a una clase, la primera letra debe estar en mayúsculas,
mientras que los nombres de variables y métodos siempre
comienzan con minúsculas.
• Evita los subrayados salvo en datos constantes: la mayoría de
programadores de Java evitan usar subrayados en los nombres.
Salvo al definir constantes sinbólicas usa notación lowerCamel.
• Nombres compuestos: si un nombre tiene varias palabras, la
primera letra de cada una se pone en mayúsculas (menos la
primera si no es el nombre de una clase o una interface). Ej: una
variable que tenga el nombre completo (nombre y apellidos de una
persona) podemos llamarla nombreCompleto.
• Nombres compuestos separados por puntos: el punto es una
operación en Java. Cuando se usa el punto (.) como separador de
nombres, se está indicando que lo de la derecha está contenido en
lo de la izquierda. Por ejemplo ya hemos usado System.out.println(),
esto indica que System contiene algo que se llama out, que a su vez
contiene algo que se llama println(). Es decir, el punto es un

25/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

operador y las palabras izquierda.derecha significan que izquierda


contiene a derecha.
2.4.2. DATOS: CONSTANTES Y VARIABLES.
Los datos con los que trabajan nuestros programas pueden ser constantes
o variables. Los datos constantes no pueden cambiar de valor mientras
que los datos variables en cierto momento pueden tener un valor que más
tarde se cambia a otro valor.
Las constantes pueden ser literales si el valor es literalmente lo que se
escribe en el programa, o simbólicas si le damos un nombre aunque su
valor no pueda cambiar.
Las variables son siempre simbólicas y son contenedores que sirven para
almacenar los datos que utiliza un programa. De forma intuitiva son
nombres que asociamos o damos a determinados datos. La realidad es que
cada variable ocupa un espacio en la memoria RAM del ordenador para
almacenar el dato al que se refiere. Es decir, cuando utilizamos el nombre
de la variable en el programa, realmente estamos usando o haciendo
referencia a la memoria RAM que almacena el valor del dato (pero nos da
igual donde se almacena).
DECLARACIÓN DE VARIABLES
Antes de utilizar una variable, en Java se debe declarar con esta sintaxis:
[modificadores] tipoDeDato nombreDeVariable;
Donde los modificadores son opcionales y por eso los he escrito entre
corchetes rojos: [modificadores] (no porque se deban escribir los
corchetes), tipoDeDato es el tipo de valores que puede almacenar la variable
(texto, números enteros, números con decimales, un valor de verdad, un
carácter, la referencia a un objeto, etc.) y nombreDeVariable es el nombre con
el que se conoce al dato en el programa. Ejemplos:
int dias; // dias es un número entero, sin decimales
boolean casado; // casado sólo puede ser true o false

También se puede hacer que la variable tome un valor inicial al declararla.

26/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Juntamos en una misma sentencia declaración e inicialización (darle un


primer valor). Ejemplo:
int diasEnAny = 365;

Y se puede declarar/inicializar más de una variable a la vez del mismo


tipo en la misma línea si las separamos con comas. Ejemplos:
int dias = 365, anyo = 23, semanas;

Al inicializar una variable se puede incluso utilizar una expresión:


int a = 13, b = 18;
int c = a + b; // es válido, c vale 31

Java es un lenguaje muy estricto al utilizar tipos de datos. Variables de


datos distintos son incompatibles. Algunos autores hablan de lenguajes
fuertemente tipados o lenguajes muy tipificados. El caso contrario sería
el lenguaje C o C++, en los que jamás se comprueban de manera estricta
los tipos de datos. Parte de la seguridad y robustez de Java se deben a esta
característica.
OPERACIÓN DE ASIGNACIÓN (CAMBIAR EL VALOR)
En Java para asignar/cambiar valores a una variable, basta con utilizar el
carácter igual (=) que representa la operación de asignación. La sintaxis
básica es:
identificador = expresión;
A la izquierda del operador va el nombre de una constante (una sola vez)
o variable y a la derecha una expresión que genera un valor que se
almacena en identificador. Ya se ha visto antes que al declarar una
variable se puede asignar un valor:
int x = 7;

Pero la asignación se puede utilizar en cualquier momento (tras haber


declarado la variable). El siguiente código es equivalente al anterior:
int x;
x = 7;

27/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

x = x + 1; // aquí deja de ser equivalente

Como se ve en la última línea anterior, la expresión para dar el valor a la


variable puede ser tan compleja como queramos.
Nota: A diferencia de lenguajes como C, en Java se asigna un valor
inicial a las variables globales. En el caso de los números es el valor cero.
int x; // x ya vale cero, si no es una variable local

CONSTANTES SIMBÓLICAS
Una constante es una variable de sólo lectura. Dicho de otro modo más
correcto, es un dato que no puede cambiar de valor (por lo tanto no es una
variable) o puede cambiar una sola vez (el primer valor que guardes no
cambia). La forma de declarar constantes es la misma que la de declarar
variables, sólo que hay que anteponer la palabra reservada final (un
modificador) que es la que indica que estamos declarando una constante
y por tanto no podremos cambiar su primer valor inicial:
final double PI = 3.141591;
PI = 4; //Error, no podemos cambiar el valor de PI una segunda vez

Nota: los nombres de las constantes simbólicas acostumbran a tener todas


las letras en mayúsculas y usar separadores: _
final double UN_MEDIO = 0.5;

ÁMBITO DE CONSTANTES Y VARIABLES:


Toda variable tiene un ámbito que es la parte del código en la que se
puede utilizar. De hecho las variables tienen un ciclo de vida:
(1) En la declaración se reserva el espacio necesario de memoria
RAM para que se puedan utilizar (se prepara su existencia).
(2) Se inicializa: Se la asigna su primer valor (la variable nace).
(3) Se utiliza en diversas sentencias: se lee, se cambia...
(4) Cuando finaliza la ejecución del bloque en el que fue declarada,
la variable muere. Es decir, se libera la memoria que ocupaba.
Una vez que la variable ha sido eliminada, no se puede utilizar. Dicho de

28/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

otro modo, no se puede utilizar una variable más allá del bloque en el que
ha sido definida. Ejemplo:
{
{
int x= 9;
}
int y = x; // error, ya no existe x -> fuera de su ámbito
}

En Java se dice que una variable es local cuando se declara dentro de un


método (o un bloque de inicialización). Por ejemplo las variables que
declaremos dentro del método main() serán locales. Ejemplo:
public class UnaVariableLocalDemo {
public static void main(String[]args){
int meses = 12; // meses es una variable local
System.out.println("Un año tiene " + meses + " meses");
}
}

EJERCICIO 2: En el siguiente código indica:


a) Variables (o identificadores) mal definidas/usadas y el motivo.
b) Variables locales.
c) Variables globales.
package e1;
import java.util.Date;
Date aniversario;
public class ejercicio1 {
private static final int diasPorSemana = 7;
private static String cuñao = "Jose";
public static void main(String[]args){
int Meses = 12;
int edad;
System.out.println("Mi edad es " + edad);
}
}

2.4.3. TIPOS DE DATOS.

29/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Cualquier dato que se almacene en la RAM del ordenador se representa


en binario (una cadena de ceros y unos). La cantidad mínima de memoria
que un programa puede intercambiar con la memoria RAM suele ser un
byte (8 bits).
Cada tipo de valor tiene unas necesidades de memoria, una
representación interna y una serie de operaciones que se le pueden
aplicar. Esas características las define un tipo de dato. Cuando
declaramos una variable tenemos que avisar de esas características (peso
en bytes, representación y operaciones permitidas) al compilador. En Java
hay unos tipos de datos básicos denominados primitivos que son estos:
• byte: almacena 8 bits que representan un número entero en
formato complemento a 2, entre -128 y 127 inclusive.
• short: pesa 2 bytes (16 bits). Almacenan números enteros en
complemento a 2 con valores entre -32768 y 32767.
• int: pesa 4 bytes (32 bits). Almacena números enteros en
complemento a 2 con valores desde -2147483648 hasta 2147483647.
• long: pesa 8 bytes (64 bits). Almacena números enteros en
complemento a 2 con valores desde -9223372036854775808 hasta
9223372036854775807.
• float: pesa 4 bytes y almacena números con decimales en coma
flotante. El máximo valor que puede almacenar es 10 elevado a 38.
Tiene 7 dígitos significativos (por tanto los números 32.3989231134
y 32.3989234399 son redondeados a 32.398923).
• double: pesa 8 bytes, almacena números con decimales en coma
flotante. El mayor valor es 10 elevado a 308, y tiene 15 dígitos
significativos (el doble de precisión de un float).
• char: pesa 2 bytes y almacena un único carácter como 'A', '*' o un
espacio en blanco: ' ', o la letra de un número: '2'. También tiene
caracteres no imprimibles como tabulador o salto de línea. En
realidad son como enteros, así que '2' – '0' = 2;
• Boolean: pesa 1 byte y almacena los valores true y false.

30/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

En la siguiente figura aparecen en forma de esquema todos los tipos de


datos que pueden utilizarse en Java. Si eres observador, verás que en el
esquema, a parte de los tipos primitivos aparecen tipos clase y dentro de
estos, abajo hay un apartado con tipos envoltorio o wrapper que contiene
clases con nombres similares a los tipos primitivos (pero la primera letra
en mayúsculas), vamos a aclarar distintas cuestiones sobre el esquema.
Un objeto es una cosa distinta a un tipo primitivo, aunque
almacene la misma información. Hay que tener siempre presente
que aunque contengan la misma información no significa en
ningún caso que sean lo mismo.

Enteros: byte, short, int, long


PRIMITIVOS
Indican: bits, Números
formato y Con decimales: float, double
operaciones que
pueden realizarse Caracteres: char

Booleanos: boolean
Cadenas de texto:
String, StringBuilder,
StringBuffer
TIPOS
Números: BigInteger,
DE Datos: BigDecimal, Number…
DATOS
Tiempo: Date, Calendar,
EN Biblioteca
LocalDate, LocalTime, …
JAVA estándar
Otros: …
Colecciones de Datos: List,
CLASES Set, Map…
Pueden tener datos
primitivos, permiten Otros: Scanner, Thread, …
fabricar Objetos que
Son algo Array: vectores y tablas. No tienen métodos!!
complejo (tienen
datos y código), hay Wrappers: Byte, Short, Integer,
Long, Float, Double,
que crearlos con Character, Boolean
new, usan
referencias… Definidas por los programadores

31/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Figura 6: Esquema de tipos de datos de Java.

Nota: no intentes memorizar ni el esquema ni los detalles de cada tipo


de dato. Basta con que te quedes con los nombres y la idea de que según
los datos con que quieras trabajar, debes usar unos u otros. Es algo que
irás interiorizando poco a poco.
De momento, recuerda que el tipo primitivo es algo elemental y el
objeto es algo más complejo. Imagina una cesta de manzanas en la
calle (algo elemental). Imagina las mismas manzanas dentro de
una nave espacial (algo complejo). El contenido es el mismo
(manzanas), pero no es lo mismo una cesta de mimbre que una
nave espacial.
¿Para qué tener esa aparente duplicidad entre tipos primitivos y
tipos envoltorio? Tened en cuenta una cosa: un tipo primitivo es
un dato elemental, mientras que un objeto es algo complejo que
además de datos, dispone de métodos (código que puede realizar
trabajos). Es posible que necesitemos utilizar dentro de un
programa un objeto que “almacene” como contenido un número
entero. Desde el momento en que sea necesario un objeto,
tendremos que pensar en un envoltorio, por ejemplo Integer.
Inicialmente nos puede costar un poco distinguir cuándo usar un
tipo primitivo y cuándo un envoltorio en situaciones en las que
ambos sean adecuados. Seguiremos esta regla: usaremos por
norma general tipos primitivos a no ser que sea necesario un
objeto.
Es decir, si somos caperucita roja y vamos a llevar manzanas de
merienda a nuestra abuelita, podemos usar una nave espacial o
una cesta de mimbre para trasportarlas, pero no tiene mucho
sentido fardar de nave. Salvo que nuestra abuela viva en marte,
usaremos la cesta.
Los nombres de tipos primitivos y envoltorio se parecen mucho.
En realidad, excepto entre int e Integer y char y Character, la

32/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

diferencia se limita a que en un caso la inicial es minúscula (por


ejemplo double) y en el otro es mayúscula (Double). Esa similitud
puede confundirnos inicialmente, pero hemos de tener muy claro
qué es cada tipo y cuándo utilizarlo y que en Java solo las clases
comienzan en mayúscula.
Una cadena de caracteres es un objeto. El tipo String en Java nos permite
crear objetos que contienen texto (palabras, frases, párrafos, documentos,
etc.). El texto debe ir siempre entre comillas dobles. Muchas veces se cree
erróneamente que el tipo String es un tipo primitivo por analogía con
otros lenguajes. En Java no es así, siempre es un objeto. ¿Cuántos tipos de
objetos de la biblioteca estándar de Java hay? Cientos o miles. Es
imposible conocerlos todos. ¿Un array es un objeto? Los arrays los
consideraremos objetos especiales, los únicos objetos en Java que no
tienen métodos.
Ahora veremos un poco en detalle los tipos de datos que más vamos a
usar en nuestros programas.

NÚMEROS ENTEROS
Los tipos byte, short, int y long sirven para almacenar datos numéricos
enteros (sin decimales) tanto positivos como negativos. Se pueden utilizar
constantes literales enteras escritas en decimal, o bien en binario o en octal
o en hexadecimal. Los valores binarios se prefijan con un cero y una b (0b
ó 0B), los octales se indican anteponiendo un cero a la izquierda del
número (012), los hexadecimales anteponiendo un cero a la izquierda y
una letra equis (0x). Ejemplos:
int numero = 16; // 16 en decimal
numero = 0b10000; // 16 en binario
numero = 020; // 16 en octal
numero = 0x10; // 16 en hexadecimal

Por defecto un valor entero escrito de forma literal se entiende que es de


tipo int salvo si al final se le coloca la letra L, y en ese caso se entenderá
que es de tipo long. Ejemplo: 7L (7 de tipo long)

33/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Por último, decir que se puede usar el carácter subrallado para separar
grupos de dígitos en los valores numéricos y hacerlos más entendibles:
int numero = 0b1000_0011; // 130 en binario
numero = 700_000; // setecientos mil +fácil leer que 700000

No se acepta, en general, asignar variables de distinto tipo. Sí se pueden


asignar valores de variables enteras a variables enteras de un tipo superior
(por ejemplo asignar un valor int a una variable long). Pero al revés no se
puede:
int i = 12;
byte b = i; //Error de compilación, posible pérdida de información

La solución es hacer una operación de casting (conversión forzosa) o


cast. Esta operación permite convertir valores de un tipo a otro. Se usa así:
int i = 12;
byte b = (byte) i; // El (cast) evita el error

Hay que tener en cuenta en estos castings que si el valor asignado


sobrepasa la capacidad de donde se va a guardar, el valor convertido no
tendrá ningún sentido ya que no puede almacenar todos los bits
necesarios para representar ese número. Ejemplo: ¿Qué valor tendrá b?
int i = 1200;
byte b = (byte) i; // El valor de b no tiene sentido, pierde bits

NÚMEROS EN COMA FLOTANTE


Los valores numéricos con decimales se almacenan en los tipos primitivos
float y double. Se les llama de coma flotante por como son almacenados
por el ordenador. Los decimales no son almacenados de forma exacta, por
eso siempre hay un posible error. En los decimales de coma flotante se
habla, por tanto de precisión. Es mucho más preciso el tipo double que el
tipo float. Para escribir valores literales con decimales en el código del
programa, hay que tener en cuenta que el separador decimal es el punto y
no la coma. Es decir para asignar el valor 2,75 a la variable x se haría:
x = 2.75;

34/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

A un valor literal (como 1.5 por ejemplo), se le puede indicar con una f al
final del número que es float (1.5f por ejemplo) o una d para indicar que es
double. Si no se indica nada, un número literal con decimales siempre se
entiende que es double, por lo que al usar tipos float hay que convertir los
literales. Se pueden representar en notación científica:
significaría 1,345 x 103 o lo que es lo mismo 1345. Lógicamente no
1.345E+3
podemos asignar valores decimales a tipos de datos enteros:
int x = 9.5; // error. Sí podremos mediante un casting
int x = (int) 9.5; // pero perdemos los decimales (x vale 9)

El caso contrario sin embargo sí se puede hacer:


int x = 9;
double y = x; //correcto, y = 9.0

Nota: Al declarar variables globales de tipo primitivo numérico del tipo


que sea, si no se indican valores iniciales, Java asigna el valor cero de
manera automática. No a las variables locales.
BOOLEANOS
Los valores booleanos (o lógicos) sirven para indicar si algo es verdadero
(true) o falso (false). Si al declarar una variable global booleana no se le da
un valor inicial, su valor inicial por defecto es false. Por otro lado, a
diferencia del lenguaje C, no se pueden en Java asignar números a una
variable booleana (en C, el valor false se asocia al número 0 y cualquier
valor distinto de cero se asocia a true). Tampoco tiene sentido intentar
asignar valores de otros tipos de datos a variables booleanas mediante
casting. Ejemplos:
boolean soyDelMadrid; // Valor inicial false si es global
boolean b = true; // Verdadero
boolean c = 5 > 9; // false
boolean d = (boolean) 9; // Error. No tiene sentido en Java

CARACTERES
Los valores de tipo carácter sirven para almacenar símbolos de escritura
(en Java se puede almacenar cualquier código Unicode). Los valores

35/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Unicode son los que Java utiliza para los caracteres. Ejemplo:
char letra;
letra = 'C'; // Los valores char van entre comillas, pero son int
letra = 67; // El código Unicode de la C es el 67. Hace lo mismo

También hay una serie de caracteres especiales que van precedidos por el
símbolo contrabarra (barra a la izquierda: \), que sirve para escapar del
significado normal de la letra que le sigue. Son los que aparecen en esta
tabla:

EJERCICIO 3: Crea un programa que declare e inicialice datos para


trabajar con: tu nombre, tu edad, tu cif, tu altura en centímetros, tu peso
en Kg, la letra inicial de tu nombre y si eres vegano usando variables
locales. Después imprime por consola esos datos.
2.4.4. CONVERSIÓN DE TIPOS AUTOMÁTICA Y CASTING
Cuando es necesario, Java cambia el tipo de dato de un valor, lo
transforma de su tipo actual a otro tipo que tenga más capacidad (más
grande) para poder realizar una operación. Es decir, si sumas por ejemplo
un int y un double, el resultado es un double porque transforma el valor
entero a decimal para sumar decimales (1.0 equivale a 1, pero 2.5 no
equivale a 2, pierde información, por eso cambia los tipos al mayor que
interviene en la operación). Ejemplo:
int x = 4;

36/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

double u = 8.0;
double w = x; // Para poder guardarlo, transforma 4 en 4.0
double z = x + y; // Para sumar transforma 4 (valor de x) en 4.0

Pero de forma automática nunca realiza cambios de un tipo más grande


(más bits) a otro más pequeño (menos bits) porque eso supone perder
información. A modo de resumen, la siguiente figura muestra mediante
flechas azules las conversiones automáticas entre tipos primitivos, que no
dan problemas y con flechas rojas las que pueden significar pérdidas de
información pero son posibles. Esas y las que no están en la figura
necesitan casting.

Figura 7: Resumen de Conversiones Automáticas de Tipos primitivos.

Ya se ha comentado anteriormente la necesidad de usar el operador de


casting para realizar asignaciones entre tipos distintos. Consiste en poner
delante de una expresión el nombre del nuevo tipo de datos encerrado
entre paréntesis y eso significa que quieres convertir o transformar el
valor de la derecha en ese tipo de dato. Ejemplos:
int a;
byte b = 12;
a = b;

El código anterior es correcto porque un dato de tipo byte es más pequeño


que uno int y Java lo convertirá de forma implícita. Lo mismo pasa de int
a double por ejemplo. Sin embargo en este caso:
int a = 1;
byte b;

37/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

b = a;

El compilador devolverá error aunque el valor 1 sea válido para un dato


byte. El compilador no se fija en el valor de ese momento (solo lo podría
hacer en tiempo de ejecución), se fija en el tipo de dato. Para evitar el error
el programador debe hacer un casting (un cambio de tipo explícito):
int a = 1;
byte b;
b = (byte) a; // Ok, el casting convierte en byte el valor de a

En el siguiente ejemplo:
byte n1 = 100, n2 = 100, n3;
n3 = n1 * n2 / 100;

Aunque el resultado es 100 y ese valor es compatible con un tipo byte, lo


que ocurrirá en realidad es un error. Se debe a que la multiplicación 100 *
100 da como resultado 10000, es decir un número de tipo int. Aunque luego
se divide entre el entero 100, no se vuelve a convertir a byte, ya que en
cualquier operación, el tipo resultante siempre se corresponde con el tipo
más grande que interviene en la operación. Lo correcto:
n3 = (byte) (n1 * n2 / 100);

Los castings también se usan con clases, pero deben de realizarse entre
clases compatibles. Es una forma de utilizar el polimorfismo de la
orientación a objetos. Por ejemplo:
String s = (String)(new StringBuilder("Hola"));// Ok, compatibles
Date f = (Date) new BigDecimal("2"); // Error:clases incompatibles

EJERCICIO 4: Crea un programa que declare e inicialice las notas enteras


de las 3 evaluaciones de un alumno y declare su media, la inicialice y la
imprima (con decimales). Intenta calcularla sin usar casting y usando
casting.
De la misma forma, no podemos aplicar casting a tipos de datos que no
sean lo mismo. Es decir, podemos cambiar un número ( double por
ejemplo) en otro número (int por ejemplo) porque aunque pueden sufrir

38/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

transformaciones como perder sus decimales, sigue siendo un valor


numérico. Por tanto no podemos hacer casting entre tipos que sean
diferentes cosas. Por ejemplo una conversión muy necesaria a menudo es
transformar tipos de datos a String y al contrario (convertir String en tipos
de datos). Si esto lo hacemos con casting genera un error porque los String
son objetos y los tipos de datos son un grupo de bytes, no son lo mismo y
por tanto son tipos de datos incompatibles.
String s = (String)5; // Error: tipos incompatibles
int i = (int)"24"; // Error: tipos incompatibles

Para realizar la conversión de String a un tipo primitivo podemos usar el


método X.parseX(String s) donde X es una de las clases envoltura de los
tipos de datos. Por ejemplo:
int i = Integer.parseInt("24"); // Convierte "24" en 24
double d = Double.parseDouble("2.4"); // Convierte "2.4" en 2.4
boolean b = Boolean.ParseBoolean("true");// "true" en true

Para realizar la conversión de un tipo de dato a String tenemos el método


String.valueOf(X). Otra alternativa es pegar a una cadena vacía el valor
que quieres convertir (usa el método toString() del objeto). Por ejemplo:
String s1 = "" + 24; // Convierte 24 en "24"
String s2 = "" + 2.4; // Convierte 2.4 en "2.4"
String s3 = "" + true; // Convierte true en "true"
String s4 = String.valueOf(24); // Convierte 24 en "24"
String s5 = String.valueOf(2.4); // Convierte 2.4 en "2.4"
String s6 = String.valueOf(true); // Convierte true en "true"

2.4.5. OPERADORES Y PRECEDENCIA.


Los datos se manipulan realizando operaciones con ellos. Los datos
numéricos por ejemplo se suman, se restan, ... y a veces se realizan
operaciones más complejas. Las operaciones se pueden realizar mediante
operadores o mediante funciones. En este apartado comentamos los
operadores, que son símbolos que representan una operación con los
datos. Hay operaciones binarias (dato operación dato) o unarias (operación
dato) como el cambio de signo (-4) o el casting: (double)3

39/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

OPERADORES ARITMÉTICOS
Son operaciones matemáticas que trabajan con datos numéricos:

El resultado de estos operadores varía notablemente si usamos enteros o si


usamos números de coma flotante. Ejemplos:
double resultado1, d1 = 14, d2 = 5;
int resultado2, i1 = 14, i2 = 5;
resultado1 = d1 / d2;
resultado2 = i1 / i2;

resultado1 valdrá 2.8 mientras que resultado2 valdrá 2. Es más, incluso:


double resultado;
int i1 = 7, i2 = 2;
resultado = i1 / i2; // Resultado valdrá 3
resultado = (double)i1 / i2; // Resultado valdrá 3.5

El operador módulo (%) sirve para calcular el resto de una división entera.
Ejemplo:
int resultado, i1 = 14, i2 = 5;
resultado = i1 % i2; // El resultado será 4

El guión además de utilizarse para la resta, se utiliza para cambiar el signo


al número que tenga a su derecha (operador unario):
int x = -14; // El resultado será -14
int y = -(x + 6); // El resultado será 8

OPERADORES CONDICIONALES Y RELACIONALES


Los operadores condicionales sirven para comparar valores, es decir
expresar condiciones simples. Los operadores lógicos o relacionales
sirven para poder hacer condiciones complejas combinando una o varias

40/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

condiciones simples. Siempre devuelven booleanos: true ó false.


Los operadores lógicos son AND, OR y NOT, sirven para construir
condiciones complejas a partir de las simples. NOT sirve para negar una
condición. Ejemplo:
boolean mayorDeEdad, menorDeEdad;
int edad = 21;
mayorDeEdad = edad >= 18; // será true. Condición simple
menorDeEdad = !mayorDeEdad; // será false !x Es lo contrario de x

El operador lógico && (AND) evalúa dos expresiones de modo que si


ambas son ciertas, el resultado será true, si no, el resultado será false. Ej:
boolean tieneCarnetConducir = true;
int edad = 20;
boolean puedeConducir = (edad >= 18) && tieneCarnetConducir;
// Si la edad es de al menos 18 años y tieneCarnetConducir es
// true, puedeConducir es true (ambas cosas: una AND la otra)

El operador lógico || (OR) también evalúa dos expresiones. El resultado


será true si al menos una de ellas es true. Ejemplo:
boolean nieva = true, llueve= false, graniza= false;
boolean malTiempo = nieva || llueve || graniza;

OPERADORES A NIVEL DE BITs


Manipulan los bits de los valores que participan. Ejemplos:
byte b = 3; // 00000011 en binario, 0x03 hexadecimal;

41/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

b = b << 1; // 00000110 en binario, 0x06 -> como multiplicar por 2


int colorRGB = 126754; // 00000000RRRRRRRRGGGGGGGGBBBBBBBB binario
int azul = colorRGB & 0xFF; // Anula el resto de bits (a cero)
int verde = (colorRGB >> 8) & 0xFF; // desplazamos 8 a derecha y..

MÁS OPERADORES DE ASIGNACIÓN


El operador fundamental es “=”. Sin embargo se pueden usar expresiones
más complejas como: x += 3;
En el ejemplo anterior lo que se hace es sumar 3 a la x (es lo mismo x += 3,
que x = x + 3). Eso se puede hacer también con todos estos operadores que
en orden serían: más igual, menos igual, por igual, and igual, or igual, xor
igual, modulo igual, desplazar a derecha igual, desplazar izquierda igual
+= -= *= /= &= |= ^= %= >>= <<=

También se pueden concatenar asignaciones:


x1 = x2 = x3 = 5; // todas valen 5

Operadores de incremento/decremento
Los operadores “++” (incremento) y “--“ (decremento) aumentan y
disminuyen respectivamente el valor de una variable numérica en 1
unidad. Ejemplos:
x++; // esto es como x = x + 1;
x--; // esto es como x = x - 1;

Pero hay dos formas de utilizar el incremento y el decremento.


• Preincremento: a la izquierda de la variable (++x)
• Postincremento: a la derecha de la variable (x++).

42/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Si la operación se realiza en una variable aislada, da igual una u otra


variedad. Pero generan resultados diferentes cuando la variable que
cambia está participando en una expresión.
• Preincremento: el operador aparece a la izquierda, primero cambia
la variable y luego se utiliza su valor en la expresión.
• PostIncremento: el operador aparece a la derecha y primero se usa
en la expresión el valor actual de la variable y luego, a posteriori,
se cambia el valor. Ejemplo:
int x = 5, y = 5, z;
x++; // da igual ponerlo antes (++x) o después (x++)
--x; // da igual ponerlo antes (--x) o después (x--)
z = x++; // (es postincremento) z vale 5 y luego x vale 6
z = ++y + 4; // y vale 6 (preincremento), z vale 10 (6 + 4 = 10)

OPERADOR TERNARIO condición ? valor1 : valor2


Este operador (conocido como if de una línea) permite seleccionar una de
dos valores según el valor de la primera expresión. Sintaxis:

expresionLogica ? ExpresionSiVerdadero : expresionSiFalso;

Ejemplo:
paga = edad > 18 ? 6_000 : 3_000;

En este caso si la variable edad es mayor de 18, la paga será de 6000, si no,
será de 3000. Se evalúa una condición y según es cierta o no se devuelve
un valor u otro. Observa que las expresiones de este operador han de
acabar siendo un valor del mismo tipo (booleano?dato1:dato2) y no es
adecuado usar una sentencia sino una expresión (acaba siendo un dato).
Es decir, no funcionaría:
edad > 18 ? paga = 6000 : paga = 3000; // ERROR!!!!

Lo destacado en amarillo es una sentencia y lo que debe ir ahí es una


expresión (una fórmula, un dato). Una sentencia puede contener
expresiones (variable = expresión;) y una expresión puede contener
operadores y datos.

43/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Cuando el operador ternario va dentro de otras expresiones, quizás se


produzcan errores por el orden en que se aplican las operaciones
(precedencia). Para evitarlo podemos encerrar todo el operador entre
paréntesis o incluso encerrar la condición entre paréntesis:
int i = (int)(Math.random() * 11);
System.out.println(i + " es " + i > 4? "mayor":"menor" + " que 4");
System.out.println(i + " es " + (i > 4? "mayor":"menor") + " que 4");

Se pueden anidar, porque en la expresión de uno puedes volver a usar un


operador ternario. Eso te permite contemplar más de dos casos:
int i = (int)(Math.random() * 11);
// Ahora contemplamos 3 posibilidades: mayor, menor o igual
System.out.println(i + " es " +
(i > 4? "mayor" : (i < 4? "menor" : "igual") ) +
" que 4");

PRECEDENCIA DE OPERADORES
A veces hay expresiones con operadores que resultan confusas. Por
ejemplo en:
resultado = 8 + 4 / 2;

Es difícil saber el resultado. ¿Cuál es? ¿6 ó 10? La respuesta es 10 y la


razón es porque el operador de división siempre precede en orden de
ejecución (se ejecuta antes) que el operador suma. Es decir, siempre se
ejecuta antes la división que la suma sin importar quien esté escrito antes.
Estas reglas, definen un orden claro de ejecución y nos deben guiar en
cómo escribimos las expresiones.
Esta tabla recoge el orden de aplicación de las operaciones (de mayor a
menor preferencia). Los operadores de la primera fila se aplican primero
(tienen mayor preferencia), después los de la segunda fila, ...
Si este orden prefijado en Java no te interesa en ciertas situaciones,
siempre puedes romperlo usando paréntesis. Todo lo que haya dentro de
un paréntesis se ejecuta antes de lo que hay fuera. Ejemplo:
resultado = (8 + 4) / 2; // Ahora no hay duda, el resultado es 6

44/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Cuando todas las operaciones tienen igual precedencia se ejecutan de


izquierda a derecha. Esto se presta a confusión, por ejemplo, en la
expresión:
resultado = 9 / 3 * 3;

¿El resultado podría ser 1 ó 9? En este caso el resultado es 9, porque la


división y el producto tienen la misma precedencia, por eso, a igual
precedencia, el compilador de Java realiza primero la operación que esté
más a la izquierda, que en este caso es la división. Una vez más los
paréntesis podrían evitar este comportamiento si no es lo que necesitas:
resultado = 9 / (3 * 3); // Ahora el resultado es 1

2.5 CLASES Y OBJETOS DE FÁBRICA.


2.5.1. MÉTODOS PRECONSTRUIDOS.
Si declaras variables dentro de un método, las variables son locales al

45/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

método. Es un buena costumbre acompañar la declaración con un


comentario que explique para que se utiliza la variable, o que valor
almacena durante la ejecución del código. Ejemplo:
double principal; // Capital de dinero a invertir
double intereses; // Incremento de capital obtenido

Puedes declarar variables en cualquier parte dentro del método, no solo al


principio. Lo normal es declarar las variables importantes (las que se usan
a lo largo de todo el método) al principio y las auxiliares (las que
solamente se utilizan en una zona del código) cuando se necesiten.
EJEMPLO 4: Programa que usa clases preconstruidas (de fábrica).
/**
* Esta clase calcula el dinero obtenido como
* intereses al invertir 17.000,00 euros a un interés
* del 2.7% durante un año. El interés y la
* ganancia se imprimen por la salida estándar.
*/
public class Intereses {
public static void main( String[] args ) {
/* Declarar las variables */
double principal; // Capital de dinero a invertir
double ratio; // El ratio de interés anual
double intereses; // ganancia al año debida al ratio

/* Hacer cálculos */
principal = 17000;
ratio = 2.7 / 100; // Se puede usar tb. 0.027
intereses = principal * ratio; // Calcular interes anual
principal = principal + interes; // Dinero después de un año
// (Nota: el nuevo valor reemplaza al anterior)
/* Mostrar resultados */
System.out.print("El interés ganado en €: ");
System.out.println(intereses);
System.out.print("Capital después de un año en €: ");
System.out.println(principal);
} // final de main()
} // final de la clase Interes

46/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Este programa usa varias llamadas a métodos (en verde). En el programa


de ejemplo hemos usado dos: System.out.print(dato) y
System.out.println(dato). La diferencia entre ellas es que la segunda añade
un salto de línea después de imprimir el dato, eso provoca el salto a una
nueva línea de la pantalla. Pero System.out.print() no añade el salto de
línea, así que cuando se imprima otra vez, se continúa en la misma línea.
Los valores que se pasan entre paréntesis es la información que se quiere
imprimir. Es un único dato que se pasa al método para que haga algo con
él (en este caso mostrarlo por pantalla). A estos datos que se pasan entre
paréntesis a un método se les llama parámetros o argumentos. No a todos
los métodos hay que pasarles parámetros. Cuando un método no tiene
parámetros, se escribe su nombre con una pareja de paréntesis vacíos:
método(p1, p2, ....); // llamada a método con parámetros
método(); // llamada a método sin parámetros

En Java, tampoco hay métodos definidos de forma aislada, porque es un


lenguaje completamente orientado a objetos. Los métodos están
contenidos siempre dentro de clases o de objetos.
Algunas clases son parte del lenguaje Java y existen solamente para
ofrecer a los programadores métodos de apoyo. También los objetos,
como cualquier String, ofrecen muchos métodos prefabricados para
ayudar al programador con tareas que son muy comunes.
MÉTODOS DENTRO DE CLASES: Math y System
En un programa, una clase comienza a existir cuando la usas por primera
vez y solo puede existir una vez, es decir, no puedes hacer que la misma
clase exista dos veces en un programa (no confundir con los objetos, es
decir, la clase Date solo existe una vez por programa, pero eso no me
impide crear dos o más fechas, porque esos elementos son objetos de la
clase, no la clase en sí misma). Las clases se utilizan principalmente para
dos cosas:
• Primera: servir de plantilla para fabricar objetos.
• Segunda: agrupar o encapsular datos y métodos.

47/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Uno de los propósitos de las clases es agrupar juntos algunas variables y


métodos. Una clase es un contenedor de variables (datos) y
comportamiento (métodos). Los datos y métodos de la clase los
reconocemos mirando su código porque tienen el modificador static. Hay
clases que tienen tanto variables como métodos estáticos. Por ejemplo, un
programa es una clase. El método main() es un miembro de la clase, por
eso escribimos la palabra reservada static al escribir un programa.
public static void main(... // static significa de la clase

Cuando una clase tiene variables o métodos estáticos que queremos usar
desde el exterior de la clase, el nombre de la clase es parte del nombre
completo de la variable o método. Por ejemplo, la clase System contiene un
método estático llamado exit(int aviso). Para usarlo en tus programas,
debes llamarlo escribiendo el nombre de la clase (no lo contiene un objeto,
lo contiene una clase al ser estático). Este método hace que un programa
acabe su ejecución y devuelva al sistema operativo un valor entero que
puede servir de indicador o de "chivato" del motivo por el que ha
finalizado. Además, la máquina virtual que lo ejecuta también acaba:
System.exit(0); // El programa ha acabado de forma correcta
System.exit(1); // El programa acaba por la causa 1

Clase System
La clase System tiene información (property) sobre el sistema que puedes
consultar con System.getProperty(String clave) y cambiar algunas:

Clave Descripción
java.version Versión del JRE
java.version.date Fecha del JRE
java.vendor Fabricante del JRE
java.vendor.url URL del fabricante del JRE
java.vendor.version Versión del fabricante
java.home Directorio de instalación de Java
java.vm.specification.version Versión de la Java Virtual Machine

48/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Clave Descripción
java.vm.specification.vendor Vendedor de la JVM
java.vm.specification.name Nombre de la JVM
java.vm.version Versión de la JVM
java.vm.vendor Fabricante de la JVM
java.vm.name Nombre de la JVM
java.specification.version Versión del JRE
java.specification.vendor Fabricante del JRE
java.specification.name Jnombre del JRE
java.class.version Número de versión de la clase
Java class path consulta
java.class.path
ClassLoader.getSystemClassLoader()
Lista de rutas de búsqueda para cargar
java.library.path
librerías de código
java.io.tmpdir Ruta por defecto a la carpeta temporal
java.compiler Número del compilador JIT
os.name Nombre del sistema operativo
os.arch Arquitectura del sistema operativo
os.version Versión del sistema operativo
file.separator Separador de ficheros ("/" en UNIX)
path.separator Separador de rutas (":" en UNIX)
line.separator Separador de líneas ("\n" en UNIX)
user.name Nombre del usuario que ejecuta
user.home Carpeta personal del usuario
user.dir Carpeta de trabajo actual del usuario
native.encoding Nombre del charset

Esta clase además de permitir consultar propiedades del sistema


operativo y acabar un programa con exit(int aviso) o consultar una
variable de entorno con getEnv(String nombre). También aporta entrada y
salida con los objetos in, out y err que puedes cambiar con métodos setter.

49/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Un ejemplo de un método sin parámetros es System.currentTimeMillis(),


que devuelve el número de milisegundos que han pasado desde el primer
segundo del 1 de enero de 1970 a las 00:00 horas (devuelve un valor de
tipo long). Este método te permite saber la cantidad de tiempo
transcurrido entre dos momentos.
También tiene el método arrayCopy() relacionado con los arrays, que
permite copiar un array en otro. Recibe cinco argumentos: el array que se
copia, el índice desde que se empieza a copiar en el origen, el array
destino, el índice desde el que se copia en el destino y el tamaño de la
copia (número de elementos de la copia). Ejemplo:
int uno[] = {1, 1, 2};
int dos[] = {3, 3, 3, 3, 3, 3, 3, 3, 3};
System.arrayCopy(uno, 0, dos, 0, uno.length);
for (int i=0; i <= 8; i++){
System.out.print( dos[i] + " " );
} //Sale 1 1 2 3 3 3 3 3 3

EJERCICIO 5: crea un programa que muestre por consola la ruta de su


carpeta de trabajo actual, su carpeta temporal, el nombre del usuario que
lo ejecuta y su carpeta personal, el nombre del sistema operativo, que
letras se usan para separar las carpetas en las rutas y el nombre del juego
de caracteres utilizado.
Clase Math
Otra clase muy usada es Math. Esta clase tiene constantes estáticas como
Math.PI y Math.E que son las aproximaciones a los números π y e. Math
también contiene un gran número de operaciones matemáticas. De forma
que cuando necesites realizar operaciones más complejas que la suma,
resta, etc. que ofrecen los operadores aritméticos, esta clase te ofrece sus
variables y métodos. Algunas funciones que la clase Math:
• Valor absoluto: Math.abs(x)
• Funciones trigonométricas: Math.sin(x), Math.cos(x) y Math.tan(x)
x representa un ángulo expresado en radianes, no grados. La
equivalencia: 360 grados = 2π radianes. Las funciones son el seno,
coseno y tangente de un ángulo.

50/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• Funciones trigonométricas inversas: Math.asin(x), Math.acos(x) y


Math.atan(x). El valor devuelto se expresa en radianes, no en
grados. Las funciones son el arcoseno, arcocoseno y arcotangente.
• Función exponencial y logarítmicas: Math.exp(x) calcula el número
e elevado a x y el logaritmo natural (en base 10) lo calcula
Math.log10(x) y el logaritmo neperiano Math.log(x).
• Función potencia: Math.pow(x,y) calcula x elevado a y.
• Función raíz cuadrada: Math.sqrt(x)
• Funciones de Redondeo: Math.floor(x), redondea x al entero
menor o igual a x. Por ejemplo, Math.floor(3.76) es 3.0.
Math.round(x) devuelve el entero más cercano a x. Math.ceil(x)
redondea x al menor entero mayor que x.
• Funciones para generar números aleatorios: Math.random(),
devuelve un nº double, aleatorio, 0.0 <= Math.random() < 1.0 que
sigue una distribución uniforme (todos los valores del intervalo
[0,1) tienen la misma probabilidad de salir).
Los parámetros que se le pasan a los métodos de Math pueden ser de
cualquier tipo numérico (pueden ser expresiones en vez de valores
literales) y los valores devueltos suelen ser de tipo double. Observa que
Math.random() no tiene parámetros.

EJEMPLO 5: Programa de ejemplo que usa los métodos matemáticos:


/**
* Usar cálculos matemáticos, mostrar resultados e indicar
* el tiempo que se ha tardado en hacerlo.
*/
public class UsarMath {
public static void main(String[] args) {
long tiempoInicio; // t cuando comienza, en milisegundos
long tiempoFinal; // t cuando acaba, en ms
double tiempo; // Diferencia de tiempo en segundos
tiempoInicio = System.currentTimeMillis();
double ancho, alto, hipotenusa; // lados de triángulo rectángulo
ancho = 42.0;
alto = 17.0;

51/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

// Teorema de pitagoras: hipotenusa = raíz del cuadrado de catetos


hipotenusa = Math.sqrt( ancho * ancho + alto * alto );
System.out.print("Hipotenusa de triángulo de catetos 42 y 17 ");
System.out.println(hipotenusa);
System.out.println("\nEn matemáticas, sin(x) * sin(x) + "
+ "cos(x) * cos(x) - 1 debe ser 0.");
System.out.println("Lo comprobamos para x = 1:");
System.out.print(" sin(1) * sin(1) + cos(1) * cos(1) - 1 es ");
System.out.println( Math.sin(1) * Math.sin(1)
+ Math.cos(1) * Math.cos(1) - 1 );
System.out.println("(Hay errores de redondeo al hacer cáclulos "
+ " con números reales!)");
System.out.print("\nAhora un número aleatorio: ");
System.out.println( Math.random() );
System.out.print("El valor de Math.PI es ");
System.out.println( Math.PI );
tiempoFinal = System.currentTimeMillis();
tiempo = (tiempoFinal - tiempoInicio) / 1000.0;
System.out.print("\nEl tiempo de ejecución en segundos ha sido: ");
System.out.println(tiempo);
} // final de main()
} // final de la clase UsarMath

MÉTODOS DENTRO DE OBJETOS.


Ahora vamos con operaciones que nos ofrecen los objetos.
Clase String
Vamos a usar String que es una de las clases para textos. Cada cadena de
texto de un programa Java es por tanto un objeto de la clase String. El dato
que contiene el objeto es la secuencia de letras de la cadena de texto.
También contiene métodos, que en este caso son funciones también. Por
ejemplo tiene una que se llama length() y que calcula y devuelve la
longitud (la cantidad de letras) que tiene la cadena de texto. Ejemplo:
String aviso;
aviso = "Aprovecha el día!"; // Construye un objeto String
/* Importante: La variable aviso no almacena el objeto String!!
Almacena la dirección de memoria (es una referencia) al lugar
donde realmente está almacenado el objeto. Es como una flecha.
Los objetos se almacenan en un área de memoria llamada heap.
*/

52/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

La función aviso.length() devuelve 16, que es la cantidad de letras que


tiene la cadena. También las podemos usar con literales, porque siguen
siendo objetos String en Java. Ejemplo:
System.out.println( "Hola mundo".length() );

A parte de dejar al compilador que construya automáticamente los objetos


(nosotros indicamos la cadena literal y el utiliza new de manera
automática) también podemos usar nosotros el operador new no solo con
constantes literales sino también con arrays de caracteres o de bytes
aunque es más cómodo que lo haga el compilador. Y además sabemos que
el operador + con String es el operador concatenar que crea nuevos
objetos inmutables de la clase String:
String texto1 = "¡Prueba de texto!"; // más sencillo
String texto2 = new String("¡Prueba de texto!"); //equivale a este
texto2 = "Este es un texto que ocupa " +
"varias líneas, no obstante se puede " + "encadenar";
// Otros constructores:
char[] palabras = {'H', 'o', 'l', 'a'}; // array de char
String cadena = new String(palabras);
byte[] datos = {97, 98, 99}; // array de bytes
// Si no indicas el charset, se utiliza ASCII
String codificada = new String(datos, "8859_1");

Ahora te indico algunas de las funciones que implementan los objetos de


tipo String, para describirlas suponderemos que s1 y s2 son variables de
tipo referencia a String o valores literales String:

MÉTODO DESCRIPCIÓN
char charAt(int i) carácter que está en la posición i
int compareTo(String s) Compara las dos cadenas. Devuelve un valor
menor que cero si la cadena s es mayor que la
original, 0 si son iguales y devuelve un valor
mayor que cero si s es menor que la original
int compareToIgnoreCase(String s) Compara dos cadenas, pero no tiene en cuenta si
el texto es mayúsculas o no.
String concat(String s) Añade la cadena s a la cadena original.

53/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

MÉTODO DESCRIPCIÓN
String copyValueOf(char[] c) Produce String igual al array de caracteres c.
boolean endsWith(s) true si la cadena termina con el texto s.
boolean equals(s) Compara ambas cadenas, true si son iguales.
boolean equalsIgnoreCase(s) Compara ambas cadenas sin tener en cuenta
mayúsculas y minúsculas.
byte[] getBytes() Devuelve array de bytes de los códigos de cada
carácter del String
void getBytes(int si, int sf, Almacena contenido de la cadena en el array de
char[] d, int di); caracteres d. Toma los caracteres desde la posición
si hasta la posición sf y los copia en el array desde
la posición di
int indexOf(s) Devuelve la posición en la cadena del texto s.
int indexOf(s, pos) Devuelve la posición en la cadena del texto
s, empezando a buscar desde posición pos
int lastIndexOf(s) Devuelve la última posición en la cadena
del texto s
int lastIndexOf(s, pos) última posición en la cadena del texto s,
empezando a buscar desde la posición pos
boolean contain(String s) Si el String contiene al argumento s devuelve true
int length() longitud de la cadena
boolean matches(er) verdadero si el String cumple la expresión regular
String replace(ca, cn) cadena idéntica al original pero que ha cambiando
los caracteres iguales a ca por cn
String replaceFirst(s1, s2) Cambia la primera aparición de la cadena s1 por
la cadena s2
String replaceAll(s1, s2) Cambia la todas las apariciones de la cadena s1
por la cadena s2
String startsWith(s) true si la cadena comienza con el texto s.
String substring(p1, p2) texto que va desde posiciones p1 a p2-1.
char[] toCharArray() array de caracteres a partir de la cadena dada

54/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

MÉTODO DESCRIPCIÓN
String toLowerCase() Convierte la cadena a minúsculas
String toLowerCase(Locale loc) Lo mismo pero siguiendo las instrucciones del
argumento local
String toUpperCase() Convierte la cadena a mayúsculas
String toUpperCase(Locale loc) Lo mismo pero siguiendo las instrucciones del
argumento local
String trim() Elimina los blancos que tenga la cadena tanto por
delante como por detrás
static String valueOf(e) Devuelve la cadena que representa el valor e. Si e
es booleano, por ejemplo, devolvería una cadena
con el valor "true" o "false".

Hay una operación muy básica y que por influencia de otros lenguajes de
programación suele provocar muchos errores en los que comienzan a
programar en Java. Esta operación es comparar dos cadenas para saber si
son iguales: hay que usar s1.equals(s2) que devuelve true si las letras
de s1 y s2 son las mismas (en cantidad y posición) y false en otro caso.

IMPORTANTE: FALLO MUY COMÚN!!


El contenido de los objetos en Java (incluidos los String) no se
comparan con el operador == para saber si tienen la misma
información.
Si usas el operador == estás comprobando si son el mismo objeto (el
continente), no si tienen el mismo contenido. Ejemplo:
"Hola" == "Hola" // Mal: puede ser false
"Hola".equals("Hola") // Bien: siempre devuelve true

Nota: ten en cuenta que en s1.toLowerCase(), s1.substring(3),


s1.trim(), etc. la cadena s1 no cambia, se crea y devuelve un nuevo
String. Si quieres cambiarlo debes usar la asignación: s1 = s1.trim();
por ejemplo.
Los objetos String pueden manipularse también con operadores. Puedes

55/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

usar el operador suma (+) que sirve para concatenar (unir o pegar)
cadenas de texto. Por ejemplo: "Hola" + "Mundo" genera "HolaMundo".
Observa que si quieres que quede un espacio entre las dos palabras, el
espacio debe formar parte de una de las cadenas de texto. Por ejemplo:
"Hola " + "Mundo" se evalúa a "Hola Mundo".

En la suma de Strings puedes usar literales o variables. Por ejemplo:


String nombre = "Jose";
System.out.println("Hola, " + nombre + ". Bienvenido!");

Además siempre puedes concatenar variables o literales de cualquier tipo


con un String, porque el otro dato se convierte a String y se concatena. Por
ejemplo, "Número" + 42 se evalúa a "Número42". Y todas estas sentencias:
System.out.print("Después de ");
System.out.print(anyos);
System.out.print(" años, el valor es ");
System.out.print(principal);

Son equivalentes a esta otra:


System.out.print("Después de " +anyos +" años, el valor es " +principal);

CLASES TRADICIONALES PARA USAR EL TIEMPO


Inicialmente se utilizaban objetos de la clase java.util.Date para trabajar
con fechas y horas. Vemos un resumen de constructores y métodos (fuente
API de Java 8):
Constructores: métodos que usamos para crear objetos Date.
• Date() crea una fecha con el momento actual. Almacena los
milisegundos pasados desde 1/1/1900.
• Date(int year-1900, int mes-1, int dia) ahora se prefiere usar
Calendar.set(year, mes, dia) o GregorianCalendar(year, mes, dia)
• Date(int year-1900, int mes-1, int dia, int hrs, int min)
• Date(int year-1900, int mes-1, int dia, int hrs, int min, int seg)
• Date(long date) crea un objeto fecha a partir del long.
• Date(String s) reemplazado por DateFormat.parse(String s).
Métodos
• boolean after(Date when) true si la actual es posterior a when.

56/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• boolean before(Date when) true si la actual es anterior a when.


• Object clone() Hace una copia del objeto.
• int compareTo(Date otra) Compara dos Dates.
• boolean equals(Object obj) Compares two dates for equality.
• int getDate() ahora Calendar.get(Calendar.DAY_OF_MONTH).
• int getDay() ahora Calendar.get(Calendar.DAY_OF_WEEK).
• int getHours() ahora Calendar.get(Calendar.HOUR_OF_DAY).
• int getMinutes() ahora Calendar.get(Calendar.MINUTE).
• int getMonth() ahora Calendar.get(Calendar.MONTH).
• int getSeconds() ahora Calendar.get(Calendar.SECOND).
• long getTime() nº milisegundos desde el 1/1/1970 a las 00:00:00
GMT hasta la fecha del objeto.
• int getTimezoneOffset() ahora
(Calendar.get( Calendar.ZONE_OFFSET ) +
Calendar.get(Calendar.DST_OFFSET)) / (60 * 1000).
• int getYear() ahora Calendar.get(Calendar.YEAR).
• int hashCode() hash del objeto.
• static long parse(String s) ahora DateFormat.parse(String s)
• void setDate(int d) ahora Calendar.set(Calendar.DAY_OF_MONTH, int d)
• void setHours(int h) ahora Calendar.set(Calendar.HOUR_OF_DAY, int h)
• void setMinutes(int m) ahora Calendar.set(Calendar.MINUTE, int m)
• void setMonth(int m) ahora Calendar.set(Calendar.MONTH, int m)
• void setSeconds(int s) ahora Calendar.set(Calendar.SECOND, int s)
• void setTime(long t) cambia la fecha por el long que contiene los
milisegundos desde el 1/1/1970 a las 00:00:00 GMT.
• void setYear(int y) ahora Calendar.set(Calendar.YEAR, y + 1900)
• String toGMTString() ahora DateFormat.format(Date date), usa GMT
TimeZone.
• String toLocaleString() ahora DateFormat.format(Date date).
• String toString() Convierte a String con formato.
• static long UTC(int year, int mes, int dia, int hrs, int min, int
seg) ahora Calendar.set(year, mes, dia, hrs, min, seg) o
GregorianCalendar(year, mes, dia, hrs, min, seg), usando UTC
TimeZone, seguido de Calendar.getTime().getTime().

Algunas cosas que debes tener en cuenta con los métodos de la clase Date
y que veremos en el ejemplo 6:
• El parámetro year debe ser year – 1900.
• El parámetro mes va de 0 a 11: 0 es enero, ..., 11 es diciembre.
• El día usa valores de 1 a 31 (sin problemas).
• Las horas van de 0 a 23.

57/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• Los minutos de 0 a 59.


• Los segundos de 0 a 61 porque hay segundos de relleno que se
introducen en algunos minutos para ajustar el calendario a la
rotación de la Tierra (ISO C).
EJEMPLO 6: Programa de ejemplo que usa métodos de la clase Date:
import java.util.Date;
public class DemoDate {
public static void main(String[] args) {
// Usando fechas para compararlas: podría dar problemas
// pero es poco probable (si la fecha no existe)
Date fallas = new Date(2022, 3, 19);
Date sanBlas = new Date(2022, 2, 3);
System.out.println("Fallas anterior a San Blas? " +
fallas.before(sanBlas) );
// Pero si interesa utilizar sus partes (year, month,...)
// o imprimirlas, tendrás problemas si no tienes en
// cuenta como son los parámetros que usa Date
System.out.println(fallas);
// Muestra: Wed Apr 19 00:00:00 CEST 3922 --->
// miércoles 19 de abril del año 3922 ¿?¿? ---> Error
fallas = new Date(2022 - 1900, 3 - 1, 19);
System.out.println(fallas); //Ok: Sat Mar 19 00:00:00 CET 2022
} // final de main()
} // final de la clase DemoDate

Algunos métodos de la clase Date están "Deprecated" que significa


obsoletos, actualmente se prefiere utilizar en los nuevos programas las
clases Calendar o GregorianCalendar. En los métodos de Date te he anotado
el método equivalente con Calendar.
No se crean objetos java.util.Calendar con el operador new, porque es una
clase abstracta, sino con una llamada a un método de la clase llamado
getInstance():

Calendar ahora = Calendar.getInstance();

Define una serie de constantes que debes utilizar para obtener y cambiar
la información. Lo mejor es consultar la ayuda de la API de Java cuando

58/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

quieras conseguir algo, pero aquí tienes algunas:


• int AM y AM_PM. El formato de la hora.
• JANUARY, FEBRUARY, MARCH, APRIL, MAY, JUNE, JULY, AUGUST,
SETEMBER, OCTOBER, NOVEMBER, DECEMBER. Valores del campo MONTH.
• DATE y DAY_OF_MONTH para identificar el campo día del mes.
• DAY_OF_WEEK campo para indicar el día de la semana.
• DAY_OF_WEEK_IN_MONTH campo para indicar el día de la semana en el
mes actual.
• DAY_OF_YEAR campo para indicar el día dentro del año actual.
• ERA campo para indicar la era, por ejemplo AD o BC.
• HOUR y HOUR_OF_DAY campo para indicar la hora de 0-11.
• MILLISECOND campo para indicar milisegundos dentro de un segundo.
• MINUTE campo para indicar el minuto dentro de la hora.
• MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
valores del campo DAY_OF_WEEK.
• MONTH campo para indicar el mes.
• SECOND campo para indicar el segundo dentro del minuto.
• long time El tiempo del objeto expresado como milisegundos
desde el 1/1/1970 0:00:00 GMT.
• WEEK_OF_MONTH campo indicando semana dentro del mes actual.
• WEEK_OF_YEAR campo indicando semana dentro del año actual.
• YEAR campo indicando el año.
• ZONE_OFFSET campo indica desplazamiento desde GMT en milisegundos.
Métodos:
• void add(int campo, int cantidad) suma (o resta) la cantidad de
tiempo indicada por campo (días, meses, ...)
• boolean after(cuando) devuelve true si el objeto actual es un
tiempo posterior al parámetro cuando.
• boolean before(cuando) devuelve true si el objeto actual es
anterior al parámetro cuando.
• Object clone() Crea una copia.
• int compareTo(otroCalendario) Compara el actual con otro.
• boolean equals(otro) devuelve true si este calandario representa
el mismo momento de tiempo que otro.
• int get(campo) Devuelve el campo (Calendar.YEAR, etc.).
• int getActualMaximum(campo) Máximo valor que puede tener campo.
• int getActualMinimum(campo) Mínimo valor que puede tener el campo.
• int getFirstDayOfWeek() primer día de la semana: SUNDAY en U.S.,
MONDAY en Francia (como en España).
• static Calendar getInstance(unLocale) crea un Calendar usando el
locale indicado.

59/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• Date getTime() Devuelve un Date del calendar.


• long getTimeInMillis() devuelve el valor en milisegundos.
• TimeZone getTimeZone() obtiene el time zone.
• int getWeeksInWeekYear() Rdevuelve nº de semanas en el año.
• int getWeekYear() la semana actual del año en el calendario.
• void set(campo, calor) cambia el campo al valor indicado.
• String toString() devuelve una representación en String.

EJEMPLO 7: Programa de ejemplo que usa métodos de Calendar:


import java.util.Calendar;
public class DemoCalendar {
public static void main(String[] args) {
Calendar ahora = Calendar.getInstance();
System.out.println("Ahora:" + ahora.getTime() );
ahora.add(Calendar.DAY_OF_MONTH, 15);
System.out.println("Dentro de 15 días: " +
ahora.getTime() );
ahora.add(Calendar.MONTH, 4);
System.out.println("Y cuatro meses después: " +
ahora.getTime());
} // final de main()
} // final de la clase DemoCalendar

La clase java.util.GregorianCalendar se comporta de una manera muy


similar a java.util.Calendar a la que mejora un poco. El calendario
Gregoriano es el que se utiliza en occidente (se ha impuesto en caso todos
los lugares del mundo). En el ejemplo vamos a mejorar un poco la manera
de imprimirla usando una clase para dar formato a las fechas.
EJEMPLO 8: Usar métodos de GregorianCalendar:
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;

public class DemoGregorianCalendar {


public static void main(String[] args) {
Calendar c1 = GregorianCalendar.getInstance();
System.out.println("Fecha actual: " +
c1.getTime().toLocaleString() );
c1.set(2000, Calendar.AUGUST, 31);

60/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

System.out.println("Fecha 31 Agosto 2000: " +


c1.getTime().toLocaleString());
c1.set(Calendar.MONTH, 13);
System.out.println("Fecha 13 meses más: " +
c1.getTime().toLocaleString());
/* como podemos observar no nos imprime la fecha, hemos
escrito una incoherencia, no hemos sumado (add) 13
meses, hemos fijado el mes a 13 */
c1.set(2000, Calendar.AUGUST, 31);
// volvemos a la fecha anterior usando set y usamos add
c1.add(Calendar.MONTH, 13); // Ahora sí, añadir 13 meses
System.out.println("Fecha 13 meses más: " +
c1.getTime().toLocaleString());
c1.roll(Calendar.HOUR, 25); // Añadir 25 horas
System.out.println("Fecha 25 horas más: " +
c1.getTime().toLocaleString());
SimpleDateFormat sdf =
new SimpleDateFormat("dd/MMMMM/yyyy hh:mm:ss");
System.out.println("Fecha Formateada: " +
sdf.format( c1.getTime() ) );
} // final de main()
} // final de la clase DemoGregorianCalendar

CLASES MÁS ACTUALES PARA TRABAJAR CON TIEMPO


Las clases de java.time: LocalDate, LocalTime y LocalDateTime. Desde el
inicio de los tiempos se han usado java.util.Date y java.util.Calendar. Si
haces una búsqueda sobre manejo de fechas en Java, verás que la mayoría
de los artículos y tutoriales se centran en el uso de estas clases. Pero desde
mi punto de vista están mal diseñadas, su uso es confuso, abusan de
enumeraciones y constantes para indicar cosas y además no son seguras
para uso multihilo (no son thread-safe). Luego se añadió java.sql.Date, que
es una subclase de java.util.Date y hereda sus mismos problemas.
En marzo de 2014 apare Java 8 y con ella estas nuevas clases que
solucionan la mayor parte de los problemas de las clases tradicionales, e
incluyen soporte automático para cosas como años bisiestos, zonas
horarias y cambio automático de zona horaria.
Las clases básicas del paquete java.time son:
• LocalDate: representa a fechas sin hora.

61/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• LocalTime: representa horas sin fecha.


• LocalDateTime: es una combinación de las dos anteriores, representa
un momento de tiempo que tiene fecha y hora.
• Instant: parecida a la anterior. Almacenar un punto determinado
en el tiempo (fecha y hora), pero guarda su valor como un
timestamp de UNIX, es decir, en nanosegundos transcurridos desde
una referencia de tiempo que es el epoch de UNIX (1/1/1970 a las
00:00) y usando la zona horaria UTC. Es muy útil para manejar
momentos en el tiempo de manera neutra e intercambiarlo entre
aplicaciones y sistemas.
• ZonedDateTime: es como LocalDateTime añadiendo una zona horaria.
• Period: ayuda a obtener diferencias entre fechas en distintos
periodos o unidades (segundos, minutos, días...) y también a
añadir esas diferencias a las fechas.
• Duration: parecida a la anterior para horas.

Construyendo fechas y horas con java.time


Estas clases producen instancias inmutables y por tanto thread-safe. No
tienen constructores públicos, así que se instancian usando métodos de
tipo "factoría", es decir, tienen métodos que construyen estas clases a
partir de parámetros que le pasemos. Las de fechas y horas disponen de:
• now(): crean instancias con la fecha y hora actual.
• of(): construyen fechas y horas concretas aportando sus datos.
• with(): modifican la actual.
Ejemplos con now():
System.out.println("Fecha actual: " + LocalDate.now());
System.out.println("Hora actual: " + LocalTime.now());
System.out.println("Fecha y hora actuales: " + LocalDateTime.now());
System.out.println("Instante actual: " + Instant.now() );
System.out.println("Fecha y hora actuales con zona horaria: " +
ZonedDateTime.now());

Al convertirlas a texto se generan en el formato ISO 8601, un estándar.


Para definir una fecha concreta (no la actual) usamos el método factoría
of(). Por ejemplo:

62/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

System.out.println("Fallas 2023: " + LocalDate.of(2023, 3, 19));


System.out.println("Fallas 2023: " + LocalDate.of(2023, Month.MARCH, 19));
System.out.println("Cita: " + LocalDateTime.of(2023, 4, 2, 16, 50, 00);

Nota: Si intentas crear una fecha incorrecta se produce una excepción.


Por ejemplo, si quieres crear el día 29 de febrero de 2019 que no es bisiesto
(leap en inglés) aparece una excepción.
Partes de una fecha o una hora
Es posible extraer cualquier parte de una fecha o una hora a través de sus
métodos getter getXXX(). Por ejemplo: getHour(), getMinute(), getMonth() o
getDayOfWeek(). También podemos modificar esa parte con sus métodos
setter: setXXX().
Transformando fechas y horas
Si queremos aplicar un cambio a una fecha ya existente para obtener otra
podemos añadir/quitar cantidades de tiempo. Por ejemplo, plusXXX() y
minusXXX() de la clase LocalDate dispone de los métodos: plusDays() y
minusDays() para sumar o restar días a la fecha, plusWeeks() y minusWeeks()
para aumentar o dismonuir semanas, plusMonths() y minusMonths() para
añadir o quitar meses y plusYears() y minusYears() para sumar o restar
años.
Del mismo modo LocalTime ofrece los métodos plusNanos(), plusSeconds(),
plusMinutes() y plusHours() para sumar nanosegundos, segundos,
minutos y horas. Del mismo modo, tiene los mismos métodos, pero con el
prefijo minus, para restarlas. Ejemplos:
System.out.println("Fecha en de 10 días: " + LocalDate.now().plusDays(10) );
System.out.println("Hace 32 horas: "+ LocalDateTime.now().minusHours(32) );

Como son objetos inmutables, recuerda, lo que se devuelve son instancias


nuevas del nuevo dato, no versiones modificadas de los datos originales.
Ajustadores temporales
Hay una clase especializada llamada TemporalAdjuster que permite definir
ajustes para las fechas para obtener nuevas fechas a partir de una existente
y una clase factoría TemporalAdjusters (en plural) para crearlos. Por
ejemplo, si queremos obtener el primer día del mes de una determinada

63/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

fecha podemos usar el método TemporalAdjusters.firstDayOfMonth(). Del


mismo modo existen "ajustadores" para otras operaciones similares, que
puedes consultar. Ejemplo para averiguar la fecha del primer día del mes
que viene:
System.out.println("Primer día del próximo mes: " +
LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth()).getDayOfWeek());

Tiempo transcurrido entre fechas y horas


En el paquete java.time.temporal están la interface TemporalUnit, la
enumeración ChronoUnit y la clase Period que se encargan de esto con sus
métodos:
• between(): tiempo transcurrido entre dos instantes de tiempo.
• until(): tiempo que falta para llegar a una fecha determinada.
Por ejemplo si queremos saber cuánto tiempo ha transcurrido entre una
fecha de nacimiento y el día de hoy:
LocalDate nace = LocalDate.of(2003, Month.MAY, 23);
System.out.println("Su edad " +
ChronoUnit.YEARS.between(nace, LocalDate.now()) +
" años." );

Si queremos saber cuánto tiempo falta para llegar a final de año:


LocalDate hoy = LocalDate.now();
LocalDate finYear = hoy.with(TemporalAdjusters.lastDayOfYear());
Period hasta = hoy.until(finYear);
int meses = hasta.getMonths();
int dias = hasta.getDays();
System.out.println("Faltan " + meses + " meses y " + dias +
" días hasta fin de año.");

Period también dispone del método estático between():


Period p Period.between(hoy, finYear);

"Parsear" fechas (Convertir texto en fechas)


Las clases java.time ofrecen el método parse() que se ocupa de esto de
manera trivial. Tiene dos sobrecargas, una que recibe la cadena a
interpretar y una segunda que además añade un formateador
especializado si lo necesitamos:

64/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

LocalDate hoy = LocalDate.parse("2020-07-06"); // formato ISO 8601


LocalDate seisNov2020 = LocalDate.parse("6/11/2020",
DateTimeFormatter.ofPattern("d/M/yyyy"));

Formatos personalizados de fechas


La clase DateTimeFormatter sirve para interpretar cadenas de texto y
convertirlas a fechas, y también para la operación contraria, convertir
fechas a texto y darles el aspecto que nos interese con el método format().
Estos ejemplos usan el formato por defecto que es ISO 8601 y luego
definiendo uno:
LocalDateTime ahora = LocalDateTime().now();
System.out.println("Por defecto: " + ahora);
System.println("ISO 8601 (explícito): " +
ahora.format(DateTimeFormatter.ISODATE_TIME));
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd/MM/yyyy hh:mm:ss");
System.out.println("Formato propio: " + ahora.format(dtf));

Hay varios formateadores ya predefinidos que puedes consultar aquí.


Para definir los formatos propios se usan letras que representan ciertas
partes o maneras de visualizarlas, puedes consultarlas en letras estándar
para formato. También hay algunos predefinidos como el formato inglés,
inglés americano, alemán, francés canadiense, francés (que sería también
el nuestro, los gabachos y nosotros usamos el mismo formato. Si lo
definimos nosotros:
DateTimeFormatter dtf = DateTimeFormatter
.ofPattern("EEEE, dd 'de' MMMM 'de' yyyy 'a las' hh:mm:ss")
.withLocale(new Locale("es","ES"));

Finalmente, si nuestro programa pueden usarlo en diferentes países, en


vez de fijar nostros el formato, hacemos que lo elija el propio programa en
función del país de su sistema:
String idioma = System.getProperty("user.language");
String pais = System.getProperty("user.country");
DateTimeFormater fl =
DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT)
.withLocale( new Locale(idioma, pais) );
System.out.println("Formato local (" + idioma + "-" + pais + ): " +

65/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

ahora.format(fL));

CLASES PARA NÚMEROS GRANDES


Al hacer cálculos, a veces la capacidad de los tipos de datos predefinidos
no es suficiente para almacenar los valores que necesitamos en algunas
aplicaciones. Los tipos predefinidos suelen coincidir en capacidad y
formato con los que manejan las CPU's de los dispositivos (el hardware).
Si no es suficiente, el software debe resolver esta debilidad, aunque sea a
costa de ralentizar las operaciones. En Java tenemos la clase BigInteger
para utilizar números enteros de tamaño ilimitado y BigDecimal para
números decimales con precisión equivalente a la obtenida trabajando en
decimal.
EJERCICIO 6: Haz un programa que defina un número entero v de valor
9876543210 y calcule su cubo (v * v * v) usando tipos int, long y double.
¿Lo calcula bien en todos los tipos? ¿Y si lo elevas a 4?
La clase BigInteger define algunas constantes y ofrece algunos métodos
para crear objetos y realizar operaciones con ellos:
• static BigInteger ONE el BigInteger 1.
• static BigInteger TEN el BigInteger 10.
• static BigInteger ZERO el BigInteger 0.
• BigInteger abs() el valor absoluto del BigInteger (valor positivo)
• BigInteger add(BigInteger v) el BigInteger actual + v
• BigInteger and(BigInteger v) el BigInteger actual & v.
• BigInteger andNot(BigInteger v) el BigInteger actual & ~v.
• int bitCount() nº de bits al representarlo en complemento a 2.
• int bitLength() devuelve el nº de bits sin contar el signo.
• BigInteger clearBit(n) BigInteger que resulta de poner el bit n
del actual a 0.
• int compareTo(BigInteger v) Compara el BigInteger con v.
• BigInteger divide(BigInteger v) devuelve el BigInteger (actual/v).
• BigInteger[] divideAndRemainder(BigInteger v) devuelve un array
que contiene dos BigInteger (actual / v) y (actual % v).
• double doubleValue() Convierte el BigInteger a double.
• boolean equals(x) true si el BigInteger actual es igual a x.
• BigInteger flipBit(int n) devuelve el BigInteger cuyo bit n se ha
cambiado (0 por 1 y viceversa).
• float floatValue() convierte el BigInteger a float.

66/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• BigInteger gcd(BigInteger v) Devuelve un BigInteger cuyo valor es


el máximo común divisor del abs(actual) y abs(v).
• int getLowestSetBit() devuelve el nº de bits a 0 a la derecha del
primer bit a 1 (cuantos bits menos significativos están a 0 antes)
• int hashCode() el hash code del BigInteger.
• int intValue() Conveierte a int.
• boolean isProbablePrime(int certeza) devuelve true si el
BigInteger actual es primo con una probabilidad de n%.
• long longValue() Convierte a long.
• BigInteger max(BigInteger v) devuelve el máximo de {actual, v}.
• BigInteger min(BigInteger v) devuelve el mínimo de {actual, v}.
• BigInteger mod(BigInteger m) devuelve el BigInteger (actual % m).
• BigInteger modInverse(BigInteger m) devuelve un BigInteger que
cumple que es (actual^-1 % m) o que es: (1/actual % m).
• BigInteger modPow(BigInteger e, BigInteger m) el BigInteger cuyo
valor es potencia(actual, e) % m.
• BigInteger multiply(BigInteger v) el BigInteger (actual * v).
• BigInteger negate() el BigInteger -actual.
• BigInteger nextProbablePrime() el primer BigInteger mayor que el
actual y que probablemente sea primo.
• BigInteger not() el BigInteger de valor (~actual, bits cambiados).
• BigInteger or(BigInteger v) el BigInteger (actual | v).
• BigInteger pow(int e) el BigInteger potencia(actual, e).
• BigInteger probablePrime(int bits, Random rnd) devuelve el
BigInteger positivo que probablemente sea primo con la cantidad de
bits indicados.
• BigInteger remainder(BigInteger v) el BigInteger actual % v.
• BigInteger setBit(int n) el BigInteger actual dejando su bit de la
posición n a 1.
• BigInteger shiftLeft(int n) el BigInteger actual << n.
• BigInteger shiftRight(int n) el BigInteger actual >> n.
• int signum() el signum del BigInteger.
• BigInteger subtract(BigInteger v) el BigInteger actual – v.
• Boolean testBit(int n) true si el bit n es 1.
• byte[] toByteArray() un array con los bytes del BigInteger en C2.
• String toString() el BigInteger como String en base 10.
• String toString(int radix) el BigInteger como String en base radix
• static BigInteger valueOf(long v) el BigInteger de valor v.

67/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• BigInteger xor(BigInteger v) el BigInteger actual xor v.

EJEMPLO 9: Programa de ejemplo que usa métodos de la clase BigInteger.


El factorial de un número n se escribe n! y es el valor del multiplicar n por
todos los enteros anteriores hasta llegar a 1 siendo 0! = 1. Por ejemplo: 3! = 3
x 2 x 1 = 6 . Cuando el entero es grande, el valor crece mucho y el hardware
tendrá problemas para manejarlo.
import java.math.BigInteger;
public class DemoBigInteger {
// Un método que calcula el factorial de un int
static int factorial(int n) {
if(n <= 1) return 1;
return n * factorial(n-1);
}
// Un método que calcula el factorial de un double
static double factorial(double n) {
if(n <= 1.0) return 1.0;
return n * factorial(n-1);
}
// Un método que nos calcula el factorial de un BigInteger
static BigInteger factorial(BigInteger n) {
if( n.compareTo(BigInteger.ONE) <= 0 )
return BigInteger.ONE;
return n.multiply(factorial(n.subtract(BigInteger.ONE)));
}
public static void main(String[] args) {
int i = 10; // Prueba tu una segunda vez con 50
System.out.println(i + "! = " + factorial(i) );
double d = 50; // Prueba tu luego con 200 ¿Qué ocurre?
System.out.println(d + "! = " + factorial(d) );
BigInteger bi = new BigInteger("200"); // Prueba con 1000
System.out.println(bi + "! = " + factorial(bi) );
} // final de main()
} // final de la clase DemoBigInteger

2.5.2. INTRODUCCIÓN A LAS ENUMERACIONES.


Java viene con 8 tipos de datos primitivos predefinidos y una gran
cantidad de clases que definen otros muchos tipos de datos como los

68/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

String.Pero esto no es suficiente para cubrir todas las necesidades a las


que un programador debe enfrentarse. Por eso Java (como otros lenguajes
de alto nivel) tiene que dar al programador la posibilidad de crear sus
propios tipos de datos.
En Java esto se hace principalmente definiendo nuevas clases. Pero ahora
comentamos un caso particular de creación de nuevos tipos de datos
mediante el uso de unas clases especiales deominadas enumeraciones
(tipos enumerados).
Nos la podemos imaginar como un tipo de dato que puede tomar una lista
fija de posibles valores que se indican cuando se define el tipo. La sintaxis
para definir de forma simplificada la enumeración:
enum nombre_del_tipo { lista_de_valores }

Esta definición es mejor que esté fuera de un método como main() de un


programa, mejor dentro de una clase o fuera (porque la propia
enumeración es una clase). La lista de valores es una lista de
identificadores (nombres separados por comas), que en realidad son
nombres de objetos de esa clase. Por ejemplo, vamos a declarar un tipo
que se llame Estaciones y represente las estaciones del año:
enum Estaciones { PRIMAVERA, VERANO, OTOÑO, INVIERNO };

Por convención, los identificadores al ser constantes simbólicas se escriben


en mayúsculas y el nombre del tipo enumerado con la primera letra en
mayúscula (porque es una clase).
Las constantes simbólicas de la lista de identificadores se consideran
constantes simbólicas, que "están contenidas" en Estaciones, lo que
significa que para referirse a ellos debemos usar la notación punteada:
Estaciones.PRIMAVERA por ejemplo.

Una vez que el tipo de dato se ha declarado, puedes usarlo para crear
variables de ese tipo de dato, igual que usas los tipos int, boolean o String.
Por ejemplo:
Estaciones vacaciones; // vacaciones es variable de tipo Estaciones

69/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Después de declararla puedes asignarle cualquier valor siempre que sea


uno de los indicados en la definición. Ejemplo:
vacaciones = Estaciones.VERANO;

Si en el programa imprimes un valor del tipo enumerado, te saldrá el


nombre del identificador sin el tipo en el que está contenido. Ejemplo:
System.out.print( vacaciones ); // Se muestra VERANO

Como un tipo enum es técnicamente una clase, cada valor es técnicamente


un objeto y tiene ciertos métodos. Uno de ellos es ordinal() y devuelve el
orden que ocupa en la lista de valores. Ejemplo:
int z = vacaciones.ordinal();
int x = Estaciones.PRIMAVERA.ordinal(); // x vale 0, el primer elemento
int y = Estaciones.VERANO.ordinal(); // y vale 1, el segundo elemento

EJEMPLO 10: Vamos a hacer un pequeño programa de ejemplo que


muestra la utilidad de tener la capacidad de crear nuevos tipos de datos.
Tendríamos la opción de definirlos como constantes, sin embargo eso nos
obliga a incrementar código en salidas y validaciones.
enum Dia { DOM, LUN, MAR, MIE, JUE, VIE, SAB }
enum Mes {ENE, FEB, MAR, ABR, MAY, JUN, JUL, AGO, SEP, OCT, NOV, DIC}
public class DemoEnum {
public static void main(String[] args) {
Dia tgif; // variable de tipo Dia
Mes libra; // variable de tipo Mes
tgif = Dia.VIE; // Asignar un dia de la semana
libra = Mes.OCT; // Asignar un mes a libra
System.out.print("Mi signo es libra, porque he nacido ");
System.out.println(libra); // Muestra OCT
System.out.print("Es el " + libra.ordinal() +
" mes del año" +
" (Contando desde 0, claro!)");
System.out.print("Además, " + tgif + " es el " +
tgif.ordinal() + " dia de la semana");
} // final de main()
} // final de la clase DemoEnum

70/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Otras operaciones que pueden aplicarse a los tipos enumerados porque las
heredan de java.lang.Enum:
• name(): String con nombre de la constante. Ej: libre = Dia.DOM;
libre.name();
• toString(): String con nombre de la constante. Ej: libre.toString();
• ordinal(): entero con la posición del enum según está declarada.
Ej: libre.Ordinal(); // si es Dia.DOM vale 0
• compareTo(Enum otro): compara el enum con otro según el orden en
el que están declarados. Ej: libre.compareTo(Dia.LUN); // < 0
• values(): devuelve un array que contiene todos los enum. Ej:
Dia.values()[2]; // el valor es Dia.MAR

2.6. ENTRADA Y SALIDA DE DATOS.


La forma más básica de sacar datos desde un programa Java ya la hemos
usado y es la función System.out.print(x), donde x puede ser un valor o
una expresión de cualquier tipo. Si el parámetro no es un String, se
convierte a String y se imprime por lo que se conoce como salida estándar
(normalmente la salida estándar de un programa está asociada a la
pantalla de una consola también llamada terminal o ventana de línea de
comandos). También puede cambiarse esto desde el sistema operativo o
desde el programa y asociarla a un fichero ( c:\java EnumDemo >
fichero.txt) o a otro programa con una tubería de GNU/Linux ( ~$ java
EnumDemo | count). Aunque en los programas que usan interfaz gráfica
(GUI) debe redirigirse a otro lugar, porque los usuarios no pueden ver
esta información (no hay consola).
SALIDA BÁSICA DE DATOS (System.out)

System.out.print(x) y System.out.println(x)
Ambas muestran x por pantalla (por defecto), con la diferencia de
quedarse en la misma línea o saltar una línea después de imprimir. De
forma que System.out.println(x) equivale a:
System.out.print(x); System.out.print( x + "\n" );
System.out.println(); o bien a:
System.out.printf( "formato", lista_de_valores )

71/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Si imprimes un número con decimales, como π, su salida será


3.141592653589793 y cuando imprimas cantidades de dinero en euros,
obtendrás cifras como 1050.0 o 43.5753333, etc. Quizás prefieras o necesites
controlar la cantidad de decimales que aparecen cuando muestras un
número con decimales (por ejemplo, por ley, las cantidades de dinero en
una factura deben tener siempre exactamente dos decimales). Controlar
como se visualizan los valores se llama formatear la salida.

La función System.out.printf() puede mostrar datos formateados. El


primer parámetro es un String que indica el formato (la apariencia) con la
que escribir uno o más datos a imprimir. El resto de parámetros que
siguen son los propios datos a imprimir. Ejemplo de uso:
double importe = 321.783;
System.out.printf( "%1.2f", importe );

En el String formato, cada vez que se quiera incluir un dato se escribe el


carácter porcentaje (%). En el ejemplo de arriba, como solo queremos
escribir un dato, el porcentaje solo aparece una vez. El especificador de
formato del dato es: %1.2f.

Algunos formatos típicos son: %d, %12d, %10s, %1.2f, %15.8e y %1.8g
Cada campo comienza con el porcentaje (%) y acaba con una letra
indicando el tipo de dato y entre medias hay indicadores del formato.
-
% indicadores tipo % 12 d
Por ejemplo %d y %12d, donde la letra “d” indica que se escribe un número
entero en decimal y la cantidad "12" del formato %12d indica la cantidad
mínima de espacios que ocupa la salida (el ancho). Si el valor mostrado
ocupa menos, se rellena con blancos los espacios que faltan hasta llegar a
12. Se dice que la salida está justificada a la derecha porque los espacios de
relleno se ponen a la izquierda. Si el valor tiene más de 12 dígitos, se
imprimen todos. Un formato %d equivale a %1d. Puedes usar también una
“x” para imprimir el número en hexadecimal.
La letra “s” al final de un formato indica String. Un número como en %20s,

72/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

indica la cantidad mínima de caracteres a usar. La "s" puede utilizarse


para String o para cualquier tipo que se convierta a String.
El formato para valores numéricos con decimales es el más complejo. Una
letra “f”, como en %1.2f, se usa para indicar un valor en punto flotante. El
1.2 significa que como mínimo se usa un espacio de ancho y el 2 es el
número de dígitos decimales que aparecen en el valor mostrado. Por
ejemplo, %12.3f indica que se muestra un valor numérico flotante con 3
decimales, con un ancho total de 12 ( signo + dígitos enteros + punto
decimal + dígitos decimales = 12 ), es decir, (1+digitos_enteros+1+3=12 ->
5+digitos_enteros=12 -> digitos_enteros=7 ) y justificado a la derecha.

Si quieres notación científica usas la letra e de exponente. Los valores


flotantes muy grandes o muy pequeños se escriben en notación científica
(exponencial), como 6.00221415e23, que representa “6.00221415
multiplicado por 10 elevado a 23”. El especificador %15.8e indica un
formato exponencial "e", letra e con 8 dígitos después del punto decimal.
Si usas la “g” en vez de la “e”, la salida se muestra en notación científica
para valores muy pequeños o muy grandes y en punto flotante para el
resto. En %1.8g, el 8 indica el número total de dígitos (incluyendo los de
antes del punto decimal y los de detrás).
En valores numéricos puedes usar la coma (,), que provoca que los dígitos
se separen en grupos para hacer más sencilla la lectura. En USA, los
grupos se separan con comas. Por ejemplo, si x es un billón, ejecutar
System.out.printf("%,d", x) muestra la salida 1,000,000,000. En otros países, el
separador decimal es la coma y el separador de grupos es el punto. La
coma debe ser el primer carácter de formato que aparezca. Ej: %,12.3f
Si quieres que la salida se justifique a la izquierda en vez de a la derecha,
debes indicarlo con un signo menos (-) en el formato. Ejemplo: %-20s.
Además de los especificadores de formato, la cadena de formato puede
contener otros caracteres que se imprimen en la salida tal y como
aparecen. Por ejemplo: si x e y son variables de tipo int, podrías ejecutar:
System.out.printf("El producto de %d por %d es %d", x, y, x * y);

73/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Si quieres que en la salida aparezca un carácter porcentaje, puedes usar el


especificador %%. Puedes usar %n para mostrar un salto de línea. También
puedes usar el carácter de escape, la contrabarra (\), para indicar dobles
comillas, tabuladores, etc.
FORMATEAR TEXTO CON String.format()
Un String también tiene la posibilidad de aplicar formato a su contenido e
incrustar campos de diferentes tipos de datos con el formato que quieras.
Comparte con printf() los indicadores. Ejemplo:
String.format("Hoy es %1$te/%1$tm/%1$tY", new Date() )

Creará una cadena con la fecha de hoy. Los especificadores de formato


tienen esta sintaxis (ten en cuenta que los corchetes en [x] indican que x es
opcional, no es obligatorio que aparezcan):
%[índice$][flags][ancho_mínimo][.precisión]conversión
El significado de cada elemento es:
• %: indica que aparece un campo de datos.
• Índice$: es opcional, si no lo indicas los argumentos se usan en el
orden en que aparecen String.format("%d %d", 1, 2) genera la
cadena "1 2". Sin embargo String.format("%2$ d %1$d", 1, 2)
genera la cadena "2 1". Es decir, indice es un número entero que
indica el número de argumento detrás de la cadena que quieres
usar para mostrar el campo. Te permite usar el mismo varias veces
como en el ejemplo, o saltar el orden en que aparecen los campos.
El primer argumento es "1$", el segundo es "2$", etc.
• flags: opcional, una o varias letras indican como quieres visualizar
un argumento. Cada tipo de dato tiene los suyos propios.
• Ancho: número decimal positivo que indica el número mínimo de
caracteres que se generan para el campo. Si al convertirlo no se
alcanza, se rellena con espacios en blanco hasta que se alcance.
• Precisión: decimal no negativo usado para restringir la cantidad
de dígitos decimales que se visualizan.
• Conversión: es una letra obligatoria que indica cómo debe ser

74/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

formateado el valor de la expresión. Según el tipo de la expresión


podremos usar solo los que sean compatibles. Para el caso de
fechas y horas, después de indicar la letra de conversión (t ó T) hay
que indicar qué parte de la fecha/hora quieres usar.
La conversión puede agruparse en varias categorías:
• General: se aplica a varios tipos de datos.
• Caracter: aplicados a char, Character, byte y short.
• Integral: aplicado a tipos numéricos sin decimales como byte,
Byte, short, Short, int, Integer, long, Long y BigInteger
• Floating Point: aplicada a valores numéricos con decimales como
float, Float, double, Double y BigDecimal
• Date/Time: aplicada a tipos que pueden representar valores de
tiempo como fechas y horas: long, Long, Calendar, Date y
TemporalAccessor
• porcentaje: sirve para obtener el caráctet '%'.
• Separador: obtiene separador de línea propio de la plataforma.
Nota: la versión mayúscula de la conversión indica salida en mayúscula.
La siguiente tabla recoge conversiones disponibles (detrás de carácter '%':

Conversión Categoría Descripción

'b', 'B' general Si argumento es null, false. Si es boolean o


Boolean, String.valueOf(arg). En otro caso true

'h', 'H' general Si argumento es null, "null". En otro caso


devuelve Integer.toHexString( arg.hashCode() )

's', 'S' general Si argumento es null, "null". En otro caso


devuelve argumento.toString().

'c', 'C' character Devuelve el carácter Unicode

'd' integral Devuelve un entero decimal

'o' integral Devuelve un entero octal

'x', 'X' integral Devuelve un entero hexadecimal

'e', 'E' Flo. point Notación científica: valor e+/-valor

75/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Conversión Categoría Descripción

'f' Flo. point Valor decimal con decimales

'g', 'G' Flo. point Según el tamaño del valor f ó g

'a', 'A' Flo. point Devuelve cadena hexadecimal de mantisa y


exponente (no para BigDecimal)

't', 'T' date/time Conversión de tiempo. Necesita otra letra

'%' porcentaje Devuelve el literal '%' ('\u0025')

'n' separador Devuelve el separador de línea de la plataforma

Las conversiones de tiempo (fecha y hora) necesitan un segundo carácter


de conversión para indicar qué parte del dato es la que quieres usar. En
esta tabla tienes los que seleccionan un solo campo de la fecha o la hora.

Letra Descripción

'B' Nombre completo del mes

'b', 'h' Nombre del mes abreviado

'A' Nombre completo del día de la semana

'a' Nombre abreviado del día de la semana

'C' Centuria con 2 dígitos. Devuelve de "00" a "99"

'Y' Año con 4 dígitos

'y' Últimos dos dígitos del año

'j' Día del año. De 001 a 366

'm' Número de mes con 2 dígitos. 01 - 12

'd' Día del mes con 2 dígitos: 01 - 31

'e' Día del mes: 1 - 31.

'H' Horas

'M' minutos

'S' segundos

76/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

Letra Descripción

'p' Antes o después del medio día

'I' Hora en formato 12 horas

'z' y 'Z' Timezone y timezone abreviada

'L' Milisegundos

'N' nanosegundos

Y esta contiene modificadores que equivalen a varios de ellos combinados:

letra Descripción

'R' Reloj formato 24 horas. Como "%tH:%tM"

'T' Reloj formato 24 horas. Como "%tH:%tM:%tS"

'r' Reloj formato 12 horas. Como "%tI:%tM:%tS %Tp"

'D' Fecha con formato "%tm/%td/%ty"

'F' Fecha con formato ISO 8601. Como "%tY-%tm-%td"

'c' Fecha y hora. Como "%ta %tb %td %tT %tZ %tY". Ej:
"Sun Jul 20 16:17:00 EDT 1969"

Flags
La siguiente tabla resume flags y con qué categorías se pueden usar.
c I
G Fl
a n
e oa
r t
n ti
á e tie
Flag e ng Descripción
c g mpo
r Po
t r
a in
e a
l t
r l

'-' y y y y y Justificado a la izquierda

'#' y - y y - Conversión alternativa

'+' - - y y - Siempre incluye signo

77/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

' ' - - y y - Incluye espacio de relleno en valores positivos

'0' - - y y - Relleno con ceros

',' - - y y - Incluye separadores de miles

'(' - - y y - Negativos encerrados en paréntesis

ENTRADA BÁSICA DE DATOS CON Scanner.


Por alguna razón, Java nunca se ha preocupado de hacer sencilla la lectura
por consola de valores de cierto tipo a los usuarios de un programa,
mientras que acertó al crear el objeto System.out para facilitar la salida, el
que se encarga de la entrada, el objeto System.in es muy primitivo y no
muy sencillo de usar.
Hasta Java 5.0 no se simplifica la entrada de datos mediante la clase
java.util.Scanner. Pero necesita algo de conocimiento de orientación a
objetos (no es lo ideal para empezar). Java 6 introduce la clase Console
para comunicar a los programas con los usuarios, pero tiene sus propios
problemas. Así que vamos a comenzar a utilizar la clase Scanner.
Para poder crear objetos de la clase Scanner, debes importar la definición
de la clase antes de usarla:

import java.util.Scanner;

Dentro de la clase del programa, declararlo global (variable de la clase con


el modificador static) o local dentro del método main(), debes crear un
objeto de la clase. Ejemplo:
Scanner sc = new Scanner( System.in );
Esta declaración crea una variable llamada sc que puede almacenar una
referencia (flecha) a un objeto de tipo Scanner. El operador new crea un
objeto de la clase Scanner y la referencia al objeto se guarda en la variable
sc. A partir de este momento, a través de la variable sc tienes acceso a una
variedad de métodos que te permiten leer datos desde el teclado, puesto
que has conectado el Scanner a System.in que está conectado al teclado por

78/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

defecto.
Por ejemplo, la función sc.nextInt() lee un valor de tipo int y lo
devuelve. Si el valor tecleado por el usuario no es un entero correcto, el
programa lanza una excepción. El valor tecleado debe estar seguido de un
espacio en blanco o un final de línea.
Hay dos grupos principales de sentencias: las que leen del origen al que
conectas el Scanner (de nombres nextX() donde X pueden ser varios tipos
de datos) y otras que antes de leer comprueban si lo que hay es lo que
pides (comienzan por hasNextX()) Algunas funciones del objeto de tipo
Scanner, primero las que leen y luego las que comprueban:
• sc.nextInt() y sc.hasNextInt() comentada antes.
• sc.nextByte() y sc.hasNextByte() lee un byte.
• sc.nextShort() y sc.hasNextShort() lee un entero short.
• sc.nextLong() y sc.hasNextLong() lee un entero long.
• sc.nextBigInteger() y sc.hasNextBigInteger() lee entero
grande.
• sc.nextBigDecimal() y sc.hasNextBigDecimal() lee decimal
grande.
• sc.nextFloat() y sc.hasNextFloat() lee un float.
• sc.nextDouble() y sc.hasNextDouble() lee un double.
• sc.nextBoolean() y sc.hasNextBoolean() lee true o false.
• sc.nextLine() y sc.hasNextLine() lee String incluido el salto de
línea y se posiciona en la siguiente línea.
• sc.next() y sc.hasNext() lee una palabra (hasta el primer
espacio/salto).

Tiene muchos más: reset() para volver a empezar a leer desde el inicio,
skip() para saltar algún elemento, useDelimiter() para cambiar caracteres
que se considerarn separadores, etc. Pero los básicos son los comentados.
EJEMPLO 11: Un programa que lee datos de un fichero:
import java.util.Scanner; // Poder usar la clase Scanner

79/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

public class InteresConScanner {


public static void main(String[] args) {
Scanner stdin = new Scanner( System.in ); // Crear objeto Scanner
double principal; // valor del capital
double ratio; // ratio anual
double intereses; // ganancia anual aportada por el interés
System.out.print("Teclee el capital a invertir: ");
principal = stdin.nextDouble();
System.out.print("Teclee el interés anual (con decimales): ");
ratio = stdin.nextDouble();
intereses = principal * ratio; // Calcular importe
principal = principal + intereses; // Sumar al capital
System.out.printf("La ganancia es %1.2f€%n", intereses);
System.out.printf("Total después del año %1.2f€%n", principal);
} // final de main()
} // final de la clase del programa

Con Scanner, el inconveniente es que a parte de que leer información


incorrecta (pides un entero y te escriben una palabra por ejemplo) puede
hacer que el programa falle, además, aparecen ciertos fallos cuando se
mezcla la lectura de valores con todos los nextX() que quieras y después
usar nextLine().

Cuando llamas a nextInt(), nextDouble(), ... next() y luego llamas a


nextLine() aparece un problema y es que no llega a leer la línea.

EJEMPLO 12: fragmento de código con el problema de pérdida de


entradas y su remedio.
System.out.print("Cuantos años tiene: ");
edad = sc.nextInt();
System.out.print("Como se llama: ");
nombre= sc.nextLine(); // No leerá el nombre, lo deja vacío

Problema: Si el usuario teclea 25 y pulsa enter, por ejemplo, nextInt() se


deja el salto de línea pendiente de leer, es decir va leyendo letras que estén
juntas y cuando encuentra el primer separador, transforma en entero las
letras que ha leído y las borra, pero deja el resto de lo que haya (en el
teclado en este caso). Si a continuación pides un string con nextLine(), se
encuentra ese salto pendiente de quitar y piensa que el usuario ha pulsado

80/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

enter y devuelve la cadena vacía de forma automática, como si el usuario


hubiese pulsado enter cuando en realidad el usuario no ha tecleado nada.
Solución: si es seguro que antes de llamar a nextLine() has dejado
pendiente un salto de línea (por haber llamado a nextInt() por ejemplo)
puedes eliminarlo haciendo dos llamadas, la primera para quitar el salto
pendiente y la segunda para leer lo que teclee el usuario. El código
anterior lo puedes cambiar por este otro:
System.out.print("Cuantos años tiene: ");
edad= sc.nextInt();
System.out.print("Como se llama: ");
sc.nextLine(); // Este para quitar el salto
nombre= sc.nextLine(); // Ahora si lee lo que teclea el usuario

Además puedes conectar el Scanner para leer desde un fichero de disco:


Scanner sc = new Scanner( new FileInputStream( "fichero.txt") );

O tambien leer datos desde un String:


String entrada = "1 Manolo 1/2/1920 \n2 Antonia 3/3/1960";
Scanner sc = new Scanner( entrada );
if( sc.hasNext() )
System.out.println( "Empleado Id: " + sc.nextInt() +
" nombre: " + sc.next() +
" nace: " + sc.next() );

ENTRADA Y SALIDA SENCILLA CON FICHEROS TEXTO


Si necesitamos escribir datos en un fichero de texto, podemos usar un
objeto java.io.PrinWriter que nos ofrece métodos similares a System.out.
La diferencia es que debemos conectarlo a un fichero y cuando acabemos
de escribir y ya no lo necesitemos más, cerrarlo. También nos obliga Java a
proteger la creación porque podemos tener errores en tiempo de ejecución
(se explica en la próxima unidad):
PrintWriter pw = null;
try {
pw = new PrintWriter( new File("ejemplo.txt"); ) {
pw.println("Paco");

81/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

pw.print("Trabajo actual: camarero ");


pw.printf("Sueldo %,.2f€\n", 1200 * 0.33);
} catch(IOException ioe){
System.out.println(ioe.getMessage());
} finally {
if(pw != null) pw.close();
}

Para leer las líneas de un fichero de texto de manera sencilla también


podemos usar un Scanner, pero en vez de conectarlo al reclado, lo
conectamos a un fichero. Como antes, debemos dejar el código protegido
y cerrar el Scanner cuando acabemos la lectura.
Es importante minimizar la cantidad de accesos a disco que hacemos
porque son operaciones mucho más lentas que cuando trabajamos en
memoria.
Scanner scFichero = null;
try {
sc = new Scanner( new File("ejemplo.txt"); ) {
if(scFichero.hasNextLine()) {
String linea = scFichero.nextLine();
Sytem.out.println(linea);
}
} catch(IOException ioe){
System.out.println(ioe.getMessage());
} finally {
if(scFichero != null) scFichero.close();
}

2.7 SENTENCIAS DE DECISIÓN.


Hasta ahora las instrucciones que hemos visto se ejecutan
secuencialmente, es decir, podemos saber lo que hace el programa
leyendo las líneas de izquierda a derecha y de arriba abajo.
Las instrucciones o sentencias de control de flujo permiten alterar esta
forma de ejecución. A partir de ahora habrá sentencias en el código que se
ejecutarán o no, dependiendo de una condición.
EXPRESIONES LÓGICAS
Una condición se define utilizando una expresión lógica. Una expresión

82/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

lógica es cualquier tipo de expresión Java que dé un resultado booleano


(verdadero o falso). Las expresiones lógicas se construyen por medio de
variables booleanas o con los operadores relacionales (==, >, <,…) que
comparan dos valores formando lo que se conoce como una condición
simple. Ejemplo:
int edad = 17;
boolean mayorDeEdad = edad >= 18;

Varias condiciones sencillas pueden unirse para formar condiciones


compuestas mediante los operadores lógicos (&&, ||, !). Ejemplo:
int edad = 17;
boolean mayorDeEdad = edad >= 18;
boolean tienePermisoConducir = false;
boolean puedeConducir = mayorEdad && tienePermisoConducir;

BLOQUES DE SENTENCIAS
El bloque de sentencias es la sentencia compuesta más simple. Su
propósito simplemente es agrupar varias sentencias para que funcionen
como una única sentencia. La sintaxis de un bloque es:
{
sentencia_o_sentencias;
}
El bloque comienza por una llave quebrada { y acaba en otra llave
quebrada }. Dentro puede no haber nada (bloque vacío) o puede tener una
o varias sentencias separadas por puntos y coma u otros bloques de
sentencias dentro (anidados).
Hay un lugar donde es obligatoria la existencia de un bloque: como
puedes imaginar, el método main() debe tener obligatoriamente un bloque
de sentencias. Dos ejemplos de bloques:
{
System.out.print("La respuesta es ");
System.out.println(respuesta);
}
{ // Este bloque intercambia los valores de x e y

83/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

int temp; // una variable temporal del bloque


temp = x; // guarda una copia de x en temporal
x = y; // Copia el valor de y a x
y = temp; // Copia el valor de temp a y
}

En el segundo bloque se declara una variable. Su ámbito será el bloque, no


puedes usarla fuera, es una variable local al bloque.
2.7.1 SENTENCIAS DE DECISIÓN ALTERNATIVA.
Sirven para ejecutar algunas sentencias de forma condicional, solo si se
dan o se cumplen ciertas condiciones que el programador define.
DECISIÓN SIMPLE
Se trata de una sentencia que, tras evaluar una condición, ejecuta una serie
de instrucciones en caso de que sea verdadera. Si la condición da
resultado falso, no se ejecutan las sentencias y se continúa por la siguiente
sentencia . Su sintaxis es:
if (condición) {
sentencias …
}

Las llaves son obligatorias sólo cuando


hay varias sentencias. En otro caso se
puede escibir el if sin llaves o con llaves:
if (condición) sentencia;

EJEMPLO 12: de sentencia if


if( nota >= 5 ) {
System.out.println("Aprobado");
aprobados++;
}

DECISIÓN SIMPLE DOS ALTERNATIVAS EXCLUYENTES.


Igual que la anterior, pero se añade una
parte else que contiene instrucciones que se
ejecutan si la condición es falsa. Sintaxis:

84/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

if (condición) {
instrucciones_si_cierta;
} else {
instrucciones_si_falsa;
}

Como en el caso anterior, las llaves son necesarias sólo si se ejecuta más de
una sentencia.
EJEMPLO 13: de sentencia if-else:
if( nota >= 5 ) {
System.out.println("Aprobado");
aprobados++;
}
else {
System.out.println("Suspenso");
suspensos++;
}

ANIDACIÓN DE SENTENCIAS
Dentro de una sentencia if se puede escribir otra sentencia if. A esto se le
llama anidación y permite crear programas donde se contemplan
escenarios que tengan más de dos posibilidades. La nueva sentencia
puede ir tanto en la parte if como en la parte else o en ambas partes. Las
anidaciones se utilizan mucho. Sólo hay que tener en cuenta que siempre
se debe cerrar primero el último if que se abrió. Es muy importante
también indentar (tabular) el código correctamente para que las
anidaciones sean legibles. El código podría ser:
if(x == 1) {
instrucciones …
if(y > 4) {
instrucciones …
}
} else {
if( x == 2) {
instrucciones …
} else {
if(x == 3) {
instrucciones …

85/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

}
}
}

EJERCICIO 7: Examina estos dos fragmentos de código que parecen ser


equivalentes. ¿Realmente lo son? Encuentra las diferencias.
int y; int y;
if (x < 0) { if (x < 0) {
y = 1; y = 1;
} }
else { if (x >= 0) {
y = 2; y = 2;
} }
System.out.println(y); System.out.println(y);

EJERCICIO 8: Vuelve a examinar ahora estos dos fragmentos de código


que parece que hacen lo mismo. Averigua el valor de x.
int x; int x;
x = -1; x = -1;
if (x < 0) if (x < 0)
x = 1; x = 1;
else if (x >= 0)
x = 2; x = 2;

ENCADENAR SENTENCIAS IF
En un solo if puedes como máximo abarcar dos posibilidades (si la
exprexión es cierta, las sentencias del if y en caso contrario las del else).
Pero si tienes un escenario en el que tu programa debe abarcar 3 ó más
posibilidades excluyentes, debes anidar setencias if hasta abarcar todas las
posibilidades.
Una forma de hacerlo es: en la parte if contemplas una y en el else el resto
de las posibilidades que quedan pendientes de controlar:
if (x == 1) {
instrucciones …
} else {
if( x == 2) {
instrucciones …
} else {

86/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

if(x == 3) {
instrucciones …
}
}
}

Una forma más legible de escribir ese mismo código sería no anidar las
sentencias, si no encadenarlas (que la sentencia del último else sea otro if):
if (x==1) {
instrucciones…
} else if (x==2) {
instrucciones…
} else if (x==3) {
instrucciones…
}

Lo que consigues es tener


sentencias que pueden
realizar una ejecución
condicional múltiple, es
como tener otra sentencia
if-else-if, tal y como se ve
en el diagrama de la
figura.
EJEMPLO 14: Haz un programa en Java que lea 3 números enteros
llamados n1, n2, n3 y los imprima en orden ascendente (de menor a mayor
valor).
Si en cada if solo comprobamos una posibilidad, tenemos 9 posibilidades
a contemplar y tendremos que anidar muchas sentencias. Para abreviar el
código, un buen enfoque es fijarnos en la primera variable y decidir si es la
menor, y si no comprobar si es la mayor, y si tampoco, es que está en el
medio. En pseudocódigo:
SI (n1 < n2 Y n1 < n3) ENTONCES // n1 es el menor
ESCRIBIR n1, (y las otras en el orden correcto)
SINO SI (n1 > n2 Y n1 > n3) ENTONCES // n1 es mayor
ESCRIBIR (n2 y n3 en el orden correcto), n1
SINO // n1 es intermedio

87/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

ESCRIBIR n1 entre (n2 y n3 en el orden correcto)


FIN SI
FIN SI

Averiguar el orden de n2 y n3 (lo que hay entre paréntesis en cada caso)


necesita otra sentencia if, así que quedaría:
SI (n1 < n2 Y n1 < n3) ENTONCES // n1 es el menor
SI n2 < n3 ENTONCES
ESCRIBIR n1, n2, n3
SINO
ESCRIBIR n1, n3, n2
FINSI
SINO
SI (n1 > n2 Y n1 > n3) ENTONCES // n1 es mayor
SI n2 < n3 ENTONCES
ESCRIBIR n2, n3, n1
SINO
ESCRIBIR n3, n2, n1
FINSI
SINO // n1 es intermedio
SI n2 < n3 ENTONCES
ESCRIBIR n2, n1, n3
SINO
ESCRIBIR n3, n1, n2
FINSI
FIN SI
FIN SI

Este enfoque funciona bien incluso si algunos de los valores son iguales.
Nota: observa que en las expresiones lógicas no podemos escribir n1 < n2
and n3 (n1 menor que n2 y n3) porque el operador "menor que" necesita
dos valores a comparar, y el operador "and" necesita dos valores true/false
a mezclar. Pero n3 en este caso es un número entero, no un booleano. En
Java esta expresión da un error sintáctico. En otros lenguajes como C++,
no da error, pero se interpreta distinto a como se debe escribir de forma
correcta: n1 < n2 and n1 < n3.
Hay más enfoques alternativos.
import java.util.Scanner;

88/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

public class Leer3 {


static public void main( String args[] ) {
Scanner teclado = new Scanner( System.in );
int n1, n2, n3;
int menor, mayor, intermedio;
System.out.print("Teclee n1: ");
n1= teclado.nextInt();
System.out.print("Teclee n2: ");
n2= teclado.nextInt();
System.out.print("Teclee n3: ");
n3= teclado.nextInt();
if (n1 < n2 && n1 < n3) { // n1 es el menor
menor = n1;
if (n2 < n3) {
intermedio = n2;
mayor = n3;
} else {
intermedio = n3;
mayor = n2;
}
} else if (n1 > n2 && n1 > n3) { // n1 es mayor
mayor = n1;
if(n2 < n3) {
intermedio = n3;
menor = n2;
} else {
intermedio = n2;
menor = n3;
}
} else { // n1 es intermedio
intermedio = n1;
if(n2 < n3) {
menor = n2;
mayor = n3;
} else {
menor = n3;
mayor = n2;
}
}
System.out.println(menor+ " " + intermedio + " " + mayor);
} // Fin de main

89/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

} // Fin de la clase

EJEMPLO 15: Hacer un programa que convierta medidas de longitud de


unas unidades de medida (pulgadas, pies, yardas, millas y metros). El
usuario tecleará por ejemplo: “17 pies” o “2.73 millas” o "74.2 metros" o
"32.9 yardas". El programa mostrará la equivalencia con el resto de
unidades. El algoritmo en pseudocódigo es sencillo:
Leer número
Leer unidad
SI unidad no es pulgadas ENTONCES
Convertir número de unidad en pulgadas
Mostrar pulgadas
FINSI
:
SI unidad no es metros ENTONCES
Convertir unidad en metros
Escribir los metros
FINSI

Este programa, usa otro algoritmo. Pasamos a una unidad y de esa unidad
convertimos al resto:
/**
* Convierte unidades de longitud: pulgadas, pies, yardas, millas,
* y metros
* El usuario teclea: número unidad
* El programa muestra la equivalencia con el resto de unidades.
*/
package ejer32;
import java.util.Scanner;
public class ConversorLongitud {
public static void main(String[] args) {
Scanner teclado = new Scanner( System.in );
double valor; // cantidad numérica
String unidad; // unidad de medida
double pulgadas, pies, yardas, millas, metros; // valores
boolean correcta= true; // indica si unidad es Ok
System.out.print("Telee (valor unidad): ");
valor = teclado.nextDouble();

90/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

// Quizás debas hacer algo con el escaner?


unidad = teclado.next();
unidad = unidad.toLowerCase(); // convertir a minúscula
if(unidad.equals("pulgadas") || unidad.equals("pulgada")) {
pulgadas = valor;
} else if (unidad.equals("pies") || unidad.equals("pie") ) {
pulgadas = valor * 12;
} else if(unidad.equals("yardas") ||unidad.equals("yarda")){
pulgadas = valor * 36;
} else if(unidad.equals("millas") ||unidad.equals("milla")){
pulgadas = valor * 12 * 5280;
} else if(unidad.equals("metros") ||unidad.equals("metro")){
pulgadas = valor * 39.37;
} else {
System.out.println("No comprendo \"" + unidad + "\".");
correcta= false;
pulgadas= -1; // para evitar un error de valor
}
/* Convierte desde pulgadas */
if (correcta) {
pies = pulgadas / 12;
yardas = pulgadas / 36;
millas = pulgadas / (12 * 5280);
metros = pulgadas / 39.37;
System.out.printf("%12.5g pulgadas", pulgadas);
System.out.printf("%12.5g pies", pies);
System.out.printf("%12.5g yardas", yardas);
System.out.printf("%12.5g millas", millas);
System.out.printf("%12.5g metros", metros);
}
teclado.close(); // para evitar un warning de Eclipse
} // fin del main()
} // fin clase

Ejecución en Eclipse:

91/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

2.7.2. DECISIÓN MÚLTIPLE.


Se la llama estructura condicional compleja porque permite evaluar
varias posibilidades a la vez. En realidad sirve como sustituta de
expresiones de tipo if-else-if (if encadenados). Por tanto debes aplicarla
cuando tengas que contemplar en tu programa muchas alternativas,
porque el código queda más claro que usar muchos if encadenados.
Sintaxis (los corchetes de [x] no se escriben, indican que x es opcional):
switch (expresión) {
case valor1: instrucciones_del_valor_1;
[break;]
[case valor2: instrucciones_del_valor 2;
[break;]]
[...]
[default: instrucciones_si_expresión_no_toma_valores_anteriores;]
}

Esta instrucción evalúa una expresión y según su valor ejecuta


instrucciones. Cada case contiene un valor posible de la expresión. Si
efectivamente la expresión equivale a ese valor, se ejecutan las
instrucciones de ese case y de los siguientes.
La instrucción break se utiliza para salir del switch. De forma que si
queremos que para un determinado valor se ejecuten las instrucciones de
un apartado case y sólo las de ese apartado, entonces habrá que finalizar
ese case con un break. Si en un case no escribes el break, y en una ejecución
entra, también ejecutará las instrucciones del siguiente case, y de los
sucesivos hasta que encuentre un break. Eso sirve para que un varios
valores puedan ejecutar las mismas sentencias.
El bloque default es opcional y sirve para ejecutar instrucciones para los
// Equivale
casos en los que la expresión no se ajuste a ningúncon if-else-if
case a:
de los escritos
if(diaSemana == 1) dia="Lunes";
anteriormente. else if(diaSemana == 2)
dia="Martes";
EJEMPLO 16: expresar con switch.
else if(diaSemana == 3)
switch (diaSemana) { dia="Miércoles";
case 1: dia="Lunes"; else if(diaSemana == 4)
break; dia="Jueves";
else if(diaSemana == 5)
dia="Viernes";
92/105 else if(diaSemana == 6)
dia="Sábado";
else if(diaSemana == 7)
dia="Domingo";
else dia="?";
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

case 2: dia="Martes";
break;
case 3: dia="Miércoles";
break;
case 4: dia="Jueves";
break;
case 5: dia="Viernes";
break;
case 6: dia="Sábado";
break;
case 7: dia="Domingo";
break;
default: dia="?";
}
// Equivale con if-else-if a:
EJEMPLO 17: if(diaSemana == 1 ||
diaSemana == 2 ||
switch (diaSemana) { diaSemana == 3 ||
case 1: diaSemana == 4 ||
case 2: diaSemana == 5)
case 3: laborable= true;
case 4: else if(diaSemana == 6 || diaSemana == 7)
case 5: laborable=true; laborable= false;
break;
case 6:
case 7: laborable=false;
}

EJEMPLO 18: Menús y Sentencia switch. Una de las muchas aplicaciones


de la sentencia switch consiste en ofrecer menús de opciones al usuario de
un programa para que elija una de las acciones que puede realizar el
programa. Por ejemplo, vamos a hacer un programa que de al usuario la
posibilidad de elegir la conversión que quiere realizar.
Scanner teclado= new Scanner( System.in );
int opcion; // Nº de opción del menú
double valor; // valor numérico tecleado por el usuario
double pulgadas; // El valor convertido a pulgadas
/* Muestra el menú */
System.out.println("Escoja las unidades que va a teclear:");
System.out.println();
System.out.println(" 1. Pulgadas");
System.out.println(" 2. Pies");

93/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

System.out.println(" 3. Yardas");
System.out.println(" 4. Millas");
System.out.println(" 5. Metros");
System.out.println();
System.out.println("Escoja la opción (1-5): ");
opcion = teclado.nextInt();
/* Convertir a pulgadas */
switch ( opcion ) {
case 1: System.out.println("Teclee el número de pulgadas: ");
valor = teclado.nextDouble();
pulgadas = valor;
break;
case 2: System.out.println("Teclee el número de pies: ");
valor = teclado.nextDouble();
pulgadas = valor * 12;
break;
case 3: System.out.println("Teclee el número de yardas: ");
valor = teclado.nextDouble();
pulgadas = valor * 36;
break;
case 4: System.out.println("Teclee el número de millas: ");
valor = teclado.nextDouble();
pulgadas = valor * 12 * 5280;
break;
case 5: System.out.println("Teclee el número de metros: ");
valor = teclado.nextDouble();
pulgadas = valor * 39.37;
break;
default: System.out.println("Error! Número de opción incorrecta");
System.exit(1);
} // fin switch

EJEMPLO 19: Similar, pero usando un String en la expresión del switch y


reduciendo las sentencias de escritura:
Scanner teclado= new Scanner( System.in );
int opcion; // Nº de opción del menú
String unidad; // Unidades tecleadas por el usuario
double valor; // valor numérico tecleado por el usuario
double pulgadas; // El valor convertido a pulgadas
/* Leer las unidades del usuario */
System.out.println("Qué unidades de Longitud va a teclear?");
System.out.print("Legal: pulgadas,pies,yardas,millas o metros: ");

94/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

unidad = teclado.nextln().toLowerCase();
/* Leer valor y convertir */
System.out.print("Teclee el número de " + unidad + ": ");
valor = teclado.nextDouble();
switch ( unidad ) {
case "pulgadas": pulgadas = valor;
break;
case "pies": pulgadas = valor * 12;
break;
case "yardas": pulgadas = valor * 36;
break;
case "millas": pulgadas = valor * 12 * 5280;
break;
case "metros": pulgadas = valor * 39.37;
break;
default: System.out.println("Unidad de medida incorrecta!");
System.exit(1);
} // fin switch

EJEMPLO 20: Asignación Definida Mediante Switch. El siguiente


fragmento de código hace una asignación aleatoria entre 3 posibilidades.
Recuerda que usando la expresión (int)(Math.random() * 3) tendremos los
enteros 0, 1 o 2 seleccionados de forma aleatoria con la misma
probabilidad (1/3):
String computador;
switch ( (int)(3 * Math.random()) ) {
case 0: computador = "Piedra";
break;
case 1: computador = "Papel";
break;
case 2: computador = "Tijeras";
break;
}
System.out.println("El ordenador saca " + computador); // ERROR!

El compilador de Java no se fia de que la variable computador tenga


asignado un valor antes de imprimirla. El compilador en muchas
ocasiones no es lo suficientemente inteligente para darse cuenta que en
este caso, al menos, no hay posibilidad de error. Pero bueno, para dejarlo
contento, lo que haremos será añadir a la sentencia switch una parte

95/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

default.

String computador;
switch ( (int)(3*Math.random()) ) {
case 0: computador = "Piedra";
break;
case 1: computador = "Papel";
break;
case 2: computador = "Tijeras";
break;
default: computador= "Piedra"; // Nunca se ejecuta pero no lo sabe
}
System.out.println("El ordenador saca " + computador); // OK!

2.8. EJERCICIOS.
E1. TEST
1. Explica brevemente la diferencia entre la sintaxis y la semántica de un
lenguaje de programación o piensa en un ejemplo que lo muestre.
2. ¿Qué efectos tiene ejecutar una sentencia de declaración de variables
en el ordenador? Da un ejemplo.
3. ¿Qué es un tipo de dato en un lenguaje de programación?
4. Uno de los tipos primitivos de Java es boolean. ¿Qué es el tipo
boolean? ¿Qué valores usa?
5. Indica para qué se utilizan estos operadores de Java:
a) ++ b) && c) != d) % e) ^ f) new g) >> h) | i) = j) ? k) .
6. Explica los efectos de una sentencia de asignación y pon un ejemplo.
¿Cuántas sentencias de asignación conoces?
7. ¿Qué indica la precedencia de operadores? ¿Cómo se calculan las
expresiones? ¿Cómo se cambia este comportamiento?
8. ¿Qué es un literal en un programa?
9. En Java, las clases tienen dos propósitos fundamentales ¿Cuáles son?

96/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

10. ¿Por qué el resultado de evaluar la expresión 2 + 3 + "test" es "5test"


mientras el valor de "test" + 2 + 3 es "test23". ¿Cuál es el valor de "test" +
2*3?
11. Indica el tipo de dato de estos valores si aparecen en un programa
Java.
a) 9.0 e) 8 h) 15d k) 900F n) 258234
b) '8' f) "888" i)"16.0d" l) 15L o) "8"
c) 0x99 g) (int)9.1 j) 1e1 m) 256f p) 900L
d) 1.0e10

12. Indica el tipo de dato del valor obtenido al evaluar estas expresiones.
a)1/2 d)0x9F + 0x3D g)(int)(5 + 5.0) j)5>=2 || 1<3
b)6.0 % 9 e)1.0 * 1/1 h)9 + (double)4 k)5 >> 1 | 2
c) 1.5f + 3 f)(int)5.0 + 5.0 i)(double)5+"6" l)9F+3D

13. Explica el motivo de que este trozo de código genere un error de


compilación en Java.
int x1, x2;
double y = 1.0;
x1 = (int)y;
x2 = 1L;
14. Determina el resultado de la variable x al ejecutar este trozo de
código Java.
double x;
int y = 90;
x = y / 100;
System.out.println("x=" + x);
15. Escribe un programa en Java que realice los siguientes pasos.
a. Declara una variable float llamada f.
b. Declara una variable int llamada k.
c. Asigna 22.5 a f.
d. Asigna el valor de f a k.
e. Convierte el valor actual de f a short y lo imprime por
pantalla.
16. Aplica las convenciones de nombres y busca los tipos adecuados con
menos peso posible al declarar:

97/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

a. Para almacenar la edad de una persona.


b. Para contar los kilómetros que ha recorrido de un coche
(hasta 400 mil).
c. Para almacenar el índice de masa corporal de Ana.
d. Para saber si un año es o no bisiesto.
e. El nombre completo (apellidos incluidos) de una persona.
f. La fecha de contratación de un empleado.
g. La constante de Fagenbaum que vale 4,66920.
17. Sean a, b y c tres variables enteras que representan las ventas de tres
productos A, B y C, respectivamente. Utilizando dichas variables,
escribe las expresiones que representen las siguientes afirmaciones:
a) Las ventas del producto A son las más elevadas.
b) Ningún producto tiene unas ventas inferiores a 200.
c) Algún producto tiene unas ventas superiores a 400.
d) La media de ventas es superior a 500.
e) El producto B no es el más vendido.
f) El total de ventas esta entre 500 y 1000.
18. Dada una variable c de tipo carácter, escribe las expresiones que
representen las siguientes afirmaciones:
a) c es una vocal. c) c es un símbolo del alfabeto.
b) c es una letra minúscula. d) c es alfanumérico (letra o dígito).
19. Escribe una sentencia if para averiguar si un password es correcto:
a) Si el valor leído en la variable entera password es 1234.
b) Si el valor leído en la variable password de tipo String es “1234”.
E2. Escribe un programa en Java que usando ******* ****** ******
** ** ** * ** *
println() imprima tus iniciales en la salida estándar ** ** * ** *
** ** * ** *
con letras que ocupen 9x9 puntos y usen un ** ****** ******
asterisco para iluminar uno de los puntos. Por **** ** ** **
** ** ** **
** **
** **
ejemplo JRR podría ser: ******* **
****** **
** **
** **
**
**

E3. Escribe un programa que simule la tirada de un par de dados. Puedes


simular la tirada de un dado escogiendo uno de los números enteros 1, 2,
3, 4, 5 y 6 al azar (Mira el método Math.random()). Por ejemplo:
El primer dado saca un 3
El segundo dado saca 5
Tu tirada suma 8
98/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

E4. Escribe un programa que pregunte al usuario su nombre y lo salude


utilizando su nombre, pero en mayúsculas. Ejemplo:
Cómo se llama? Toni
Hola, TONI.

E5. Escribe un programa que ayude al usuario a contar el dinero de su


bolsillo. El programa le preguntará cuantas monedas de 50 céntimos tiene.
Luego le preguntará cuántas de 20 céntimos. Luego cuántas de 10
céntimos, cuántas de 5, cuántas de 2 céntimos y cuántas de 1 céntimo. Al
final, el programa mostrará cuánto dinero tiene en euros. Ejemplo:
Cuántas monedas de 50 céntimos? 2
Cuántas monedas de 20 céntimos? 3
Cuántas monedas de 10 céntimos? 4
Cuántas monedas de 5 céntimos? 3
Cuántas monedas de 2 céntimos? 0
Cuántas monedas de 1 céntimo? 6
En total tiene 2.21 euros

E6. Escribe un programa que pregunte al dueño de una granja cuantos


huevos han puesto hoy sus gallinas y calcule cuantos envases grandes
necesita (un envase grande tiene 144 huevos), cuantos envases de una
docena, cuantos de media docena y cuantos huevos sueltos le quedan sin
envasar. (Pista: Si tienes N huevos, tienes N/12 docenas y N%12 huevos
sin agrupar. Este ejercicio va de operaciones dividir y módulo). Ejemplo:
Cuántos huevos han puesto hoy? 308
Necesitas:
2 envases grandes.
1 envase de una docena.
1 envase de media docena.
Te quedan 2 huevos sin envasar.

E7. Escribe un programa que


pregunte por la fuerza (F)
ejercida por un operario que

99/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

tira de una carga, el ángulo (en grados) y la distancia (d) recorrida por la
carga en metros, y muestre el trabajo realizado (T) con 6 decimales:
Teclee Fuerza (Newtons): 10.5
Teclee distancia (metros): 2.1
T = F x d x cos(angulo) Teclee ángulo (grados): 45
Trabajo = 15,59170453 julios

E8. Haz un programa que pregunte al usuario por su nombre y dos


apellidos sin partículas (Toni de la Dehesa López -> Toni Dehesa López).
Lee y almacena toda la respuesta en una variable String. Rompe la cadena
en 3 subcadenas, una que contenga el nombre, otra que contenga el primer
apellido y otra que contenga el segundo apellido (Pista: para hacerlo
puedes localizar donde comienzan los apellidos averiguando la posición
de los espacios en blanco que separan unas palabras de otras). Luego el
programa te muestra cada parte de tu nombre, con las latras que tiene
cada una y cuales son tus iniciales. Ejemplo:

Teclee su nombre y dos apellidos (sin partículas): José Rosa Rodríguez


Su nombre es JOSÉ y tiene 4 letras.
Su primer apellido es ROSA y tiene 4 letras.
Su segundo apellido es RODRÍGUEZ y tiene 9 letras.
Sus iniciales son JRR.

E9. Escribe en un fichero de texto llamado “datos.txt” tu nombre en la


primera línea y 3 notas en controles de una asignatura (pueden tener
decimales). Haz un programa que lea la información por la entrada
estándar y muestre el nombre, las tres notas y la media de las notas.
a) Debes ejecutarlo de forma normal (para que tengas que pasarle la
información por teclado).
D:\java\e8\java E8
Antonio
4
5
6
Alumno: Antonio
Notas: 4, 5 y 6
Media: 5.00

100/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

b) Ahora lo ejecutas redirigiendo el fichero a su entrada estándar.


D:\java\e8\java E8 < datos.txt
Alumno: Antonio
Notas: 4, 5 y 6
Media: 5.00
E10. Escribe un programa que pregunte por los caballos de vapor de un
coche y muestre los Kilowatios de potencia que genera el motor, con 2
decimales. La conversión es: 1CV = 735.499 watios
Teclee los CV: 100
Equivalen a 73.55 Kw

E11. Escribe un programa que pregunte por un DNI (8 dígitos del 0-9) y
saque el mensaje "Correcto" si es correcto o "Incorrecto" si no lo es.
a) Leyendo un valor entero. Piensa en una desventaja.
b) Leyendo una cadena de texto. Sin usar expresiones regulares en
el método matches() de los objetos String, ni sentencias if-else, for,
while, do-while..
c) Leyendo una cadena de texto. Usando una expresión regular en
el método matches() de los objetos String, pero no sentencias de
control: if-else, while...
Teclee DNI (8 dígitos): 12345 Teclee DNI (8 dígitos): 12345ABC
Incorrecto Incorrecto

E12. Lee dos números enteros e imprime el mayor sin usar sentencias de
control.
E13. Lee dos números enteros e imprime si el mayor es el primero, si lo es
el segundo o si son iguales sin usar sentencias de control.
E14. Lee un CIF (8 dígitos y una letra como 12345678A) e indica:
• Si tiene la longitud correcta (9): true/false.
• Si hay 8 dígitos y una letra: true/false.

101/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

• La letra es legal: true/false. Si la letra del dígito de control es una


de estas: "TRWAGMYFPDXBNJZSQVHLCKE" es legal.
• CIF correcto: true/false. El resto de dividir las 8 primeras cifras
entre 23 te indica la posición de la letra del dígito de control dentro
de la cadena anterior.
No debe provocar errores de ejecución independientemente de la longitud
o el formato de la cadena que se lea. Puedes usar if-else.
E15. Pregunta por una cantidad. Si es mayor o igual de 5 le cobras la
unidad a 0.5. Si está entre 2 y 4 se la cobras a 0.6. Si es menor de 1 se la
cobras a 0.7. Si es menor de 0, cambia por 0. Muestra la cuenta de su
compra con 2 decimales de precisión.
E16. Utiliza el método CurrentTimeMillis() de la clase System para saber
cuantos milisegundos han pasado desde el 1 de enero de 1970 a las
00:00:00 horas hasta el momento de ejecutarlo. ¿Serías capaz de hacer un
programa que te diga la hora, los minutos y los segundos aprovechándote
de ese valor? Pista: si al valor le quitas los días, te quedan horas, minutos
y segundos...
E17. Usa la clase Date para crear e imprimir la fecha y hora actual, luego
genera e imprime la fecha de noche buena (el 24 de diciembre del año
actual) y usando su método getTime() indica cuantos días quedan por
pasar hasta esa fecha.
E18. Usa la clase java.util.Date para crear un objeto con la fecha y hora
actual. Luego crea un objeto de la clase SimpleDateFormat con este formato:
“yyyy/MM/dd HH:mm:ss”. Por último, imprime la fecha formateada con ese
formato.
E19. Usa ahora la clase java.util.Calendar para crear un objeto con la fecha y
hora actual. Luego crea un objeto de la clase SimpleDateFormat con este
formato: “yyyy/MM/dd HH:mm:ss”. Por último, imprime la fecha formateada
con ese formato pero antes muestra el día de la semana usando del
método get() de la clase Calendar:

102/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

E20. Usa la clase java.time.LocalDateTime para crear un objeto con su método


now() y luego imprimir datos con getYear(), getMonthValue(), getDayOfMonth(),
getHour(), getMinute() y getSecond().

E21. Crea un programa que pida por teclado un número decimal llamado
x e imprima por consola |x| (su valor absoluto, es decir si es menor que
cero imprime -x, y en otro caso x).
a) Usando una sentencia if.
b) Usando el operador ternario.
E22. Crea un programa que pida por teclado el tamaño de un tornillo y
muestre por pantalla el texto correspondiente al tamaño, según la
siguiente tabla:
de 1 cm (incluido) hasta 3 cm (no incluido) → pequeño
de 3 cm (incluido) hasta 5 cm (no incluido) → mediano
de 5 cm (incluido) hasta 6.5 cm (no incluido) → grande
de 6.5 cm (incluido) hasta 8.5 cm (no incluido) → muy grande
E23. Crea un programa que pida una fecha formada por tres valores
enteros (día, mes y año), y determine si la fecha corresponde a un valor
válido. Pista: se debe tener presente el valor de los días en función de los
meses y de los años. Es decir:
– Los meses 1, 3, 5, 7, 8, 10 y 12 tienen 31 días.
– Los meses 4, 6, 9 y 11 tienen 30 días.
– El mes 2 tiene 28 días, excepto cuando el año es bisiesto.
E24. Crea un programa que pida los coeficientes a y b de una ecuación de
primer grado y (ax+b=0) y calcule la solución y la imprima con 4
decimales de precisión. Ten en cuenta que existen tres posibles soluciones:
• Cuando a ≠ 0 existe la solución única x = -b/a.
• Cuando a = 0 y b ≠ 0 no existe solución.
• Cuando a = 0 y b = 0 existen infinitas soluciones.
E25. Crea un programa que lea un valor entero que representa el día de la
semana (1 = lunes, 2 = martes, … 7 = domingo). Haz que si el valor está
entre 1 y 7 escriba por pantalla su nombre o “día incorrecto” en caso de

103/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

ser un valor fuera del intervalo.


a) Usando sentencias if.
b) Usando sentencia switch.
E26. Crea un programa que lea el día de la semana (1 = lunes, 2 = martes,
… 7 = domingo). Con una sentencia switch haz que si el valor está entre 1
y 5 escriba por pantalla "laborable" y si está entre 6 y 7 escriba "fin de
semana" o si es otro valor escriba "dia incorrecto".
E27. Crea un programa que Ecuación Recta que Pasa por Puntos p1 y p2
lea las coordenadas de dos ==========================================

puntos (valores con Coordenadas (x y) de p1: 1 1


decimales). Coordenadas (x y) de p2: 3 2

Ecuación de la recta: y = 0.500 x + 0.500


A partir de ellos calcula la Pendiente: 0.500
pendiente (a) y el punto de Punto de corte: 0.500
corte (b) de la ecuación de la Tabla de valores:
recta que los une: y = ax + b. x | y = 0.500 x + 0.5000
-----+---------------------
Si la pendiente no se puede -1.0 | -0.000
calcular, porque px1 es igual -0.5 | 0.250
-0.0 | 0.500
que px2. 0.5 | 0.750
1.0 | 1.000
En otro caso, imprime la
ecuación y una tabla con los valores de la ecuación en los puntos x = -1.0, -
0.5, -0.0, +0.5, +1.0. Formatea la salida para mostrar valores alineados y
con 3 decimales de precisión.
Explicación de como hacer los cálculos a continuación:

104/105
1DAM PROG. UNIDAD 2. Primeros Pasos en Java.

105/105

También podría gustarte