Share Knowledge and Skills

Saturday, 4 October 2014

CORE JAVA

12:14 Posted by Unknown , No comments
INTRODUCTION:
    Gosling’s solution to the problems of C++ was a new language called Oak. Oak preserved the familiar syntax of C++ but omitted the potentially dangerous features like explicit resources references, pointer arithmetic, and operator overloading.  Oak incorporated memory management directly into the language, freeing the programmer to concentrate on the tasks to be performed by the program.  To be successful as an embedded systems programming language, Oak needed to be able to respond to real-world events within microseconds. It also needed to be portable; that is, it had to be able to run on a number of different microprocessor chips and environments.  This hardware independence would allow a toaster manufacturer to change the chip used to run the toaster without changing the software.  The manufacturer could also use some of the same code that ran the toaster to run a similar appliance, such as a toaster oven.  This would cut down on development and hardware costs, as well as increase reliability.
    As Oak matured, the World Wide Web was growing dramatically, and the development team at Sun realized Oak was perfectly suited to Internet programming. Thus in 1994, they completed work on a product known as Web Runner, an early Web browser written in Oak.  Web Runner was later renamed Hot Java, and it demonstrated the power of Oak as an Internet development tool.  Hot java is well versions under development.
    Finally, in 1995, Oak was renamed java (for marketing and legal reason) and introduced at Sun World 95, since then, Java’s rise in popularity has been meteoric. Even before the first release of the java compiler in January ’96, the development community considered java a standard for Internet development.

JAVA ARCHITECTURE


    To create reliable network based application, java language is used to run securely over a network and work as wide range of platform.
    As write other programming languages, java uses a compiler to convert human readable code into executable program.
    Traditional compilers produce a code that can be executed by specific hardware.  For ex. Windows95  c++ compiler creates executable that can be executed by Intel compatible processors.
    Java compiler generates architecture independent byte code.
    This byte code can be executed by java virtual machine JVM, which is java architecture implemented in s/w rather than h/w.
    Java byte code files are called class files, because they contain single java class.
    To execute java byte codes, the JVM uses class reader to files the byte code from a disk or a n/w.
    Each class files is fed to a byte code verifier to check the class whether it is formatted correctly.
    The execution unit of JVM carries out the instructions specified in the byte code.
This is an interpreter, which is a program that reads the byte codes, interprets that meaning and then performs the associated function.

OOPS


Oops is a way of thinking about the problem solutions.


-    Instead of taking program in top-down linear fashions, oops attempts to break the problem with its layout parts.
-    The solution focuses on them without objects and their relative to other objects.
-    In oops, the structure and its related routines and combined or encapsulated with a single entity called as class.
-    Routines defined inside a class are called member functions or methods.
-    The variables declared inside a class are called data members.
-    The class definition in a pattern or template for variables to be created likes that class data type.
-    Variables which the class data types are called objects. An object is a storage variable created based on a class.
-    Objects are called to be instances of a class.
-    Classes defined the variables and routines that are members of all the objects of that class.
-    An object variable is a reference to an object.
-    Creating a reference to an object and creating the actual object itself are two separate steps.
-    The object reference variable can have two possible values i.e. number or object.
-    To create an object referred by class ref. Variable like an ‘new’ operator.
-    Encapsulation also allows having data hiding, which is a way to prevent direct access to the data members in the object.
-    This will force to methods to read data in member variables, rather than accessing them directly.
Class Inheritance
-    Like technique, we can inherit both data members and methods of an thirsty class into newly creation class.
-    The class, which is inherited, is called super class and the newly derived class is called as sub class.
-    We can early override the method of the parent class by regularly the method in the sub class.
-    For this inheritance, we use extends clause such as
-    class B extends A
-    {
-    }

-    For a given sub class, there should be only one super class i.e. only hierarchical inheritance is allowed in Java.

Using ‘this’ and ‘super’
-    These two keyboards are used for two purposes.
1.    To refer the hidden data members and method,
2.    To refer the constructors of the current class and its super class.
1.    Members reference:
-    Local variable is a method can share the same houses as instance variables as class variables.
-    Sub class can define their own instance variables to hide those defined in this super class.
-    Sub classes can also define methods to override the method, defined in their super class.
-    Two special reference variables are available inside any instance method to allow for accessing the hidden variables or overridden methods of that instance i.e.
-    this    -    it is used to refer the object, the method is called upon i.e. owner object.
-    Super -    it is used to access the methods or data members defined in the super class.
-    Ex. – 1. class A
{    int x1;
int x2;
void f1 (int x1, int x2)
{this .x1 = x1;
this .x2 = x2;
}
}
Ex : 2 – class B extends A
        {
        int x1;
        int x2:
        void f2(int x1, int x2)
        {
        this .x1=super.x1 = x1;
        this .x2 = super .x2 = x2;
        }
        }
2.As constructor reference
-    In this concept of inheritance, in the constructor of subclass there is an applied first statement i.e. the super class constructor with no arguments is called automatically.
-    If we do not like this default behavior, we can over side it by using this () or super () method call as the first statement to refer other constructor, of the object of same class or super class respectively.
Ex :     class A
        {
        int x1;
        int x2;
        A (int x1)
        {
        this .x1 = x1;
        }
        A (int x1, int x2)
        {
        this (x1);
        this .x2 = x2;
        }
        }
Ex : class B extends A
        {
        int x3;
        B (int x1, int x2, int x3)
        {
        Super (x1, x2);
        this .x3 = x3;
        }
        }
Accesing super class members outside the class definition
1.    Data references are resolved at compile time
oa .x // A’s x
ob .x // B’s x
(A)    ob.x // A’s x
oa = ob; oa.x // A’s x
(B)    oa.x // B’s x
2.    Method references are resolved at run time
oa .f1 () // A’s f1 ()
ob .f1 () // B’s  f1 ()
oa = ob;
oa.f1 () // B’s f1 ()


Constructors and Finalize

We can define two special kinds of methods in a class i.e.
1.    Constructors, i.e. the method, that return new instance of the class. If we do not define a constructor, we can use the default constructor to create an instance of a class.
2.    Finalizers i.e. the functions that are called just before an object in garbage collected.
-    The default constructor is automatically added to the class by the java  compiler.
-    The constructor allocates storage memory for any member variables that are declared on Java’s built in data types.
-    A constructor is defined in the same way as an ordinary method, but it must have the same name as the class and have no return type.
-    We can define any number of constructors for a class by having different parameter list and this is called constructor overloading.
-    We can define any no. of methods for a class with the same name and different parameter list and this is called method overloading.
-    Java virtual machine automatically retains the memory used by an object when no variable is referred to that object.
-    The process is known as garbage collection.
-    Finalizers are used in a situation where a class needs to clean itself before the garbage collection.
-    Finalizers are called just before an object of a class is garbage collector.
-    Finalizers are used to close opened files or connections to unsure that the related taxes are completed before the object is garbage collected.
-    Example definition of this finalize method is
Void finalize ()
{
__
__
__
}

Examples :



class A
{

int x1=10;

int x2=20;

int x3=30;


A(int x1)
{

this.x1=x1;

}

A(int x1,int x2)
{

this(x1);

this.x2=x2;

}


A(int x1,int x2,int x3)
{

this(x1,x2);

this.x3=x3;

}


void display()
{

System.out.println(x1);

System.out.println(x2);

System.out.println(x3);

}



public static void main(String args[])
{

A oa1=new A(11);

oa1.display();

A oa2=new A(11,12);

oa2.display();

A oa3=new A(11,12,13);

oa3.display();

}

}

Example 2:



class A
{

int x1=10;

int x2=20;

int x3=30;



void display()
{

System.out.println(x1);

System.out.println(x2);

System.out.println(x3);

}


void adisplay()
{

System.out.println(" this is A display");

display();

}


}



class B extends A
{

int x1=40;

int x2=50;

int x4=60;

void display()
{

System.out.println(x1);

System.out.println(x2);

System.out.println(x3);

System.out.println(x4);

}


void bdisplay()
{

System.out.println("this is B display");

display();

}


}


class overrideex2
{

public static void main(String args[])
{

A oa=new A();

oa.display();

oa.adisplay();


System.out.println(oa.x1);

System.out.println(oa.x2);


oa=new B();

oa.display();

oa.adisplay();



//oa.bdisplay();

System.out.println(oa.x1);

System.out.println(oa.x2);

System.out.println(oa.x3);

//System.out.println(oa.x4);



A oa1=new A();

oa1.adisplay();

B ob=new B();

ob.adisplay();

ob.bdisplay();



}


}



Example 3:





class A
{


int ax1=10;



class B
{


int bx1=20;



void bdisplay()
{



System.out.println(ax1);

System.out.println(bx1);

}


}



static class C
{

int cx1=30;



void cdisplay()
{

System.out.println(cx1);

//System.out.println(ax1);

}


}


static void adisp()
{

C oc=new C();

//B ob=new B();

}



void adisplay()
{



C oc=new C();


oc.cdisplay();

B ob=new B();

ob.bdisplay();

System.out.println(ax1);

//System.out.println(bx1);

}



}



class staticdemo2
{

public static void main(String args[])
{

A oa=new A();

oa.adisplay();

//B ob=new B();

//A.B oab=new A.B();


A.C oc=new A.C();

oc.cdisplay();



}



}






Example 4:


abstract class  A
{


int ax1=10;

int ax2=20;


void set(int p1,int p2)
{

ax1=p1;

ax2=p2;

}

abstract void display();

}




class B extends A
{

int bx1=30;

void display()
{

System.out.println(ax1);

System.out.println(ax2);

System.out.println(bx1);

}


}



class C extends A
{

int cx1=40;

int cx2=50;

void display()
{

System.out.println(ax1);

System.out.println(ax2);

System.out.println(cx1);

System.out.println(cx2);

}

}


class abstractex

{


public static void main(String args[])
{

//A oa=new A();

B ob=new B();

ob.display();

C oc=new C();

oc.display();

}


}

















Java’s Datatype and Method Modifiers
    A modifier is a keyword that affects either the lifetime or the accessibility of a class, a variable, or a member function.
Storage and Lifetime Modifiers
    The following sections describe the storage and lifetime modifiers: abstract, static, synchronized, native, volatile, transient, and final.

The abstract Modifier
    When applied to a class, the abstract modifier indicates that the class has not been fully implemented and the that is should not be instantiated. If applied to member function declaration, the abstract modifier means that the function will be implemented in a subclass. Since the function has no implementation, the class cannot be instantiated and must be declared as abstract. Interfaces are abstract by  default.

The static Modifier
    Ordinarily, each instance of a class has its own copy of any member variables. However, it is possible to designate a member variable as belonging to the class itself, independent of any objects of that class. Such member variables are called static members and are declared with the static modifier keyword. Static member variables are often used when tracking global information about the instances of a class. The following class tracks the number of instances of itself using a static member variable called instanceCount :
public class Myclass {
    public static int instanceCount:
    public Myclass( ) {
    // each time the constructor is called,
    // increment the instance counter
    instanceCount++;
}
static {
    instanceCount  = 0 :
    }
}

The synochronized Modifier
     A synchronized member function allows only one thread to execute the function at a time. This prevents two threads of execution from undoing each other’s work..

For example, suppose you have two threads, called threads A and B, responsible for updating a bank balance. Suppose also that the account has $100 in it. Now, simultaneously, thread a tries to deposit $50 in the account, while thread B find it at $100. Each of them, independently, adds its deposit to the old sum and $150. If thread B finishes last, the account balance is $175. Of course, neither of these new figures is correct! The account should have $225 in it (100 + 50 + 75). The problem is that both threads tried to execute the same code (querying and changing the balance) at the same time. This exactly the scenario that the synchronized keyword can prevent.

Synchronized methods are not static by default, but they may be declared as static.
    The synchronized modifier does not apply to classes or member variables.

The native Modifier
   
    Native methods are implemented in other Languages, such as C, so they have no code block. Many of the classes in the Core API are native because they need to access operating system-specific routines, such as those for drawing graphics on the screen Here is an excerpt form the API’S math class:
/* *
* Returns the trigonometric sine of an angle.
* @ param a an assigned angle that is measured in radians
*/
public static native double sin (double a ) ;

    This declaration calls a funcition in a native code libarary that calculates the sine of the angle a. On an Intel x86 platform, the native code would call the sine function in the x86 processor’s floating-point unit or coprocessor. On other platforms, the native code function may do the computation with software instead. This function also happens to be declared with the public and static modifiers also.

The volatile Modifier
    A volatile variable is one whose value may change independent of the Java program itself. Typically, volatile variables represent input from the outside world, such as a variable that denotes the time of day. They are also used to flag variables that could be changed by other threads of execution . The volatile keyword will prevent the compiler from attempting to track changes to the variable. The variable will always be assumed by the compiler to have a (potentially) new value each time it is accessed by Java code. Use of this modifier is rare but necessary, as Just-in-time (JIT) compliers are now common in most Java Virtual Machines.

The transient Modifier
    One of the changes introduced with Java 1.1 is adding meaning to the transient modifier. Java 1.0 supported the modifier, but it had no purpose. It is used in conjunction with serialization to provide for persistent objects. These objects can be aved to disk and restored on another machine or on the same machine. For more information about serialization, see Chapter 19. The transient modifier means not to save the variable.

The final Modifier
    Most languages have a way to declare a variable as constant (that is , unchangeable), which is true of Java as well. The final keyword indicates that a local variable or member variable connot be altered. The main use of final variables is as symbolic constants. You can refer to a constant by name and define that name in a single location in your code. If you later need to change the number in your code, you need only make the change at the point your final variable is defined.

    Note that if you declare a variable as final, you must also initialize it at the same time:
    final int MAX_PAGES =23 :


Accessibility Modifiers
    Java has other modifiers used to change the accessibility of classes and their members to ther classes. By default, a class, its member functions, and its variables are known only to other classes in the same package. For simple applets, this means that a class is accessible only to other classes in the same directory.

A public class can be accessed by any other class. When a VM is asked to execute a new applet, the class for the applet must be public. However, any other classes required by the applet need not be public, as long as they are accessible.

Methods and member variables of public classes that are themselves declared as public can be accessed by code form other classes. Public members can also be accessed  by JavaScript, VBScript, and ActiveX controls operating outside the VM. If members of a nonpublic (default) class are declared as public, those members will be accessible to all other classes within the same package. As a guideline, a void defining, methods and variables as public unless it is necessary.
If no modifier is specified, the default accessibility for the class, variable, or method is assumed.
Private
The private modifier restricts access to members of a class so that no other classes can call member functions or directly access member variables.

Protected
A protected member is similar to default access but gives preferred access for subclasses in other packages. Member functions are some times created within a class for utility purposes (that is, to be used only within the class itself itself and not for general consumption). Declaring utility functions as protected allows them to be used not only be the class itself but by its subclasses as well.

Object Memory Model
-    The dynamically charging part of a program can be divided into two areas i.e.
1.    Stack memory area, which is used to store the local variables declared in methods, and blocks.
2.    These variables are popped out of this stack upon list from the enclosing method or blocks.
3.    A heap memory area, which is used the store the memory for dynamically allocated objects.
-    References to the objects are placed in the Stack area, but the space for his data members of the objects will reside in this heap area.
-    Whenever a block of memory calls is no longer referred by any reference variables, then these unused calls can be freed or garbage collected.
Static Members
-    It is possible to create a member that can be used by itself, without reference to specific instance i.e. object of a class.
-    To create such a member, we precede its declaration with the keyword static.
-    When a member is declared static, it can be accessed before any objects of its class are created and without reference to any object.
-    We can declare both methods and variables as static.
-    The variables, which are declared inside the class, are called class variables, which are the global variables.
-    All the instances of the class share the same static variables.
-    The method, declared as static have the following restrictions i.e.
1.    They can only call other static methods.
2.    They must only access static data.
3.    They cannot refer to this or super variables.
-    We can declare a static block inside the class, which gets executed once when the class is loaded.
-    Outside the class, the static method, and static variable can be used in dependant of any object
-    These static members can also be referenced through an object reference.
-    But, non-static members must be referenced through only object reference. I.e. they cannot be referenced with the class name.
-    Inside the non-static methods, we can refer both static and non static members of the class.

Nested and Inner Classes
-    It is possible to define a class within another class; such classes are called as nested classes or inner classes.
-    The scope of a nested class is bonded by the scope of its enclosing classes. I.e. if B class is defined inside the class A, then B is known to only A, but not outside of A.
-    A nested class has access to the members of its unclosing class including private member.
-    But enclosing class i.e. outer class does not have access to the members of the nested class i.e. inner class.
-    There are two types of nested classes. I.e. static and non static.
-    The static nested class is the one, which is defined with static modifier.
-    The static nested class cannot refer the members of outer class directing i.e. it must access through an object.
-    The non-static nested class can access all the method, and variable of its outer class directly.
-    If the inner class is static, then it must be used to create an object outside of the containing class with a hierarchical name as shown below.

class A
    {
    static class B
        {
        }
    }
class C
{
public static void main (String args [])
        {
A.    B  ob = new A.B ();
__
__
}
}

Abstract class and abstract methods
-    Some times we want to create a super class that only defines generated from that will be shared by all of its subclass, learning each sub class to fill the details
-    Such a class, which is not complete with the implementation of all the methods, is called abstract and it should specify with abstract modifier.
-    The methods which are incomplete in the abstract class are called abstract methods
-    The declaration of abstract methods in the abstract class must be specified with abstract as shown below
abstract  class A
    {
    void f1()
    {
        ---------
        --------
        ---------
    }
   
abstract void f2();//abstract method
}

-    If there is one single abstract method is a class, then the class must be declared as abstract.
-    These abstract classes cannot be used to create the objects.  But they can be used to inherit into the subclasses.
-    The subclasses must compulsorily implement the abstract methods of the inherited super class; otherwise the sub class will be come as abstract class.
-    We cannot declare constructors and abstract static methods of a class.
-    Abstract classes can be used to create object references, so that the super class reference variable can refer to can objects of its subclasses.
Ex:

Using Final modifier:
--     This final modifier is used to prevent overriding i.e. the methods declared as final, cannot be overridden in the subclass. As shown below.

    class A
    {
        final void f1()
        {
            ---
            ----
            -----
        }
    }
    class B extends A
    {
        void f1()  //error , can’t override
        {
        }
    }
--    This final modifier is used to prevent a class from being inherited.
--    For this we precede the class declaration like final modifier as shown below.
Final class A
{
    ------
    ------
    ------
    }
class B extends A // errors,, can not subclass A.
{    }


JAVA BUILT-IN DATA TYPES

    The compiler itself, without reference to any libraries or the Core API, understands Java’s built-in data types.  These types can be classified into numeric, Boolean, and character data types.
    Before using my variable, it must first be declared.  A variable declaration specifies the data type, the variable name, and, optionally, the default value for the variable.  The following sections describe variable declarations, each of the basic datatypes, and classes declarations.

Variable Declarations
    A general variable declaration looks like the following:
Datatype identifier [ = defaultvalue ] {, identifier [= defaultvalue ] };
    Identifiers are just symbols; in this case, they are the names of the variables being defined.  To define integer variables i,j, and k, and initialize them to 1,2, and 3, respectively, you can enter.

int i;
int j;
int k;


i=1;
j=2;
k=3

or in an abbreviated form:

   int i=2,j=2,k=3;

    You can place variable declarations any where in your code, as long as they precede the first use of the variable.  However, it is common practice to place the declarations at the top of each block of code.  This makes your code easier to read, especially for programmers who are used to languages that require you to declare your variables at the beginning of functions. Later in this chapter, you will see how to limit across to a variable in its declaration.

The Numeric Datatypes
    Java has six numeric datatypes that differ in the size and precision of the numbers they can hold.  The basic numeric datatypes are listed in the table.
























Interfaces

--    By using the keyword interface, we can specify what a class must do, but not how to do
--    interfaces are syntactically similar to classes, but no in variables and methods are declared without any body.
--    Once an interface is defined, then any no. of classes can implement this interface or one class can implement any no. of interfaces.
--    To implement an interface, a class must define or implement the complete set of methods declared in the interface as shown below.
interface iface1
{
  void f1();
  void f2();
}
interface iface2
{
  void f3();

}

class A implement iface1
{
    public void f1()
    {
        -------
        -------
    }
    public void  f2()
    {
        -------   
        -------
    }
    }
class B implements iface1, iface2
{
    public void f1()
        {
            ------
            -----
        }
        public void f2()
        {
            ------
            ------
        }

        public void f3()
        {
            ------
            ------
        }
           }
       
   

--    The method, that implement a interface must be declared public and also the type signature of the implementing method must math abstractly with the type signature specified in the interface declaration.
--    If a class implements two interfaces that declare the same methods, then the same method will be used of with either the interface.
--    We can declare variables of the interface as object references that use an interface.
--    Any instance of any class that implements the interface can be stored in such interface variables.
--    When we call a method through the interface reference variable, the correct version will be called based on the actual instance of the interface being referenced to and this is one of the key feature of interface.
--   This process is similar to using a super class reference to access a sub class object.
-   If a class implements interface, but does not fully implement this method, deferred                         by that interface, then that class must be declared as abstract.
-    We can use this variables in the interface, to have shared constants into multiple classes by simply declaring an interface that contains variables which are initiated to the desired value.
-    One interface can inherit another by using the key and extend, such as
-    Interface iface3  extends iface1, iface2.
-    When a class implements such interface, it must provide implementation for all the methods defined which the interface inheritance chain.

Examples :






interface iface1
{


void  display();


}



interface iface2

{

void incrx1();

void decrx1();

}

interface iface3 extends iface1,iface2
{

void set(int p1);

}


class A implements iface3
{


int x1=10;

int x2=20;


public void display()
{

System.out.println(x1);

System.out.println(x2);

}


public void set(int p1)
{

x1=x2=p1;

}

public void incrx1()
{

x1++;

}

public void decrx1()
{

x1--;

}


}


class B implements iface1,iface2
{


int x1=30;

public void display()
{

System.out.println(x1);

}

public void incrx1()
{

x1++;

}


public void decrx1()
{

x1--;

}


}



class interfaceex2
{

public static void main(String args[])
{


iface3 face3;


face3=new A();

face3.incrx1();

face3.display();

face3.set(11);

face3.display();

face3.decrx1();

face3.display();


//face3=new B();

iface1 face1;

B ob=new B();

face1=ob;

face1.display();

//face1.incrx1();


iface2 face2;

face2=ob;

face2.incrx1();


ob.display();




}


}






Packages

-    Packages are containers for classes that are used to keep the class name space.
-    A unique name has to be used for each class to child name continues in the same name open.
-    The package is a both name and visibility control mechanism.
-    We can define classes inside a package that are not accessible by code outside that package.
-    We can also define member, that are only exposed to other members of the same package.
-    This allows the classes to have the knowledge of each other, but not expose that knowledge to the rest of the world.
-    To create a package, we simply include package statement as the first statement in a java source file.
-    Any classes declared within that file will belong to the specified package, i.e. package statement defines a name space in which classes are stored.
-    If we omit the package statement, the class names are placed in the default package.
-    Example for this package statement is
package my pack;
-    Java uses file system directories to store packages and the directory name must match with the package name.
-    Here that one file can include the same package statement i.e. the package statement simply specifies to which package the classes defined in a file belong to package.
-    We can also create a hireracly of package. To do so we simply separate each package name from the one above by using a period such as
Package Naidu.mypack;
-    The package hierarchy must reflect the file system i.e. the java file had to be stored in Naidu1 my pack directory.
-    CLASS PATH environmental variable is used to specify the specific location that the java compiler to combine for the class reference.
-    The default current working directory is usually set for the class path environmental variable defined for the java runtime system.
-    In Java, we use import statement to being certain classes or package into visibility such as
Import packagename;
-    This package name can be single name or hierarchal name.
-    This import statement should be given used to package statements if any and before any class definitions.
-    The examples of this import statement are
Import mypack .A; // for class A of package mypack
Import Naidu.*;// for all the classes of package Naidu
-    If a class with the same name consists in two different packages that we import, then the compiler will generate an error when we try to use that class name. In such class we should specify the fully qualified name such as
Mypack.A oa = new mypack.A();
-    When a package is imported, only those items which the package are declared as public. Will be available in the import code.
-    Java’s access controlled mechanism is performed with access specifier of private, public, protected and default.
-    Private member of a class can be accused only in other member of a class.
-    Packages add another dimension to those access specifies and they are shown in the following table.

    Private    Default    Protected    Public
Same class    Yes    Yes    Yes    Yes

Same pack
Non sub class    No    Yes    Yes    Yes

Same pack
Sub class    No    Yes    Yes    Yes

Different pack
Non sub class    No    No    No    Yes
Different pack
sub class    No    No    Yes    Yes



Examples :



package temp2;


public class A
{

int x1=30;
public void display()
{

System.out.println(x1);

}

}

//class usea uses A class

import temp2.A;


class usea
{

public static void main(String args[])
{

A oa=new A(11,12);

oa.pubdisplay();

//oa.pridisplay();

//oa.prodisplay();

//oa.defdisplay();

}



}

Example 2



package temp2;


public class A
{

int x1=10;

int x2=20;



public A()
{


}


public A(int p1,int p2)

{

x1=p1;

x2=p2;

}


public void pubdisplay()
{

System.out.println(x1);

System.out.println(x2);
}

protected void prodisplay()
{


System.out.println(x1);

System.out.println(x2);

}

private void pridisplay()
{

System.out.println(x1);

System.out.println(x2);
}

 void defdisplay()
{

System.out.println(x1);

System.out.println(x2);
}


}


// Class subusea uses class A



import temp2.A;


class B extends A
{



void bdisplay()
{

prodisplay();

pubdisplay();

//defdisplay();

//pridisplay();

}

}



class subusea
{

public static void main(String args[])
{

B ob=new B();

ob.bdisplay();


}

}

//class usea uses A class



import temp2.A;


class usea
{

public static void main(String args[])
{

A oa=new A(11,12);

oa.pubdisplay();

//oa.pridisplay();

//oa.prodisplay();

//oa.defdisplay();

}

}



Arrays

An array is a group of variables of the same type referable by a common name. The type can be either a primitive datatype like int or an object type like  String. For example, you can define an array of integers to hold the daily high temperature in a month as :

Int dailyhigh[ ]

On the other hand, using the point class defined in the java.awt package, you can define an array to hold a list of two-dimensional points as:

Point points [ ]

An array is an objects; that is, it is handled by reference. When you pass an array to a method, only the reference to the array is passed, rather than the whole array of elements. Declaring an array variable creates only a placeholder for the reference to the array, not the memory holding the array of elements per se. Also, the actual memory used by the array elements is dynamically allocated either by a new statement or an array initializer. The memory referenced by the array variable will be authomatically garabage-collected when no longer reference. Every array object has a public instance variable 1 ength to hold the size of the array.

    The following example gives you a close look at the memory model of an array. First, a class to hold a point in two-dimensional graphics is defined as follows :
class Point {
    int    x ;
    int    y;
    Point  (int     x,  int y)    {    / / constructor
       this.x=x;
       this.y=y;
    }
}

The Type Wrapper Classes
Java deals with two different types of entities: primitive types and true objects. Numbers, Booleans, and characters behave very much like the familiar equivalents of procedural languages such as Pascal, C, or even C++. Other object-oriented languages, like Smalltalk, do not handle these primitive types in the same way. Smalltalk, for example, uses objects for everything-numbers are objects, Booleans are objects, characters are objects, and so on.
Although Java is truly object-oriented, it does not use objects for the most primitive types for the usual reason: performance. Manipulating primitive types without any object-oriented overhead is quite a bit more efficient. However, a uniform and consistent playing field, made up of only objects, is simpler and can be significantly more powerful.
Java contains many subsystems that can work only with objects. With many of these subsystems, the need frequently arises to have the system handle numbers, flags (Booleans), or characters. How does Java get around this dilemma? By wrapping the primitive types up in some object sugar coating. You can easily create a class, for example, whose sole purpose is encapsulating a single integer. The net effect would be to obtain an integer object, giving you the universality and power that comes with dealing with only objects (at the cost of some performance degradation).
Package java. Lang contains such “type wrapper” classes for every Java primitive type:
Class Integer for primitive type int
Class Long for primitive type long
Class Byte for primitive type byte
Class Short for primitive type short
Class Float for primitive type float
Class Double for primitive type double
Class Character for primitive type char
Class Boolean for primitive type Boolean
Class Void for primitive type void
Among the numeric types, class Integer, Long, Byte, Short, Float, and Double are so similar that they all descend from an abstract super class called Number. Essentially, every one of these classes allows you to create an object from the equivalent primitive type, and vice versa.





Exception Handling

-    An excreation is the abnormal condition that disturb the normal program slow.
-    There are many cases when abnormal conditions happen during proform excation. Such as
1.    The file we try to opens may not must.
2.    The class file we want to lead is missing.
3.    The n/w communication may be disconnected due to some reasons.
4.    The operand is not in the legal range for ex. An array and element index cannot exceed the range of the array and a devision is a diverse operation cannot be zero.
If those abnormal conditions are not prerelated or not handled properly then the program will be terminated abrustly or it leads to incorrect results.
Throwing an exception is ___ than terminating the program.
Java provides the sub classes of exceptional class to handle then abnormal conditions.
To handle the exceptions in the program, we use try-catch-finally construct.
We will keep the normal statements in the try block. If there is any exception is raised, then the JVM will through the respective exception object automatically from the point of abnormal candidate.
This throws exception object will be caught by the catch handler which is following the try block.
The finally block will be executed irrespective of whether the exception is thrown or not.
Catch or finally block must be followed by try block or both can be followed.
Try black may be followed by one or more catch blocks.
Exception propagate up the stack at run time until an exception handler catches it otherwise the exception will be terms on to the user’s face by terminating the program.
The term statement is used in the program to normally throw the exception such as
Thrown new IoException (“cannot find the directory”);
-    The throw, clause is used in the method definition to specify that the method may throw the respective exception and the exception need to be handled at the caller method. The example for this throws clause is
-    Void f1() throws IOException
{
__
__
__
}
Why use Exception Handling?

You should use exception handling for several reasons. One is that error-handling code is separated from normal program flow to increase the readability and maintainability of the program.
Imagine how you would rewrite the example from the previous section in C if exception handling was not available. You would need an if statement after every I/O operation to make sure they were completed successfully. You would also need to use an if statement to check whether the user provided enough filenames. To handle these abnormal conditions, you would either add more code in place or use goto statements to branch to the code fragment that handles common failures. Add a few more I/O calls, and even you, the author of the program, will not be able to easily recognize easily recognize what the program was originally intended to accomplish. With Java, there is no need to test if an exception happens. Adding more handlers requires adding more catch clauses, but the original program flow is unaffected.
Another reason to use exception handling is so you can easily say where the exception will be handled. Exceptions propogate up the call stack at run time-first up the enclosing try blocks and then back to the calling method – until an exception handler catches them. For example, the previous example can be rewritten as a method with input and output filenames as the arguments. The synopsis of this new method is as follows:
Int copyFile(String inputFile, String outputFile)
The caller of this method may want to handle the abnormal condition itself. For example, an application with a GUI may want to display a dialog box prompting the user for another filename when the input file does not exist. In this case, the error handler for an I/O exception is removed from the method and a throws clause is added to the method declaration. The caller can then have its own error handling routines for these abnormal conditions. Here is the modified method definition:
Int copyFile(String inputFile, String outputFile) throws IOException  {
Int bytesInOneRead, byteCount = 0;
Byte buffer[] = new byte[512];
FileInputStream fin = new FileInputStream(inputFile);
FileOutputStream fout= new FileOutputStream(outputFile);
While ((bytesInOneRead = fin.read(buffer)) != -1) {
Fout.write(buffer, 0, bytesInOneRead);
ByteCount += bytesInOneRead;
}
return byteCount;
}
Here is a code fragment to call this method and handle the abnormal conditions itself:
int byteCount = 0;
String inputFile = null;
String outputFile = null;
PrintWriter out = new PrintWriter(System.out, true);
try {
inputFile = args[0];
outputFile = args[1];
byteCount = copyFile(inputFile, outputFile);
} catch (ArrayIndexOutOfBoundsException e){
out.printIn(“Usage: java MyCopy [inputFile] [outputFile]”);
}catch (FileNotFoundException e){
out.printIn(“Cannot open input file: “ + inputFile);
} catch (IOException e) {
out.printIn(“I/O exception occurs!”);
} finally {
if (byteCount > 0)
out.printIn(byteCount + “bytes written”);
}
Exceptions are objects with hierarchical relationships. You can create a single exception handler to catch all exceptions from a class and its subclasses, or you can create a series of exception handlers, each handling exceptions from individual subclasses. The MyCopy example demonstrates another option. The second catch clause deals with FileNotFoundException, and the next one catches may other IOException. FileNotFoundException is a subclass of IOException so you can check for both subclass and superclass exceptions.

Hierarchy of Exception Classes

Just like nearly everything else in Java, exceptions are either objects or class instances. Exception classes form their own class hierarchy. The root class of all the exception classes is the Throwable class, which is an immediate subclass of the object class. is the Throwable class, which is an immediate subclass of the objects class. Methods are defined in the Throwable class to retrieve the error message associated with the exception and to print the stack trace showing where the exception occurs (see the next section for more details).

    Class throwable has two immediate subclasses : class Error and class Exception. Subclasses of class Exception have the suffix Exception./ Subclasses of class Error have the suffix Error (and then there is ThreadDeath, a subclass of Error). The sub classes of Error are basically used for signaling abnormal system conditions. For example, on out of memory Error signals that the Java Virtual Machine has run out of memory and that the garbage collector is unable to claim any more free memory. A Stackover flowError gignals a stack overflow in the interpreter. These Error exceptions are, in general, unrecoverable and should not be handled.

    The subclasses of the Exception class are, in general, recoverable. For example, an EOFException signals that a file you have opened has no more date for reading. A file not Found Exception signals that a file you want to open does not exist in the file system. You can choose to handle the exceptions by using a try-catch block to enclose the statements whose exceptional conditions will be handled.

The following example loops through four pathological cases in which the system throws four types of Runtime Exception :

ArithmeticException  For exceptional arithmetic conditions like integer division by zero
NullPointerException  For accessing a field or invoking a method of a null object.
ArrayIndexOutofBoundsException For accessing an array element by providing an index value less than zero or greater than or equal to the array size.
StringIndexOutofBoundsException For accessing a character of a string of String Buffer with an index less than zero or greater than or equal to the length of the string.

Here is the test program:

import java.io.*;
public class ExceptionTest  {
public static void main(String args[])  {
PrintWriter out  =  new PrintWriter(System.out, true);
For (int I = 0; I < 4; i++)    {
Int k;
try  {
switch (i)  {
case 0:    // divided by zero
int zero = 0;
k = 911/zero;
break;
case 1:   // null pointer
int b[] = null;
k = b[0];
break;
case 2:    // array index out of bound
int c[] = new int[2];
k = c[9];
break;
case 3:    // string index out of bound
char ch = ‘abc’.charAt(99);
break;
}
}  catch (Exception e)  {
out.printIn(“\nTest case #”  +  I + “\n”);
out.printIn(e);
}
}
}
}
The output of the previous test program is shown here:
C:\MasteringJava\Ch07>java ExceptionTest
Test case #0
Java.lang.ArithmeticException:  / by zero
Test case #1
Java.lang.NullPointerException:
Test case #2
Java.lang.ArrayIndexOutOfBoundsException:  9
Test case #3
Java.lang.StringIndexOutOfBoundsException: String index out of range: 99

Examples
#2

class finallyex
{


public static void main(String args[])
{

int x1=10;

int x2=5;

int p=30;

int a[]=new int[5];


try
{

x2=x1/x2;



a[p]=40;

}

catch(ArithmeticException e)
{

System.out.println(e);


System.out.println("this is arithmetic exception");

}

/*catch(ArrayIndexOutOfBoundsException e)
{

System.out.println(e);


System.out.println("this is Array exception");

} */

finally
{


System.out.println("this is out of try catch block");

}


}


}


#2



class A

{


void test(int p) throws ArithmeticException
{

int x1=10;

try
{

x1=x1/p;

}


finally
{

System.out.println(" this is in test method");

}

}

}


class throwsex
{

public static void main(String args[])

{

A oa=new A();

try
{

oa.test(0);

}
catch(Exception e)
{

System.out.println(e);

System.out.println("exception in test method of A caught in main ");

}



System.out.println("this is in main method");

}

}




Threads & MultiThreading

In a single thread program if the program executes is breaked while waiting for the complete of sme I/O operator. Then no other portion of the program can proceed execution.
Multithreading allows multiple tasks to execute concurrently within a single program.
Programs with multiple thread, will utilize the system resrouces better including CUP because another time of execution can grab the CPU when an time of execution is stacked.
We can run multiple tasks like animation, playing music, displaying documents etc. parallely.
A thread is a single flow of control within a program and it is some time called as execution control.
Each thread will have its own resources like program control, execute stack etc.
All threads, ina program may share same common resources like memory space, opened files etc.
A thread is also called light process because it is a single flow of control like a process, but it is easy o create and destroy than a process because less resources is involved.
Once a thread is waiting for something, then the JVM can choose another runnable thread for execution.

Creating and Running a Thread:
When we need to create a thread in the application, then there are two ways to do this.
1.    Create a new class as subclass of Thread.
2.    declare a class implements Runnable interface

When we create a subclass of Thread, this subclass should define its own run() method to override run() method of Thread class.

The run() method is where he taks is performed i.e. the entry part of the Thread.
Just as the main() method is the first user defined method the JVM calls to start an application, the run() method is the first user defined method the JVM calls to start the thread.
An instance of subclass is created by statement followed by a call to the Thread start() method to have the run() method executed.
The Runnable interface remains only one method to be implemented i.e. run() method.
We first create an instance of the class with the new statement, followed by creation of thread instance with another new statement and finally called to start() method to start performing the task defined in the run() method.
The class instance must be passed as an argument is creates the thread instance, so that when the start method is the thread instance is called, the Java run time known which run() method has to be executed.
The second technique of creating of thread is useful when the class design run() method new to be a subclass of another class.

The Thread control methods:
Many methods define in thread class are used to control the running of thread.
The following are the some of the methods that are most commonly used.

Start()
This is used to start the execution body defined in run() method.
Program control is immediately returned to the caller and new thread is scheduled to execute the run() method concurrently with the calling thread.

Stop()
This is used to stop the execution of the thread no matter what the thread is doing.
The thread is considered as dead i.e. the internal status of the thread are cleared.
The method have the data inconistant state, so this matter should be avoided.

Suspend()
This is used to temporarily stop the execution of the thread.
All the statements and resources are retained the thread can later be restarted by calling resume() method.
This method will the dead lock situation so it should be avoided.

Resume()

This is used to resume the execution of suspended thread will be scheduled to run.
This method causes dead lock, it should be avoided.

Sleep()

The static method causes the javarun time to plce the caller thread to sleep for specified time period.

Join()

This is used for caller thread to wait till some thread to die by coming to the end of run() method.

Yield()

This static method temporarily stops the caller’s thread and places the thread t the end of the queue to wait for another thread to be executed.
It is used to make sure that other thread of the same priority have the chance to run.

Threads & Synchroniztion:

Synchronization is the way to avoid data corruption caused by simultaneous access to the same data.

Because all the thread in a program shake the same memory space, so it is possible for the threads to access the same variable or run the same method of the same object at the same time.

Problems may occur when multiple threads are accesing the same data concurrently.
Threads may vary each other, one thread may overwrite the data just written by another thread.
Some mechanism is needed to block one thread access to the critical data if the data is being accessed by another thread.

Java’s Monitor Model for Synchronization:

Java uses monitors to synchronize the access to the data.
A monitor is a like guarded place, where all the protected resources have the same locks.
Only a single key puts all the locks inside a monitor, and a thread must get the key  to enter the monitor and access these protected resources.
If many threads wants to enter the monitor simultaneously, only one thread is loaded the key to the other threads must want outside the monitor until the keyholding thread finishes its use of the resources and hands the key back to the java internal machine.

Inter-thread Communications
Inter-thread communications allow threads to talk to or wait for each other. You can have threads communicate with each other through shared data or by using thread-control methods to have threads wait for each other.

Threads Sharing Data
All the threads in the same program share the same memory space. If the reference to an object is visible to different threads by the syntactic rules of scopes, or explicitly passed to different threads, these threads share access to the data members of that objects. As explained in the previous section, synchronization is sometimes necessary to enforce exclusive access to the data to avoid racing conditions and data corruption.

Threads Waiting for Other Threads
By using thread-control methods, you can have threads communicate by waiting for each other. For example, the joint() method can be used for the caller thread to wait for the completion of the called thread. Also, a thread can suspend itself and wait at a rendezvous point using the suspend() method; another thread can wake it up through the waiting thread’s resume() method, and both threads can run concurrently thereafter.

Deadlock may occur when a thread holding the key to a monitor is suspended or waiting for another thread’s completion. If the other thread it is waiting for needs to get into the same monitor, both threads will be waiting forever. This is why the suspend() and resum () methods are now deprecated and should not be used. The wait(), notify(), and notifyAll() methods defined in class Object of the java.lang package can be used to solve this problem.
The wait() method will make the calling thread wait until either a time-out occurs or another thread calls the same object’s notify() or notifyAll() method. The synopsis of the wait() method is:

Wait()
Or
Wait (long timeoutPeriodInMilliseconds)
The former will wait until the thread is notified. The latter will wait until either the specified time-out expires or the thread is notified, whichever comes first.
When a thread cals the wait() method, the key it is holding will be released for another waiting thread to enter the monitor. The notify() method will wake up only one waiting thread, if any. The notifyAll() method will wake up all the threads that have been waiting in the monitor. After being notified, the thread will try to reenter the monitor by requesting the key again and may need to wait for another thread to release the ky.
Note that these methods can be called only within a monitor, or synchronized block. The thread calling an object’s notify() or notifyAll() method needs to own the key to that object’s monitor; otherwise, IllegalMonitorStateException, a type of RuntimeException, will be thrown.
The next example demonstrates the use of the wait() and notify() methods to solve the classical producer and consumer problem. In this problem, the producer will generate data for the consumer to consume. However, if the producer produces data faster than the consumer can consume, the newly created data may be over-written before it is consumed. On the other hand, if the consumer consumes faster than the producer can produce, the consumer may keep using already processed data. Synchronization alone will not solve the problem because it only guarantees exclusive access to the data, not availability.
The first implementation uses a monitor, an instance of the NoWaitMonitor class, to control the access to the data, token. The producer and consumer will set and get, respectively, the token value in random intervals, with the maximum interval length regulated by the speed argument passed to their constructors. The main program accepts up to two command-line arguments for setting the producing and consuming speed, creates an instance of the monitor, creates a producer and a consumer, and watches them run for 10 seconds. The program is listed as follows:

Import java.io.*;
Public class NoWaitPandC  {
Static int produceSpeed = 200;
Static int consumeSpeed = 200;
Public static void main (String args[]) {
If (args.length > 0)
ProduceSpeed = Integer.parseInt (args[0]);
If (args.length > 1)
ConsumeSpeed = Integer.parseInt (args[1]);
NoWaitMonitor monitor = new NoWaitMonitor();
New NoWaitProducer (monitor, produceSpeed);
New NoWaitConsumer (monitor, consumeSpeed);
Try {
Thread.sleep (1000);
} catch (InterruptedException e)  {
}
System.exit(0);
}
}
class NoWaitMonitor {
int token = -1;
PrinterWriter out = new PrintWriter (System.out, true);
// get token value
synchronized int get ()  {
out.printIn (*Got: “  +  token);
return token;
}
// put token value
synchronized void set (int value)  {
token = value;
out.printIn (“Set: “ + token);
}
}
class NoWaitProducer implements Runnable  {
NoWaitMonitor monitor;
Int speed;
NoWaitProducer (NoWaitMonitor monitor, int speed)  {
This.monitor = monitor;
This.speed = speed;
New Thread (this, “Producer”).start();
}
public void run()  {
int I = 0;
while (true)  {
monitor.set (I++);
try  {
Thread.sleep ((int) (Math.random() * speed));
} catch (Interrupted Exception e) {
}
}
}
}
class NoWaitConsumer implements Runnable {
NoWaitMonitor monitor;
Int speed;
NoWaitConsumer (NoWaitMonitor monitor, int speed)  {
This.monitor = monitor;
This.speed = speed;
New Thread (this, “Consumer”).start();
}
public void run()  {
while (true)  {
monitor.get();
try {
Thread.sleep(int)  (Match.random()  *  speed));
} catch (InterruptedException e) []
}
}
}
Here is an example of the output of the program where the producer outpaces the consumer:
C:\MasteringJava\Ch08>java NoWaitPandC  100  400
Set: 0
Got: 0
Set: 1
Set: 2
Set: 3
Set: 4
Got: 4
Set: 5
Set: 6
Set: 7
Set: 8
Set: 9
Set: 10
Got: 10
Set: 11
Set: 12

