Iniciación a Java

Sep 2020

Si ya tienes las herramientas de programación de Java JDK, con estos sencillos pasos te enseñamos a realizar tu primer programa en Java. ¡Es sencillo y portable!

Qué es Java

Java es un lenguaje de programación orientado a objetos que consiste en procesar ficheros de texto con extensión .java escritos por personas con un compilador, produciendo unos binarios eficientes y portables entre diferentes arquitecturas que son procesados por la máquina virtual de Java JVM.

La JVM es un software que se debe instalar en todos aquellos ordenadores que desean ejecutar programas escritos con Java. La JVM aporta una capa unificada e independiente entre los diferentes sistemas operativos para que los programadores únicamente deban aprender una sola interfaz de programación.

Por otro lado tanto Java como la JVM es software altamente eficiente ya que tanto en la compilación como en la ejecución de programas con Java se realizan multitud de optimizaciones sobre el código resultante, como por ejemplo el JIT Just In Time Compilation. Básicamente el JIT compila el código multiplataforma generado por el compilador a un código nativo específico de la plataforma en donde se está ejecutando para beneficiarse de las particularidades de la propia arquitectura que da soporte a la ejecución.

Por qué aprender a programar con Java

Java goza de una gran popularidad en el mundo del desarrollo de software y sobre todo en aquellas aplicaciones orientadas a Internet, hay muchas empresas importantes que le dan soporte y financian las evoluciones del lenguaje. Puede consultar el artículo de porqué java es el mejor lenguaje para aprender programar.

Como conclusión podemos indicar que Java es el lenguaje de programación más usado en el mundo empresarial y sobre todo en aquellas empresas que desarrollan software basado en el protocolo Http. Este hecho se convierte en que en el mercado laboral hay muchas más ofertas de trabajo para programadores Java que en cualquier otro lenguaje de programación.

Cómo instalar el JDK de Java

Para programar en Java, necesariamente se necesita el Java Development Kit (JDK) que contiene las herramientas de compilación y las librerías básicas del lenguaje. Pero será conveniente que tengas también Apace Maven ya que aporta estandarización de los proyectos, se encarga de la compilación y la construcción de la aplicación o librería que desees generar y además resuelve muy eficientemente las dependencias y el uso de librerías de terceros usando unos repositorios públicos con un gran abanico de éstas de uso libre, como Guava proporcionada por Google, o Apache Commons proporcionadas por la Apache Foundation.

Tu primer programa en Java

Una vez que tengas instalado el JDK como se explica en el artículo deberías poder ejecutar el compilador, comando javac, desde cualquier directorio, así como también la máquina virtual con el comando javac. Estos comandos están contenidos en un directorio del JDK, llamado bin, que debe están en el Path de tu sistema operativo. Si has hecho lo correcto, puedes verificarlo ejecutando:

java -version

Si se imprime la versión de Java instalado, la configuración es correcta.

El siguiente paso es posicionarte en un directorio vacío para las pruebas que vamos a realiar ahora. Por ejemplo \\Java si estás en Windows, o ~/Java si estás en Mac/Linux. Una vez ahí crearemos una primera aplicación.

En el directorio creado para tal fin, crea el fichero App01.java con el siguiente contenido:

public class App01 {
    public static void main(String[] args){
        System.out.println("Hola Mundo!");
    }
}

Este es uno de los programas más pequeños que podemos crear con Java. Fíjese que el nombre del archivo coincide con el nombre de la clase. Debe coincidir en la capitalización de las letras.

Para poder generar el binario que la JVM pueda ejecutar, debemos invocar al compilador. Éste generará los binarios, en este caso App01.class, correspondiente con las instrucciones contenidas en un formato denominado byte code.

Compila el primer programa con:

javac App01.java

Aparentemente no ha ocurrido nada, pero si miras el directorio aparecerá un nuevo archivo App01.class. Éste ya puede ser ejecutado por la JVM:

java App01
Hola Mundo!

¡Enhorabuena! Has creado tu primer programa en Java, y además de una forma muy manual. Actualmente los programadores no invocan directamente a java o javac, si no que lo hacen directamente desde el entorno integrado de programación, el cual ayuda enormemente a realizar este tipo de tareas, sobre todo cuando hay cientos o miles de ficheros Java.

Organización del código en paquetes

En un proyecto con cientos de clases se ve obligatorio implementar algún mecanismo de organización de los archivos Java. La manera más natural es clasificarlos en diferentes directorios. Ahora bien, si desde un archivo Java se hace referencia a otro archivo de este tipo, el compilador debe saber que se encuentra en otro directorio para que pueda encontrarlo. Por este motivo aparece el concepto de package o paquete.

