Interfaces and Packages
Interfaces
The Java programming language supports interfaces that you use to define a protocol of behavior that can be implemented by any class anywhere in the class hierarchy.Defining an interface is similar to creating a new class. An interface definition has two components: the interface declaration and the interface body.
interfaceDeclaration { interfaceBody }The interfaceDeclaration declares various attributes about the interface such as its name and whether it extends another interface. The interfaceBody contains the constant and method declarations within the interface
To use an interface you write a class that implements the interface When a class claims to implement an interface the class is claiming that it provides a method implementation for all of the methods declared within the interface (and its superinterfaces).
When you define a new interface you are in essence defining a new reference data type. You can use interface names anywhere you'd use any other type name: variable declarations, method parameters and so on.
If you ship public interfaces to other programmers, here's a limitation of interfaces that you should be aware of: Interfaces cannot grow.
Creating and Using Packages
To make classes easier to find and to use, to avoid naming conflicts, and to control access, programmers bundle groups of related classes and interfaces into packages.A package is a collection of related classes and interfaces providing access protection and namespace management.
The classes and interfaces that are part of the Java platform are members of various packages that bundle classes by function: fundamental classes are in java.lang, classes for reading and writing (input and output) are in java.io, and so on. You can put your classes and interfaces in packages, too.
Let's look at a set of classes and examine why you might want to put them in a package. Suppose that you write a group of classes that represent a collection of graphic objects, such as circles, rectangles, lines, and points. You also write an interface Draggable, that classes implement if they can be dragged with the mouse by the user:
//in the Graphic.java file public abstract class Graphic { . . . } //in the Circle.java file public class Circle extends Graphic implements Draggable { . . . } //in the Rectangle.java file public class Rectangle extends Graphic implements Draggable { . . . } //in the Draggable.java file public interface Draggable { . . . }
Creating Interfaces?
An interface defines a protocol of behavior that can be implemented by any class anywhere in the class hierarchy. An interface defines a set of methods but does not implement them. A class that implements the interface agrees to implement all the methods defined in the interface, thereby agreeing to certain behavior.
An interface is a named collection of method definitions (without implementations). An interface can also declare constants.
Because an interface is simply a list of unimplemented, and therefore abstract, methods, you might wonder how an interface differs from an abstract class. The differences are significant.
- An interface cannot implement any methods, whereas an abstract class can.
- A class can implement many interfaces but can have only one superclass.
- An interface is not part of the class hierarchy. Unrelated classes can implement the same interface
Let's set up the example we'll be using in this section. Suppose that you have written a class that can watch stock prices coming over a data feed. This class allows other classes to register to be notified when the value of a particular stock changes. First, your class, which we'll call StockMonitor, would implement a method that lets other objects register for notification:
public class StockMonitor { public void watchStock(StockWatcher watcher, String tickerSymbol, double delta) { ... } }The first argument to this method is a StockWatcher object. StockWatcher is the name of an interface whose code you will see in the next section. That interface declares one method: valueChanged. An object that wants to be notified of stock changes must be an instance of a class that implements this interface and thus implements the valueChanged method. The other two arguments provide the symbol of the stock to watch and the amount of change that the watcher considers interesting enough to be notified of. When the StockMonitor class detects an interesting change, it calls the valueChanged method of the watcher.
The watchStock method ensures, through the data type of its first argument, that all registered objects implement the valueChanged method. It makes sense to use an interface data type here because it matters only that registrants implement a particular method. If StockMonitor had used a class name as the data type, that would artificially force a class relationship on its users. Because a class can have only one superclass, it would also limit what type of objects can use this service. By using an interface the registered objects class could be anything--Applet or Thread--for instance, thus allowing any class anywhere in the class hierarchy to use this service.
Using an Interface as a Type
When you define a new interface you are defining a new reference data type. You can use interface names anywhere you can use any other data type name. Recall that the data type for the first argument to the watchStock method in the StockMonitor class is StockWatcher:Only an instance of a class that implements the interface can be assigned to a reference variable whose type is an interface name. So only instances of a class that implements the StockWatcher interface can register to be notified of stock value changes. StockWatcher objects are guaranteed to have a valueChanged method.public class StockMonitor { public void watchStock(StockWatcher watcher, String tickerSymbol, double delta) { ... } }
Defining an Interface
An interface definition has two components: the interface declaration and the interface body.
The interface declaration declares various attributes about the interface such as its name and whether it extends other interfaces. The interface body contains the constant and the method declarations for that interface.
For example:
public interface StockWatcher { sunTicker = "SUNW"; void valueChanged(String tickerSymbol, double newValue); }This interface defines three constants which represent ticker symbols. The interface also declares, but does not implement, the valueChanged method. Classes that implement this interface provide the implementation for that method.
If public was not declared, the interface would be accessible only to classes defined in the same package as the interface.
An interface declaration can have one other component: a list of superinterfaces.
An interface can extend other interfaces, just as a class can extend or subclass another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces. The list of superinterfaces is a comma-separated list of all the interfaces extended by the new interface
The interface body contains method declarations for all the methods included in the interface A method declaration within an interface is followed by a semicolon (;) because an interface does not provide implementations for the methods declared within it. All methods declared in an interface are implicitly public and abstract.
An interface can contain constant declarations in addition to method declarations. All constant values defined in an interface are implicitly public, static, and final.
Member declarations in an interface disallow the use of some declaration modifiers; you cannot use transient, volatile, or synchronized in a member declaration in an interface Also, you may not use the private and protected specifiers when declaring members of an interface Previous releases of the Java platform allowed you to use the abstract modifier on interface declarations and on method declarations within interfaces. However, this is unnecessary, because interfaces and their methods are implicitly abstract. You should not use abstract in your interface declarations or in your method declarations within interfaces.
Implementing an Interface
An interface defines a protocol of behavior. A class that implements an interface adheres to the protocol defined by that interface To declare a class that implements an interface include an implements clause in the class declaration. Your class can implement more than one interface (the Java platform supports multiple inheritance for interfaces), so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class.
The implements clause follows the extends clause, if it exists.
Here's a partial example of an applet that implements the StockWatcher interface:
Note that this class refers to each constant defined in StockWatcher,sunTicker, oracle-Ticker, imple name. Classes that implement an interface inherit the constants defined within that interface. So those classes can use simple names to refer to the constants. Any other class can use an interfaces constants with a qualified name, like this:public class StockApplet extends Applet implements StockWatcher { ... public void valueChanged(String tickerSymbol, double newValue) { if (tickerSymbol.equals(sunTicker)) { ... } else if (tickerSymbol.equals(oracleTicker)) { ... } else if (tickerSymbol.equals(ciscoTicker)) { ... } } }
When a class implements an interface, it is essentially signing a contract. Either the class must implement all the methods declared in the interface and its superinterfaces, or the class must be declared abstract. The method signature--the name and the number and type of arguments in the class--must match the method signature as it appears in the interface. The StockApplet implements the StockWatcher interface, so the applet provides an implementation for the valueChanged method. The method ostensibly updates the applets display or otherwise uses this information.StockWatcher.sunTicker
Interfaces Cannot Grow
Suppose that you want to add some functionality to StockWatcher. For instance, suppose that you want to add a method that reports the current stock price, regardless of whether the value changed:However, if you make this change, all classes that implement the old StockWatcher interface will break because they dont implement the interface anymore! Programmers relying on this interface will protest loudly.public interface StockWatcher { void valueChanged(String tickerSymbol, double newValue); void currentValue(String tickerSymbol, double newValue); }Try to anticipate all uses for your interface up front and specify it completely from the beginning. Given that this is often impossible, you may need either to create more interfaces later or to break your customers code. For example, you could create a StockWatcher subinterface called StockTracker that declared the new method:
Now users of your code can choose to upgrade to the new interface or to stick with the old interface.public interface StockTracker extends StockWatcher { void currentValue(String tickerSymbol, double newValue); }
Creating a Package
To create a package, you put a class or an interface in it. To do this, you put a package statement at the top of the source file in which the class or the interface is defined. For example, the following code appears in the source file Circle.java and puts the Circle class in the graphics package:The Circle class is a public member of the graphics package.package graphics; public class Circle extends Graphic implements Draggable { . . . }You must include a package statement at the top of every source file that defines a class or an interface that is to be a member of the graphics package. So you would also include the statement in Rectangle.java and so on:
package graphics; public class Rectangle extends Graphic implements Draggable { . . . }The scope of the package statement is the entire source file, so all classes and interfaces defined in Circle.java and Rectangle.java are also members of the graphics package. If you put multiple classes in a single source file, only one may be public, and it must share the name of the source files base name. Only public package members are accessible from outside the package.
If you do not use a package statement, your class or interface ends up in the default package, which is a package that has no name. Generally speaking, the default package is only for small or temporary applications or when you are just beginning development. Otherwise, classes and interfaces belong in named packages.
Naming a Package
With programmers all over the world writing classes and interfaces using the Java programming language, it is likely that two programmers will use the same name for two different classes. In fact, the previous example does just that: It defines a Rectangle class when there is already a Rectangle class in the java.awt package. Yet the compiler allows both classes to have the same name. Why? Because they are in different packages, and the fully qualified name of each class includes the package name. That is, the fully qualified name of the Rectangle class in the graphics package is graphics.Rectangle, and the fully qualified name of the Rectangle class in the java.awt package is java.awt.Rectangle.This generally works just fine unless two independent programmers use the same name for their packages. What prevents this problem? Convention.
Companies use their reversed Internet domain name in their package names, like this: com.company.package. Some companies now choose to drop the first element com. in this example from their package names. Name collisions that occur within a single company need to be handled by convention within that company, perhaps by including the region or the project name after the company name, for example, com.company.region.package.
Managing Source and Class Files
Many implementations of the Java platform rely on hierarchical file systems to manage source and class files, although The Java Language Specification does not require this. The strategy is as follows.You put the source code for a class or an interface in a text file whose name is the simple name of the class or the interface and whose extension is .java. Then you put the source file in a directory whose name reflects the name of the package to which the class or the interface belongs. For example, the source code for the Rectangle class would be in a file named Rectangle.java, and the file would be in a directory named graphics. The graphics directory might be anywhere on the file system.
The qualified name of the package member and the path name to the file are parallel, assuming the UNIX file name separator slash (/):
class name graphics.Rectangle pathname to file graphics/Rectangle.java As you may recall, by convention a company uses its reversed Internet domain name in its package names. The fictional company whose Internet domain name is taranis.com would precede all its package names with com.taranis. Each component of the package name corresponds to a subdirectory. So if Taranis had a graphics package that contained a Rectangle.java source file, it would be contained in a series of subdirectories.
When you compile a source file, the compiler creates a different output file for each class and interface defined in it. The base name of the output file is the name of the class or the interface, and its extension is .class.
Like a .java file, a .class file should also be in a series of directories that reflect the package name. However, it does not have to be in the same directory as its source. You could arrange your source and class directories separately.
By doing this, you can give the classes directory to other programmers without revealing your sources.
You need to manage your source and class files in this manner so that the compiler and the interpreter can find all the classes and interfaces your program uses. When the compiler encounters a new class as its compiling your program, it must be able to find the class so as to resolve names, do type checking, and so on. Similarly, when the interpreter encounters a new class as its running your program, it must be able to find the class to invoke its methods, and so on. Both the compiler and the interpreter search for classes in each directory or ZIP file listed in your class path.
A class path is an ordered list of directories or ZIP files in which to search for class files.
Each directory listed in the class path is a top-level directory in which package directories appear. From the top-level directory, the compiler and the interpreter can construct the rest of the path, based on the package and the class name for the class. For example, the class path entry for the directory structure shown in the previous diagram would include classes but not com or any of the directories below com. Both the compiler and the interpreter construct the path name to a .class file with its full package name.
By default, the compiler and the interpreter search the current directory and the ZIP file containing the Java platform class files. In other words, the current directory and the Java platform class files are automatically in your class path. Most, if not all, classes can be found in these two locations. So its likely that you don't have to worry about your class path. In some cases, however, you might have to set your class path.
Using Package Members
Only public package members are accessible outside the package in which they are defined. To use a public package member from outside its package, you must do one or more of the following:
- Refer to the member by its long (qualified) name
- Import the package member
- Import the members entire package
Each is appropriate for different situations, as explained in the following sections.
Referring to a Package Member by Name
So far, the examples in this tutorial have referred to classes and interfaces by their simple names, such as Rectangle and StockWatcher. You can use a package members simple name if the code you are writing is in the same package as that member or if the members package has been imported.However, if you are trying to use a member from a different package and that package has not been imported, you must use the members qualified name, which includes the package name. This is the qualified name for the Rectangle class declared in the graphics package in the previous example:
graphics.RectangleYou could use this long name to create an instance of graphics.Rectangle:
graphics.Rectangle myRect = new graphics.Rectangle();You'll find that using long names is okay for one-shot uses. But you'd likely get annoyed if you had to write graphics.Rectangle again and again. Also, your code would get very messy and difficult to read. In such cases, you can just import the member instead.
Importing a Package Member
To import a specific member into the current file, put an import statement at the beginning of your file before any class or interface definitions but after the package statement, if there is one. Here's how you would import the Circle class from the graphics package created in the previous section:import graphics.Circle;Now you can refer to the Circle class by its simple name:
Circle myCircle = new Circle();This approach works well if you use just a few members from the graphics package. But if you use many classes and interfaces from a package, you can import the entire package.
Importing an Entire Package
To import all the classes and interfaces contained in a particular package, use the import statement with the asterisk (*) wildcard character:Now you can refer to any class or interface in the graphics package by its short name:import graphics.*;Circle myCircle = new Circle(); Rectangle myRectangle = new Rectangle();The asterisk in the import statement can be used only to specify all the classes within a package, as shown here. It cannot be used to match a subset of the classes in a package. For example, the following does not match all the classes in the graphics package that begin with A:
import graphics.A*; // does not workInstead, it generates a compiler error. With the import statement, you can import only a single package member or an entire package.
For your convenience, the Java runtime system automatically imports three entire packages:
- The default package (the package with no name)
- The java.langpackage
- The current package
Disambiguating a Name
If by some chance a member in one package shares the same name with a member in another package and both packages are imported, you must refer to each member by its qualified name. For example, the previous example defined a class named Rectangle in the graphics package. The java.awt package also contains a Rectangle class. If both graphics and java.awt have been imported, the following is ambiguous:In such a situation, you have to be more specific and use the members qualified name to indicate exactly which Rectangle class you want:Rectangle rect;graphics.Rectangle rect;
![]()