2.gh.1 - Importación de Librerías y Uso de Constructores

Objetivos

1. Contenidos

1.1 Dos elementos que ya hemos utilizado

En esta página vamos a estudiar con más detalle dos elementos que ya han aparecido en programas anteriores: la importación de librerías y el uso de constructores.

Hasta ahora hemos usado clases como Scanner para leer datos o Math para realizar cálculos. También hemos creado objetos con la palabra new. En ambos casos estábamos utilizando características propias de Java que conviene entender bien antes de avanzar en programación orientada a objetos.

Idea principal: importar una clase permite utilizar código que ya existe en Java o en una librería externa. Utilizar un constructor permite crear un objeto correctamente inicializado.

1.2 ¿Por qué hay que importar librerías en Java?

Java incluye muchas clases ya preparadas para resolver tareas habituales: leer datos, trabajar con fechas, manejar listas, gestionar ficheros, realizar cálculos matemáticos, etc. Estas clases están organizadas en paquetes. Un paquete es una forma de agrupar clases relacionadas.

Por ejemplo, la clase Scanner está dentro del paquete java.util. Por eso, cuando queremos usarla en un programa, normalmente escribimos al principio del fichero:


import java.util.Scanner;
				

La sentencia import indica al compilador dónde se encuentra la clase que queremos utilizar. No copia la clase dentro de nuestro programa: simplemente permite usar su nombre corto. Gracias al import, podemos escribir Scanner en lugar de escribir siempre java.util.Scanner.

Ejemplo sin importación:


public class DemoSinImport {
	public static void main(String[] args) {
		java.util.Scanner lector = new java.util.Scanner(System.in);

		System.out.println("Introduce tu nombre:");
		String nombre = lector.nextLine();

		System.out.println("Hola, " + nombre);
		lector.close();
	}
}
				

El programa anterior funciona, pero es incómodo porque hay que escribir el nombre completo de la clase. Por eso se suele importar la clase al principio del fichero.

Ejemplo con importación:


import java.util.Scanner;

public class DemoConImport {
	public static void main(String[] args) {
		Scanner lector = new Scanner(System.in);

		System.out.println("Introduce tu nombre:");
		String nombre = lector.nextLine();

		System.out.println("Hola, " + nombre);
		lector.close();
	}
}
				

Contexto profesional: en una aplicación real es habitual usar muchas clases ya hechas: LocalDate para fechas, ArrayList para colecciones, File para ficheros o BigDecimal para importes económicos.

1.3 ¿Cómo se importan las clases?

Las importaciones se escriben al principio del fichero Java, antes de la declaración de la clase principal.


import paquete.NombreClase;
				

También es posible importar todas las clases de un paquete usando *, aunque en proyectos profesionales suele ser más claro importar solo las clases que se van a utilizar.


import java.util.*;
				

Ejemplo con varias clases importadas:


import java.time.LocalDate;
import java.util.Scanner;

public class RegistroEmpleado {
	public static void main(String[] args) {
		Scanner lector = new Scanner(System.in);

		System.out.println("Nombre del empleado:");
		String nombre = lector.nextLine();

		LocalDate fechaAlta = LocalDate.now();

		System.out.println("Empleado: " + nombre);
		System.out.println("Fecha de alta: " + fechaAlta);

		lector.close();
	}
}
				

En este ejemplo se han importado dos clases:

  • java.util.Scanner, para leer datos.
  • java.time.LocalDate, para trabajar con fechas.

1.4 ¿Qué clases no necesitan importarse?

No todas las clases necesitan escribirse con import. Hay varios casos importantes:

  • Las clases del paquete java.lang se importan automáticamente.
  • Las clases que están en el mismo paquete que nuestro programa no necesitan importarse.
  • Las clases que escribimos en el mismo fichero también pueden utilizarse sin importación.

El paquete java.lang contiene clases muy utilizadas, como String, System, Math, Integer, Double o Boolean. Por eso podemos escribir programas como el siguiente sin añadir ninguna importación:


public class DemoJavaLang {
	public static void main(String[] args) {
		String producto = "Teclado mecánico";
		Double precio = 79.90;
		Double precioRedondeado = Math.round(precio);

		System.out.println("Producto: " + producto);
		System.out.println("Precio redondeado: " + precioRedondeado);
	}
}
				

Importante: que una clase pueda usarse con import no significa que esté instalada en cualquier proyecto. Si se trata de una librería externa, además de importarla, habrá que añadirla al proyecto mediante el sistema correspondiente, por ejemplo Maven o Gradle.

1.5 ¿Cómo saber qué librería hay que importar?

La forma más fiable de saber qué paquete hay que importar es consultar la documentación oficial de Java. Cada clase de la API oficial indica a qué paquete pertenece.

Por ejemplo, si buscamos la clase Scanner en la documentación oficial, veremos que aparece dentro del paquete java.util. Por tanto, la importación correcta es:


import java.util.Scanner;
				

Si buscamos la clase LocalDate, la documentación indica que pertenece al paquete java.time. Por tanto, la importación correcta es:


import java.time.LocalDate;
				

El proceso recomendado es:

  1. Buscar la clase en la documentación oficial de Java.
  2. Comprobar el paquete indicado en la página de la clase.
  3. Escribir la sentencia import con el paquete y el nombre de la clase.
  4. Utilizar la clase en el programa con su nombre corto.

1.6 ¿Qué es un constructor?

Un constructor es un bloque especial de código que se ejecuta cuando se crea un objeto con la palabra new. Su objetivo es inicializar los atributos del objeto.

Un constructor se parece a un método, pero tiene dos diferencias importantes:

  • Se llama exactamente igual que la clase.
  • No tiene tipo de retorno, ni siquiera void.

Cuando escribimos new Scanner(System.in), estamos creando un objeto de la clase Scanner y llamando a uno de sus constructores. El constructor recibe la información necesaria para preparar el objeto.


Scanner lector = new Scanner(System.in);
				

En nuestras propias clases también podemos crear constructores para obligar a que los objetos nazcan con datos válidos.

1.7 Uso de constructores en clases de usuario

Supongamos que estamos desarrollando una aplicación para gestionar clientes. Cada cliente debe tener un nombre, un correo electrónico y una cantidad inicial de puntos de fidelización. El constructor permite establecer esos valores en el momento de crear el objeto.


class Cliente {
	String nombre;
	String correo;
	Integer puntos;

	Cliente(String nombreCliente, String correoCliente) {
		nombre = nombreCliente;
		correo = correoCliente;
		puntos = 0;
	}

	void mostrarFicha() {
		System.out.println("Cliente: " + nombre);
		System.out.println("Correo: " + correo);
		System.out.println("Puntos: " + puntos);
	}
}

public class DemoConstructorCliente {
	public static void main(String[] args) {
		Cliente cliente = new Cliente("Laura Sánchez", "laura@empresa.com");

		cliente.mostrarFicha();
	}
}
				

En este ejemplo, la línea:


Cliente cliente = new Cliente("Laura Sánchez", "laura@empresa.com");
				

realiza tres acciones:

  1. Reserva memoria para un nuevo objeto de tipo Cliente.
  2. Ejecuta el constructor Cliente(String nombreCliente, String correoCliente).
  3. Guarda la referencia al objeto en la variable cliente.

Buena práctica: un constructor debe dejar el objeto en un estado coherente. Después de ejecutarse, el objeto debería estar preparado para usarse.

1.8 Constructor por defecto y constructor personalizado

Si una clase no tiene ningún constructor escrito por el programador, Java crea automáticamente un constructor por defecto sin parámetros. Gracias a eso podemos escribir new NombreClase().


class ProductoSinConstructor {
	String nombre;
	Double precio;
}

public class DemoConstructorDefecto {
	public static void main(String[] args) {
		ProductoSinConstructor producto = new ProductoSinConstructor();

		producto.nombre = "Monitor";
		producto.precio = 149.99;

		System.out.println("Producto: " + producto.nombre);
		System.out.println("Precio: " + producto.precio);
	}
}
				

Sin embargo, cuando definimos un constructor personalizado, Java deja de crear automáticamente el constructor por defecto. En el siguiente ejemplo, el objeto Producto debe crearse indicando los datos que necesita el constructor.


class Producto {
	String codigo;
	String nombre;
	Double precio;

	Producto(String codigoProducto, String nombreProducto, Double precioProducto) {
		codigo = codigoProducto;
		nombre = nombreProducto;
		precio = precioProducto;
	}

