Portada » Informática » Conceptos Esenciales de Programación Java: POO, Hilos, Excepciones y Arreglos
Los paquetes son mecanismos para organizar clases en grupos lógicos, facilitando su acceso y controlando su visibilidad. Actúan como contenedores que ayudan a estructurar el código y a prevenir conflictos de nombres.
Una clase es una plantilla o molde que define la estructura y el comportamiento de los objetos. En ella se especifican los atributos (características) y métodos (acciones) que tendrán los objetos creados a partir de ella.
Los atributos son las variables que definen las características o el estado de un objeto. Constituyen la estructura interna de los objetos de una clase.
public class Ejemplo {
public String cadena;
private int numero;
}
Los métodos son bloques de código que definen las operaciones o acciones que un objeto puede realizar, interactuando a menudo con sus atributos.
public class Ejemplo {
public String cadena = "Hola";
private int numero = 1;
public void main(String args[]) {
// Algún código
}
public void saludo() {
System.out.println("Este es el saludo de un método");
}
}
Un objeto es una instancia concreta de una clase. Representa una entidad con un estado (definido por sus atributos) y un comportamiento (definido por sus métodos).
Un objeto se crea en el momento en que se define una variable de dicha clase, por ejemplo:
Ejemplo objeto = new Ejemplo();
La herencia es un pilar fundamental de la Programación Orientada a Objetos (POO) que permite a una clase (subclase o clase hija) heredar atributos y métodos de otra clase (superclase o clase padre). Esta característica promueve la reutilización de código y la creación de jerarquías de clases. Es importante destacar que los constructores no se heredan.
extends
.Ejemplo:
public class Felino extends Animal {
}
La clase Object
es la clase raíz de la jerarquía de clases en Java. Todas las clases en Java, directa o indirectamente, heredan de Object
, que pertenece al paquete java.lang
.
super
es una palabra reservada en Java que se utiliza para referirse a la superclase inmediata de una clase. Sus usos principales incluyen:
Los arreglos (o arrays) son estructuras de datos que permiten almacenar una colección de elementos del mismo tipo en una secuencia contigua de memoria. Se definen con un tamaño fijo y una capacidad determinada.
La estructura de un arreglo puede ser de las siguientes maneras:
tipo_de_dato[] nombreArreglo;
tipo_de_dato nombreArreglo[];
Las declaraciones anteriores son para arreglos unidimensionales. Para arreglos bidimensionales (matrices), se añade un par de corchetes adicionales:
tipo_de_dato[][] nombreArreglo; // Esta es una matriz.
En Java, la inicialización de un arreglo se vería así:
int[] vector = new int[10];
Para almacenar datos en un arreglo, es fundamental considerar dos aspectos:
Teniendo en cuenta estas dos cosas, podemos guardar un dato en el arreglo de la siguiente manera:
arreglo[posición] = dato;
En Java:
vector[3] = 15;
Al crear un arreglo, es posible inicializarlo directamente con valores:
int[] vector = {1, 2, 3, 4, 5};
Las excepciones son eventos que interrumpen el flujo normal de un programa. En Java, el manejo de excepciones se realiza principalmente con los bloques try
, catch
y finally
. El bloque try
encierra el código que podría generar una excepción. Si una excepción ocurre, el control se transfiere a un bloque catch
asociado, donde se especifica el tipo de excepción a manejar.
try {
// Instrucciones que se intentan ejecutar. Si se produce una
// situación inesperada, se lanza una excepción.
} catch (TipoExcepcion1 e) {
// Instrucciones para tratar esta excepción específica.
} catch (TipoExcepcion2 e) {
// Instrucciones para tratar otra excepción específica.
} finally {
// Instrucciones que se ejecutarán siempre, después de un bloque try,
// se haya producido o no una excepción.
}
// Se pueden escribir tantos bloques catch como sean necesarios.
Los hilos (threads) son unidades de ejecución independientes dentro de un programa. Permiten realizar múltiples tareas concurrentemente. La clase Thread
en Java encapsula el control necesario sobre estos hilos.
currentThread()
El método estático Thread.currentThread()
devuelve una referencia al objeto Thread
que representa el hilo de ejecución actual.
yield()
El método estático Thread.yield()
sugiere al planificador de hilos que el hilo actual está dispuesto a ceder su tiempo de CPU a otros hilos de igual o mayor prioridad. Es útil para evitar la inanición de hilos de menor prioridad.
sleep(long millis)
El método estático Thread.sleep(long millis)
pausa la ejecución del hilo actual durante el número de milisegundos especificado. Después de este tiempo, el hilo vuelve a estar disponible para ser ejecutado. Existe una sobrecarga sleep(long millis, int nanos)
para mayor precisión.
A continuación, se presentan algunos de los métodos de instancia más relevantes de la clase Thread
.
start()
El método start()
inicia la ejecución de un hilo. Internamente, invoca el método run()
del hilo en un nuevo contexto de ejecución. Es crucial no llamar a start()
más de una vez sobre el mismo objeto Thread
.
run()
El método run()
contiene el código que será ejecutado por el hilo. Es el único método de la interfaz Runnable
. Es invocado por el método start()
una vez que el hilo del sistema ha sido inicializado. Cuando run()
finaliza, el hilo se detiene.
stop()
(Desaconsejado)El método stop()
detiene la ejecución de un hilo de forma abrupta e insegura. Su uso está desaconsejado debido a que puede dejar los objetos en estados inconsistentes. Se recomienda utilizar mecanismos de interrupción cooperativa para detener hilos de manera segura.
suspend()
(Desaconsejado)El método suspend()
pausa la ejecución de un hilo sin liberar los recursos que este pueda estar utilizando, lo que puede llevar a interbloqueos (deadlocks). Al igual que stop()
, su uso está desaconsejado. Para reanudar un hilo suspendido, se utilizaba resume()
.
resume()
(Desaconsejado)El método resume()
se utilizaba para reanudar un hilo previamente suspendido. Dado que suspend()
está desaconsejado, resume()
también lo está.
En Java, existen dos formas principales de crear hilos de ejecución:
Thread
:
class MiThread extends Thread {
public void run() {
// Lógica del hilo
}
}
Runnable
:
class MiRunnable implements Runnable {
public void run() {
// Lógica del hilo
}
}
// Para ejecutar:
// Thread t = new Thread(new MiRunnable());
// t.start();
Las aplicaciones Java comienzan su ejecución en el método main()
. Desde allí, se pueden crear y arrancar otros hilos. Para iniciar un hilo, se invoca su método start()
.
Ejemplo de creación y arranque:
// Suponiendo una clase TestTh que extiende Thread
TestTh t1 = new TestTh("Thread 1", (int)(Math.random() * 2000));
// ...
t1.start();
Para generar números aleatorios en Java, se utiliza la clase Random
del paquete java.util
. Los pasos generales son:
import java.util.Random;
Random
.nextInt()
: Devuelve un número entero positivo o negativo dentro del rango de enteros.nextInt(int n)
: Devuelve un número entero >= 0
y menor que n
.nextDouble()
: Devuelve un número positivo de tipo double
mayor o igual que 0.0
y menor que 1.0
.Por ejemplo, para generar 5 enteros al azar:
Random rnd = new Random();
for (int i = 1; i <= 5; i++) {
System.out.println(rnd.nextInt());
}
Un posible resultado de este código es:
-394395199
1133763686
-424454120
1147379979
-2049113297
Para generar 5 enteros entre 0 y 6:
for (int i = 1; i <= 5; i++) {
System.out.println(rnd.nextInt(7));
}
Para generar 5 enteros entre 1 y 6:
for (int i = 1; i <= 5; i++) {
System.out.println(rnd.nextInt(6) + 1);
}
En general, para generar enteros al azar entre dos límites DESDE
y HASTA
, ambos incluidos:
rnd.nextInt(HASTA - DESDE + 1) + DESDE
Por ejemplo, para generar 5 números aleatorios entre 10 y 20:
for (int i = 1; i <= 5; i++) {
System.out.println(rnd.nextInt(20 - 10 + 1) + 10);
}