Listado completo de tutoriales

93 - Interfaces en el API de Java


En el concepto anterior aprendimos como crear y consumir nuestras propias interfaces. Ahora veremos que el API de Java hace un uso amplio de interfaces.

Cuando vimos la librería de componentes visuales Swing utilizamos interfaces para la captura de eventos.

Ahora conociendo como se crea una interface repasaremos algunos problemas donde el API de Java las utiliza.

Problema:

Implementar un formulario que muestre un menú de opciones y un botón. Permitir finalizar el programa cuando se selecciona el MenuItem o el JButton.

Clase: Formulario

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class Formulario extends JFrame implements ActionListener{
    JButton boton1;
    JMenuBar mb1;
    JMenu menu1;
    JMenuItem menuItem1;
    
    public Formulario() {
        setLayout(null);
        boton1=new JButton("Salir");
        boton1.setBounds(650, 480, 100, 30);
        add(boton1);
        boton1.addActionListener(this);
        
        mb1=new JMenuBar();
        setJMenuBar(mb1);
        menu1=new JMenu("Opciones");
        mb1.add(menu1);
        menuItem1=new JMenuItem("Salir");
        menu1.add(menuItem1);        
        menuItem1.addActionListener(this);
    }
    
    public void actionPerformed(ActionEvent e) {
        if (boton1==e.getSource()) 
            System.exit(0);
        if (menuItem1==e.getSource())
            System.exit(0);
    }
    
    public static void main(String[] args) {
        Formulario formulario1=new Formulario();
        formulario1.setBounds(0, 0, 800, 600);
        formulario1.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        formulario1.setVisible(true);
    }
}

En el problema implementamos la interface 'ActionListener':

public class Formulario extends JFrame implements ActionListener{

La interface 'ActionListener' se encuentra almacenada en el paquete: java.awt.event:

import java.awt.event.ActionListener;

Luego la clase 'Formulario' al implementar la interface 'ActionListener' debe codificar el método 'actionPerformed':

    public void actionPerformed(ActionEvent e) {
        if (boton1==e.getSource()) 
            System.exit(0);
        if (menuItem1==e.getSource())
            System.exit(0);
    }

Para que los objetos 'boton1' y 'menuItem1' puedan llamar al método 'actionPerformed' debemos pasar la referencia del objeto formulario1 llamando al método 'addActionListener':

        boton1.addActionListener(this);
        menuItem1.addActionListener(this);

Recordemos que el mismo problema lo podemos resolver creando objetos de clases anónimas que implementan la interfaz 'ActionListener' cuando llamamos a los métodos 'addActionListener':

Clase: Formulario

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class Formulario extends JFrame {
    JButton boton1;
    JMenuBar mb1;
    JMenu menu1;
    JMenuItem menuItem1;

    public Formulario() {
        setLayout(null);
        boton1 = new JButton("Salir");
        boton1.setBounds(650, 480, 100, 30);
        add(boton1);
        boton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        mb1 = new JMenuBar();
        setJMenuBar(mb1);
        menu1 = new JMenu("Opciones");
        mb1.add(menu1);
        menuItem1 = new JMenuItem("Salir");
        menu1.add(menuItem1);
        menuItem1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });
    }

    public static void main(String[] args) {
        Formulario formulario1 = new Formulario();
        formulario1.setBounds(0, 0, 800, 600);
        formulario1.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        formulario1.setVisible(true);
    }
}

De esta forma la clase 'Formulario' no implementa la interfaz 'ActionListener', sino las clases anónimas que declaramos cuando llamamos a los métodos 'addActionListener' del JButton y el JMenuItem:

        boton1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });


        menuItem1.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

Podemos analizar el código fuente de las API de Java en el sitio github:

Una interfaz puede heredar de otra interfaz:

public interface ActionListener extends EventListener {

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);

}

Hay que tener en cuenta que una interfaz en Java puede heredar inclusive de múltiples interfaces, a diferencia de una clase que puede heredar solo de una.

Problema:

Declarar una clase 'Persona' y sus atributos 'nombre' y 'edad'. Implementar la interface 'Comparable' con tipo genérico.

Crear un ArrayList de tipo 'Persona' y ordenar las personas en forma alfabética.

Clase: Persona

public class Persona implements Comparable<Persona> {
    private String nombre;
    private int edad;

    public Persona(String nombre, int edad) {
        this.nombre = nombre;
        this.edad = edad;
    }

    String retornarNombre() {
        return nombre;
    }

    int retornarEdad() {
        return edad;
    }

    public int compareTo(Persona o) {
        return nombre.compareTo(o.nombre);
    }
}

Existen interfaces genéricas que debemos indicar el tipo de dato que procesa, esto sucede con la interface 'Comparable':

public class Persona implements Comparable<Persona> {

La interface 'Comparable' debe implementar el método 'compareTo':

    public int compareTo(Persona o) {
        return nombre.compareTo(o.nombre);
    }

Para probar la clase 'Persona':

Clase: PruebaPersona

import java.util.ArrayList;
import java.util.Collections;

public class PruebaPersona {

    public static void main(String[] args) {
        ArrayList<Persona> lista1 = new ArrayList<Persona>();
        lista1.add(new Persona("Juan", 33));
        lista1.add(new Persona("Ana", 22));
        lista1.add(new Persona("Pedro", 50));

        for (Persona per : lista1)
            System.out.println(per.retornarNombre() + "-" + per.retornarEdad());

        Collections.sort(lista1);

        System.out.println("Lista luego de ordenar en forma alfabética.");
        for (Persona per : lista1)
            System.out.println(per.retornarNombre() + "-" + per.retornarEdad());

    }

}

Para ordenar la lista de personas llamamos al método estático 'sort' de la clase 'Collections'. Dicho método requiere que la lista implemente la interface genérica 'Comparable'.


Retornar