Los packages permiten organizar ficheros Java en diferentes directorios, todos ellos compartiendo una misma raíz, de manera que se puedan usar unos ficheros desde otros. Los ficheros Java, a parte de estar ubicados en un sub directorio u otro, la ruta completa de carpetas debe aparecer en el preámbulo del archivo. Por ejemplo, un archivo ubicado en ./org/eadp/Utilidad.java deberá tener la declaración del package como sigue:

package org.eadp;
public class Utilidad {
    public static void sayHello(){
        System.out.println("Hello World!");
    }
}

Así, desde nuestra segunda aplicación con nombre App02.java y con el siguiente contenido, podemos invocar el uso de Utilidad.java:

import org.eadp.Utilidad;

public class App02 {
    public static void sayHello(){
        Utilidad.sayHello();
    }
}

Para que esta segunda aplicación funcione correctamente, hemos supuesto que App01 y App02 están en el directorio raíz de Java. Mientras que Utilidad.java está Java/org/eadp. Siempre que se usa un archivo desde otro que no está en el mismo directorio o paquete debe importarse. Para compilar y ejecutar la segunda aplicación introduciremos:

javac App02.java
java App02

Java, automáticamente recurrirá a la compilación de todas los archivos usados por App02, siempre y cuando los encuentre dentro del directorio del proyecto en base a los imports indicados.

Todas las funciones aquí utilizadas van con el prefijo static, por ser métodos de clase y no de una instancia u objeto. Fácilmente podemos convertir el método sayHello de Utilidad a uno que no contenga esta limitación:

// contenido de ./App03.java
import org.eadp.Utilidad2;

public class App03 {
    public static void sayHello(){
        Utilidad2 instancia = new Utilidad2();
        instancia.sayHello();
    }
}

// contenido de ./org/eadp/Utilidad2.java
public class Utilidad2 {
    public void sayHello(){
        System.out.println("Hello World!");
    }
}

En esta tercera versión, para poder quitar el static al método sayHello, se debe crear una instancia de la clase Utilidad2 mediante new Utilidad2(). Esto reserva el espacio en memoria para guardar un objeto del tipo Utilidad2. La dirección de memoria en donde está ubicado se guarda en una variable (instancia) la cual podemos referenciar para invocar el método sayHello.

Si desea aprender más acerca de la programación orientada a objetos puede adquirir la Guía Javañol, un extenso libro de más de 450 páginas con toda la información necesaria para convertirse en un profesional.

Definición y uso de variables

En Java hay dos tipos de variables, las que almacenan o mejor dicho apuntan a un objeto, o las variables denominadas primitivas. Éstas últimas empiezan por minúscula y en vez de contener una dirección contienen el dato en sí mismo, ya que estos almacenan el dato de forma local en la pila de llamadas.

Los tipos primitivos que posee Java son los siguientes:

Category Types Size (bits) Minimum Value Maximum Value Precision Example
Integer byte 8 -128 127 From +127 to -128 byte b = 65;
char 16 0 2^16-1 All Unicode characters char c = 'A'; <br>char c = 65;
short 16 -2^15 2^15-1 From +32,767 to -32,768 short s = 65;
int 32 -2^31 2^31-1 From +2,147,483,647
to -2,147,483,648
int i = 65;
long 64 -2^63 2^63-1 From +9,223,372,036,854,775,807
to -9,223,372,036,854,775,808
long l = 65L;
Floating-point float 32 2^-149 (2-2^-23)·2^127 From 3.402,823,5 E+38
to 1.4 E-45
float f = 65f;
double 64 2^-1074 (2-2^-52)·2^1023 From 1.797,693,134,862,315,7 E+308
to 4.9 E-324
double d = 65.55;
Other boolean false, true boolean b = true;
void

Sea cual sea el tipo de variable que desee crear, primero se pone el tipo y luego el nombre de la variable. Opcionalmente puede asignar un valor inicial. Véase los siguientes ejemplos:

boolean b1 = true;
Utilidad util = new Utilidad();
int i = 365;
float f1 = i + 3.0f;

Fíjese que los tipos primitivos (los que empiezan por minúsculas) no necesitan la invocación de new, sin embargo la variable util al ser un puntero a objeto, requiere de reservar la memoria. Java se encarga automáticamente de liberar las reservas hechas (con new) gracias a su Garbage Collector.

Las variables pueden ser locales, como las indicadas en el bloque de código anterior, pero también pueden ser de objeto o de clase. Las variables de objeto se añaden justo debajo de la definición de la clase como se muestra en el siguiente ejemplo:

