In this lesson, you will learn about interfaces and annotations.
Interfaces define a standardized set of commands that a class will obey.
The commands are a set of methods that a class implements.
The interface definition states the names of the methods and their return types and argument signatures. There is no executable body for any method that is left to each class that implements the interface.
Once a class implements an interface, the Java compiler knows that an instance of the class will contain the specified set of methods. Therefore, it will allow you to call those methods for an object referenced by a variable whose type is the interface.
Implementing an interface enables a class to be "plugged in" to any situation that requires a specific behavior (manifested through the set of methods).
An analogy: a serial interface on a computer defines a set of pin/wire assignments and the control signals that will be used. Note that:
Using an interface rather than inheritance to specify a certain set of methods allows a class to inherit from some other class.
Interfaces can also specify constants that are public, static,
and final.
Like this Java tutorial? Try our self-paced online Java courses, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
To create an interface definition:
interface instead of class.public and abstract,
and cannot have any other state; it is OK to specify those terms, but not
necessary (usually public is specified and abstract is
not - that makes it easy to copy the list of methods, paste them into a
class, and modify them).public.
protected or private; these involve what are called inner
classes.[modifiers] interface InterfaceName {
// declaring methods
[public abstract] returnType methodName1(arguments);
// defining constants
[public static final] type fieldName = value;
}
public interface Printable {
void printAll();
}
This interface requires only one method. Any class implementing Printable must
contain a public void printall() method in order to compile.
Because the above interface is defined as public, its definition
must be in its own file, even though that file will be tiny.
An interface definition may also define fields that are automatically public
static final -
these are used as constants.
Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
A class definition may, in addition to whatever else it does, implement one or more interfaces.
Once a class states that it implements an interface, it must supply all the methods defined for that interface, complete with executable code.
abstract class
that can only be used as a base class (where some derived class would then
fully implement the interface).To implement an interface:
[modifiers] class ClassName implements InterfaceName {
any desired fields
// implement required methods
[modifiers] returnType methodName1(arguments) {
executable code
}
any other desired methods
}
It is important to note that a class may implement an interface in addition to whatever else it might do, so it could have additional fields and methods not associated with the interface.
A class may implement more than one interface - that merely adds to the list of required methods. Use a comma-separated list for the interface names.
[modifiers] class ClassName implements Interface1Name, Interface2Name {
// must implement all methods from all implemented interfacse
}
The complete example will use three separate files (the third file will be shown shortly):
public interface Printable {
void printAll();
}
class Person implements Printable {
private String name = new String("Bill");
private int age = 22;
public void printAll() {
System.out.println("Name is " + name + ", age is " + age);
}
}
class Stock implements Printable {
private String tickerSymbol = new String("XYZ");
private int shares = 100;
private int currentPrice = 4000; // in pennies
public void printAll() {
System.out.println(tickerSymbol + " " + shares +
" shares at " + currentPrice);
System.out.println("Value: " + currentPrice * shares);
}
public void sell() {
System.out.println(tickerSymbol + " sold");
}
}
This file contains two classes with package access. Since the classes are
not public, they can both be in the same file, and the file name does
not need to match either class name. This is done purely as a convenience; it is not a good programming practice in general, but is sometimes
useful if one class is highly coupled (interrelated) with the other,
which is not the case here. Both classes implement the
Printable interface, but are otherwise not related. Stock has
another method not related to Printable.
Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
An interface is like a class where the internal structure and some of the behavior is hidden.
.class file, and get loaded by the same process that
loads true classes.Since a class that implements an interface is a class in all other respects, you can create a reference variable for that class, as usual.
You can also create a reference variable whose type is the interface name.
Printable variable containing a Stock instance,
the sell method is not visible, since it is not declared
in Printable.To access an interface-implementing class with an interface class reference:
[modifiers] InterfaceName variableName;
Example:
Person and Stock implement Printable.Printable,
and assign either a Person or a Stock object
to it.printAll() method from the Printable reference
variable, since the compiler knows that method will exist, no matter which
type of object is actually stored in the variable.Person p = new Person(); Stock s = new Stock(); Printable pr; pr = p;
or
pr = s;
or
pr = new Person();
If you have a variable that is declared as a reference to the interface type, you can use it to call an interface method.
public class PrintableTest {
public static void main(String[] args) {
Person p = new Person();
Stock s = new Stock();
p.printAll();
s.printAll();
Printable pr;
pr = p;
pr.printAll();
pr = s;
pr.printAll();
}
}
Once pr has been assigned a Printable instance, we can call pr.printAll();
sell() method when pr refers
to a Stock, since the compiler would not associate it
with a variable whose type was Printable. Note: to compile this, use *.java; since the name of the file containing Stock and Person
is PrintableThings.java, the compiler won't be able to find those classes, since it would be
looking for Person.java and Stock.java.
Note: you can test the type of object actually contained in an interface reference, and typecast it back to that type.
sell() method for a Stock:if (pr instanceof Stock) ((Stock) pr).sell();
Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
If a class implements an interface, then all subclasses of it will also automatically implement the interface.
javadoc,
if the base class is not in the same group of files).An interface definition can inherit from another interface.
The following interface extends the Printable interface
and adds another required method (the new method overloads printAll to print
to a specified destination instead of to System.out):
import java.io.PrintStream;
public interface Printable2 extends Printable {
public void printAll(PrintStream p);
}
A class implementing Printable2 must define both versions of printAll.
import java.io.PrintStream;
class Cat implements Printable2 {
public void printAll() {
printAll(System.out);
}
public void printAll(PrintStream out) {
out.println("Meow");
}
}
public class Printable2Test {
public static void main(String[] args) {
Printable2 c = new Cat();
c.printAll(System.err);
c.printAll();
}
}
import employees.*;
import vendors.Invoice;
import finance.*;
import util.*;
public class Payroll {
public static void main(String[] args) {
---- C O D E O M I T T E D ----
for (int i = 0; i < e.length; i++) {
---- C O D E O M I T T E D ----
}
---- C O D E O M I T T E D ----
Invoice[] inv = new Invoice[4];
inv[0] = new Invoice("ABC Co.", 456.78);
inv[1] = new Invoice("XYZ Co.", 1234.56);
inv[2] = new Invoice("Hello, Inc.", 999.99);
inv[3] = new Invoice("World, Ltd.", 0.43);
CheckPrinter.printChecks(e);
CheckPrinter.printChecks(inv);
}
}
The last several lines of code create an array of invoices, then
use the CheckPrinter to print employees and invoices separately. It
would also be possible to create an array of Payable objects, and add
in the elements from both the employees and invoices arrays, but that
seems like an unneccessary complication for this application.
Like this Java tutorial? Try our self-paced online Java courses, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
A real-world use of interfaces is for event-handling
interface method
for each object.implements the interface that is expected for that event - therefore it will
have the specified method.Assuming that there is an event type called XXXEvent:
XXXListener.addXXXListener.protected utility
method called fireXXXEvent that it uses to trigger the event
notifications (and it is available for you to call if you extend the class).The ActionListener interface is used for GUI events like button
clicks.
actionPerformed method
for any registered listeners (the code to do this is already built into
the GUI classes, and the Java API defines the interface shown below).public interface ActionListener {
public void actionPerformed(ActionEvent e);
}
A class can listen for events if it implements ActionListener.
this:public class MyClass implements ActionListener {
...
public void actionPerformed(ActionEvent e) {
System.out.println("Event occurred");
}
someOtherMethod() {
guiComponent.addActionListener(this);
}
}
For the class that fires the event, registering is done with the addActionListener(ActionListener) method,
which receives a reference to an ActionListener object:
java.util.Vector)
of listeners.actionPerformed() for
each element on the list (and passing a reference to an event object that
it creates).For the sake of completeness, when the listener interface has multiple methods,
there are often abstract classes that implement most or all of the methods
as do-nothing methods - so that all you need to do is extend the class and
implement the methods that you choose
TableModel interfaceThe Swing classes contain a component called JTable, which
displays a spreadsheet-like grid. Note that:
TableModel interface defines a set of methods that allow
a JTable (the controller) to query a data model to find out information
in order to display it.Below are some of the methods from TableModel:
public interface TableModel
|
|---|
int getColumnCount()
|
| Returns the number of columns in the model. |
int getRowCount()
|
| Returns the number of rows in the model. |
String getColumnName(int columnIndex)
|
Returns the name of the column at columnIndex. |
Class<?> getColumnClass(int columnIndex)
|
| Returns the most specific superclass for all the cell values in the column. |
Object getValueAt(int rowIndex, int columnIndex)
|
Returns the value for the cell at columnIndex and rowIndex. |
boolean
isCellEditable(int rowIndex, int columnIndex)
|
Returns true if the cell at rowIndex and columnIndex is editable. |
void setValueAt(Object aValue, int rowIndex, int columnIndex)
|
Sets the value in the cell at columnIndex and rowIndex to aValue. |
You can see the conversation that will take place between the controller and the model. Note that:
getColumnClass, so it can determine from its
settings how to display the values (instances
of Number, which Integer, Double,
etc., extend, get right-aligned, Boolean columns use a check
box, all others get left-aligned - these settings are configurable).getColumnName.isCellEditable.
setValueAt.import java.util.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableModelExample {
public static void main(String[] args) {
DemoTableModel model = new DemoTableModel();
new TableGUI("Table Model Example", model).setVisible(true);
new TableConsole(model);
new TableHTML(model);
}
}
class DemoTableModel extends AbstractTableModel {
String[] titles = { "Name", "Active", "Grade" };
String[] names = { "Mary", "Joe", "Sue" };
Boolean[] actives = { new Boolean(true), new Boolean(false),
new Boolean(true) };
Integer[] grades = { new Integer(99), new Integer(87),
new Integer(89) };
public int getRowCount() { return names.length; }
public int getColumnCount() { return 3; }
public String getColumnName(int col) {
return titles[col];
}
public Object getValueAt(int row, int column) {
if (column == 0) return names[row];
else if (column == 1) return actives[row];
else return grades[row];
}
public void setValueAt(Object v, int row, int column) {}
public Class getColumnClass(int column) {
if (column == 0) return String.class;
else if (column == 1) return Boolean.class;
else return Integer.class;
}
public boolean isCellEditable(int row, int column) {
return false;
}
}
class TableGUI extends JFrame {
public TableGUI(String title, DemoTableModel model) {
super(title);
JTable jt;
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
jt = new JTable(model);
setSize(600,170);
getContentPane().add(jt);
}
}
class TableConsole {
TableModel model;
public TableConsole(TableModel model) {
int rows = model.getRowCount();
int cols = model.getColumnCount();
for (int c = 0; c < cols; c++) {
System.out.print(fixedStringLength(model.getColumnName(c), 15));
}
System.out.println();
System.out.println("-------------- -------------- -------------- ");
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
System.out.print(
fixedStringLength(model.getValueAt(r, c).toString(), 15));
}
System.out.println();
}
}
private String fixedStringLength(String in, int size) {
if (in.length() > size) in = in.substring(0, 15);
char[] blankArray = new char[size - in.length()];
for (int i = 0; i < blankArray.length; i++) blankArray[i] = ' ';
return in + String.valueOf(blankArray);
}
}
class TableHTML {
TableModel model;
public TableHTML(TableModel model) {
java.io.PrintStream out = System.out;
int rows = model.getRowCount();
int cols = model.getColumnCount();
out.println("<html><Head><title>My Table</title></head>");
out.println(
"<body><table border='1' cellpadding='8' cellspacing='0'><tr>");
for (int c = 0; c < cols; c++) {
out.print("<th>" + model.getColumnName(c) + "</th>");
}
out.println("</tr>");
for (int r = 0; r < rows; r++) {
out.println("<tr>");
for (int c = 0; c < cols; c++) {
System.out.print("<td>" + model.getValueAt(r, c) + "</td>");
}
out.println("</tr>");
}
out.println("</table></body></html>");
}
}
For convenience, all the classes are in one file.
The DemoTableModel class implements TableModel by
extending AbstractTableModel,
thus gaining implementations of several methods (like those relating to
model change event listener lists), then adding the remaining methods.
The model is based on parallel arrays of student data: name, grade, and active or not- each array represents one column of data, and element 0 in each array is the same student.
The titles array holds column names.
getColumnCount returns 3, because we know that in advance.
getRowCount returns the length of one of the data arrays.
For getColumnName, we return an appropriate string from the titles array.
For getValueAt, we pick an array based on the column number,
and return the element at the row index.
getColumnClass returns a class object that matches the type
of data for each array.
isCellEditable returns false, and setValueAt does
nothing, because our model is not editable.
We then have three possible views of the data: a Swing GUI view that
uses a JTable, a console view that prints column-aligned data,
and an HTML view that produces HTML code to the console (you can copy that
and paste it into a file to view in a browser, like in
tablemodel.html).
Since the JTable is the whole reason TableModel exists,
it knows what to do with the model. The TableConsole and TableHTML view
objects have to explicitly call the appropriate methods in order to display
the data.
It is actually possible to have an interface that requires no methods at all! This creates what is called a marker interface.
A declaration that a class implements the interface makes it an instance of that interface, so that it can be passed as a parameter to a method expecting an instance of the interface, or as a return value from a method that declares it returns an instance of the interface.
An example from the API is Serializable
Serializable may be turned into
a serial data stream, perhaps to save in a file or send across a network
connection.writeObject method of ObjectOutputStream accepts a parameter whose
type is Object, but throws an exception if it doesn't implement Serializable.Serializable, but any of its object fields
must also reference objects that are Serializable (or marked
as transient), and any of their fields ... .Like this Java tutorial? Try our self-paced online Java courses, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
Java 5 added a new syntax element: the annotation. An annotation
is a piece of descriptive data (metadata) about a class, field, or method.
It is somewhat like a comment, except that individual annotations are predefined,
reusable, and can have effects on either the compilation process or the
use of the class once compiled. If you have used an IDE like Eclipse or NetBeans,
you may have seen the @Override annotation on editor-supplied template code.
This particular annotation tells the compiler that the method that immediately
follows is meant to override a base class method (or a method required by
an interface). If it does not (because perhaps you spelled the name incorrectly,
or got the parameter list wrong), then a compiler error is issued.
Annotations provide Java with a means to achieve, at least to some extent, Aspect-Oriented Programming, or AOP. AOP recognizes cross-cutting concerns, that is, aspects of an element that cut across classes that might not be related by inheritance or implementation of an interface.
An example
is a Java web service. While servlets usually extend a Java EE base class
(and will always implement the Servlet interface), there is
no specified base class or interface for a web service. Instead, configuration
information informs the web server that a specific class is intended to
be used as a web service, and the server takes steps to make that happen.
Prior to annotations, that information was supplied solely by XML configuration
files. With Java EE 5, annotations were provided with which a class could
be internally marked as a web service.
Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
@ symbol
precedes the interface keyword in the declaration (as in @interface).
When used, an @ symbol is prepended to the name.value is special - if it is the
only element, then it does not need to be named when used (a single
value passed to the annotation will be assumed to be the value).value.Serializable interface. SOURCE policy), or preserved into the compiled class
(CLASS persists, but the JVM isn't required to keep the information after the
class is loaded, and RUNTIME annotations do remain with the class in the
JVM).
@Override is an example of the source type, since it is
only needed by the compiler @Deprecated,
which states that an element is deprecated - you will receive a compiler
warning if your code uses an element marked with this annotation (and,
since you might be accessing the element in an already-compiled class,
this annotation must persist into the compiled class file). @Target and @Retention are used before the annotation definition
to specify which type of element receives the annotation, and what the retention is.Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
To apply an annotation to a class or element, precede the item with the name
of the annotation, prefixed with the @ symbol.
If the annotation takes parameters, supply them in parentheses, as a comma
separated list of parameterName=parameterValue. If the only parameter
is called value, then you can just supply the parameterValue, without specifying
it by name.
@AnnotationName(value=parameterValue, parameter2Name=parameter2Value, ...)
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import java.util.Date;
@WebService(serviceName="DateTimeService")
public class AnnotatedWebService {
@WebMethod
public Date getDate() {
return new Date();
}
@WebMethod
public Date getFutureDate(@WebParam(name="days") int daysOffset) {
Date d = new Date();
d.setDate(d.getDate() + daysOffset);
return d;
}
}
The @WebService annotation persists into compiled code.
Tools that work with enterprise-level
web servers (like Glassfish, JBoss, etc.),
can read the annotation via reflection, and install
the class as a web service, performing all the necessary tasks, such
as creating a WSDL file, establishing a URL for the service, and installation
it under that URL. The annotation can be parameterized with the name
for the service (which defaults to the class name followed by "Service"),
as well as several other items affecting the setup as a web service.
serviceName parameter to the @WebService annotation
tells the server to set up the service under that name, as opposed to
the default, which would have been AnnotatedWebServiceService (the default
behavior appends "Service" to the class name, which, in this case, would
be redundant).@WebMethod annotations tell the server that these methods
should be set up as RPC methods which can be remotely invoked (by default,
the methods are exposed, the annotation is actually only needed when
renaming the method, or to exclude the method from the service, but common
practice is to include the unparameterized annotation for methods to be
exposed as is). @WebParam annotation is used to rename the daysOffset parameter,
which would be used from ordinary Java code,
to days when the RPC is remotely
invoked. Due to the limitations of reflection, where parameter names
are not preserved into compiled classes, this annotation is necessary
to avoid having the parameters be called arg0, arg1,
etc. Like this Java tutorial? Try our self-paced online Java course, which includes videos and exercises in addition to the content in this Java tutorial. Not sure if you want to pay for that? Register for a free demo of the course.
This page was last updated on 2013-01-03
All pages and graphics in this Java Tutorial is copyright 2013 and are the property of Webucator, Inc. unless otherwise specified. The purpose of this website is to help you learn Java on your own and use of the website implies your agreement to our Terms of Service.