JAVA Mod5
JAVA Mod5
Module 5
Packages and Interfaces, Exception Handling
Packages and Interfaces:
Packages,
Access Protection,
Importing Packages,
Interfaces,
Exception Handling:
Exception-Handling Fundamentals,
Exception Types,
Uncaught Exceptions,
Using try and catch,
Multiple catch Clauses,
Nested try Statements,
throw, throws, finally,
Java’s Built-in Exceptions,
Creating Your Own Exception Subclasses,
Chained Exceptions,
Using Exceptions.
Packages:
The name of each example class was taken from the same name space. This means
that a unique name had to be used for each class to avoid name collisions.
Java provides a mechanism for partitioning the class name space into more
manageable chunks. This mechanism is the package.
The package is both a naming and a visibility control mechanism. You can define
classes inside a package that are not accessible by code outside that package. You can
also define class members that are only exposed to other members of the same
package.
Defining a Package:
To create a package is quite easy: simply include a package command as the first
statement in a Java source file.
Any classes declared within that file will belong to the specified package.
The package statement defines a name space in which classes are stored. If you omit
the package statement, the class names are put into the default package, which has no
name.
package pkg;
Here, pkg is the name of the package.
For example, the following statement creates a package called MyPackage.
package MyPackage;
Java uses file system directories to store packages. For example, the .class files for
any classes you declare to be part of MyPackage must be stored in a directory called
MyPackage.
Remember that case is significant, and the directory name must match the package
name exactly.
More than one file can include the same package statement. The package statement
simply specifies to which package the classes defined in a file belong.
You can create a hierarchy of packages. To do so, simply separate each package name
from the one above it by use of a period.
Access Protection:
Packages add another dimension to access control.
Java provides many levels of protection to allow fine-grained control over the
visibility of variables and methods within classes, subclasses, and packages Classes
and packages are both means of encapsulating and containing the name space and
scope of variables and methods.
Packages act as containers for classes and other subordinate packages.
Classes act as containers for data and code. The class is Java’s smallest unit of
abstraction.
Because of the interplay between classes and packages, Java addresses four categories
of visibility for class members:
• Subclasses in the same package
• Non-subclasses in the same package
• Subclasses in different packages
• Classes that are neither in the same package nor subclasses
The three access specifiers, private, public, and protected, provide a variety of ways
to produce the many levels of access required by these categories.
Table sums up the interactions.
Importing Packages:
Given that packages exist and are a good mechanism for compartmentalizing diverse
classes from each other, it is easy to see why all of the built-in Java classes are stored
in packages.
There are no core Java classes in the unnamed default package; all of the standard
classes are stored in some named package.
Java includes the import statement to bring certain classes, or entire packages, into
visibility.
Once imported, a class can be referred to directly, using only its name. The import
statement is a convenience to the programmer and is not technically needed to write a
complete Java program.
If you are going to refer to a few dozen classes in your application, however, the
import statement will save a lot of typing.
There is no practical limit on the depth of a package hierarchy, except that imposed by
the file system.
Finally, you specify either an explicit classname or a star (*), which indicates that the
Java compiler should import the entire package.
This code fragment shows both forms in use:
import java.util.Date;
import java.io.*;
All of the standard Java classes included with Java are stored in a package called
java.
The basic language functions are stored in a package inside of the java package called
java.lang. This is equivalent to the following line being at the top of all of your
programs:
import java.lang.*;
If a class with the same name exists in two different packages that you import using
the star form, the compiler will remain silent, unless you try to use one of the classes.
In that case, you will get a compile-time error and have to explicitly name the class
specifying its package.
It must be emphasized that the import statement is optional. Any place you use a
class name, you can use its fully qualified name, which includes its full package
hierarchy.
Interfaces:
Using the keyword interface, you can fully abstract a class’ interface from its
implementation.
That is, using interface, you can specify what a class must do, but not how it does it.
Interfaces are syntactically similar to classes, but they lack instance variables, and
their methods are declared without any body.
In practice, this means that you can define interfaces that don’t make assumptions
about how they are implemented.
Once it is defined, any number of classes can implement an interface. Also, one class
can implement any number of interfaces.
To implement an interface, a class must create the complete set of methods defined by
the interface. However, each class is free to determine the details of its own
implementation.
By providing the interface keyword, Java allows you to fully utilize the “one
interface, multiple methods” aspect of polymorphism.
Interfaces are designed to support dynamic method resolution at run time.
Normally, in order for a method to be called from one class to another, both classes
need to be present at compile time so the Java compiler can check to ensure that the
method signatures are compatible.
Defining an Interface:
An interface is defined much like a class.
This is the general form of an interface:
Here is an example of an interface definition. It declares a simple interface that contains one
method called callback( ) that takes a single integer parameter.
interface Callback {
void callback(int param);
}
Implementing Interfaces:
Once an interface has been defined, one or more classes can implement that interface.
Here is a small example class that implements the Callback interface shown earlier.
class Client implements Callback {
// Implement Callback's interface
public void callback(int p) {
System.out.println("callback called with " + p);
}
}
Notice that callback( ) is declared using the public access specifier.
It is both permissible and common for classes that implement interfaces to define
additional members of their own.
For example, the following version of Client implements callback( ) and adds the
method nonIfaceMeth( ):
class Client implements Callback {
// Implement Callback's interface
public void callback(int p) {
System.out.println("callback called with " + p);
}
void nonIfaceMeth() {
System.out.println("Classes that implement interfaces " +
"may also define other members, too.");
}
}
}
}
Now, try the following class:
class TestIface2 {
public static void main(String args[]) {
Callback c = new Client();
AnotherClient ob = new AnotherClient();
c.callback(42);
c = ob; // c now refers to AnotherClient object
c.callback(42);
}
}
The output from this program is shown here:
callback called with 42
Another version of callback
p squared is 1764
Partial Implementations:
If a class includes an interface but does not fully implement the methods defined by
that interface, then that class must be declared as abstract.
For example:
abstract class Incomplete implements Callback {
int a, b;
void show() {
System.out.println(a + " " + b);
}
// ...
}
Here, the class Incomplete does not implement callback( ) and must be declared as
abstract.
Any class that inherits Incomplete must implement callback( ) or be declared
abstract itself.
Nested Interfaces:
An interface can be declared a member of a class or another interface. Such an
interface is called a member interface or a nested interface.
A nested interface can be declared as public, private, or protected.
This differs from a top-level interface, which must either be declared as public or use
the default access level, as previously described.
When a nested interface is used outside of its enclosing scope, it must be qualified by
the name of the class or interface of which it is a member.
Thus, outside of the class or interface in which a nested interface is declared, its name
must be fully qualified.
}
Notice that A defines a member interface called NestedIF and that it is declared
public.
Next, B implements the nested interface by specifying implements A.NestedIF
Notice that the name is fully qualified by the enclosing class’ name.
Inside the main( ) method, an A.NestedIF reference called nif is created, and it is
assigned a reference to a B object. Because B implements A.NestedIF, this is legal.
Applying Interfaces:
To understand the power of interfaces, let’s look at a more practical example. In
earlier chapters, you developed a class called Stack that implemented a simple fixed-
size stack. However, there are many ways to implement a stack.
First, here is the interface that defines an integer stack. Put this in a file called
IntStack.java.
else
stck[++tos] = item;
}
// Pop an item from the stack
public int pop() {
if(tos < 0) {
System.out.println("Stack underflow.");
return 0;
}
else
return stck[tos--];
}
}
class IFTest {
public static void main(String args[]) {
FixedStack mystack1 = new FixedStack(5);
FixedStack mystack2 = new FixedStack(8);
// push some numbers onto the stack
for(int i=0; i<5; i++) mystack1.push(i);
for(int i=0; i<8; i++) mystack2.push(i);
// pop those numbers off the stack
System.out.println("Stack in mystack1:");
for(int i=0; i<5; i++)
System.out.println(mystack1.pop());
System.out.println("Stack in mystack2:");
for(int i=0; i<8; i++)
System.out.println(mystack2.pop());
}
}
Variables in Interfaces:
You can use interfaces to import shared constants into multiple classes by simply
declaring an interface that contains variables that are initialized to the desired values.
It is as if that class were importing the constant fields into the class name space as
final variables.
The next example uses this technique to implement an automated “decision maker”:
import java.util.Random;
interface SharedConstants {
int NO = 0;
int YES = 1;
int MAYBE = 2;
int LATER = 3;
int SOON = 4;
int NEVER = 5;
}
class Question implements SharedConstants {
Random rand = new Random();
int ask() {
int prob = (int) (100 * rand.nextDouble());
if (prob < 30)
return NO; // 30%
else if (prob < 60)
return YES; // 30%
else if (prob < 75)
return LATER; // 15%
else if (prob < 98)
return SOON; // 13%
else
return NEVER; // 2%
}
}
class AskMe implements SharedConstants {
static void answer(int result) {
switch(result) {
case NO:
System.out.println("No");
break;
case YES:
System.out.println("Yes");
break;
case MAYBE:
System.out.println("Maybe");
break;
case LATER:
System.out.println("Later");
break;
case SOON:
System.out.println("Soon");
break;
case NEVER:
System.out.println("Never");
break;
}
}
public static void main(String args[]) {
Question q = new Question();
answer(q.ask());
answer(q.ask());
answer(q.ask());
answer(q.ask());
}
}
When a class implements an interface that inherits another interface, it must provide
implementations for all methods defined within the interface inheritance chain.
Following is an example:
// One interface can extend another.
interface A {
void meth1();
void meth2();
}
// B now includes meth1() and meth2() -- it adds meth3().
interface B extends A {
void meth3();
}
// This class must implement all of A and B
class MyClass implements B {
public void meth1() {
System.out.println("Implement meth1().");
}
public void meth2() {
System.out.println("Implement meth2().");
}
public void meth3() {
System.out.println("Implement meth3().");
}
}
class IFExtend {
public static void main(String arg[]) {
MyClass ob = new MyClass();
ob.meth1();
ob.meth2();
ob.meth3();
}
}