public class Coche {
    int numRuedas = 4;
}

Si creamos un objeto de este tipo con new, podremos acceder a su número de ruedas.

Coche c = new Coche();
System.out.println(c.numRuedas);

c.numRuedas = 8;
System.out.println(c.numRuedas);

Sin embargo, cuando un atributo es de tipo clase (static), no es necesario hacer un new, ya que la variable no va asociada a ningún objeto, si no al tipo o clase al que pertenece.

public class Coche {
    static int numRuedas = 4;
}

Al ser ahora numRuedas estático el acceso debe hacerse mediante el nombre de la clase más un punto:

int n = Coche.numRuedas;

El mismo comportamiento que se obtiene con los atributos o variables de objetos sucede con los métodos si éstos se prefijan con la palabra reservada static como se ha visto al principio del tutorial.

Java permite muchas colecciones de datos, pero dentro de los básicos tenemos los arrays o cadenas de variables. Se definen como en C y en otros muchos lenguajes usando los corchetes ‘[‘ y ‘]’ y entre estos símbolos se introduce el tamaño del array o el índice del dato al que queremos referirnos, según si estamos definiendo o usando el array. La primera posición es el 0. Ejemplos:

// creación de un array de 10 enteros.
int[] arrayDeInts = new int[10];
arrayDeInts[0] = 1;
arrayDeInts[1] = 2;

int tmp = arrayDeInts\[2\];

// la siguiente asignación da ERROR!
// por salir de los límites
arrayDeInts[10] = 11;

Los arrays se pueden definir de cualquier tipo primitivo u objeto de Java. Pero se debe destacar que al inicializar un array con new, se reserva espacio para poder almacenar la cantidad de valores indicado, pero eso no significa que los datos en sí contengan algún valor. Hay que inicializar cada una de las casillas del array.

Estructuras de control

Las estructuras de control en Java no difieren mucho de las de C y C++. Las más básicas son if para realizar bifurcaciones en la ejecución. While y for para realizar iteraciones mientras se cumpla una expresión o para recorrer todos los elementos de una colección de datos. A continuación algunos ejemplos:

Ejecmplo del uso de condicional if, los cuales pueden encadenarse con else if o definir un caso general con else.

int v1 = 3 + 5;
if ( v1 < 3 ){
    System.out.println("Número menor que 3");
} else if ( v1 < 5){
    System.out.println("Número menor que 5 y mayor o igual a 3");
} else {
    System.out.println("Número mayor o igual que 5");
}

Los recorridos con while y for tienen algunas opciones más que las citadas aquí, pero mostraremos algunos ejemplos simples como representación.

La construcción while acepta una expresión como el if que produce la repetición de las sentencias que engloba entre llaves mientras la expresión devuelva cierta. No importa lo compleja que sea la expresión o condición, siempre que ésta devuelva en su evaluación un booleano. Por ejemplo:

int num = 0;
while (num < 10){
    System.out.println("Num es " + num);
    num = num + 1; // o num++;
}

Por otro lado, Java proporciona la construcción for en dos modalidades, la tradicional en la que acepta tres expresiones y la relativamente más moderna que acepta una colección.

El for En la modalidad 1, las tres expresiones corresponden con la inicialización del recorrido, condición de parada y por último la expresión de actualización. Veamos un ejemplo:

for (int num = 0 ; num < 10 ; num++ ){ // i++ es quivalente a i = i + 1
    System.out.println("Num es " + num);
}

El for en esta construcción resulta algo más compacto que while porque la creación, inicialización y actualización de la variable del recorrido se realiza en la misma línea, pero todos estos pasos separados por punto y coma ‘;’.

El for En la modalidad 2, simplifica la iteración de elementos almacenados en una colección. Su sintaxis se reduce a la declaración de una variable local que irá variando en cada pasada de la iteración, cogiendo como valor cada uno de los elementos de la colección, y la colección en sí misma que se desea iterar.

String[] array = new String[]{ "hola", "caracola" };
for (String palabra : array ){
    System.out.println("La palabra actual es: "+palabra);
}

Todos los recorridos aceptan dos palabras clave para alterar el comportamiento de la iteración. La primera de ellas es continue que cuando se ejecuta, automáticamente se pasa a tratar la siguiente iteración del bucle que lo contiene. La segunda es break que provoca lo contrario, es decir cuando se ejecuta sale del bucle que lo contiene, aunque queden elementos por tratar. Un ejemplo combinado de éstos sería el siguiente, ¿sabría decir cuántos mensajes serán impresos?:

for (int num = 0 ; num < 10 ; num++ ){
    if (i == 0){
        continue;
    } if (i >= 7){
        break;
    }
    System.out.println("Num es " + num);
}

Colecciones de datos

Los arrays son muy útiles pero poco flexibles, ya que no puede variarse su tamaño una vez inicializados, se debe crear un array nuevo o usar alguna estructura más potente como colecciones de datos en Java. Java proporciona cientos de colecciones de datos, la mayoría genéricas pero otras muchas especializadas en usos particulares para beneficiarse de un rendimiento extra si se conoce la circunstancia del problema a tratar. Dejando de lado las específicas, entre las generales están las 3 más importantes: List, Set y Map. Todas ellas son interfaces que definen métodos pero no los implementan. Hay toda una serie de implementaciones distintas como las citadas especializadas o las genéricas.

  • java.util.List representa una lista variable de elementos, respeta el orden de inserción y admite duplicados. Su implementación más usada es java.util.ArrayList.
  • java.util.Set representa un conjunto variable de elementos, NO respeta el orden de inserción y en su uso más básico NO admite duplicados. Su implementación más usada es java.util.HashSet.
  • java.util.Map representa un diccionario variable de elementos, NO respeta el orden de inserción y en su uso más básico NO admite duplicados para una misma clave. Su implementación más usada es java.util.HashMap.

Veamos un ejemplo de uso del Api java.util.List a través de java.util.ArrayList:

import java.util.List;
import java.util.ArrayList;
...
List<Integer> lista = new ArrayList<Integer>();
lista.add(1);
lista.add(2);

//devuelve el elemento de la posición 0
int p0 = lista.get(0);

if ( ! lista.isEmpty()){ // ! = negación de un boolean
    lista.clear();
}

Veamos un ejemplo de uso del Api java.util.Set a través de java.util.HashSet:

import java.util.Set;
import java.util.HashSet;
...
Set<String> set = new HashSet<String>();
set.add("hola");
set.add("hola");
set.add("abc");

// size == 2 al no permitir duplicados
int size = set.size();

// el recorrido no garantiza el orden de inserción
for (Integer i : set ){
    System.out.println(i);
}

Veamos un ejemplo de uso del Api java.util.Map a través de java.util.HashMap:

import java.util.Map;
import java.util.HashMap;
...
Map<String,Integer> edades = new HashSet<String,Integer>();
edades.put("Pepito",25);
edades.put("Juanito",60);
edades.put("Pepito",26);

// size == 2 al no permitir duplicados
int size = set.size();

// acceso a un mapa por clave
int edadJuanito = edades.get("Juanito");

// el recorrido no garantiza el orden de inserción
for (Entry<String,Integer> entry : edades.entrySet() ){
    System.out.println(entry.getKey() + " -> " + entry.getValue());
}

Documentación del JDK

Java y el JDK dispone de una documentación amplia y extensa navegable por HTML y que se genera automáticamente del código fuente a través de comentario alojado en los ficheros Java mediante la herramienta javadoc. Esta documentación está disponible online para cada versión de Java. A continuación se dejan los enlaces más relevantes:

Librerías útiles

Para ser un buen programador no sólo se ha de conocer bien el lenguaje, sino también se ha de familiarizar con las principales librerías que se usan del ecosistema de Java. Son muchas las disponibles, cada una de ellas enfocada en resolver un tema en particular. Según cada caso convendrá hacer una búsqueda por Internet y experimentar con una o varias opciones antes de introducirla en un proyecto. Pero en general, las dos más usadas que sí o sí conviene conocer son las siguientes:

Tu primera aplicación web

Si ya estás familiarizado con Java y con las principales librerías de uso común publicadas en internet, por qué no dar el siguiente paso y aprender el framework web por excelencia en java: Spring Boot.

Prueba a crear una primera aplicación Web con Spring Booy usando Spring Initializr.

Iniciación a Java

¿Con ganas de seguir leyendo?

Nuestra guía de Java

Cerca de 450 páginas en un libro de tapa blanda que podrás utilizar para aprender a programar en Java desde cero sin conocimientos previos. Explicamos como usar las herramientas más usadas en el mundo empresarial, todas ellas son totalmente gratis y Open Source.

Aprende conceptos como TDD para desarrollar software con garantías. Conecta tus apps con JPA en bases de datos SQL. Integra tus proyectos con Maven y mantenlos bajo control con Git. Mantente al día con la programación funcional de Java 8+.

Nuestra guía de Java
Libro Javañol