You can see there is a lot of data generated (shown as Set) but overwritten before it is processed (shown as Got).
Here is an example of the program’s output where the consumer is faster than the producer:

C:\MasteringJava\Ch08>java NoWaitPandC 400 100
Set: 0
Got: 0
Got: 0
Got:0
Got:0
Got:0
Got:0
Set: 1
Set: 2
Got: 2
Set: 3
Got: 3
Got: 3
Got: 3
Got: 3
Got: 3
Set: 4
Got: 4
Got: 4
Got: 4
Got: 4
Got: 4
This time, some of the data is processed multiple times.

The second implementation of the sample program uses the wait() and notify() methods to make sure all data is created and used exactly once. The program is the same as the previous one, except for the implementation of the monitor. A Boolean variable, valueSet, is added to indicate whether the data is ready for consumption or already used. The get() method will first test if the data is ready for consumption. If not, the calling thread will wait until some other thread sets the data and notifies the current thread. The Boolean variable is then set to indicate that the data is consumed. Any thread waiting to produce new data will then be notified to start the production. If there is no thread waiting to produce, the notify() method will be ignored. The get() method is shown here:

Synchronized int get()  {
If (! ValueSet)
Try {
Wait();
} catch (InterruptedException e)  {
}
valueSet = false;
out.printIn (“Got: “ + token);
notify();
return token;
}
Symmetrically, the set() method will first test whether the data is already used. If not, the calling thread wil wait until some other thread uses the data and notifies the current thread. The Boolean variable is then set to indicate that the data is ready for consumption. Any thread waiting to consume the data will then be notified to start the consumption. If there is no thread waiting, the notify() method will be ignored. The set() method is shown here:
Synchronized void set (int value)  {
If (ValueSet)
Try {
Wait();
}  catch (InterruptedException e)  {
}
valueSet = true;
token = value;
out.printIn (“Set: “ + token);
notify();
}

The full program listing is shown here:

Import java.io.*;
Public class PandC  {
Static int produceSpeed = 200;
Static int consumeSpeed = 200;
Public static void main (String args[])  {
If (args.length > 0)
ProduceSpeed = Integer.parseInt (args[0]);
If (args.length > 1)
ConsumeSpeed = Integer.parseInt (args[1]);
Monitor monitor = new monitor();
New Producer(monitor, produceSpeed);
New Consume(monitor, consumeSpeed);
Try {
Thread.sleep(1000);
}  catch (InterruptedException e)  {
}
System.exit(0);
}
}
class Monitor  {
PrintWriter out = new PrintWriter (System.out, true);
Int token;
Boolean valueSet = false;
// get token value
synchronized int get ()  {
if (! ValueSet)
try {
wait();
}  catch (InterruptedException e)  {
}
valueSet = false;
out.printIn (“Got: “ + token);
notify();
return token;
}
// set token value
synchronized void set (int value) {
if (valueSet)
try {
wait();
} catch (InterruptedException e) {
}
valueSet = true;
token = value;
out.printIn (“Set: “ + token);
notify();
}
}
class Producer implements Runnable {
Monitor monitor;
Int speed;
Producer (Monitor monitor, int speed)  {
This.monitor = monitor;
This.speed = speed;
New Thread (this, “Producer”).start();
}
public void run() {
while (true) {
monitor.get();
try {
Thread.sleep (int) (Match.random()  * speed));
} catch (InterruptedException e)  {
}
}
}
}

Here is an example of the output of this program:

C:\MasteringJava\Ch08>java PandC 400 100
Set: 0
Got: 0
Set: 1
Got: 1
Set: 2
Got: 2
Set: 3
Got: 3
Set: 4
Got: 4
This time, every piece of data generated is consumed exactly once.

Examples
#1





class depositthread extends Thread
{

monitor mon;

int amount;

depositthread(monitor pmon,int pamt)
{

mon=pmon;

amount=pamt;

}

public void run()
{

mon.setbalance(amount);

}


}


class monitor

{

int bal;


void setbalance(int pamt)
{

System.out.println("getting balance....");

bal=getbal();

bal=bal+pamt;

System.out.println("setting balance....");

setbal(bal);

}


int getbal()
{

return(Account.balance);

}

void setbal(int pamt)
{

Account.balance=pamt;

}


}



class Account
{

static int balance=1000;


public static void main(String args[])
{


monitor mon=new monitor();

depositthread dp1=new depositthread(mon,1000);

depositthread dp2=new depositthread(mon,1000);

dp1.start();

dp2.start();

try
{

dp1.join();

dp2.join();

}

catch(Exception e)
{
}

System.out.println("total balance is..."+balance);

}

}


#2





class token

{

int data;

boolean setval=false;


synchronized void set(int p)
{


if(setval)
{

try
{
wait();
}
catch(Exception e)
{

}

}



System.out.println("setting data........"+p);
data=p;

setval=true;

notify();

}


synchronized void get()
{

if(!setval)
{

try
{
wait();
}
catch(Exception e)
{

}

}


System.out.println("getting data..."+data);

setval=false;

notify();

}


}




class producer extends Thread
{


token t;


producer(token pt)
{

t=pt;

}


public void run()
{

int i=0;


while(true)
{

try
{

Thread.sleep(2000);

}
catch(Exception e)
{
}



t.set(i++);

}

}

}


class consumer extends Thread
{


token t;

consumer(token pt)
{

t=pt;

}
public void run()
{

while(true)
{

try
{

Thread.sleep(4000);

}

catch(Exception e)
{
}


t.get();

}

}

}



class synpandc
{

public static void main(String args[])
{

token t=new token();


producer p=new producer(t);

consumer c=new consumer(t);

p.start();
c.start();


}


}

#3




class monitor
{


synchronized static void classmethod(int pid,monitor pmon,String pmsg)
{

pmon.tick(pid,pmsg);

}


synchronized void objectmethod(int pid,String pmsg)
{

tick(pid,pmsg);

}


void objectblock(int pid,String pmsg)
{

synchronized(this)
{

tick(pid,pmsg);

}

}



void tick(int pid,String pmsg)
{

int i;

for(i=1;i<=3;i++)
{

try
{

Thread.sleep(4000);

}

catch(Exception e)
{
}


System.out.println(pid+pmsg+"tick # "+i);


}


}


}



class childthread extends Thread
{

monitor mon;

int id;


childthread(monitor pmon,int pid)
{

mon=pmon;

id=pid;

}



public void run()
{

switch(id % 3)
{


case 0:




monitor.classmethod(id,mon,"  class method  ");

break;

case 1:



mon.objectmethod(id,"  object method  ");

break;

case 2:



mon.objectblock(id,"  object block  ");

}

}


}




class Syntypes
{

public static void main(String args[]) throws Exception
{


monitor m=new monitor();


childthread ct[]=new childthread[10];

for(int i=0;i<=9;i++)
{

ct[i]=new childthread(m,i);

ct[i].start();

}



}


}





Graphical User Interface (GUI)
  Abstract Window Toolkit (AWT)

Java’s GUI Approach
Ever since Xero’s pioneer work in the 1970s and Apple’s subsequent mass-market introduction of mouse- and icon-driven user interfaces, developers have needed introduction of mouse- and icon-driven user interfaces, developers have needed to pick competing GUI “standards” and stick to them religiously. Mastering any given GUI standard is not a trivial exercise, so it is not surprising that developers do not switch GUI APIs at the drop of a hat. Like computer languages themselves, GUIs have been thoroughly mutually incompatible. This, and the associated lack of a standard terminology, greatly segregated the various GUI schools, a wasteful and divisive state of affairs. Java’s GUI approach could abolish the GUI wars by supporting a functionally equivalent set of most modern GUI components and presenting them through a new platform-independent API.
At this point, you might ask yourself whether AWT also imposes a new look and feel on our brave new (Java) world. If you are used to, for example, the Macintosh user interface, it is annoying to suddenly have a application that stubbornly thrusts upon you a Windows95-style interface instead. Modern machines have personalities that they impose on us through their native and often proprietary GUI. AWT respects these personalities by employing the underlying machine’s native GUI API to construct its own universal components or manage its behavior itself. Java applications build around AWT reassuringly retain the Mac look and feel on Macs and the Windows look and feel on PCs. Or, if you prefer, you can easily use an interface that appears the same on all platforms. AWT is that flexible.
Since AWT consequently does not specify the exact look and feel-and there-fore the dimensions and exact pixel rendering-of your GUI elements, how do you ensure your GUIs will look great on every platform? The AWT answer is layout managers. These fundamental AWT classes are responsible for laying out all the visual components in aesthetically acceptable ways without requiring you to specify absolute positions. Unfortunately, this process is not yet fully automatic. Java’s AWT does not have artificial intelligence or graphic design experts embedded in its layout managers. Instead, your applications give these layout managers hints as to component placement and preferred sizes. These hints vary from quite vague (“north,” “Center,” or “third” placements) to quite specific (grid coordinates).

AWT Environment: Applets and Applications
Before embarking on your exploration of Java’s novel layout system and the components it affects so thoroughly, you need to understand the two quite different contexts in which a Java GUI can be embedded. Java’s AWT can be used in the following two environments:
    Java applets (mini-Web applications)
    Stand-alone applications
Both have different frameworks to respect. The AWT itself is not aware of the context you choose to deploy it in, but the chosen context means different coding techniques, possibilities, and limitations for your Java programs. The easiest context to start using is Java applets.

The Code Framework for Applets
As you’ve learned, an applet is a small program that runs embedded in a Web browser’s HTML page. As such, any applet has a drawing or work area equal to an imaginary picture situated in the same spot, as illustrated in Figure 12.1.

When applet code starts running, it can immediately use its applet area without any further initializations or checks. For example, the first statement in an applet could be to draw a diagonal line across its surface. The ease with which you can have an applet up and running is what makes applets easier then applications (although it gets more complex for nontrivial applets). It is quite possible to write simple little applets without knowing much about the underlying AWT mechanisms.

Here is an example that draws the diagonal line:

Import java.awt.Graphics;
Public class Appletlet extends java.applet.Applet  {
Public void paint (Graphics g)  {
g.drawLine (0,0,  100,100);
}
}

As you can see, the applet has no lengthy initializations whatsoever before it starts using AWT classes. Here you use the Graphics class to draw a line with its drawLine() method (Chapter 10 discussed Java’s drawing primitives and the Graphics class). To write an applet, you begin by extending (or subclassing) class Applet. That’s because the browser needs your applets to be instances of the Applet class. Any old Java program will not do. The paint() method used in this example is an Applet method that you override.

Applet Methods
Whenever the browser needs to draw the page containing this applet, it tells the applet to draw itself by calling the paint() method. For simplistic applets, this calling protocol between the browser and your applet might be all that you need, but for more complex applets (for example, those using animation), this approach is too limited. In fact, the browser calls many more Applet methods that were not overridden here, so only a small subset of the full browser-applet protocol was used.
For starters, the browser calls the init() method to initialize an applet. There was not an init() method in the simple example because nothing needed to be initialized. But if your applet has any initalization to do (namely, code it needs to execute only once, at the start of its execution), it should put all this code in an overridden init() method. Here is an example that overrides the init() method:

Import java.awt.Graphics;
Import java.unil.Date;
Public class Applet2 extends java.applet.Applet {
String message;
Public void init ()  {
Date date = new Date (System.currentTmeMillis());
Message = “I was born at:  “ + date.toString();
}
public void paint (Graphics g)  {
g.drawstring (message, 10, 20);
}
}

In addition to the paint() method responsible for the redrawing of the applet, you now have a customized init() method. This method will be called once by the browser before the applet is displayed. In this example, the init() method records the date and time at the moment the applet is initialized and converts this to a string that the paint() method will use to draw this frozen time when the applet needs to be redrawn.
Graphically printing a string is done with the Graphics drawnString() method. It takes a string and the coordinates for the string’s position.
The browser invokes three more methods on an applet during an apple’ts life cycle:
Start()    When the applet’s HTML page comes into view or the browser is deiconified
Stop()    When the applet’s HTML page is left or the browser is iconified
Destroy()    When the browser’s garbage collector determines the applet is no longer necessary to keep in memory.
To see the full browser-applet protocol in action, type in the following program, compile it, and tell your favourite Web browser to load a Web page with the applet embedded in it. Make sure you rbrowser shows “Java console output.” On Net-scape’s Navigator browser, you enable this by selecting Show Java Console in the program’s Options menu. For Internet Explorer, it actually logs output to disk instead of sending it to the console. Here’s the code:
Import java.awt.Graphics;
Public class AppletLife extends java.applet.Applet   {
Public void init ()  {
System.out.printIn(“browser wants me to: initialize myself”);
}
public void start ()  {
System.out.printIn(“Browser wants me to: start running”);
}
public void stop () {
System.out.printIn(“Browser wants me to: stop running”);
}
public void paint (Graphics g) {
System.out.printIn(“Browser wants me to: redraw myself”);
}
public void destroy ()  {
System.out.printIn(“Browser wants me to: clean up before being removed.”);
}
}
The first time you load the HTML page, you should see the following output printed to the Java console:
Browser wants me to: intialize myself
Browser wants me to: start running
Browser wants me to: redraw myself
This means the init(),start(), and paint() Applet methods are always called when an applet is first loaded and run. The sequence can differ from what is listed here; due to asynchronous aspects of the protocol, the paint() method can legally be called before the start() method. The init() method, however, is guaranteed to be called before all others.
Now, whenever the browser window needs to repaint itself-for example, after having been obscured by another window overlapping it-you should see an additional:
Browser wants me to: redraw myself
This is because the browser needed to completely redraw itself to undo the graphically inconsistent picture it was showing.
Remember that the entire GUI desktop metaphor your machine maintains is just a clever, graphical illusion. Any computer has a flat, uniform screen bitmap that doesn’t enforce or care about these “overlapping” and clipping rectangular areas called “windows.” The “nutural behavior” of a computer screen is much more like that of a painting canvas in a painting program: The canvas has no restrictions whatsoever. In a GUI environment, then, when windows are depth-arrange in this plain bitmap environment, it means some windows will be partially or entirely overwritten, while others will need to redraw themselves. Since your applet is part of a window, it too must play along to maintain the illusion. If not, your applet will soon become graphically corrupted, or more likely, erased completely. This is why it is important to have an applet repaint itself using the paint() method whenever the browser commands it to (and as quickly as possible, as always).
If you load a different Web page in your browser or just iconify it, you should see your applet print the following line:

Browser wants me to: stop running
You will probably wonder what this means since your applet was not executing any code at the time anyway. Think about the kind of applications applets can be used for-animation, real-time updating of information fetched from an Internet server, general entertainment, and so on. All these types of applets are real-world applets, and they are very different from what has been demonstrated so far in this book. Real-world applets usually run constantly.
To illustrate, imagine that the start() method in your last applet never ended because it had to animate something all the time. Such an applet would be very wasteful of processor resources if it kept on animating even after the user switched to a different page. Yet that is exactly what it would do if you didn’t take any steps to avoid this problem; the way to avoid the problem is by using threads.
In Chapter 8, you saw how threads allow you to do several things at the same time. Imagine all of an applet’s core processing and functionality (the animating, for example) being run in a separate thread. This way, whenever the applet’s page is displaced by a new page, you can simply freeze the thread, and when the applet’s page is reloaded, you can let the thread run again; this is the real purpose of the start() and stop() methods of Applet. They assume that all your applets are written with multithreading in the first place. In later chapters, you will learn how to actually write applets built around a thread, but for now, just keep in mind that start() and stop() are really meant to control applet threat so that they do not consume processor resources while they are not in view.

If you now click on your browser’s Back button to revisit the page with our applet, or deiconify the browser, you will see the console print:

Browser wants me to: start running
Browser wants me to: redraw myself

Because the browser assumed your applet thread had been put to sleep when you switched pages, it now asks your applet to wake up the thread again, immediately followed by an urgent request to repaint the applet. This is because the applet’s façade was overwritten a long time ago by the previous page and any of its applets.

The final method (literally) that abrowser can invoke on applets is the destroy() method. Just quit your browser altogether and carefully watch the console window again. What you should have seen just before the console vanished was:

Browser wants me to : stop running
Browser wants me to : clean up before being removed

The final call to destroy() gives your applet an opportunity to release any persistent and/or expensive resources it had locked while in existence. Files, I/O streams, network connections, unwritten buffers, and similar resources might need some extra closing bookkeeping operations before the applet is discarded.

Automating the Applet Tag Process
You may find the process of modifying the <APPLET CODE= …> HTML tag repetitive and a waste of time. You can make your life easier by automating the process. The following is a shell utility written in Java that takes your applet’s class name (with out the .HTML extension) and generates a minimal HTML file with the <APPLET> tag pointing correctly to your applet. The program uses file and stream I/O, so you may wish to ignore its internals until you are ready for the chapter dealing exclusively with the java.io packag.

•    GenAppietHTML utility
•    Usage: java GenAppletHTML <AppletName>
•    This Java application generates an HTML file named after the class file,
•    Which can be passed to the JDK appletviewer utility to test applets.
Import java.io.*;
Public class GenAppletHTML {
Public static void main (String args[]) throws IOException  {
FileWriter fw;
PrintWriter html;
//we need the name of an applet as argument
if (args.length == 0)  {
System.out.printIn(“Please specify the name of the applet to view.”);
System.exit(10;
}
// give usage summary if user asks for it
if (args[0].indexOf(“?”) != -1 || args[0].equals(“-h))  {
System.out.printIn(“Usage: java GenAppletHTML <AppletName>”);
System.exit(0);
}
//guard against illegal class names being passed (GIGO)
if (!(Character.isLowerCase (args[0].charAt(0))  ||
Character.isUpperCase (args[0].charAt(0))))   {
System.out.printIn(“’” + args[0] + “’ is not a legal class name.”);
System.out.printIn(args[0];
System.out.printIn(‘ ‘)
System.out.printIn(“is lower case.”);
System.exit(12);
}
//open file (combining FileOutputWriter and Printwriter)

fw=new FileWriter (args[0] + “.html”);
html = new PrintWriter (fw);

/*Generate an HTML file with the following structure:
<HTML?
<HEAD></HEAD>
<BODY>
<HR>
<APPLET CODE= ………… WIDTH=400 HEIGHT=300>
<PARAM NAME=argl VALUE=”val1”)
<PARAM NAME=arg2 VALUE=”val2”>
</APPLET>
<HR>
</BODY>
</HTML>
*/
html.print(“<HTML><HEAD></HEAD><BODY><HR><APPLET CODE=”);
html.print(args[0] + “.class”);
html.printIn(“WIDTH=400  HEIGHT=300>”);
html.printIn(<PARAM NAME=arg1 VALUE=\”val1\”>”);  // note backslash esc
html.printIn(“<PARAM NAME=arg2 VALUE=\”val2\”>”);
html.printIn(“<APPLET><HR></BODY></HTML>”);
html.close();
}
}
To run the program, you invoke it as a stand-alone application; that is, from the command line:

C:\> java GenAppletHTML MyApplet
This would generate the file MyApplet.html. The GenAppletHTML utility is useful mainly on non-Unix machines that lack powerful batch-processing command languages. It also nicely illustrates how Java can be used as a powerful and universal batch-programming language.
You should now have a clear overview of applet internals. As you can see, the difficulties lie not in any special precautions you need to take when using AWT classes in applets. The precautions to be taken are imposed on you by the browser applet calling protocol.

The Code Framework for Applications
Since stand-alone applications are by definition responsible for every aspect of themselves, such Java programs are free from any browser protocol and do not inherit a window or drawing area to use “straight away.”
Because they do not rely on a browser protocol, anything goes for applications: They do not need to be subclasses of class Applet and do not consequently need any overridden init(),paint(),start(),or stop() methods. An application can be any class, as long as it has the obligatory static main() method as a starting point for the code.

The absence of an inherited window or drawing area is the main difference when you are waiting applications instead of applets (if you are used to writing applets). Applications do not have a convenient window in which to draw or add GUI components. All this needs to be somehow acquired by the application itself, and this is how a minimal application does it:

Import java.awt.Frame;
Import java.awt.Color;
Import java.awt.event.WindowEvent;
Import java.awt.event.WindowAdapter;
Public class Application  {
Public static void main (String args[])  {
Frame myWindow = new Frame(“Window !”);
myWindow.setBackground(Color.blue);
myWindow.setSize(300,300);
myWindow.setvisible(true);
myWindow.addWindowListener  (new WindowAdapter()  {
public void windowClosing (WindowEvent e)  {
System.exit(0);
}
{);
}
}
The program first creates a window (which initially is not visible) by constructing a new Frame object.

The Frame constructor takes a string that will be the window’s title. After construction, the frame’s background color is set to blue. Next, the program specifies a size for this window using the setSize() method (the window still is not visible). And finally, it commands the window to pop open and display itself by invoking the setVisible() method. For simple applications of the same (trivial) complexity as the first applet example presented in this chapter, this is all that is required to set up a window in which you can then draw and/or build a GUI.


The FlowLayout Manager
The FlowLayout layout manager is the simplest layout manager in the AWT. As the new suggests, it lays out your GUI elements in a flowing, writing-like fashion, similar to how a word processor arranges words in a paragraph. The exact behavior can be understood more intuitively by running the following program:

Import java.awt.*;
Import java.awt.event.*;
Public class FlowingButtons {
Public static void main (String args[])  {
Frame win = new Frame();
Win.setLayout (new FlowLayout());
Win.setSize(120,180);
Win.setVisible(true);
Win.addWindowListener (new WindowAdapter()  {
Public void windowClsoing (WindowEvent e)  {
System.exit(0);
}
});
for (int I = 0; I < 15; I++) {
win.add (new Button Integer.toString(i)));
win.validate();
try  {
Thread.sleep(1500);
}  catch (Exception e)  {
}
System.out.printIn(i);
}
}
}

The program successively addes one button at a time and forces a redisplay of all the buttons so far. This way, you can see exactly what effect the layout manager has on the size and location of the buttons.
This program is not an applet this time. It lacks the code hallmarks of an applet, so it must be an application (you can run it without using your Web browser or the appletviewer utility). Like all applications, the program starts executing with its static main() method. Here, you create a new window with the Frame() constructor. Then, you select the FlowLayout layout manager for this window, size the window to some initial dimensions, and order it to display itself.

Once the window is visible, the program enters a short loop that adds and displays increasing numbers of buttons. The validate() method indirectly notifies the layout manager for the window (that is, the Container for the buttons) and redisplays the result.
The program uses the simplest FlowLayout object constructor possible: the one taking no arguments. But FlowLayout can be customized somewhat by specifying an optional alignment style and the minimum gaps to use between the components.
Public FlowLayout(int align)
Public FlowLayout(int align, int hgap, int vgap)

The alignment parameter should be one of these five FlowLayout class constaints:
Public final static int LEFT
Public final static int CENTER
Public final static int RIGHT
Public final static int LEADING
Public final static int TRAILING

The default constructor used so far is actually shorthand for:
New FlowLayout(FlowLayout.CENTER)

This is why the sample program centered all the buttons on each line. You can familiarize yourself with the predictable results of the four other alignment styles by substituting the line:

Win.setLayout (new FlowLayout());
With:
Win.setLayout (new FlowLayout (FlowLayout.RIGHT));
And again with FlowLayout.LEFT, FlowLayout.LEADING, and FlowLayout.TRAILING.
The third FlowLayout constructor lets you specify a pixel component spacing in both the horizontal and vertical directions.

Unlike most classes you will use when Java programs, most layout manager classes are not called directly at all (apart from their various constructors). This makes them very simple to use. Using the setLayout() method, you just pick one of the existing managers, and from them on the container will be managed by that layout manager. If you are curious about the internal workings of alyout managers or think you need to write one yourself to use in your software productions, look at the “Layout Managers Internals: Interface LayoutManager” section later in the chapter.

Container Insets
One layout feature that is not a layout manager and yet affects all layout styles is called insets. Every container can define a border to be left clear of any components. This border is called the container’s insets. If you look back at the definition for class Container, you’ll see a method with the following signature:
Public Insets getInsets()
The method is there to be overridden by your classes and must return an instance of an Insets object. Class Insets is simple; here is its definition:
Public class Insets extends Object implements Cloneable  {
Public int bottom;
Public int left;
Public int right;
Public int top;
Public Insects(int top, int left, int bottom, int right);
Public Object clone();
Public Boolean equals (Object obj);
Public String toString();
}
Since it does not have any instance methods to speak of, it is not much of a class; it is more of a pure data structure. The constructor for the Insets class takes four parameters that together specify the border to be left clear of components. This is illustrated in the following example of how insets affect the final layout of a container. The following is a Java application program that creates a window laid out using the FlowLayout style and using custom insets. Four different getInsets() methods are listed disabled. You should enable them one at a time (by taking away the double-slash comments), compile, and run each version. Each getInsets() method accentuates insetting one edge at a time. Figure 12.4 shows the results.

Import java.awt.*;
Import java.awt.event.*;
//_____________________________
public class InsetTest  {
public static void main (String args[])   {
MyFrame win = new MyFrame();
Win.setlayout (new FlowLayout());
Win.add (new Button(“One”));
Win.add (new Button(“Two”));
Win.add (new Button(“Three”));
Win.add (new Button(“Four”));
Win.pack();
Win.setVisible(true);
Win.addWindowListener (new WindowAdapter()  {
Public void windowClosing (WindowEvent   e) {
System.exit(0);
}
});
System.out.printIn (win.getInsets());
}
//__________________________________
static class MyFrame extends Frame  {
//public Insets getInsets() {return new Insets(100, 2, 2, 2);}
//public Insets getInsets() {return new Insets(25, 100, 2, 2);}
// public Insets getInsets() {return new Insets(25, 2, 100, 2);}
public Insets getInsets() {return new Insets(25, 2, 2, 100);}
}  // End of class
//___________________________________
}// End of main class

The BorderLayout Manager
The second layout manager is not quite as simple as FlowLayout. Class Border-Layout enforces a five-zone layout, as depicted in Figure 12.5. The BorderLayout manager is the default layout manager for Frame and Japplet (the Appletsub-class when using the Swing components). The zones reflect the typical distribution of components in and around a window.
The five zones in Figure 12.5 are, in fact, filled by exactly the same type of buttons as those used by the FlowLayout example.
BorderLayout, as you can see, sizes its components so that they expand to fill the space available to them. Here is the program that created the output of Figure 12.5:
Import java.awt.*;
Public class BorderLayoutTest extends java.applet.Applet   {
Public void int()  {
SetLayout(new BorderLayout());
Add(new Button(“North”), BorderLayout.NORTH);
Add(new Button(“South”), BorderLayout.SOUTH);
Add(new Button(“West”), BorderLayout.WEST);
Add(new Button(“East”), BorderLayout.EAST);
Add(new button(“Center”), BorderLayout.CENTER);
}
}

The coding differences with the FlowLayout example lie, for one, with the selection of a BorderLayout by passing an instance of the BorderLayout class to setLayout(). Second, the add() method used when adding components to a container with a BorderLayout is not the simple add(Component) one. You need to use the labeled add(Component comp, Object constraints) overloaded variant. As you can see from the code, th eposition is indicated by name instead of by number. This makes the code much more readable.
A BorderLayout can deal with only five components to be laid out: for components located flush against the four edges of a container and one component located centrally and occupying the bulk of the container’s surface area. When using a BorderLayout manager, you are not obliged to specify all five components. Figure 12.6 shows what BorderLayout does when the “Center” component is left out.
As you can see, the four edge components do not grow to fill the void created by the missing center component. Only when one or more of the edge components is left out will the space vacated by those be used by other components. Although there are 32 (25) different BorderLayout component combinations, the subset shown in Figure 12.7 should suffice to give you an accurate feel for how BorderLayout manipulates components when not all five are specified. Basically, when enough space is available, the north and south quadrants are the width of the area and the height of the component; the east and west quadrants are the remaining height of the area and the width of the component. Center is everything else.
As with the FlowLayout layout manager, a variant of the BorderLayout constructor allows you to specify additional horizontal and/or vertical spacing when the border layout is applied. Replace the setLayout() line with the following line to see which effects you can obtain:

SetLayout(new BorderLayout(10,50));

The CardLayout Manager and JtabbedPane
The CardLayout layout manager is not really a layout manager as such. What it does is let you define any number of “cards” containing, typically, a logically related collection of components. Figure 12.9 shows a typical card-based configuration window (which wasn’t implemented using Java but could easily be).

The following program demonstrates the use of CardLayout with five cards containing a single button each:

Import java.awt.*;
Import java.awt.event.*;
Public class cards extends Frame
Implements ActionListener  {
CardLayout layout;
Public Cards()  {
Super (“CardLayout Tester”);
Layout = new CardLayout();
SetLayout(layout);
For (int I=.0; I<5; I++)  {
Button b = new Button (“Card “ + I + “Button”);
Add (b, “Btn”+I);
b.addActionListener(this);
}
}
public void actionPerformed(ActionEvent e)  {
layout.next(this);
}
public static void main (String args[])  {
Frame f = new Cards();
f.setSize (200,  150);
f.setVisible(true);
f.addWindowListener (new WindowAdapter()  {
public void windowClosing (WndowEvent e)   {
System.exit(0);
}
});
}
}

Notice the add() method used to add cards to a CardLayout. As with border layouts, you need to use the constraints variety to pass a card name (in addition to the card itself) to the layout manager. Later, you can refer to your cards by name, instead of indexed by number, for example. Also note that a CardLayout variable was created. In the previous layout manager examples, you simply had a new SomeLayoutManager() within the brackets of the setLayout() call. But in this example, you actually need to refer to your CardLayout object after you have created it-this is why you need the variable to keep a reference to it.
To demonstrate the abilityto cycle through the cards, this applet was made to listen for action from any of the buttons; the next card is displayed whenever you click on one of the buttons. The next() method tells the application to show the next card under its control. When it reaches the last card and you ask it to show the next() card again, it simply cycles back to the beginning.

You probably expected to see a full-fledged rendering of our five different cards (as in Figure 12.9), including the clickable tabs to select any one of the cards. Unfortunately, CardLayout does not do this for you. You must either implement the tabs and the card outlines yourself or use the JtabbedPane container. The following program expands on the previous example to demonstrate the usage of JtabbedPane:
Import java.awt.*;
Import java.awt.event.*;
Import com.sun.java.swing.*;
Public class Cards2 extends Frame {
Public Cards2()  {
Super (“JtabbedPane Tester”);
JtabbedPane jtp = new JtabbedPane();
For (int I=0; I<5; I++)  {
Button b = new Button(“Card” + I + “Button”);
Jtp.addTab (“Btn”+I, b);
}
add (jtp, BorderLayout.CENTER);
}
public static void main (String args[])  {
Frame f = new Cards2();
f.setSize (250, 150);
f.setVisible(true);
f.addWindowListener (new WindowAdapter()  {
public void windowClosing (WindowEvent e) {
System.exit (0);
}
});
}
}
Each card is added with the addTab() method, instead of the plain add() method. Also, notice the event-handling code to move between cards is automatically performed by the JtabbedPane. Because of this added value of JtabbedPane, you’ll find yourself almost never using CardLayout.


The GridLayout Manager
The GridLayout layout manager enforces a grid-based layout on components. Figure 12.13 shows an example of this type of layout.

Here is the program that produced the apple in Figure 12.13:

Import java.awt.*;
Public class GridLayoutTest extends java.applet.Applet {
Public void int()  {
SetLayout(new GridLayout(3,2));
Add(new Button(“First”));
Add(new Button(“Second”));
Add(new Button(“Third”));
Add(new Button(“Fourth”));
Add(new Button(Fifth”));
}
}

You specify the number of grid rows and columns to the constructor for class GirdLayout. In this example, three rows and two columns wereused. Again, five test buttons were addedusing the default add(Component) method. Notice the order in which the buttons end up:  The linear adding sequence is used to fill the rows top to bottom. If this implicit ordering is not suitable for your program, you can use the second Container add() method, which takes an additional single numerical position argument, as follows:

Add(new Button(“First”), 0);
Add(new Button(“Second”), 1);
Add(new Button(“Third”), 2);
Add(new Button(“Fourth”), 3);
Add(new Button(“fifth”), 4);

The resulting layout is exactly the same as in Figure 12.13. In order words, you have simply separated the adding order from the positioning.

The GridBagLayout Manager and GridBagConstraints
All of the examples used to demonstrate the different layout managers so far simply use buttons that have not been asked to appear drawn to any set size. Before inspecting the last and most complex standard layout manager, classGridBagLayout, you first should learn a bit about component sizes.

Component Dimensions
Every Component can give hints to layout managers as to how big or small it would like to appear in the GUI. Three sizes can be explicitly specified: a preferred, a minimum, and a maximum size. To specify these for your AWT components, you need to create a subclass of the generic component class (Button, List, TextField, and so on) and override the following three Component methods:
Public class Component extends Object implements ImageObserver  {
:
:
public Dimension getPreferredSize();
public Dimension getMaximumSize();
public Dimension getMinimumSize();
:
:
}
Because there is no way to specify these size hints for non-sub classed components, these methods are not used in the previous examples. (using them would have required creating Button subclasses in all of the layout manager examples, and that would have detracted your attention from the core layout manager issues.) In real-lie applets and applications, however, windows and their contents can be resized (unless you take explicit steps to force a window to be of fixed size). But when a user shrinks your window, it can reach point where simply linearly scaling every component accordingly will result in either an ugly or a plainly nonfunctional GUI. Similarly, when a user stretches your window, a point may be reached where your components scaled up proportionally will look ridiculous. Methods getPreferredSize(), getMinimumSize(), and getMaximumSize() help layout managers size your components so that the result of any window resizing operation remains acceptable.
If you rerun the GridLayout demos using the JDK tool appletviewer and play around with the applet window size, you will see that the five buttons can be stretched or shrunk to very extreme sizes. You can counter this flexibility overkill by creating Button subclasses that specify some reasonable sizes using getPreferredSize() and getMinimumSize(), and using a layout manager that honors these hints, like GridBagLayout (GridLayout does not). The way this is done is by overriding the method. For example:

Public Dimension getPreferredSize()  {
Return new Dimension(200,150);
}
If this overridden method was included in any Component subclass you created, it would tell any layout manager that this components’ preferred dimensions are 200 x 150 pixels.

GridBagLayout
GridBagLayout is special among the standard layout managers in that it uses a helper class (GridBagConstraints) to specify a whole host of layout parameters, normally one class instance per component. The GridBagLayout manager’s main (but by no means only) advantage over GridLayout is that it allows a component to use up more than one grid cell.
A component’s size can be specified as the number of horizontal and/or vertical grid cells the component should occupy on the grid. The helper GridBagConstraints class, which is defined as follows, controls these parameters:

Public class GridBagConstraints extends Object implements
Cloneable, java.io.Serializable  {
Public static final int BOTH;
Public static final int CENTER;
Public static final int EAST;
Public static final int HORIZONTAL;
Public static final int NONE;
Public static final int NORTH;
Public static final int NORTHEAST;
Public static final int NORTHWEST;
Public static final int RELATIVE;
Public static final int REMAINDER;
Public static final int SOUTH;
Public static final int SOUTHEAST;
Public static final int SOUTHWEST;
Public static final int VERTICAL;
Public static final int WEST;
Public int anchor, fill;
Public int gridx, gridy;
Public int gridwidth, gridheight;
Public Insets insets;
Public int ipadx, ipady;
Public double weightx, weighty;
Public GridBagConstraints();
Public Object clone();
}
This class consists essentially of instance variables and a collection of class constants (it also has a constructor and an overridden implementation of the Objectclone() method, discussed later in the chapter)

The most important GridBagConstraints fields are gridx, gridy, gridwidth, and gridheight. These fields control a component’s placement and size in the grid. Unlike with the one-dimensional placement limitations of the add() method for components added to a GridLayout, the gridx and gridy fields allow you to specify GridBagLayout components in any order and in two dimensions. With a GridBagLayout, you use a special version of add() that takes the GridBagConstraints as its second parameter.
Figure 12.16 shows a sample GridBagLayout that clearly demonstrates the additional possibilities the class provides over classes FlowLayout and GridLayout.

Here is the program that produced the GUI layout in figure 12.16:

Import java.awt.*;
Public class Gridbag extends java.applet.Applet  {
Public void init()  {
GridBagLayout gb = new GridBagLayout();
GridBagConstraints gbc = new GridBagConstraints();
Button b;
SetLayout(gb);
Gbc.gridwidth = 1;
Gbc.gridheight = 1;
Gbc.gridx = 0;
Gbc.gridy = 0;
Gbc.fill = GridBagConstraints.BOTH;
B = new Button(“First”);
Add(b, gbc);
B = new Button(“Second”);
Gbc.gridx = 1;
Gbc.gridwidth = 2;
Add (b, gbc);
B = new Button(“Third”);
Gbc.gridx = 3;
Gbc.gridwidth = 1;
Add(b, gbc);
B  = new Button(“Fourth”);
Gbc.gridx = 0;
Gbc.gridy++;
Gbc.gridwidth = 4;
Add(b, gbc);
B = new Button(“Fifth”);
Gbc.gridy++;
Gbc.gridwidth = 1;
Add(b, gbc);
B=new Button(“Sixth”);
Gbc.gridx = 1;
Gbc.gridwidth = 3;
Gbc.gridheight = 2;
Add(b, gbc);
B = new Button (“Seventh”);
Gbc.gridx = 0;
Gbc.gridy++;
Gbc.gridwidth = 1;
Gbc.gridheight = 1;
Add(b, gbc);
}
}
This applet’s init() method begins by creating one new GridBagLayout object and one helper GridBagConstraints object. After setting the current layout to GridBagLayout, the code initializes “constraint” parameters for the first object to be added. Filling in GridBagConstraints fields does this. You set the width and height to 1 cell and start adding components in the top-left corner of the grid (grid coordinates 0,0).
The next line sets the fill style for the components. This determines how a component will fill the available space if that space allows it to stretch beyond its preferred size. The legal values for the fill variable are NONE, HORIZONTAL, VERTICAL, and BOTH. You then associate these layout parameters with yor component by calling the add() method, passing the GridBagConstraints as a second argument.
To summarize, adding a component to a GridBagLayout-style container consists of these two steps:
1.    Set any desired GridBagConstraints parameters.
2.    Invoke the two-parameter version of the add() method to add the component to the container.
Regarding the first step, there is an interesting subplot going on in the sample code. First, you initialize some of the GridBagConstraints object’s fields, and then you add the button to its container. This lets the GridBagLayout manager bind the first button with the GridBagConstraints object as defined at that point. You then proceed to modify some of the GridBagConstraints values call add() again to bind the second button with your same but modified Grid-BagConstraints object (you have only one instance for the entire program). You just changed its gridx and gridwidth instance variables, but left the gridy and gridheight variables alone. This means you have just clobbered half of the GridBagConstraints parameters for button one.
Remember that Java objects are passed by reference and not by value (that is, objects are not copied). Shouldn’t you therefore have needed to create a new GridBagConstraints object for each button? Normally, yes, but in this exceptional case, no. The reason lies hidden inside the GridBagLayout class itself. Method setConstraints() used the clone() method to make a copy of the GridBagConstraints objects given to it. And this is why you can safely use a single GridBagConstraints object instance for any number of components.
The clone() method is available only on classes that implement the Cloneable interface. If you check back at the definition of GridBagConstraints, you will see that this class odes just that. Since very few classes do implement this interface, this type of object “pass-by-value” feature is rare in Java. The norm is that method arguments let your objects have full (shared) access to the passed object, and thus the programming technique used in our example would be quite incorrect. In this instance, however, it has become a Java idiom, so you can improve readability of code sections dealing with GridBagLayout managers by exploiting the object-cloning behavior.
There is one more GridBagConstraints parameter to be introduced. To see its effect, recompile and run the applet with the following line removed:
Gbc.fill = GridBagConstraints.BOTH;

The layout suddenly looks very un-gridlike (if you look closely, the Second and Sixth buttons are not aligned to any grid). This is because of the other GridBagConstraints parameter: anchor. Without an explicit value for the fill parameter, you simply get its default: NONE. This means that any components will be sized to their preferred size (if possible). The odd-looking placement of buttons Second and Six is the result of the default anchor style. This default style centers components within the grid space they allocated, using gridwidth and gridheight. If you now add the following line (where you removed the fill style line), you should obtain the result shown in figure 12.18.

Gbc.anchor = GridBagConstraints.NORTHWEST;

Now that you have been introduced to the standard AWT layout managers, you will next explore the innards of layout managers. The following section explains what all layout managers have in common.

Examples

// how to create various components

import java.awt.*;

class FormEx extends Frame
{
     Label reglb,loglb,pwdlb,genlb,lanlb,courlb,addrlb;   
     TextField logid,pwd;
     TextArea addr;
     Checkbox mchk,fchk,eng,hin,tel;
     CheckboxGroup cbg=new CheckboxGroup();
     List cour;
     Button subm,can,ex;

     FormEx()   
     {
    setTitle("Registration Form");
    setBackground(Color.cyan);
    setLayout(null);
    reglb=new Label("REGISTRATION FORM");
    reglb.setFont(new Font("TimesRoman",Font.BOLD,25));
    reglb.setForeground(Color.blue);
    loglb=new Label("Login-Id : ");
    pwdlb=new Label("Password : ");
    genlb=new Label("Gender : ");
    addrlb=new Label("Address : ");
    lanlb=new Label("Languages Known : ");
    courlb=new Label("Course : ");
    logid=new TextField(15);
    pwd=new TextField(15);
    pwd.setEchoChar('*');
    mchk=new Checkbox("Male",cbg,true);
    fchk=new Checkbox("Female",cbg,false);
    addr=new TextArea(10,10);
    eng=new Checkbox("English");
    hin=new Checkbox("Hindi");
    tel=new Checkbox("Telugu");
    cour=new List(3,true);
    cour.add("DCA");
    cour.add("PGDCA");
    cour.add("C Language");
    cour.add("C++ Programming");
    cour.add("Core Java");
    cour.add("Adv. Java");
    subm=new Button("Submit");
    can=new Button("Cancel");
    ex=new Button("Exit");
    reglb.setBounds(250,50,300,50);
    loglb.setBounds(200,125,75,20);
    logid.setBounds(350,125,100,20);
    pwdlb.setBounds(200,175,75,20);
    pwd.setBounds(350,175,100,20);
    genlb.setBounds(200,225,75,20);
    mchk.setBounds(350,225,50,20);
    fchk.setBounds(450,225,100,20);
    addrlb.setBounds(200,275,75,20);
    addr.setBounds(350,275,150,100);
    lanlb.setBounds(200,400,150,20);
    eng.setBounds(350,400,75,20);
    hin.setBounds(450,400,75,20);
    tel.setBounds(550,400,75,20);
    courlb.setBounds(200,450,75,20);
    cour.setBounds(350,450,100,50);
    subm.setBounds(275,525,50,20);
    can.setBounds(350,525,50,20);
    ex.setBounds(425,525,50,20);
    add(reglb);
    add(loglb);
    add(logid);
    add(pwdlb);
    add(pwd);
    add(genlb);
    add(mchk);
    add(fchk);
    add(addrlb);
    add(addr);
    add(lanlb);
    add(eng);
    add(hin);
    add(tel);
    add(courlb);
    add(cour);
    add(subm);
    add(can);
    add(ex);
     }
     public static void main(String ar[])
     {
          FormEx fe=new FormEx();
          Toolkit tk=Toolkit.getDefaultToolkit();
          fe.setSize(tk.getScreenSize());
          fe.setVisible(true);   
     }   
}

#2

import java.awt.*;


class flowlayout
{

public static void main(String args[])
{

Frame f=new Frame("flow layout");

f.setSize(400,400);

f.setBackground(Color.red);

f.setLayout(new FlowLayout());

Button b1=new Button("first");

f.add(b1);

Button b2=new Button("second");

f.add(b2);

f.setVisible(true);

}

}


Event Handling

Java’s Event-Delegation Model

In Java, events are objects.  The java. awt. event package defines a rich hierarchy of event types, described later in this chapter.  Through this package, instances of the various event classes are constructed when users use GUI components.  It is up to the programmer to decide how to handle the generated event.  For example, when a user clicks on a button, the system constructs an instance of class Action Event, in which it stores details about the event (when, where, and so on).  At this point, the programmer has three options:

.  Ignore the event.

•    Have the event handled by the component (in this case, a button) where the event originated.

•    Delegate event handling to some other object, possibly yourself, or objects called listeners.



Ignoring the Event

In the absence of any explicit event-handling code, events will be ignored.  You already saw this in Chapter 13, where a sample applet was presented for each type of component.  You could activate all the components (that is, you could move the slider, push the button, select from the list, and so on), and the components would respond visually, but the test programs do not do anything about your input.

Just because it is possible to respond to input from a component, it is not necessary to do so.  Consider a hypothetical Java-based mail tool, with a text area for composing messages, a text field for entering a recipient, and a Send button.  While composing a mail message, a user types and clicks with the mouse, creating a large number of events in the text area and the text field.  This hypothetical program could provide event-handling code to deal with these events, but what would that code do?  The only time the program cares about the state of the text area and the text field is when the user clicks the Send button.  A clean implementation of this program would handle events from only the Send button; the event would read the contents of the other two components and build an appropriate mail message.  This example shows there are times when the best response to an event is none at all.

Handling the Event in the Originating Component

A self-contained component is one that handles the events that it generates.  None of the Swing or AWT components are self-contained, if you want a component to handle its own events, you need to create a subclass.  The subclass must do two things:

•    Enable receipt of events by calling enable events () with the necessary event mask setting

.    Provide a process action Event () method, which will be called when the component is activated

The following code implements a simple self-contained button:

import java.awt.*;
import java.awt.event.*;
public class SelfButton extends Button {
public SelfButton (String label) {

super(label);
enableEvents(AVrEvent.ACTION_EVENT_MASK);
}
public void processActionEvent (ActionEvent e)  {
super.processActionEvent (e);
System.out.println('Action!');
}
}
The constructor calls enable events, passing in AWT Event.  ACTION-EVENTMASK, which tells the button component that it is interested in action events.

When a user clicks on a Self button, the system generates an action event and then checks whether the Self Button has enabled action events.  Since action events are enabled, the system calls the processActionEvent() method.  In the example, this method does its default behavior and then just prints a brief message.

By passing in different event masks to enableEvents(), you can sensitize a component, to catch many different kinds of events; all of the event handlers have names of the format processXXXEvents(), where XXX stands for the event type. (The various event types are discussed later in "Java's Event Types.")

You use a self-contained component just like any other component: construct one, and then add it to a container.  The following code produces a simple applet that demonstrates the use of Self-button:


import jdva.applet.*;
public class SelfButtonTest extends Applet {
public void init ()  {
add (new SelfButton("Push Me"));
}
}

Delegating the Event

One of the fundamental principles of object-oriented design is that the object best suited to the task should perform the task.  There will be times when self-contained components are not the way to go because the component may not be the object best suited to handling its own events.

The process of assigning an object to handle a component's events is called delegation.  The event-handling objects are called listeners.  To tell a button that it should delegate handling of action events to some listener, you call the button's add actionListener() method, passing in a reference to the desired listener.  Every component class in AWT has one addXXXListener() method for each event type that the component generates.

A component may have multiple listeners for an event. if for example, a button has five action listeners, each of the listeners will be notified when the button is activated.  This is sometimes useful, but it has two drawbacks.  First, there is no guarantee about the order in which listeners will be notified.  Second, spreading event-handling responsibility among several objects can quickly lead to code that is difficult to maintain.  However, multiple listeners.
    When a button with an action listener is clicked, the listener receives an actionPe rformed () call.  The listener class should implement this method however it is supposed to respond.  The following example has a button in an applet.  The button delegate’s action handling to a third object, which is an instance of class Test Listener:

import java.awt.*;
import java.awt.event.*;
public class ButtonDelegateTest extends java.applet.Applet {
public void init () {
Button b = new Button(III have a listener!');,
add(b);
ActionListener listener = new TesiListenet();
        b.addActionListener(listener);
            }
        class TestListener implements ActionListener {
        public void actionperformed (ActionEvent e) {
        System.out.println ("Listener here: the button was clicked.");
        }
        }
        }
    You should notice several things about this program:

•    The button is a plain Button, not a subclass.  When you use event delegation, your design takes on some complexity, but you are spared the necessity of sub classing.

•    There is the call to addActionListener().  This is called on the button, passing in the test listener.  This means that before addActionListener() can be called, the listener must be constructed.

•    The declaration line for TestListener says that the class implements the ActionListener interface.

ActionListener is a simple interface with only one method:
public interface ActionListener extends EventListener {
public abstract void actionPerformed(ActionEvent e);
}
The declaration for method addActionListener() requires that the listener parameter implement this interface:

public void addActionListener(ActionListener listener);

Since the listener is required to implement the interface, you know that when an action event occurs, the system can safely make an actionPerformed() can on the listener, because the listener definitely has an actionPerformed() method.


Delegating the Event to Yourself
As the "Handling the Event in the Originating Component" section shows, you can easily handle events yourself by enabling an event mask and overriding an event-processing method.  While there is nothing wrong with the way this works, it is much easier to just add yourself as the event listener.  The Self button from above can be changed to the following (the two changes made are bold):
import java.awt.*;
import java.awt.event.*;
public class SelfButton2 extends Button implements ActionListener {
public SelfButton2 (String label) {
super(label);
addActionListener (this);
    }
public void actionPerformed (ActionEvent e) {
System.out.println(“Actionl”+e);
    }
    }
The self-contained class implements the listener for the event, and the cons adds itself as a listener.


Java’s Event Types

SO far, you have looked at one type of event: the action event.  There are actually 16 concrete event types, which are contained in .the java. awt. event and com . sun.java. swi ng. event packages. (There is also an intermediate super class, Input Event, which is the parent of KeyEvent and MouseEvent.) All of the event classes, except two, MenuEvent and PopupMenuEvent, extend from two abstract superclasses: java. uti 1. EventObject and java. awt.AVrEvent.

The ancestor of the hierarchy is java.uti1. Event Object, which provides a method called geSource().  This method returns the component in which the event tookplace.  One level below java.uti1. Event Object is java.awt.event.Event, which provides a method called getID(.  This method returns an i nt that describes the nature of the event.  For example, calling getIDo on an instance of MouseEvent results in an i nt whose value might be MouseEvent.  MOUSE-PRESSED, MouseEvent.  MOUSE-DRAGGED, or one of several other possible values, depending on which specific mouse activity triggered the event.


Examples

#1
import java.awt.*;
import java.awt.event.*;

class MouseMotionEx extends Frame implements MouseMotionListener
{
     int xNew,yNew,xOld,yOld;
     boolean start=true;

     MouseMotionEx()
     {
          addMouseMotionListener(this);
          addMouseListener(new MouseAdapter()
                           {
                              public void mouseReleased(MouseEvent me)
                              {
                    start=true;
                          }
                           });
     }
     public void mouseDragged(MouseEvent me)
     {
          xNew=me.getX();
          yNew=me.getY();
          if(start)
          {
           start=false;
               xOld=xNew;
               yOld=yNew;
          }
      repaint();
     }
     public void update(Graphics g)
     {
          g.drawLine(xOld,yOld,xNew,yNew);
          xOld=xNew;
          yOld=yNew;
     }
     public void mouseMoved(MouseEvent me)
     {
     }
     public static void main(String[] a)
     {
          MouseMotionEx mm=new MouseMotionEx();
          Toolkit tk=Toolkit.getDefaultToolkit();
          mm.setSize(tk.getScreenSize());
          mm.setVisible(true);
     }
}


#2
import java.awt.*;
import java.awt.event.*;

class FocusEx extends Frame implements FocusListener,ActionListener
{
     TextField uid,pwd,cpwd;
     String str="LOGIN IN PROGRESS";
     Button res;

     FocusEx()
     {
          uid=new TextField(15);
          pwd=new TextField(15);
          cpwd=new TextField(15);
          pwd.setEchoChar('*');
          cpwd.setEchoChar('*');
          Panel pn=new Panel();
          pn.add(new Label("User-Id : "));
          pn.add(uid);
          pn.add(new Label("Password : "));
          pn.add(pwd);
          pn.add(new Label("Confirm Password : "));
          pn.add(cpwd);
          add("North",pn);
          res=new Button("Reset");
          Panel ps=new Panel();
          ps.add(res);
          add("South",ps);
          setBackground(Color.pink);
          uid.addFocusListener(this);
          pwd.addFocusListener(this);
          cpwd.addFocusListener(this);
          res.addActionListener(this);
     }
     public void actionPerformed(ActionEvent ae)
     {
          uid.setText("");
          pwd.setText("");
          cpwd.setText("");
          uid.requestFocus();
     }
     public void focusLost(FocusEvent fe)
     {
          if(fe.getSource().equals(cpwd))
          {
               String user=uid.getText().toUpperCase();
               String pass=pwd.getText().toUpperCase();
               String cpass=cpwd.getText().toUpperCase();
               if(user.equals("SCOTT") && pass.equals(cpass))
                    str="WELCOME "+user;
               else
                    str="SORRY! INVALID USER.";
               repaint();
          }
     }
     public void focusGained(FocusEvent fe)
     {
          if(fe.getSource().equals(uid))
          {
               str="Please enter your User Id";
               repaint();
          }
          else
          if(fe.getSource().equals(pwd))
          {
               str="Please enter your Password";
               repaint();
          }
     }
     public void paint(Graphics g)
     {
          g.setFont(new Font("Courier",Font.BOLD,30));
          g.setColor(Color.blue);
          g.drawString(str,200,300);
     }
     public static void main(String a[])
     {
          FocusEx te=new FocusEx();
          Toolkit tk=Toolkit.getDefaultToolkit();
          te.setSize(tk.getScreenSize());
          te.setVisible(true);
     }
}



IOStreams

Java.io package contains the classes which are used for input and output operations.
There is a class called Random Access File, which is used to perform yet and output operations on only files.
The files can be opened in read i.e. ‘r’ or read write i.e. ‘rw’ mode to perform input and output operations on files.
The following are the constructors and methods of Random Access file class.
1.    Random Access File (Study filename, String mode),
ex. Random Access File rf = new Random Access File (“Naidu.txt”, “r”);
2.    long length ( )
3.    long get File Partner ();
4.    int read ();
5.    int read (byte[] b);
6.    int read (byte[] b, int start, int no. of bytes);
7.    String read Line ();
8.    void write (int);
9.    void write (byte[] b);
10.    void write (byte[] b, int start, int no. of b bytes);
11.    void write bytes (string S);
12.    void close ();


Java’s File Class
    To shield Java applications from this incompatibility obstacle, class File defines platform-independent methods for manipulating a file maintained by a naitve filing system. Here is the definition of class File:
    Public class File extends object implements Serializable, Comparable {
        Public static final string pathSeparator;
        Public static final char pathSeparatorChar;
        Public static final Staring separator;
        Public static final char sepatatorChar;

        Public File (String path);
        Public File (String path, String name);
        Public File (File dir, String name);
        Public boolean canRead();
        Public Boolean canWrite();
        Public int compareTo (Fine anotherFile);
        Public int compareTo (Object o);
Public boolean createNewFile ();
        Public static File createTempFile (String prefix) throws IOException;
        Public static File createTempFile (string pattern, File dir)
    Throws IOExcetion;
        Public boolean delete();
        Public void deleteOnExit();
        Public Boolean equals(object obj);
        Public Boolean exists();
        Public File getAbsoluteFile ();
        Public String getAbsolutePath ();
        Public File getCanonicalFile() throws IOException;
        Public String getCanonicalPath() throws IOException;
    Public String getName();
    Public string getParent ();
    Public File getparentFile();
    Public String getPath();
    Public int hashcode();
    Public Boolean isAbsolute();
    Public Boolean isDirectory();
    Public Boolean isFile();
    Public long lastModified();
    Public long length();
    Public String[] list();
    Public String[] list (FilenameFilter filter);
    Public File[] listFiles();
    Public File[] listFiles(FileFilter filter);
    Public File[] listFiles(FilenameFilter filter);
    Public static File[] listRoots();
    Public Boolean mkdir();
    Public Boolean mkdirs();
    Public Boolean renameTo(File dest);
    Public Boolean setLastModified (long when);
    Public Boolean setReadOnly();
    Public String toString(0;
    Public URL toURL() throws MalformedURLException;
    }
    As you can see from the list of supported methods, class File does not allow you to access the contents of the file. No read() or write() methods of File let you do this. Class File primarily names files, queries file attributes, and manipulates directories or temporary files, all in a system-independent way. The following is a description of what you can do with files without opening them.
Naming Files
    Files are named in two manners. You can either provide both a directory and a file within the directory, or you can provide both, comdined into one value. Either way, you are providing the full name of a file you wish to potentially access. The benefit of providing a directory and file name separately is that you don’t have to worry about how to combine the two. For instance, on Microsoft Windows-based platforms, the separator character is the forward slash character (‘\’). While you can ask the File class what the separator character is via the separator class variable, why bother combining the two terms yourself if you can let the constructor of the File class do it for you?
    To demonstrate, the following code fragment attempts to create three File objects. Each line does succeed in creating a File object. However, if you try to use the File object, only the second or third attempts will succeed on all platforms, as they do not have a file separator value hard-coded into the source code.
    File f1 = new File (“tmp/foo”);
        File f2 = new File (“tmp”, “foo”);
    File f3 = new File (new File (“tmp”), “foo”);
Querying File Attributes
    Class File provides a handful of methods for querying a minimal set of file attributes:
    Whether the file exists
    Whether the file is read protected
    Whether the file is write protected
    Whether the file is, in fact, a directory
    Whether the file is hidden
    Discovering other common file attributes, such as whether a file is a system or an archived file, is not supported. As with Java’s AWT classes, the designers of these classes have taken the least common denominator of all filing systems for their model. If Java included features (like an archived attribute) that aren’t supported by some systems, its universal compatibility across platforms would be jeopardized.
    The following program shows how to use a File instance to query the attributes of a file. The file is specified as a command-line parameter:
    Import java.io. *;
    Public static void main (String args[]) {

        File path;
        Path = new File(args[0]); // grab command-line argument
    String exists    = path .exists()    ?    “yes”    :    “No” ;
    String canRead    =    path.canRead()    ?    “yes”    :    “No” ;
    String canWrite    =    path.canWrite()    ?    “yes”    :    “No” ;
    String isFile    =    path.isFile()    ?    “yes”    :    “No” ;
    String isHid    =    path.isHid()    ?    “yes”    :    “No” ;
    String isDir    =    path.isDir()    ?    “yes”    :    “No” ;
    String isAbs    =    path.isAbsolute()    ?    “yes”    :    “No” ;

System.out.println (“File attributes for ‘ “ + args[0] = “ ‘ “) ;

System.out.println (“Exists    :    “ + exists);
If (path.exists()) {
    System.out.println (“Readable    :    “ + canRead) ;
    System.out.println (“Writable    :    “ + canWrite) ;
    System.out.println (“Is directory    :    “ + isDir) ;
    System.out.println (“Is File    :    “ + is File) ;
    System.out.println (“Is hidden    :    “ + is Hid);
    System.out.println (“Absolute path    :    “ + isAds);
    }
    }
    }
    You can experiment with this program by passing it various filenames and directory names, either relative or absolute.
Note
    Note the use of the ternary operator (?) to select either a “yes” or “No” string for variables. This approach is more compact than the logical equivalent of using ifelse statements.
    Manipulating Directories
    A handier program would be one that could list the contents of a directory, like the dir or ls commands in most operating systems. Fortunately, class File supports directory-list generation via its list() and listFiles() methods. Here’s another program that recursively (that is, calling upon itself) lists directories and their contents:
    Import java.io.*;
    Import java.util.*;
    Public class Dir {
    Static int indentlevel = -1;
    Dir (String path) {
    ListPath (new File (path));
    }
    void listpath (file path) {
    File files []; // list of files in a directory
    Indentlevel++;    // going down…
    // create list of files in this dir
    files = path.listFiles();

    //Sort with help of Collections API
    Arrays.sort (files);
    For (int I=o, n=files.length; I < n;  I++) {
    For (int indent = 0; indent < indent level; indent++) {
    System.out. print (“    “);
    }
    System.out.println (files [I]. ToString());
    If (files [I]. IsDirectory ()) {
    // recursively descend dir tree
    listpath (files [I]);
    }
    }
    indentlevel--;    // and going up
    }
    public static void main (String args[]) {
    new Dir(args[0];
    }
    }
    The program relies on a couple of interesting concepts. First of all, it calls itself recursively in the statement listpath (files[I]). This repeated invocation of the listpath () method restarts listpath () with a new path, initialized to contain the deeper directory to list.
    The directory listing is sorted, using the Arrays class of the Collections API, described in Chapter 17.
    To highlight the current directory level, the contents of a directory are indented according to its nesting level in the filing hierarchy. The depth of the recursion level, tracked in the class variable indentlevel, determines this nesting level. When a method exits, class variables are not destroyed as are simple method variables. The program relies on this behavior to track the recursion level across multiple invocations of listpath().
    Static variables have one more interesting attribute: They are not allocated anew each time a new instance of a class is made. Therefore, they are also called class variables. (This aspect of variable indentlevel is not relevant in the program because it does not explicitly create multiple instances of class Dir, although Dir is instantiated once when the example program is loaded.)
Mainpulating temporary Files
    One nice feature of the File class, added with java 1.2, is support for temporary files. Prior to Java 1.2, if your program needed to use a temporary file, you had to manage the file location and name all by yourself. Now, thanks to the static createTempfile() methods and the java. Io.tmpdir system property, you can guarantee that the file object created by the method did not previously exist. Also, by calling deleteOnExit(), you can ensure the file will be deleted if the Java environment ends naturally.
Note
    The system property java.io.tmpdir contains the system-dependent temporary file location. This would typically be C:\TEMP for Microsoft Windows platforms and \tmp for UNIX systems.

Java’s RandomAccessFile Class
    Class File doesn’t let you read or write files, but other classes provide this functionality. To read or write files, you can use of two approaches. You can use the extremely powerful stream classes (which are discussed later in this chapter), or you can use class RandomAccessFile. The latter option is easy to use but has severe limitation if you want to start writing flexible or more complex applications. Class RanbomAccessFile does I/O only on files, whereas the stream I/O classes can do I/O on almost anything, including files. So, bear in mind that there is a much more powerful way to do the same procedures (see “Java’s I/O Stream Manipulation Methods” later in this chapter for more information).
    The definition of class RandomAccessFile neatly sums up its functionality:
    Public class RandomAccessFile extends object implements DataInput, DataOutput {
    Public RandomAccessFile (File file, String mode) throws IOException:
    Public RandomAccessFile (String name, String mode) throws IOException:

    Public native void close() throws IOException;
    Public final filedesctiptor gerFD() throws IOException;
    Public natice long getfilepointer() throws IOException;
    Public native long length() throws IOException;
    Public native int read() throws IOException;
    Public int read(byte b[]) throws IOException;
    Public int read(byte b[], int off, int len) throws IOException;
    Public final Boolean readBoolean() throws IOException;
    Public final byte readByte() throws IOException;
    Public final char readChar() throws IOException;
    Public final double readBouble() throws IOException;
    Public final float readfloat() throws IOException;
    Public final void readfully (byte b[]) throws IOException;
    Public final void readfully (byte b[], int off, int len) throws IOException;
    Public final int readint() throws IOException;
    Public final String readling() throws IOException;
    Public final long readlong() throws IOException;
    Public final short readshort() throws IOException;
    Public final int readusignedByte() throws IOException;
    Public final int readusingnedShort() throws IOException;
    Public final string readUTF() throws IOException;
    Public native void seek(long pos) throws IoException;
    Public native void setlength (long newlength) throws IoException;
    Public int skipBytes (int n) throws IOException;
    Public void write(byte b[]) throws IOException;
    Public void write(byte b[]), int off, int len) throws IOException;
    Public native void write(int b) throws IOException;
Public final void writeBoolean(Boolean v) throws IoException;
    Public final void writeByte (int v) throws IOException;
    Public final void writeBytes (String s) throws IOException;
    Public final void writeChar(int v) throws IOException;
    Public final void writeChars(String s) throws IOException;
    Public final void writeDouble (double v) throws IOException;
    Public final void writeFloat (float v) throws IOException;
    Public final void writeInt (int v) throws IOException;
    Public final void writeLong (long v) throws IOException;
    Public final void writeShort (int v) throws IOException;
    Public final void writeUTF (String str) throws IOException;
    }
    In terms of organization, the class can be viewed simply as implementing the two interfaces DataInput and DataOutput. Class RandomAccessFile does not add much functionality deyond the methods defined in these two interfaces. Here is the definition for interface DataOutput;
Public interface DataOutput extends Object {
Public abstract void write(byte.b[]) throws IOException;
Public abstract void write(byte b[], int off, int len) throws IOException;
Public abstract void write(int b) throws IOException;
Public abstract void writeBoolean(Boolean v) throws IOException;
Public abstract void writeByte(int v) throws IOException;
Public abstract void writeBytes(String s) thows IOException;
Public abstract void writeChar(int v) throws IOException;
Public abstract void writeDouble(double v) throws IOException;
Public abstract void writeFloat(float v) throws IOException;
Public bastract void writeLong(long v) throws IOException;
Public bastract void writeShort(int v) throws IOException;
Public abstract void writeUTF(String str) throws IOException;
}
The DataOutput interface specifies a list of output (writing) methods that allow you to write any kind of simple Java type. It also requires all implementing classes to be able to write bytes or blocks or bytes. Outputting objects, beyond String, is supported by the more advanced ObjectOutput interface, discussed later in this chapter. The exact bitstream produced by these methods sould not concern you because a symmdetrical inteface (DatabInput) specifies the equivalent reading methods that allow you to read back any data written out.
Here is the definition for the companion DataInput interface:
Public interface dataInput extends object   {
Public abstract Boolean readBoolean() throws IOException;
Public abstract byte readByte() throws IOException;
Public abstract char readChar() throws IOException;
Public bastract double readDouble() throws IOException;
Public abstract float readFloat() throws IOException;
Public abstract void readFully(byte b[]) throws IOException;
Public abstract void readFully(byte b[], int off, int len) throws IOException;
Public abstract int readInt() throws IOException;
Public abstract long readLong() throws IOException;
Public abstract short readShort() throws IOException;
Public abstract int readUnsignedByte() throws IOException;
Public abstract int readUnsignedShort() throws IOException;
Public abstract String readUTF() throws IOException;
Public abstract int skipBytes(int n) throws IOException;
}
Some of the asymmetrical differences of the two interfaces are the skipBytes() method, the unsigned number reading methods, and the readLine() method instead of the writeBytes()/Chars() methods. In actuality, the two interfaces really are each other’s opposites. Class RandomAccessFile, then, if you look back at its definition, is mainly the implementation of these two interfaces. The following are the main additional methods in RandomAccessFile:
Void seek(long pos) throws IOException
Long getFilePointer() throws IOException
Long length() throws IOException
Void close() throws IOException
Void setLength( long newLength) throws IOException;
There is no open() method because constructing a RandomAccessFile object opens the file for you. The seek() method is the method that reflects the class’s random-access reading and writing capability. Using seek(), you can position the file pointer to any position within the file to read or write in any place. You are not limited to sequential reads or writes (although that is what the reading and writing methods default to). Method getFilePointer() lets you find out where the next read or write will occur. For a newly opened file, it is always position 0; in other words, the beginning of the file. The setLength() method is good for truncating a file, when newLength <length()If newLength > length(), the new contents are undefined.

By now, you have noticed the universal exception type used by class Random-AccessFile (and the DataInput and DataOutput interfaces), which signals a failure within any of its methods: exception IOException. The explicit throws clause at the end of every method’s signature means you are required to either:

    Add explicit error-handling code to methods that use RandomAccessFile by enclosing uses within a try-catch pair.
Let the exception bubble up to the caller of your method by declaring your methods to throw IOException in turn.
As an example of using this class, including the explicit handling of possible exceptions, the following program uses two RandomAccessFile objects to compare two files:

Import java.io.*;
Public class Diff  {
//_______________________
// program main()
//
//check command-line argument (filename)
//open & load files
// process files
// close files
//________________________
public static void main (String args[])  {
RandomAccessFile fh1 = null;
RandomAccessFile fh2=null;

Int    bufsize;        //size of smallest file
Long filesize1 = -1;
Long filesize2 = -1;
Byte buffer1[];    //the two file caches
Byte buffer2[];

// check what you get as command-line arguments
if (args.length == 0 || args[0].equals(“?”)  {
System.err.printIn (“File Diff v1.2 © 06/98 L. Vanhelsuwe”);
System.err.printIn (“_____”);
System.err.printIn (“USAGE: java Diff <file> <file2>  | ?”);

System.err.printIn ();
System.exit(0);
}
// open file ONE for reading
try {
fh1 = new RandomAccessFile (args[0], “r”);
filesize1 = RandomAccessFile (args[0], “r”);
filesize1 = fh1.length();
} catch (IOException ioErr)  {
System.err.printIn (“Could not find “ + args[0]);
System.err.printIn (ioErr);
System.exit(100);
}
//open file TWO for reading
try {
fh2 = new RandomAccessFile (args[1], ‘r’);
filesize2 = fh2.length();
} catch (IOException ioErr)  {
System.err.printIn (“Could not find “ + args[1]);
System.err.printIn (ioErr);
System.exit(100);
}
if (filesize1 !=filesize2)  {
System.out.printIn (“Files differ in size !”);
System.out.printIn (“1” + args[0] + “’ is “ + filesize1 + “ bytes”);
System.out.printIn (“1” + args[1] + “’ is “ + filesize2 + “ bytes”);
}
// allocate two buffers large enough to hold entire files

bufsize = (int) Math.min(filesize1, filesize2);
buffer1=new byte [bufsize];
buffer2=new byte [bufsize];

try {
fh1.readFully (buffer1, 0, bufsize);
fh2.readFully (buffer2, 0 bufsize)

// now the HEART of the program…
for (int I= 0; I < bufsize; I++)  {
if (buffer1[I] ! = buffer2 [I])  {
System.out.printIn (“Files differ at offset  “ + I);
Break;
}
}
} catch (IOException ioErr)  {
System.err.printIn (“ERROR: An exception occurred while processing the files”);
System.err.printIn (ioErr.toString());
} finally {
try {
fh1.close();
fh2.close();
} catch (IOException ignored)  {}
}
}
}

The program uses a performance-enhancing trick that is often useful when processing files. If buffers the entire files in memory by reading them, in one swoop, using readFully(). This technique can be much quicker than reading a file bit by bit in a loop. Once the two files are cached in momory, they can be compared very quickly using simple array access (the nearest Java gets to the even more efficient pointer addressing of C and C++).
Remember the I/O method invocations need to be surrounded by try-catch statements. Because Java (quite rightly) insists that programs catch potential exceptional circumstances or events, you must explicitly add error-handling code for thos occasions. The alternative would be to declare the main() method as being able to throw an IOException itself. While this strategy would have made the example easier to read, it would not be good programming practice. The main() method is the topmost method, and any exceptions it throws will be thrown straight into the user’s face. This is not acceptable, so you should opt to catch the errors explicitly and translate them into more user-friendly error messages (instead of erroneous behavior!).
Because exceptions can seriously disturb an algorithm’s programmed flow of control (exceptions are essentially goto statements), you need to ensure both files are closed under all circumstances. You do this in the finally statement at the end of the main() method. Regardless of whether any exceptions occurred, the code within the finally statement will always execute so that statement is the perfect place to put you file close() calls.

Java’s I/O Stream-Manipulation Methods
The invention of streams is surprisingly recent, dating back to 1984 when Dennis Ritchie (who co-designed the C language with Brian Kernighan) implemented the first stream I/O system for AT&T’s Unix operating system. Software streams are linear flows of data. As with real rivers of water, users can come upto a stream and sequentially fish out (in other words, read) items floating toward them, or they can throw items into the stream (that is, write) in the secure knowledge that the items will be carried to a known destination at the end of a stream.
Every stream has either a data source (like a spring), in the case of input streams, or a destination (called a sink, like a river’s delta), in the case of output streams. Both input and output streams, therefore, have the need to be connected to something before they will do any useful work. Input streams should be connected to some device producing data, and output streams should be connected to some device that can accept data.
The package java.io consists mostly of stream, reader, and writer I/O classes. Stream input and output classes manipulate bytes; readers and writers manipulate characters (recall that in Java, unlike C, a character is two bytes). The package defines four root classes from which most of the package’s stream subclasses are derived. Not surprisingly, they are InputStream, OutputStream, Reader, and Writer. Study these abstract classes before tackling any of the concrete stream classes; all stream classes rely on the fundamental functionality of the superclasses.

Input Streams and Readers
All input streams can read bytes of data from some kind of data source. Their core functionality is reading data in the form of bytes (andonly bytes). This reading can be done on a byte-by-byte basis or in blocks or arbitrary length. All other functionality encapsulated in InputStream is peripheral to this elementary reading functionality. Here is the full definition of class InputStream.

Public abstract class InputStream extends Object  {
Public InputStream();
Public int available() throws IOException;
Public void close() throws IOException;
Public synchronized void mark(int readlimit);
Public Boolean markSupported();
Public abstract int read() throws IOException;
Public int read(byte b[]) throws, IOException;
Public int read(byte b[], int off, int len) throws IOException;
Public synchronized void reset() throws IOException;
Public long ski[9long n) throws IOException;
}
    The three mark-related methods-mark(), reset(), and markSupported()- deal with an optional input stream support for undoing read() methods. All input streams should implement markSupported() but are free to return either true or false. Most return false, meaning that mark() and reset() don’t do anything (or throw exceptions). Abstract class InputStream itself implements markSupported() to return false, so all classes that inherit from InputStream without overriding this method do not support marks.
    When the mark feature is supported, the system works as follows: You can mark any position (in an input stream) to come back to later if you want to undo the reading of data that has been read since the mark was placed. The readLimit argument to the mark() method determines how far you can read ahead while still legally being able to reset() the reading position to the marked position. The readlimit is expressed in bytes. It is used to internally allocate a buffer for all the data that potentially needs to be unread. If you read past the readlimit and still do a reset(), the results are undefined.
    A whole collection of concrete classes descends from class InputStrem:
FileInputStream
ByteArrayInputStream
StringBufferInputStream
SequenceInputStream
PipedInputStream
ObjectInputStream
FilterInputStream
    BufferInputStream
    DataInputStream
    LineNumberInputStream
    PushbackInputStream
    All of these classes have one thing in common (apart from being subclasses of InputStream): All of their constructors let you specify a data source in one way or another. In the case of the FileInputStream, ByteArrayInputStream, StringBufferInputStream, SequenceInputStream, objectInputStream, and pipedInputSteram classes, this data source is the attribute that differentiates that class from the others in the list. A FileInputStream, for example, is just that because the data stream that flows from it is sourced from a file that is part of your machine’s filing system. In the same way, a PipedInputStream is just that because the stream that flows from it is sourced from a pipe (a pipe is a mechanism that allows two different processes to communicate). And so on….
    All the FilterInputStream descendants have a very different purpose. Their constructors also allow you to specify a data source, but this is in the form of another input stream as the source for the stream. However, if that were all FilterInputStreams could do, there would be little point in them; they would simply pass on the data unmodified. However, the purpose of FilterInputStreams is not to connect to any specific data source (like the previous classes) but to enchace streams. Streams can be enchanced either by altering the stream’s data itself (for example, by compressing it) or by adding handy features to the minimal functionality enshined in class InputStream.
    The abstrect Reader class is very similar to InputStream. Here is its definition:
Public abstract class Reader extends object {
Public abstract void close() throws IOException;
Public void mark(int readAheadLimit) throws IOException;
Public Boolean markSupported();
Public int read() throws IOException;
Public int read(char cubf[]) throws IOException;
Public abstract int read(char cubf[], int off, int len) throws IOException;
Public boolean read() throws IOException;
Public void reset() throws IOException;
Public long skip(long n) throws IOException;
}

    The difference between readers and input streams is that readers manage characters while input streams manage bytes. Reader has the following subclasses:
FileReader
CharArrayReader
StringReader
PipedReader
InputStreamReader
FilterReader
    BufferedReader
    LineNumberReader
    PushbackReader
    Readers, like input streams, have various possible data sources, such as files and strings. The filter subclasses take other readers as their data sources and modify the source’s characters. Most (but not all) of the input stream classes have corresponding reader classes.
FileInputStream and FileReader
    Class FileInputStream is an input stream whose data is sourced from an everyday file. As such, you could consider it ad (nearly) half of class RandomAccessFile, which allows you to read and write files. You could use two fileInputStream objects to implement the featured file difference program with equal ease. The constructions for class FileInputStream are what the class really adds to the abstract class InputStream:
    Public FileInputStream(File File) throws FileNotFoundException
    Public FileInputStream(File Desctiptor fd) throws FileNotFoundException
    Public FileInputStream(string name) throws FileNotFoundException
    These constructors create a new FileInputStream object and, at the same time, open the file, ready for reading. The first constructor takes a filename as a String, but you should avoid doing this if the filename has any platform-dependent characters in it. For example, a filename of abc\def would work fine on a Windows platform but would fail on a Unix machine.
    The second constructor is the one more commonly exployed. It takes a platform independent File object describing which file needs to be accessed.
    The constructors for FileReader are identical to those for FileInputStream:
Public FileReader(File file) throws FileNotFoundException
Public FileReader(FileDescriptor fd) throws FileNotFoundException
Public FileReader(String name) throws FileNotFoundException
    File input streams should be used only for reading byte-oriented data. For text files, file readers are preferred because reader classes support full 16-bit characters.
    Here is a program that uses the FileReaser class to read a text file and calculate its word frequencies;
Import java.io.*;
Import java.until.TreeMap;
Import java.until.Iterator;
Public class WC {
Public static void main (String args []) throws IOException {
    WordFrequencyCounter wfr;
    FileReader    LongText;
    StreamTokenizer    WordStream;
String    Word;
Int    tok;
If (args. Length !=1) {
System.err.println( “Usage: java WC <textfile>”);
System.exit(10);
}
wfr    = new wordFrequencyCounter();
LongText    = new FileReader (args[0]);
Wordstream    = new StreamTokenizer (longText);

// treat any punctuation as word delimiters
wordStream.whitespaceChars (‘!’, ‘@’(;
while ((tok = wordStream.nextToken()) != StreamTokenizer.TT_EOF) {
if (tok = StreamTokenizer.TT_WORD) {
word = wordStream.sval;
wfr.count (word);
}
}
Iterator it = wfr.keySet().iterator();
While (it.hasNext()) {
Word = (String) it.next();
System.out.pringln (wfr.frequency(word) + “ “ + word);
}
}
}
//----------------------------------------
class wordFrequencyCounter extends TreeMap {

// no consturctor needed; this class is just a fancy sorted tree
//------------------------------------
//first see if this word has already been encountered;
//if not, then create a fresh counter for it;
//otherwise, increment its counter
//-----------------------------------------------
public synchronized int count (String word) {
Integer counter;
Counter = (Integer get(word);
If (counter = null) {
Counter = new Integer(1);
} else {
counter = new Integer (counter.intvalue() + 1);
}
put (word, counter);
return counter.intvalue();
}
//----------------------------
// find out how many times this word has been encountered
//-----------------------
public synchronized int frequency (String word) {
Integer counter;
Counter = (Integer) get (word);
If (counter == null) {
Return 0;
} else {
return conter.intvalue();
}
}
} // End of class wordfrequencycounter
    The program consists of two classes: the main driver class WC (which stands for Word Counter, in case you were woundering) and a thoroughly reusable wordFrequencycounter class. The main class (WC) opens the file specified as a commandline argument by creating a FileReader object. It then passes that object stringht to another java.ioclass: StreamTokenizer.
    Class Stream Tokenizer takes a reader as an argument to its constructor and then allows you to have the stream tokenized. In this case, tokenized simply mans chopped up into its constituent words. The StreamTokenizer method next Token() divides the file stream up into words and makes the stream of words available via the StreamTokenizer instance variable sval (String value). The StreamTokenizer class is discussed in more detail later in the chapter.
    The individual words thus extracted from the stream are then passed on to the wordFrequencyCounter object, whose duty it is to keep track of which words have already been encountered and, if so, how many times. It keeps track by relying heavily on the functionality provided by class Treemap, part of package java.utill.
    A Java TreeMap implements a sorted map, or dictionary, data structure. Dictionaries consist of paired entries: the first half called the key and the second half called the value. The program uses a dictionary to track the number of occurrences of each word because dictionary keys cannot occur more than once. Therefore, the word itself is the key to the dictionary entry, with the count being the value of the entry. Although the word count need only be a humble integer, a Java TreeMap requires int) are not supported. That’s why you should use a heavyweight Integer object instead, to hold the counter. The main TreeMap methods are put (key, value) and get (key). Because the WordFrequencyCounter class extends TreeMap, it is able to use these methods unqualifies in other words action on itself (the this object reference is implied).
    There’s another interesting aspect to this program: To actually list every encountered word, along with its associated frequency, the program uses the iteration and sorting capability of TreeMap.
ByteArrayInputStream and StringBufferInputStream
    The ByteArrayInputStream and String BuggerInputStream classes are virtually identical. They both create input streams from strings of bytes. ByteArrayInputStream does this literally, from an array of bytes. StringBufferInputStream uses a String (and not a StringBuffer) as its array of bytes.
    Because Java strings are essentially arrays of Java chars (in other words, 16-bit wide Unicode characters), you might wonder how the resulting byte (input) stream is structures: low byte first or high byte first? Well, neither. StringBufferInputStream discards the high byte of the Unicode characters. Although this is fine for Java characters in the range 0 to 255, all other characters that make use of Unicode’s vastly expanded encoding space will lose information or be corrupted in the string-to-stream transformation.
    The following are the main constructors for the two classes:
    Public ByteArrayInputStream (byte bug[])
    Public StringBufferInputStream (String s)
    The two classes have one major but subtle difference. Neither class copies its respective input data into internal buffers. Therefore, in the case of ByteArrayInputStream, the source array might be modified by the client application at any time while the stream is being used. This type of conflict con be the source of bugs that are very hard to find. This problem cannot occur for StringBufferInputStreams, because the source String can never be modified “under the stream’s nose”. For this reason alone, it is safer to always convert a byte array that will be used as a stream into a string by using the string constructor String (byte array []) or String (byte array[], String encoding)
CharArrayReader and stringReader
    The charArrayReader and StringReader classes are the character-oriented counterparts of byte array input streams and string buffer input streams. The main constructors for these classes are:
    Public CharArrayReader (char chars [])
    Public StringReader (String s)
    As with the corresponding streams, there is a possible data-integrity probles. If a char array reader’s is modifies, the reader’s behavior could be unpredictable. This is not an issue with a string reader because the data source is an unchangeable string.
SequenceInputStream
Class SequenceInputStream allows you to seamlessly glue together two or more input streams to create one long, concatenated stream. (There is no corresponding reader class.) Whenever you read from such a “super” stream and an EOF (end of file) is encountered by one of the building block streams, class SequenceInput-Stream proceeds to the next stream in the list (without letting the EOF (a-1 returened by read ()). The constructors give you two ways of specifying the sequence of streams:
Public SequenceInputStream(InputStream sl, InputSteam s2)
Public SequenceInputStream(Enumeration e)
    The first form is convenient when you only need to gule two input streams together. The second form is more general in its ability to take an open-ended list of input streams. The required argument type is rather surprising, though. Stream[] list) to be the ideal way to specify an ordered list of InputStreams. Instead, a much fuzzier Enumeration object is expected. Since any Enumeration you might think you need to create a brand-new class that implements interface ever, there’s an easier workaround: Declare a simple vector in which you addElement() the sequence of InputStreams, and then use the Vector method elements() to get an Enumeration object that will do the trick.
PipedInputStream and pipedReader
    Pipes are another Unix invention. In fact, the concept is close to the stream concept, except that the application of pipes is less generic. Pipes are typically used when two different processes (or tasks or threads) need to communicate large(ish) amounts of data in a synchronized fashion.
    Remember from Chapter 8 that one of the most difficult aspects of using multiple threads is their synchronization. Few multithreaded systems can avoid the need, at one time or another, to have some threads rendezvous for whatever purpose. If that purpose is the exchange of data, pipes can cleanly solve the problem. A less technical example is the use of the vertical-bar character | (pipe) to chain together programs at the Unix or DOS command prompts. For example:

C:\> DIR | SORT | MORE
Creates two pipes, the first connecting the output of the DIR command to the input of the SORT command. The second pipe would similarly connect the output of SORT to the input of MORE. The result would be a directory listing that is sorted by the SORT utility before being displayed page by page.

ObjectInputStream
Object input and output streams support object serialization. With serialization, what you read or write is not a byte or an array of bytes, but an object and every-thing it references. This is certainly more complicated than writing any other kind of data. Many issues are involved, including security, data privacy, and class version management.
With serialization, an object can be stored outside the Java VM (Virtual Machine) that created it and restored later. For example, a painting program might represent its state as an object of a class (probably a quite complicated class) called Picture. When the user wants to save the painting, the program can open a file output stream and pass that stream to the constructor of an object output stream. Then, with a single method, the program can save the entire Picture, which can be written to the object output stream, through the file output stream and onto the disk. Later, perhaps in a different invocation of the painting program, an object input stream and a file input stream can restore the Picture object so that the user can continue working.
Serialization also palys an essential role in Remote Method Invocation (RMI), whereby a Java program can make a method call on an object running on a different machine. RMI must support passing method parameters to the remote object and returning return values to the caller. Parameters and return values might be objects; if this is the case, the RMI infrastructure uses object input streams and object output streams to serialize the data. All the serialization pieces are discussed together at the end of the chapter, while Chapter 25 discussed RMI in more detail.
InputStreamReader
The input stream reader was designed for converting byte-oriented situations to character-oriented situations. An input stream reader reads bytes from an input stream and converts them to characters, according to a mapping algorithm. The default mapping recognizes bytes as common ASCII characters and converts them to Java’s Unicode characters.
The constructor for the InputStreamReader class take an input stream as its data source:

Public InputStreamReader(InputStream src)

FilterInputStream and FilterReader
Classes FilterInputStream and FilterReader are the superclasses for the java.io classes BufferedInputStream, BufferedReader, DataInputStream, LineNumberInputStream, LineNumberReader, PushbackInputStream, and PushbackReader. FilterInputStream is pseudo-abstract, and FilterReader is genuinely abstract. The important point is that they are both for subsclassing not for instantiating.
The FilterInputStream class looks like this:

Public class FilterInputStream extends InputStream  {
Protected InputStream in;
Protected FilterInputStream (InputStream in)
Public int available() throws IOException;
Public void close() throws IOException;
Public synchronized void mark(int readlimit);
Public Boolean markSupported();
Public int read() throws IOException;
Public int read(byte b[]) throws IOException;
Public int read(byte b[], int off, int len) throws IOException;
Public booleab ready() throws IOException;
Public void reset() throws IOException;
Public long skip(long n) throws IOException;
}

BufferedInputStream and BufferedReader
Class BufferedInputStream enhances bare-bones InputStream by adding a buffer of bytes to InputStream, which usually improves reading performance significantly. BufferReader adds a buffer of characters to Reader. To demonstrate the speed-up, here’s a program that uses a vanilla FileReader to read in a while file, byte by byte.
Import java.io.*;
Import java.util.*;
Public class Unbuffered  {

Public static void main (String args[])  {
Reader reader;
Int ch;
System.out.printIn(“Start! “ + new Date());
Try {
Reader = new FileReader (args[0]);
While ((ch=reader.read())  ! = -1  {
// read entire file
}
} catch (IOException ioErr) {
System.err.printIn (ioErr.toString());
System.exit(100);
}
System.out.printIn (“Stop! “ + new Date());
}
}
When you run this program on a reasonably large file (for example, Windows 95’s COMMAND.COM, which is 92,870 bytes), it takes 16 seconds to simply read in every byte. Now if you change the Reader assignment line into the following two lines:
FileReader fr = new FileReader (args[0]);
Reader = new BufferedReader (fr);
The time has been reduced to less than three seconds! A five-fold improvement. Clearly, taking the trouble to “warap” unbuffered input streams up in an instance of a BufferedReader pays off handsomely. The exact performance gain is determined by the size of the buffer used by the BufferedReader object. While the example uses the default constructor (resulting in a default, but undefined, buffer size being used), you can explicitly set the buffer size, at constructor time, by using constructors with the following, predictable signatures:

Public BufferedInputStream (InputStream in, int size)
public BufferedReader (Reader in, int size)
Classes BufferedStream and BufferedReader are among the few standard java.io classes that implement the mark and reset mechanism.

DataInputStream
Remember the DataInput interface discussed earlier in the chapter as part of class RandomAccessFile? Well, there is the only other class that implements this interface: class DataInputStream. This RandomAccessFile/DataInputStream kindship also exists in theoutput branch of the java.io classes. Class DataOutputStream implements interface DataOutput, which was also implemented by RandomAccessFile. Therefore, there is data-format compatibility between data written by Rnadom-AccessFile and data read back in by DataInputStream, or, conversely, data written by DataOuptutStream can be read back via a RandomAccessFile. In practice, through, this cross-communication does not occur often because data will be written and read back using the naturally corresponding class, most often simply DataOutputStream and DataInputStream.
Here is the definition of class DataInputStream.
Public class DataInputStream extends FilterInputStream implements DataInput {
Public DatainputStream(InputStream in);
Public final static String readUTF(DataInput in) throws IOException;
Public final int read(byte b[]) throws IOException;
Public final int read(byte b[], int off, int len) throws IOException;
Public final boolean readBoolean() throws IOException;
Public final byte readByte() throws IOException;
Public final char readChar() throws IoException;
Public final double readDouble() throws IOException;
Public final float readFloat() throws IOException;
Public final void readFully(byte b[]) throws IOException;
Public final void readFully(byte b[], int off, int len) throws IOException;
Public final int readInt() throws IOException;
Public final long readLong() throws IOException;
Public final short readShort() throws IOException;
Public final int readUnsignedByte() throws IOException;
Public final String readUTF() throws IOException;
Public final int skipBytes(int n) throws IOException;
}


Output Streams and Writers
The second main hierarchy branch in package java.io consists of all stream and writer classes concerned with output. The roots for this branch are the classes OutputStream and Writer. Here is the full definition of class OutputStream.
Public abstract class OutputStream extends Object {
Public OutputStream();
Public void close() throws IOException;
Public void flush() throws IOException;
Public abstract void write(int b) throws IOException;
Public void write(byte b[]) throws IOException;
Public void write(byte b[], int off, int len) throws IOException;
}
The definition for Writer is nearly identical:
Public abstract class Writer extends Object {
Public Writer();
Public Writer(object lock);
public void close() throws IOException;
public void flush() throws IOException;
public abstract void write(int b) throws IOException;
public void write(byte b[]) throws IOException;
public void write(byte b[], int off, int len) throws IOException;
}
The second form of the constructor takes an object as an argument. When this form is used, the writer will synchronize its writing, flushing, and closing operations on the objects’ lock; this prevents competing threads from corrupting the writer’s data.
Output streams and writers are even simpler than input streams and readers in that they don ot support the mark/reset mechanism (it simply does not make sense for output). The core functionality is to be able tow rite bytes or characters one at a time or in blocks. The destination for this written data can be anything, in theory; in practice, the concrete destinations of files, byte arrays, and network connections are supported (the latter via java.net classes, discussed in Chapter 20). Because there is very little difference between output and input (apart from the direction of information flow), what follows is a condensed overview of the output stream and writer classes.

ByteArrayOutputStream and CharArrayWriter

The ByteArrayOutputStream and CharArrayWriter classes are the exact opposites of ByteArray InputStream and CharArrayReader. The classes provide for some extra methods above the minimal writer() methods defined by Output-Stream and Writer. Here is the full definition of ByteArrayOutput Stream:

Public class ByteArrayOutputStream extends OutputStream  {
Protected byte buf[];
Protected int count;
Public ByteArrayOutputStream();
Public ByteArrayOutputStream(int size);
Public synchronized void reset();
Public int size();
Public synchronized byte toByteArray()[];
Public String toString();
Public String toString(int hibyte);
Public String toString(String enc) throws UnsupportedEncodingException;
Public synchronized void write(int b);
Public synchronized void writeTo(OutputStream out) throws IOException;
}
The definition of CharArrayWriter is almost identical:
Public Classs CharArrayWriter extends Writer {
Public CharArrayWriter();
Public CharArrayWriter(int initialSize);
Public void close();
Public void flush();
Public void reset();
Public int size();
Public char toCharArray()[];
Public String toString();
Public void write(char c[], int off, int len);
Public void write(int c);
Public void write(String str, int off, int len);
Public void writeTo(Writer out) throws IOException;
}
After these classes have been written to, the data may be retrieved by calling toByteArray() (for a ByteArrayOutputStream) or toCharArray() (for a CharArrayWriter).

FilterOutputStream and FilterWriter
The FilterOutputStream and FilterWriter classes are the superclasses of the higher-level filtering output streams and writers. Like their input counterparts, they are supposed to be subclassed, not directly instantiated. The following is the definition of FilterOutputStream:
Public class FilterOutputStream extends OutputStream {
Public FilterOutputStream(OutputStream out);
Public void close() throws IOException;
Public void flush() throws IOException;
Public void write(byte b[]( throws IOException;
Public void write(byte b[], int off, int len) throws IOException;
Public void write(int b) throws IOException;
}
And here is the definition of FilterWriter:

Public abstract class FilterWriter extends Writer {
Public void close() throws IOException;
Public void flush() throws IOException;
Public void write(char cbuf[], int off, int len) throws IOException;
Public void write(int c) throws IOException;
Public void write(String str, int off, int len) throws IOException;
}

BufferedOutputStream and BufferedWriter
Buffering output can enhance writing performance in exactly the same way as buffering input enhances reading performance. The BufferOutputStream and BufferedWriter classes are the same as BufferedInputStream and Buffered-Reader, except they work with output. The following program highlights the difference a write buffer makes by writing a file without buffering and then writing a file buffering:

Import java.io.*;
Import java.util.*;
Public class BufferDiff {
Public static void main (String args[]) throws IOException  {
FileOutputStream    unbufStream;
BufferedOutputStream bufStream;
UnbufStream = /* a raw file stream */
New FileOutputStream(“test.one”);
BufStream = new BufferedOutputStream(
New FileOutputStream(“test.two”));
System.out.printIn (“Write file unbuffered: “ +
Time (unbufStream) + “ms”);
System.out.printIn (“Write file buffered: “ +
Time (BufStream   ) + “ms”);
}
static int time (OutputStream os) throws IOException  {
Date then = new Date();
For (int I=0; I<50000; I++)  {
Os.write(1);
}
os.close();
return (int)((new Date()).getTime() – then.getTime());
}
}
When run, the program produced the following statistics on my machine:
Write file unbuffered: 8190ms
Write file     buffered: 1370 ms
As you can see, the simple wrapping of a BufferedOutputStream object around the final destination stream (that is, the last stage in a chain of output streams) substantially improves write performance.

DataOutputStream
Class DataOutputStream implements the DataOutput interface, which was described earlier in the chapter in the discussion of class RandomAccessFile.
Basically, interface DataOutput specifies methods for saving (writing) every type of Java primitive type plus String. Although the exact representationof the types output this way is irrelevant, the reality is that DataOutputStream generates a binary stream; that is, output not interpretable by people.
When you need to keep external databases whose sizes are an issue, binary is usually the most efficient representation. Say your application manipulates large 3-D models. The definition for those models consists of large amounts of triplets (x,y,z), each of type double, plus extra data of various data types. Such models would probably best be saved in binary to conserve storage resources.

ObjectOutputStream
As explained in the discussion of ObjectInputStream, object input and output streams read and write entire objects. More precisely, they write the state of an object’s instance variables. This is a more complicated operation than you might guess. Some instance variables are themselves references to other objects, and they also must be written to an object output stream or read from an object input stream.
The process of writing out an object’s state is called serialization. Reading is an object’s state is called deserialization. Serialization and deserialization are useful in their own right; they are also essential for RMI, which allows method calls to be made on objects running on external machines. For more information about serialization and deserialization, see the “Object Persistence and Serialization” section later in this chapter.

Properties
Although the Properties class is not part of the java.io package (it is part of java.util), it is so closely related to I/O issues that it is discussed here. This class has the following definition:

Public class Properties extends Hashtable  {
Public Properties();
Public Properties(Properties defaults);
Public String getProperty(String key);
Public String getProperty(String key, String defaultValue);
Public void list(PrintStream out);
Public void list(PrintWriter out);
Public synchronized void load(InputStream in) throws IOException;
Public Enumeration propertyNames();
Public synchronized Object put(Object key, Object value);
Public synchronized Object SetProperty(String key, String value);
Public synchronized void store(OutputStream out, String header)
Throws IOException;
}
Class Properties is basically a Hastable with load() and save() methods added. These take input and output streams, respectively, as arguments, so you can send or receive your Properties objects to or from more than just an external file. You can think of a configuration file as a kind of dictionary, pairing configuration variables with their values.
    
Examples

        #1

import java.io.*;

import java.util.*;


class BuffTime
{

public static void main(String args[]) throws IOException
{

FileOutputStream fout1=new FileOutputStream("raj");

FileOutputStream fout2=new FileOutputStream("ram");

BufferedOutputStream bout=new BufferedOutputStream(fout2);


System.out.println("time taken for unbuffered is  "+time(fout1));

System.out.println("time taken for buffered is  "+time(bout));

bout.close();

fout1.close();

}


static int time(OutputStream os) throws IOException
{

Date start=new Date();

for(int i=1;i<=500000;i++)
os.write(65);

return( (int)( new Date().getTime()-start.getTime() ) );
}

}


#2

import java.io.*;
class SequenceEx
{
public static void main(String s[])throws IOException
{
FileInputStream fis1=new FileInputStream("first.dat");
FileInputStream fis2=new FileInputStream("second.dat");
SequenceInputStream sis=new SequenceInputStream(fis1,fis2);
int ch=sis.read();
while(ch!=-1)
{
System.out.print((char)ch);
ch=sis.read();
}
sis.close();
fis2.close();
fis1.close();
}
}




Object Persistence and Serialization
   
    Ordinarily, a Java object lasts no longer than the program that created it.  An object may cease to exist during run time if it is reaped by the garbage collector. ff it avoids that fate, it still dies when the user terminates the browser (for an applet) or the object's runtime envirom-nent (for an application).
    In this context, persistence is the ability of an object to record its state so it can be reproduced in the future, perhaps in another environment.  For example, a persistent object n-dght store its state in a file.  The file can then be used to restore the object in a different runtime enviroziimexit.  It is not really the object itself that persists, but rather the information necessary to construct a replica of the object.
    An object records itself by writing out the values that describe its state.  This process is known as serialization because the object is represented by an ordered series of bytes.  Java provides classes that write objects to streams and restore objects from streams.
    The main task of serialization is to write the values of an object's instance variables.  If a variable is a reference to another object, the referenced object must also be serialized.  This process is recursive; serialization may involve serializing a complex tree structure that consists of the original object, the object's object's objects, and so on.  An object's ownership hierarchy is known as its graph.

Criteria for Serialization

    Not all classes are capable of being serialized.  C)nly classes that implement the
Serializable or Externalizabl e interfaces successfully be serialized.  Both of these interfaces are in the java.io package.  An external object, which in practice is a type of output stream, can serialize a serializable object; an externalizable object must be capable of writing its own state, rather than letting the work be done by another object.

You can serialize any class as long as it meets the following criteria:
•    The class, or one of its superclasses, must implement the java.io.Seria1izable interface.
•    The class must participate with the writeObject() method to control data that is being saved and append new data to existing saved data.
•    The class must participate with the readObject() method to read the data that was written by the corresponding writeObject() method.
   
    If a serializable class has variables that should not be serialized, those variables must be marked with the transi ent keyword; then the serialization process will ignore them.

NOTE : Implementing write0bject( and readobject( ) methods and throwing the NotSerializableException will prevent serialization of an object.  The 0biectoutput Stream (or ObjectInputStream) will catch the exception and abort the process.

The Serializable interface
   
    The Serializable interface does not have any methods.  When a class declares that it implements Serializabl e, it is declaring that it participates in the serializable protocol.  When an object is serializable and the object's state is written to a stream, the stream must contain enough information to restore the object.  This must hold true even if the class being restored has been updated to a more recent (but compatible) version.

The Externalizable Interface
    The Externalizable interface identifies objects that can be saved to a stream but that are responsible for their own states. Then an externalizable object is written to a stream, the stream is only responsible for storing the name of the object's class; the object must write its own data.  The Externalizable interface is defined as:
   
public interface Externalizable extends Serializable
public void writeexternal (ObjectOutput out) throws IOException;
public void readexternal (ObjectInput in) throws IOException, ClassNotFoundException;
    An extemalizable class must adhere to this interface by providing a writeExternal() method for storing its state during serialization and a readExternal() method for restoring its state during deserialization.

Examples

#1



import java.io.*;

class myclass implements Serializable
{

int x1=20;

int x2=30;


myclass()
{

}


myclass(int p1,int p2)
{

x1=p1;

x2=p2;

}


void display()
{

System.out.println(x1);

System.out.println(x2);

}



public String toString()
{

return( "x1= " +x1+"x2=  "+x2 );

}


}



class serialex

{


public static void main(String args[]) throws Exception
{


myclass m1=new myclass(11,22);

myclass m2=new myclass();



FileOutputStream fout=new FileOutputStream("raj.obj");

ObjectOutputStream oos=new ObjectOutputStream(fout);

oos.writeObject(m1);

oos.writeObject(m2);

oos.close();


}


}


#2



import java.io.*;


class deserialex
{

public static void main(String args[]) throws Exception
{


myclass m1,m2;


FileInputStream fin=new FileInputStream("raj.obj");

ObjectInputStream ois=new ObjectInputStream(fin);


Object o=ois.readObject();

m1=(myclass)o;

o=ois.readObject();

m2=(myclass)o;


System.out.println(" deserialized first object is..."+m1);

System.out.println(" deserialized second object is..."+m2);

m1.display();

m2.display();


ois.close();

}

}



Networking


Java’s Networking Protocols: TCP/IP
Java’s view of networking means TCP/IP, and only TCP/IP. Novell, IBM, and DEC proprietary networking protocols do not make the grad-and quite rightly so, since TCP/IP is the only true “open” networking standard that links together the four corners of the globe, via the Internet.
TCP/IP stands for Transmission Control Protocol/Internet Protocol, the two data communication protocols on which the Internet relies for all its functionality. With the Internet, a whole collection of related protocols run on top of TCP/IP, using TCP/IP to communicte behind the scenes. SMTP (Simple Mail Transfer Protocol) and NNTP (Network News Transfer Protocol) are examples of two older (but still ubiquitous) protocols. The new kid on the block, HTTP (Hypertext Transfer Protocol), has become so much a part of the Internet, and therefore TCP/IP, that many people confuse the Web with the Internet.
IP: The Heart of Internet Data Communications
Whatever application protocol is used to implement an Internet service, IP lies at the heart of all Internet data communications. IP is a datagram protocol, which means transmitted packets of information (packets, for short) are not guaranteed to be delivered. IP packets also do not form part of a stream of related packets; IP is a connectionless protocol. EachIP packet travels on its own, like an individual letter ina postal network (or a guru looking for enlightenment).

Instead of writing down 32-digit long bitstrings, like 11001110110000110001011111010000, Internet addresses are almost always expressed in their humanreadable, textual form (for example, www.sybex.com). On the rarer occasions when the address need to be expressed numerically, these 32-bit IP addresses are written as four decimal bytes (for example, 192.31.32.225). The remainder of the header encodes a collection of fields, including the total packet length in bytes. Sixteen bits are allocated for this field, so an IP packet can be a maximum of 64KB long.

TCP: For Guaranteed Delivery
Since IP packets are never guaranteed to arrive at their destination, a higher-level protocol, TCP, provides a basic service that does guarantee delivery. TCP manages this by using IP as a building block.

Whereas IP is a connectionless datagram service, TCP presents a connection-oriented data stream service (like the telephone network). Before sending data via TCP, a computer needs to connect with the computer at the other end; only then can data be exchanged. Another difference is that the TCP protocol sends and receives arbitrary amounts of dat as one big stream of byte data. IP, on the other hand, is theoretically limited to sending a 65,536-byte packet, which would be insufficient for sending many files or even many large GIF images embedded in Web pages. TcP solves this problem by breaking up the user’s data stream into separate IP packets, numbering them, and then reassembling them on arrival. Thisis the function of the sequence number and sequence acknowledge number fields.
The most important TCP header fields, from a user’s standpoint, are the source and destination port fileds. While IP allows you to send an IP packet to an individual machine on the network, TCP forces you to refine this addressing by adding a TCP ports (or sockets).
A large collectionof standard port numbers has been defined. Table 20.1 shows some port addresses for familiar Internet services; for example, port 21 is universally used for file transfers using FTP (File Transfer Protocol), and port 80 is used for all communications with World Wide Web HTML servrs. In later examples, you will talk to port 25 on your Internet provider’s machine to send e-mail, and to port 80 of any Web server in the world to request a Web page to be transmitted to you.

Port Name    Port Number    Service Description
Echo    7    Echoes whatever you send to it
Discard    9    Discards whatever you send to it
Daytime    13    Produces the dstination machine’s local time
Qotd    17    Produces the “quote of the day” for that machine
Charge    19    Produces a test stream of characters (character generator)
ftp-data    20    FTP data port
ftp    21    FTP control port
telnet    23    Telnet protocol port
smtp    25    SMTP port
finger    79    Finger protocol port
http    80    Web server port
pop3    110    POP version 3 port
nntp    119    NNTP port

The majority of application-level TCP/IP protocols (like SMTP for e-mail transfer) rely on TCP, not IP, to achieve their functionality. This is because they invariably need guaranteed or error-free transmission of unlimited amounts of data.
One more low-level IP protocol, besides TCP, builds on IP to achieve its functionality: UDP (User Datagram Protocol). UDP is a datagram protocol with the same 64KB packet-size limit of IP, but it also allows port addresses to be specified. In fact, every machine has two sets of 65,536 ports to communicate through: one for TCP and one for UDP. The TFTP (Trivial File transfer Protocol) protocol does the equivalent of FTP, but over UDP communications. Instead of the TCP dealing with problems like dropped packets, TFTP does. The end result is still the transfer of a file.
Now that you have reviewed some TCP/IP basics, you are ready to explore the core java.net package classes.


Internet Addressing
One of the java.net clsses allows you to manipulate a 32-bit IP address (that is, an Internet host address) in a more high-level fashion than by just using a single 32-bit integer. Class InetAddress essentially lets you convert a textual Internet address of the form host.subdomain.domain into an object representing that address.

Here is the definition for class InetAddress:
Public final class Inetaddress extends Object
Implements Serializable {
Public static InetAddress[] getAllByName (String host)
Throws UnknownHostException;
Public static InetAddress getByName (String host)
Throws UnknownHostException;
Public static synchronized InetAddress getLocalHost()
Throws UnknownHostException;
Public Boolean equals (Object obj);
Public byte[] getAddress();
Public String getHostAddress();
Public String getHostName();
Public int hashCode();
Public Boolean isMulticastAddress();
Public String toString();
}
The class deviates from the object-oriented norm by not providing a constructor and relying instead on static class methods, getByName() and getAllByName(), to create InetAddress instances. These methods take as their argument the textual address of any host on the Internet, in the form of a String. You can also turn the Internet address of your own machine (localhost) into an InetAddress by calling InetAddress.getLocalHost().
To experiment with the InetAddress methods, and most other java.net methods and classes, you need to have your machine online. That is, you need to be connected to a live TCP/IP network, if not the Internet itself. One of the reasons for this is that the java.net classes need to be able to do full domain name lookups via the Domain Name System (DNS). You already learned that Internet addresses are encoded as 32-bit integers within the IP packets exchanged on the Internet. Mnemoric addresses like www.miningco.com or web.mit.edu are used only for your benefit, and they must be translated to 32-bit addresses for any real Internet communication to be initiated based on those addresses.

Looking Up a Textual Address
Method getByName() in class InetAddress is the transparent interface to the DNS service. When you invoke getByName(), your machine will contact the DNS server “directly” (using its numeric address) and ask to look up and return the numeric address for the textual address you passed to getByName(). If your machine is not online, this lookup mechanism will fail, and an UnknownHostException will java.net classes), unless you are looking up your own machines’ IP address, Passing your machine’s name as a string.

Communicating with Remote Systems
Now that you know how to specify an Internet destination using instances of class InetAddress, how do you actually communicate with a remote system? Package jave.net provides several ways.

Low-Level Communication Using UDP
The most basic method of communicating with a remote system is to use UDP datagram. A UDP dtagram is embodies in an instance of class DatagramPacket:

Public final class DatagramPacket extends Object  {
Public DatagramPacket (byte buf[], int length);
Public DatagramPacket(byte buf[], int offset, int length);
Public DatagramPacket (byte buf[], int length, InetAddress addr, int port);
Public DatagramPacket (byte buf[], int offset, int length,
InetAddress addr, int port);
Public synchronized InetAddress getAddress();
Public synchronized byte[] getData();
Poublic synchronized int getLength();
Public synchronized int getOffset();
Public synchronized int getPort();
Public synchronized void setAddress (InetAddress addr);
Public synchronized void setData (byte buf[]);
Public synchronized void setData (byte buf[], int offset, int length);
Public synchronized void setLength (int length);
Public synchronized void setPort (int port);
}
Class DatagramPacket provides four constructors: two to receive datagram and two to transmit datagrams. With both sets of constructors, you need to specify a byte buffer and its length (the buf array can be bigger than length, but not smaller). The transmitting constructors additionally need the destination machine and port number for the datagram (in each of these constructor’s case, the byte buffer contains the message).
As you can see, the class does not actually give you the means for sending or receiving any datagrams. This functionality is the responsibility of a companion class, class DatagramSocket:

Public final class DatagramSocket extends Object  {
Public DatagramSocket() throws SocketException;
Public DatagramSocket (int port) throws SocketException;
Public DatagramSocket (int port, InetAddress laddr) Throws SocketException;
Public void close();
Public InetAddress getLocalAddress();
Public int getLocalPort();
Public synchronized int getReceiveBufferSize() throws
SocketException;
Public synchronized int getSendBufferSize() throws SocketException;
Public synchronized int getSoTimeout() throws SocketException;
Public synchronized void receive (DatagramPacket p) throws IOException;
Public void send (DatagramPacket p) throws IOException;
Public synchronized void setReceiveBufferSize(int size)
Throws SocketException;
Public synchronized void setSendBufferSize(int size)
Throws SocketException;
Public synchronized void setSoTimeout (int timeout)
Throws SocketException;
}



Examples

import java.net.*;
import java.io.*;

class EchoClient
{
     public static void main(String[] a) throws Exception
     {
               Socket client=new Socket("localhost",9001);
               DataInputStream stdin=new DataInputStream(System.in);
               DataInputStream fromserver=new DataInputStream(client.getInputStream());
               PrintStream toserver=new PrintStream(client.getOutputStream());
        while(client!=null)
        {
    System.out.print("Client : ");
                  String clientmsg=stdin.readLine();
                   toserver.println(clientmsg);
               if(clientmsg.equals("bye"))
    break;             
                         String clientinp=fromserver.readLine();
       
                         System.out.println("\nEcho from Server : "+clientinp+"\n");
              }
                    fromserver.close();
                    toserver.close();
                    client.close();
     stdin.close();
     }
}
         
#2

import java.net.*;
import java.io.*;

class EchoServer
{
     public static void main(String[] a) throws Exception
     {
    ServerSocket ss=new ServerSocket(9001);
               Socket server=ss.accept();
               DataInputStream fromclient=new DataInputStream(server.getInputStream());
               PrintStream toclient=new PrintStream(server.getOutputStream());
               DataInputStream stdin=new DataInputStream(System.in);
          while(server!=null)
          {   
                  String serverinp=fromclient.readLine();
    if(serverinp.equals("bye"))
       break;
         System.out.println("\nEcho from client : "+serverinp+"\n");
    System.out.print("Server : ");
     String servermsg=stdin.readLine();
                         toclient.println(servermsg);
               }  
     stdin.close();
                    toclient.close();
                    fromclient.close();
                    server.close();
     }
}
         

#3

import java.net.*;
import java.io.*;

class EchoServer
{
     public static void main(String[] a) throws Exception
     {
    ServerSocket ss=new ServerSocket(9001);
               Socket server=ss.accept();
               DataInputStream fromclient=new DataInputStream(server.getInputStream());
               PrintStream toclient=new PrintStream(server.getOutputStream());
               DataInputStream stdin=new DataInputStream(System.in);
          while(server!=null)
          {   
                  String serverinp=fromclient.readLine();
    if(serverinp.equals("bye"))
       break;
         System.out.println("\nEcho from client : "+serverinp+"\n");
    System.out.print("Server : ");
     String servermsg=stdin.readLine();
                         toclient.println(servermsg);
               }  
     stdin.close();
                    toclient.close();
                    fromclient.close();
                    server.close();
     }
}
  
#4
import java.net.*;
import java.util.*;

class TimeServer
{
     public static void main(String arg[]) throws Exception
     {
          DatagramSocket ds=new DatagramSocket(9002);
          byte[] b=new byte[50];
          DatagramPacket dp=new DatagramPacket(b,b.length);
          ds.receive(dp);
          InetAddress client_addr=dp.getAddress();
          int client_port=dp.getPort();
          String msg=new String(b);
          System.out.println("From Client : "+msg);
          Date d=new Date();
          String data=d.getHours()+":"+d.getMinutes()+":"+d.getSeconds();
          byte[] b1=data.getBytes();
          DatagramPacket dp1=new DatagramPacket(b1,b1.length,client_addr,client_port);
          ds.send(dp1);
          System.out.println("Packet Dispatched");
          ds.close();
     }
}

      

0 comments:

Post a Comment