	void mostrarProducto() {
		System.out.println("Código: " + codigo);
		System.out.println("Nombre: " + nombre);
		System.out.println("Precio: " + precio);
	}
}

public class DemoProducto {
	public static void main(String[] args) {
		Producto producto = new Producto("PR-001", "Ratón óptico", 18.50);

		producto.mostrarProducto();
	}
}
				

Esta forma es más segura porque evita crear productos incompletos. Si el programa necesita que todo producto tenga código, nombre y precio, el constructor ayuda a cumplir esa regla.

1.9 Ejemplo completo: importaciones y constructores

El siguiente ejemplo combina importación de librerías, uso de Scanner y creación de objetos mediante un constructor.


import java.time.LocalDate;
import java.util.Scanner;

class Incidencia {
	String titulo;
	String tecnico;
	LocalDate fechaRegistro;
	Integer prioridad;

	Incidencia(String tituloIncidencia, String tecnicoAsignado, Integer prioridadInicial) {
		titulo = tituloIncidencia;
		tecnico = tecnicoAsignado;
		prioridad = prioridadInicial;
		fechaRegistro = LocalDate.now();
	}

	void mostrarResumen() {
		System.out.println("Incidencia: " + titulo);
		System.out.println("Técnico asignado: " + tecnico);
		System.out.println("Prioridad: " + prioridad);
		System.out.println("Fecha de registro: " + fechaRegistro);
	}
}

public class DemoIncidencia {
	public static void main(String[] args) {
		Scanner lector = new Scanner(System.in);

		System.out.println("Título de la incidencia:");
		String titulo = lector.nextLine();

		System.out.println("Técnico asignado:");
		String tecnico = lector.nextLine();

		Incidencia incidencia = new Incidencia(titulo, tecnico, 3);

		incidencia.mostrarResumen();

		lector.close();
	}
}
				

En este programa hay tres ideas importantes:

  • Scanner necesita importarse desde java.util.
  • LocalDate necesita importarse desde java.time.
  • El constructor de Incidencia inicializa los atributos del objeto.

2. Ejercicios

2.1 Registro de proveedor

Crea un programa Java llamado RegistroProveedor que utilice la clase Scanner para pedir el nombre de un proveedor y su correo electrónico.

Después, crea una clase Proveedor con los atributos nombre, correo y activo. La clase debe tener un constructor que reciba el nombre y el correo, y que inicialice activo con el valor true.

Añade un método mostrarFicha() que muestre los datos del proveedor con System.out.println.

Requisitos: importa java.util.Scanner, crea el objeto con new Proveedor(...) y cierra el objeto Scanner al final del programa.

2.2 Producto de almacén

Crea un programa Java llamado InventarioAlmacen con una clase ProductoAlmacen.

La clase debe tener los atributos codigo, nombre, precioUnitario y unidades. Su constructor debe recibir todos esos datos e inicializar los atributos del objeto.

Añade dos métodos:

  • Double calcularValorStock(), que devuelva el resultado de multiplicar el precio unitario por las unidades.
  • void mostrarResumen(), que muestre el código, el nombre, las unidades y el valor total del stock.

En el método main, crea dos productos con datos fijos y muestra el resumen de ambos.

Reto: Sistema básico de reservas de salas

Desarrolla un programa Java llamado GestionReservas para registrar reservas de salas de reuniones en una empresa.

El programa debe incluir una clase ReservaSala con los siguientes atributos:

La clase debe tener un constructor que inicialice todos los atributos. Para la fecha puedes utilizar la clase LocalDate, por lo que tendrás que importar la librería correspondiente.

Añade los siguientes métodos:

  1. Double calcularImporte(), que devuelva el importe total de la reserva.
  2. void mostrarResumen(), que muestre toda la información de la reserva.

En el método main:

  1. Utiliza Scanner para pedir al usuario el responsable de una reserva.
  2. Crea una reserva usando el responsable introducido y el resto de datos fijos.
  3. Crea una segunda reserva con todos los datos fijos.
  4. Muestra el resumen de las dos reservas.

Pista: necesitarás importar java.util.Scanner y java.time.LocalDate. Para crear una fecha fija puedes usar LocalDate.of(2026, 5, 18).

3. Bibliografía