Interface Package-1
Interface Package-1
Interface Package-1
Interfaces
Introduction
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.
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 bythe 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.
Defining an Interface
An interface is defined much like a class. This is the general form of an interface:
access interface name {
return-type method-name1(parameter-list);
return-type method-name2(parameter-list);
type final-varname1 = value;
type final-varname2 = value;
// ...
return-type method-nameN(parameter-list);
type final-varnameN = value;
}
When no access specifier is included, then default access results, and the interface is only
available to other members of the package in which it is declared. When it is declared as
public, the interface can be used by any other code. In this case, the interface must be the
only public interface declared in the file, and the file must have the same name as the interface.
name is the name of the interface, and can be any valid identifier. Notice that the methods that
are declared have no bodies. They end with a semicolon after the parameter list. They are,
essentially, abstract methods; there can be no default implementation of any method specified
within an interface. Each class that includes an interface must implement all of the methods.
Variables can be declared inside of interface declarations. They are implicitly final and
static, meaning they cannot be changed by the implementing class. They must also be
initialized. All methods and variables are implicitly public.
Implementing Interfaces
Once an interface has been defined, one or more classes can implement that interface. To
implement an interface, include the implements clause in a class definition, and then create
the methods defined by the interface. The general form of a class that includes the
implementsclause looks like this:
Example:
interface Callback {
}
}
class TestIface {
public static void main(String args[]) {
Callback c = new Client();
c.callback(42);
}
}
The output of this program is shown here:
callback called with 42
example 2
the below program explain about dynamic polymorphism.
interface Callback {
}
}
// Another implementation of Callback.
class AnotherClient implements Callback {
// Implement Callback's interface
public void callback(int p) {
System.out.println("Another version of callback");
System.out.println("p squared is " + (p*p));
}
}
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);
}
}
interface X
{
public void myMethod();
}
interface Y
{
public void myMethod1();
}
class vj3 implements X, Y
{
public void myMethod()
{
System.out.println("Implementing more than one interfaces one is
x");
}
public void myMethod1()
{
System.out.println("Implementing more than one interfaces ther is
y");
}
Example4:stack operations
interface IntStack {
void push(int item); // store an item
int pop(); // retrieve an item
}
// An implementation of IntStack that uses fixed storage.
class FixedStack implements IntStack {
private int stck[];
private int tos;
// allocate and initialize stack
FixedStack(int size) {
stck = new int[size];
tos = -1;
}
class IFTest {
extending interfaces
class IFExtend
{
public static void main(String arg[])
{
MyClass ob = new MyClass();
ob.meth1();
ob.meth2();
ob.meth3();
}
}
Package:
A package is a namespace that organizes a set of related classes and interfaces. Conceptually
you can think of packages as being similar to different folders on your computer.
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.
class Balance {
String name;
double bal;
Balance(String n, double b) {
name = n;
bal = b;
}
void show() {
if(bal<0)
System.out.print("--> ");
System.out.println(name + ": $" + bal);
}
}
class AccountBalance
{
public static void main(String args[])
{
Balance current[] = new Balance[3];
current[0] = new Balance("K. J. Fielding", 123.23);
current[1] = new Balance("Will Tell", 157.02);
current[2] = new Balance("Tom Jackson", -12.33);
for(int i=0; i<3; i++) current[i].show();
}
}
ACCESS PROTECTION
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 following example shows all combinations of the access control modifiers. This example
has two packages and five classes. Remember that the classes for the two different
packages need to be stored in directories named after their respective packages—in this
case, p1 and p2.
The source for the first package defines three classes: Protection, Derived, and SamePackage.
The first class defines four int variables in each of the legal protection modes. The variable n
is declared with the default protection, n_pri is private, n_pro is protected, and n_pub is
public.
EXAMPLE:~
This is file Protection.java:
package p1;
public class Protection {
int n = 1;
private int n_pri = 2;
protected int n_pro = 3;
public int n_pub = 4;
public Protection() {
System.out.println("base constructor");
System.out.println("n = " + n);
System.out.println("n_pri = " + n_pri);
System.out.println("n_pro = " + n_pro);
System.out.println("n_pub = " + n_pub);
}
}
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. Since classes within packages must be fully qualified
with their package name or names, it could become tedious to type in the long dot-separated
package path name for every class you want to use. For this reason, 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.
In a Java source file, import statements occur immediately following the package statement
(if it exists) and before any class definitions. This is the general form of the import statement:
import pkg1[.pkg2].(classname|*);
Here, pkg1 is the name of a top-level package, and pkg2 is the name of a subordinate
package inside the outer package separated by a dot (.). There is no practical limit on the
depth of a package hierarchy, except that imposed by the file system.
package MyPack;
public class Balance {
String name;
double bal;
public Balance(String n, double b) {
name = n;
bal = b;
}
public void show() {
if(bal<0)
System.out.print("--> ");
System.out.println(name + ": $" + bal);
}
}
As you can see, the Balance class is now public. Also, its constructor and its show( )
method are public, too. This means that they can be accessed by any type of code outside
the MyPack package. For example, here TestBalance imports MyPack and is then able to
make use of the Balance class:
import MyPack.*;
class TestBalance {
public static void main(String args[]) {
/* Because Balance is public, you may use Balance
class and call its constructor. */
Balance test = new Balance("J. J. Jaspers", 99.88);
test.show(); // you may also call show()
}
}
Threads:
Introduction to threads
Multitasking threads require less overhead than multitasking processes. Processes are
heavyweight tasks that require their own separate address spaces. Interprocess
communication
is expensive and limited. Context switching from one process to another is also costly.
Threads,
on the other hand, are lightweight. They share the same address space and cooperatively
share the same heavyweight process.
Multithreading enables you to write very efficient programs that make maximum use of
the CPU, because idle time can be kept to a minimum. This is especially important for the
interactive, networked environment in which Java operates, because idle time is common.
creating threads
The Java run-time system depends on threads for many things, and all the class libraries
are designed with multithreading in mind. In fact, Java uses threads to enable the entire
environment to be asynchronous. This helps reduce inefficiency by preventing the waste
of CPU cycles.
The value of a multithreaded environment is best understood in contrast to its counterpart.
Single-threaded systems use an approach called an event loop with polling. In this model, a
single thread of control runs in an infinite loop, polling a single event queue to decide what
to do next. Once this polling mechanism returns with, say, a signal that a network file is
ready to be read, then the event loop dispatches control to the appropriate event handler.
Until this event handler returns, nothing else can happen in the system. This wastes CPU
time. It can also result in one part of a program dominating the system and preventing any
other events from being processed. In general, in a singled-threaded environment, when a
thread blocks (that is, suspends execution) because it is waiting for some resource, the entire
program stops running.
The benefit of Java’s multithreading is that the main loop/polling mechanism is eliminated.
One thread can pause without stopping other parts of your program. For example, the idle
time created when a thread reads data from a network or waits for user input can be utilized
elsewhere. Multithreading allows animation loops to sleep for a second between each frame
without causing the whole system to pause. When a thread blocks in a Java program, only
the single thread that is blocked pauses. All other threads continue to run.
Threads exist in several states. A thread can be running. It can be ready to run as soon as
it gets CPU time. Arunning thread can be suspended, which temporarily suspends its activity.
Asuspended thread can then be resumed, allowing it to pick up where it left off. A thread
can be blocked when waiting for a resource. At any time, a thread can be terminated, which
halts its execution immediately.
Extending Thread:-
Class NewThread extends Thread{
Thread t;
NewThread(){
super(”Demo Thread”);
System.out.println(“child thread:”+this);
start();
}
Public void run(){
try{
for(i=5;i>0;i--)
{
System.out.println(“child Thread”+i);
Thread.sleep(500);
}
}catch(InterruptedException e){
System.out.println(“child thread interrupted”);
}
System.out.println(“Exiting child thread”);
}
}
Class threadDemo{
Public static void main(String args[])
{
New NewThread();
try{
for(i=5;i>0;i--)
{
System.out.println(“Main Thread:”+i);
Thread.sleep(1000);
}
}catch(InterruptedException e){
System.out.println(“Main thread interrupted”);
}
System.out.println(“Main thread exiting”);
}
OUTPUT
Child thread:Thread[Demo thread,5,main]
Main Thread:5
Child Thread:5
Child Thread:4
Main Thread:4
Child Thread:3
Child Thread:2
Main Thread:3
Child Thread:1
Exiting child thread
Main Thread:2
Main Thread:1
Main Thread exiting
Main thread: When a Java program starts up, one thread begins running immediately. This
is usuallycalled the main thread of your program, because it is the one that is executed when
your
program begins. The main thread is important for two reasons:
• It is the thread from which other “child” threads will be spawned.
• Often, it must be the last thread to finish execution because it performs various
shutdown actions.
IsAlive() and join():Two ways exist to determine whether a thread has finished. First, you
can call isAlive( ) on the thread. This method is defined by Thread, and its general form is
shown here:
finalbooleanisAlive( )
TheisAlive()methodreturnstrueifthethreaduponwhichitiscalledisstillrunning.Itreturns
falseotherwise. While isAlive( ) is occasionally useful, the method that you will more
commonly use to wait for a thread to finish is called join( ), shown here:
final void join( ) throws InterruptedException
This method waits until the thread on which it is called terminates. Its name comes from the
concept of the calling thread waiting until the specified thread joins it. Additional forms of
join()allowyoutospecifyamaximumamountoftimethatyouwanttowaitforthespecified thread to
terminate. Hereisanexamplethatuses join()toensurethatthe
mainthreadisthelasttostop.Italsodemonstratesthe isAlive()method.
// Using join() to wait for threads to finish.
classNewThread implements Runnable {
String name; // name of thread
Thread t;
NewThread(String threadname) {
name = threadname;
t = new Thread(this, name);
System.out.println("New thread: " + t);
t.start(); // Start the thread
}
// This is the entry point for thread.
public void run() {
try {
for(inti = 5; i> 0; i--) {
System.out.println(name + ": " + i);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println(name + " interrupted.");
}
System.out.println(name + " exiting.");
}
}
classDemoJoin {
public static void main(String args[]) {
NewThread ob1 = new NewThread("One");
NewThread ob2 = new NewThread("Two");
NewThread ob3 = new NewThread("Three");
System.out.println("Thread One is alive: " + ob1.t.isAlive());
System.out.println("Thread Two is alive: " + ob2.t.isAlive());
System.out.println("Thread Three is alive: " + ob3.t.isAlive());
// wait for threads to finish
try {
System.out.println("Waiting for threads to finish.");
ob1.t.join();
ob2.t.join();
ob3.t.join();
} catch (InterruptedException e) {
System.out.println("Main thread Interrupted");
}
System.out.println("Thread One is alive: " + ob1.t.isAlive());
System.out.println("Thread Two is alive: " + ob2.t.isAlive());
System.out.println("Thread Three is alive: " + ob3.t.isAlive());
System.out.println("Main thread exiting.");
}
}
Sample output from this program is shown here.
New thread: Thread[One,5,main]
New thread: Thread[Two,5,main]
New thread: Thread[Three,5,main]
Thread One is alive: true
Thread Two is alive: true
Thread Three is alive: true
Waiting for threads to finish.
One: 5
Two: 5
Three: 5
One: 4
Two: 4
Three: 4
One: 3
Two: 3
Three: 3
One: 2
Two: 2
Three: 2
One: 1
Two: 1
Three: 1
Two exiting.
Three exiting.
One exiting.
Thread One is alive: false
Thread Two is alive: false
Thread Three is alive: false
Main thread exiting.
As you can see, after the calls to join( ) return, the threads have stopped executing.
Thread Priorities
Thread priorities are used by the thread scheduler to decide when each thread should be
allowed to run. In theory, higher-priority threads get more CPU time than lower-priority
threads. In practice, the amount of CPU time that a thread gets often depends on several
factors besides its priority. (For example, how an operating system implements multitasking
can affect the relative availability of CPU time.) A higher-priority thread can also preempt a
lower-priority one. For instance, when a lower-priority thread is running and a higher-priority
thread resumes (from sleeping or waiting on I/O, for example), it will preempt the
lowerpriority
thread.
To set a thread’s priority, use the setPriority( ) method, which is a member of Thread.
This is its general form:
final void setPriority(int level)
Here, level specifies the new priority setting for the calling thread. The value of level must be
within the range MIN_PRIORITY and MAX_PRIORITY. Currently, these values are 1
and
10, respectively. To return a thread to default priority, specify NORM_PRIORITY, which is
currently 5. These priorities are defined as static final variables within Thread.
You can obtain the current priority setting by calling the getPriority( ) method of Thread,
shown here:
final int getPriority( )
lo.stop();
hi.stop();
// Wait for child threads to terminate.
try {
hi.t.join();
lo.t.join();
} catch (InterruptedException e) {
System.out.println("InterruptedException caught");
}
System.out.println("Low-priority thread: " + lo.click);
System.out.println("High-priority thread: " + hi.click);
}
}
The output of this program, shown as follows when run under Windows, indicates that
the threads did context switch, even though neither voluntarily yielded the CPU nor blocked
for I/O. The higher-priority thread got the majority of the CPU time.
Low-priority thread: 4408112
High-priority thread: 589626904
Deadlock
A special type of error that you need to avoid that relates specifically to multitasking is
deadlock, which occurs when two threads have a circular dependency on a pair of
synchronized
objects. For example, suppose one thread enters the monitor on object X and another thread
enters the monitor on object Y. If the thread in X tries to call any synchronized method on Y,
it will block as expected. However, if the thread in Y, in turn, tries to call any synchronized
method on X, the thread waits forever, because to access X, it would have to release its own
lock on Y so that the first thread could complete. Deadlock is a difficult error to debug for
two reasons:
• In general, it occurs only rarely, when the two threads time-slice in just the right way.
• It may involve more than two threads and two synchronized objects. (That is, deadlock
can occur through a more convoluted sequence of events than just described.)
To understand deadlock fully, it is useful to see it in action. The next example creates two
classes, A and B, with methods foo( ) and bar( ), respectively, which pause briefly before
trying to call a method in the other class. The main class, named Deadlock, creates an A
and a B instance, and then starts a second thread to set up the deadlock condition. The
foo( ) and bar( ) methods use sleep( ) as a way to force the deadlock condition to occur.
// An example of deadlock.
class A {
synchronized void foo(B b) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered A.foo");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("A Interrupted");
}
System.out.println(name + " trying to call B.last()");
b.last();
}
synchronized void last() {
System.out.println("Inside A.last");
}
}
class B {
synchronized void bar(A a) {
String name = Thread.currentThread().getName();
System.out.println(name + " entered B.bar");
try {
Thread.sleep(1000);
} catch(Exception e) {
System.out.println("B Interrupted");
}
System.out.println(name + " trying to call A.last()");
a.last();
}
synchronized void last() {
System.out.println("Inside A.last");
}
}
class Deadlock implements Runnable {
A a = new A();
B b = new B();
Deadlock() {
Thread.currentThread().setName("MainThread");
Thread t = new Thread(this, "RacingThread");
t.start();
a.foo(b); // get lock on a in this thread.
System.out.println("Back in main thread");
}
public void run() {
b.bar(a); // get lock on b in other thread.
System.out.println("Back in other thread");
}
public static void main(String args[]) {
new Deadlock();
}
}
When you run this program, you will see the output shown here: