En Java, como en la mayoría de los lenguajes de programación, se pueden obtener números aleatorios, es decir, al azar. Para el caso concreto de Java, disponemos de la clase Random (java.util.Random) que se permite la generación de valores aleatorios.

Creación de objeto Random

Para poder usar esta clase para la generación de valores aleatorios será necesario tener creado un objeto Random a partir del cual se puedan usar los métodos que incorpora para la generación de los valores. Ten en cuenta que con un sólo objeto Random podrás crear todos los valores aleatorios que se deseen. Piensa que un objeto Random es como una máquina generadora de valores aleatorios, por lo que sólo necesitarás una de estas máquinas para generar múltiples valores aleatorios.

En la documentación de la API puedes ver que se pueden usar 2 métodos constructores diferentes:

Captura de pantalla 2020 06 08 a las 11.41.05 da437

En decir, puedes usar el constructor sin parámetros, o bien indicando un único parámetro de tipo long que representa un valor, al que se denomina seed (semilla). La semilla se utiliza como un valor que utilizará internamente esta clase en sus fórmulas para generar los valores aleatorios. Lo habitual es que te sirva el constructor sin parámetros, por lo que puedes crear los objetos Random de la misma manera habitual que se crean los objetos en Java:

En este ejemplo se va asignar a una variable llamada random el objeto Random que se crea, pero podrías usar el nombre de variable que desees, como es habitual.

Random random = new Random();

Recuerda, que como siempre que utilices por primera vez una clase de Java en un archivo de código, debes importar la clase a utilizar indicando el nombre del paquete en el que se encuentra, a no ser que cuando hagas referencia a la clase Random especifiques el nombre del paquete (java.util.Random)

import java.util.Random;

La otra manera a la que hacía referencia antes, que no necesitaría el uso del import sería:
java.util.Random random = new java.util.Random();

Generación de números aleatorios de tipo entero

Método nextInt(int bound)

El método nextInt(int bound) de la clase java.util.Random permite generar un valor aleatorio de tipo entero (int), entre 0 y el valor límite que se indique como parámetro (bound) no inclusive. En la documentación de la API aparece declarado así:

Captura de pantalla 2020 06 08 a las 12.56.17 376f7

Por ejemplo, para generar valores aleatorios entre 0 y 9, mostrándolo a continuación en la salida estándar:

Random random = new Random();
int valor = random.nextInt(10);
System.out.println(valor);

Es habitual que no desees empezar los números aleatorios en 0. Por ejemplo, si deseas simular el lanzamiento de un dado, deberás obtener valores entre 1 y 6. Para conseguir esto, la clase Random no dispone de un método que permita indicar el valor inicial y el final, por lo que hay que adaptarse al método que acabamos de ver. Pero esto se puede hacer con una simple suma, añadiendo al valor aleatorio obtenido el valor más bajo deseado, y como parámetro debes indicar la cantidad de posibles valores a obtener.

Random random = new Random();
int dado = random.nextInt(6)+1;
System.out.println(dado);

En este ejemplo, con nextInt(6) se obtendría un valor entre 0 y 5, por lo que al sumarle 1 se obtiene un valor entre 1 y 6. 

Ten cuidado con el lugar donde haces la suma, porque si lo haces dentro del paréntesis, lo que estás cambiando no es el resultado del valor aleatorio, sino el límite utilizado para obtener el valor aleatorio. Así que, si sumas 1 al parámetro (6+1) estarán obteniendo valores entre 0 y 6.

Random random = new Random();
int dado = random.nextInt(6+1); // No es correcto (0 a 6)
System.out.println(dado);

Obtener varios valores aleatorios

Un vez comprobado que se obtiene el valor aleatorio, podría ser recomendable generar varios valores para asegurarte de que los valores que se generan son correctos. Por ejemplo, para el caso del dado podrías simular la tirada del dado 20 veces y comprobar que todos los valores están entre 1 y 6. Eso lo puedes hacer con un bucle for como se muestra en este ejemplo:

Random random = new Random();  // sólo se necesita un objeto random
for(int i=0; i<20; i++) {
    int dado = random.nextInt(6)+1; 
    System.out.print(dado + " ");
}

La ejecución podría dar un resultado como:  6 2 4 3 4 4 2 2 6 3 6 1 5 4 3 1 4 1 2 2 (se han generado 20 valores entre 1 y 6).

En otras ocasiones puede que debas obtener una serie de valores aleatorios deteniendo su generación cuando se obtenga un determinado valor. Para estos casos es más recomendable usar un bucle while o do-while. Por ejemplo, si deseas generar valores del dado hasta que se obtenga un 5:

Random random = new Random();
int dado; // Hay que hacer visible la variable fuera
do {
    dado = random.nextInt(6)+1; 
    System.out.print(dado + " ");
} while(dado != 5);

La ejecución podría dar un resultado como:  2 6 6 6 1 2 4 4 1 6 4 5 (se han generado valores entre 1 y 6 hasta obtener un 5). 

Generación de números aleatorios de tipo real (con decimales)

Métodos nextDouble() y nextFloat()

En caso de que necesites generar uno o varios números aleatorios con decimales, deberás usar otro método diferente de la clase Random, ya que el método nextInt sólo generar números enteros. Ahora necesitarás usar el método nextDouble() o el método nextFloat(). El funcionamiento de ambos métodos es similar, pero con el primero se obtiene un valor de tipo double y con el segundo lo obtendrás de tipo float. Si no recuerdas la diferencia existente entre ambos tipos de datos repara los distintos tipos de datos básicos de Java, pero básicamente el tipo double permite gestionar valores decimales con más precisión que el tipo float. El uso de un método u otro dependerá de la precisión que requieran los cálculos que se hagan posteriormente con los valores aleatorios obtenidos.

Debes tener en cuenta que tanto el método nextDouble() como el método nextFloat() permiten obtener únicamente un valor entre 0 y 1 (sin incluir el 1), es decir, un valor de ejemplo podría ser: 0.3301335119207437 y no hay ningún otro método que permita indicar otro rango de valores como sí hemos visto que había con nextInt().  

Captura de pantalla 2020 06 09 a las 13.11.57 63ddc

En la documentación que ofrece la API sobre el método nextDouble() puedes observar que retorna un valor de tipo double, por lo que el resultado de la llamada a este método puedes almacenarlo en una variable de ese mismo tipo. Puedes hacer una prueba con un ejemplo como este:

Random random = new Random();
double num = random.nextDouble();
System.out.println(num);

Al igual que hemos visto en el caso de los números enteros, puede ser que necesites obtener valores aleatorios dentro de un rango de valores diferentes al de 0 y 1. Esto se puede solucionar multiplicando el valor aleatorio obtenido por el valor límite deseado. Por ejemplo, si se desea obtener un valor aleatorio con decimales entre 0 y 10 (recuerda que no se alcanzará el último valor de 10, pero se aproximará a 9.99999999):

random.nextDouble()*10

Si necesitas empezar en un valor superior al 0, puedes sumarle el valor necesario. Por ejemplo, para obtener un valor entre 100 y 110:

random.nextDouble()*10+100

Uso de la clase Math para generación de valores aleatorios 

Para ello se dispone en este caso del método random() de la clase Math.

Este método genera un número aleatorio de tipo double entre 0 y 1, por ejemplo: 0.4150224193182078.

Se puede probar con:

System.out.println(Math.random());

Pero lo normal es que se desee obtener un número entero entre un valor mínimo y otro máximo. Por ejemplo, entre 1 y 6 para simular el lanzamiento de un dado.

Para ello se puede utilizar esta fórmula, en la que se le asigna ese número a la variable dado:

int dado = (int)(Math.random()*6)+1;

Es decir, se multiplica por la cantidad de valores posibles que se desean obtener, se convierte a entero y se le suma el valor mínimo.

De forma general se podría decir:

variable = (int)(Math.random() * numValores) + mínimo;