Java Tutorial 4: Interfaces, and a Basic Swing App

The following code illustrates a basic Swing application. Swing is the standard GUI (Graphical User Interface) API for creating desktop applications with Java.

Note, aside from a bunch of unfamiliar classes, we also use the notion of an interface to create the basic Swing app.

import java.awt.Container;

import javax.swing.JFrame;
import javax.swing.JLabel;

// Note, we will implement the Runnable interface

public class Application implements Runnable {


    public static void main(String[] args) {
        
        // Create an Application object
        Application app = new Application();
        
        // Run the Swing thread. 
        // invokeLater requires a class that implements the Runnable interface
        javax.swing.SwingUtilities.invokeLater(app);
    }

    public void run() {
        // Create a new window with the title "Hello World"
        JFrame frame = new JFrame("Hello World");
        
        // Tell the application to exit if the user closes the frame
        // by clicking on the X in the corner.
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        
        // Create a label to add to the frame.
        JLabel label = new JLabel("Hi there");
        
        // Add the label to the frame's content pane
        // Note, this is an example of method
        
        // Get the frame's content pane.
        Container content = frame.getContentPane();
        
        content.add(label);

        // Set the frame size.
        frame.setSize(400, 100);
        
        // Make the frame visible.
        frame.setVisible(true);
        

}







The interface shows itself in the keyword implements. When we create a Swing application, we have to run the application in a special thread. What this thread is or does is beyond the scope of this tutorial. The main thing to note is that we can create the thread by passing the code we want to run in this thread to javax.swing.SwingUtilities.invokeLater().

This isn't a normal way to create a thread in Java -- it's just for Swing.

We want to tell invokeLater() to run the code that creates our GUI. But how can we tell it what code to run?

The answer is that we pass it an object containing a method called run(). We put the code we want it to run in the run method.

But how can invokeLater() be certain that it will only be passed objects containing a run() method? What stops us passing it any old rubbish? That's where interfaces come in. An interface is a sort of textual contract that specifies what methods a class must contain (at the minimum). In this example we wrote implements Runnable after the name of our Application class.

Runnable is an interface. It specifies that the class MUST define a run() method -- or else the program will not compile. Meanwhile, invokeLater() specifies that the object that is passed to it MUST implement Runnable, and hence must contain a run() method.

There's nothing very fancy here -- no abstruse object-oriented methodology, just a simple textual contract that is automatically enforced when you make use of the implements keyword.

Let's take a look at the simplest possible example of defining and using an interface.

Interfaces



Firstly, let's define an interface. We will create an interface that says that a class must contain a method called "greet()", with return type void, taking no parameters.


public interface Greeter {
    public void greet();
}




That's all there is to it. This interface forces any class that 'implements' it to have a greet method.

Let's create a class and say that it implements the Greeter interface.

public class Person implements Greeter {

}





This class won't compile. Why not? Because we have said that it implements Greeter, but it does not contain the mandatory greet() method. Let's add it.

public class Person implements Greeter {


    public void greet() {
        System.out.println("Hello there");
    }

}





Much better. Now the class compiles. We've also added an instruction to write "Hello there" to the console. We can put whatever code we like in the greet() method, or not code at all. The compiler is happy just so long as the method exists, as specified by the Greeter interface.

Finally, we'll create an object with a method that accepts any object that implements the Greeter interface.

public class RunGreeter {
    public void speak(Greeter greeter) {
        greeter.greet();
    }
}





The Speak method of the RunGreeter class can accept as a parameter any object that implements the Greeter interface. Furthermore, because all objects that implement this interface must contain a greet() method, RunGreeter can happily call that method, knowing that it must exist.

Let's put this all together in our main application method.

public class Application {

    public static void main(String[] args) {

        Person person = new Person();
        
        RunGreeter runner = new RunGreeter();
        
        runner.speak(person);

    }

}





Hello there




This is a complete application, which we can run to produce the output shown above.

interfaces may seem a little strange at first, but in fact they greatly simplify Java code, removing the need for the confusing "multiple inheritance" which is found in many other object oriented languages. They are used extensively in Java. One great thing about an interface is that it specifies only the minimum of which methods a class can contain. A class can therefore implement many interfaces and be used in many different ways.