Sunday, 31 May 2015

Java Importing packages

We discuss this concept with reference to previous example. Given that packages exist and are a good mechanism for compartmentalizing diverse classes from each other, it is easy to see why all of the built in Java classes are stored in packages.

There are no core java classes in the unnamed default package; all of the standard classes are stored in some named package.

Since classes within packages must be fully qualified with their package name or names, it could become tedious to type the long dot-separated package path name for every class you want to use. For this reason, Java includes the import statement to bring certain classes, or entire package into visibility. Once imported, a class can be referred to directly, using only its name.

Note: The import statement is a convenience to the programmer and is not technically needed to write a complete Java program. If you are going to refer to a few dozen classes in your application, however, the import statement will save a lot of typing.

In Java source file, import statements occur immediately following the package statement. (if it exists) and before any class/interface definitions.

The geneal form of import statement:

import pkg1 [.pkg2] [.pkg3].[classname | *];

Note: 

1. The star form may increase compilation time. However, the star form has absolutely no effect on the run-time performance or size of your classes.

2. All of the standard Java classes included with Java are stored in a package called java. The basic language functionality is stored in a package inside of the java package called java.lang. Normally, you have to import every package or class that you want to use, but since Java is useless without much of the functionalities in java.lang, it is implicitly imported by the compiler for all programs. This is equivalent to the following line being at the top of all of your programs:

import java.lang.*;

3. If a class with the same name exists in two different packages that you import using the star form, the compiler will remain silent, unless you try to use one of the classes. In that case, you will get a compile-time error and have to explicitly name the class specifying its package.

4. Any place you use a class name, you can use its fully qualified name, which includes its full package hierarchy. When a package is imported, only those items within the package declared as public will be available to non-subclasses in the importing code.

Java visibility of class members

Classes and packages are both means of encapsulating and containing the name space and scope of variables and methods. Packages act as containers for classes and other subordinate packages. Class act as container for data and method code. The class is Java’s smallest unit of abstraction. Because of the interplay between classes and packages, Java addresses five categories of visibility for class members:

1. Visibility within the class

2. Visibility in sub-classes in the same package

3. Visibility in non-sub classes in the same package

4. Visibility in sub-classes in different package

5. Visibility in classes that are neither in the same package nor are sub classes.

A top-level class or interface has only two possible access levels: default and public. When a class is declared public, it is accessible by any other code. If a class has default access, then it can only be accessed by other code within the same package.

The visibility of class members is summarized in the following table:


Note: The member visibility has meaning only if the class is visible. If visibility modifier of the class is default then even public members of the class will be visible only within the package.

Example:

Protection.java

package p1;

public class Protection

{

int n = 1;

private int n_pri = 2;

protected int n_pro = 3;

public int n_pub = 4;

public Protection()

{

System.out.println("Base Constructor");

System.out.println(n);

System.out.println(n_pri);

System.out.println(n_pro);

System.out.println(n_pub);

}

}

To compile: javac –d . Protection.java

Derived.java

package p1;

class Derived extends Protection

{

public Derived()

{

 System.out.println(n);

System.out.println("Derived Constructor");

//System.out.println(n_pri);

System.out.println(n_pro);

System.out.println(n_pub);

  }

}

To compile: javac –d . Derived.java

SamePackage.java

package p1;

class SamePackage

{

public SamePackage()

  {

Protection p = new Protection();

System.out.println("Same Package constructor");

System.out.println(p.n);

//System.out.println(p.n_pri);

System.out.println(p.n_pro);

System.out.println(p.n_pub);

}

}

To compile: javac –d . SamePackage.java

Protection2.java

package p2;

class Protection2 extends p1.Protection

{

Protection2()

{

System.out.println("Protection2 Constructor");

//System.out.println(n);

//System.out.println(n_pri);

System.out.println(n_pro);

System.out.println(n_pub);

}

}

To compile: javac –d . Protection2.java

OtherPackage.java

package p2;

class OtherPackage

{

OtherPackage()

{

p1.Protection p = new p1.Protection();

System.out.println("OtherPackage Constructor");

//System.out.println(p.n);

//System.out.println(p.n_pri);

//System.out.println(p.n_pro);

System.out.println(p.n_pub);

}

}

To Compile: javac –d . OtherPackage.java

Test1.java

package p1;

class Demo

{

public static void main(String args[])

{

Protection ob1 = new Protection();

Derived ob2 = new  Derived();

SamePackage ob3 = new SamePackage();

}

}

To Compile: javac –d . Test1.java

Output:

Base Constructor1234
Base Constructor1234
Derived Constructor134
Base Constructor1234
Same Package Constructor134

Test2.java

package p2;

class Demo

{

public static void main(String args[])

{

Protection2 ob1 = new Protection2();

OtherPackage ob2 = new OtherPackage();

}

}

To Compile: javac –d . Test2.java

Output:

Base Constructor1234
Protection2 Constructor
34
Base Constructor1234
OtherPackage Constructor
4

Java Packages

If no package name is specified in any java file then the class is part of the unnamed package. This requires that every class must have a unique name to avoid collisions. After a while, without some way to manage the namespace, you could run out of convenient descriptive names for individual classes.

You also need some way to be assured that the name you choose for a class will be reasonably unique and not collide with class names chosen by other programmers.

Java provides a mechanism for partitioning the class name space into more manageable chunks. This mechanism is the package.

The package is both a naming and visibility control mechanism.
You can define classes inside a package that are not accessible by code outside that package.
You can also define class members that are only exposed to other members of the same package.
This allows your classes to have intimate knowledge of each other, but not expose that knowledge to the rest of the world.

Defining a package

To create a package, include a package command as the first statement in a Java source file. Any classes declared within that file will belong to the specified package. The package statement defines a name space in which classes are stored. If you omit the package statement, the class names are put into the default package, which has no name and is called un-named package.

This is the general form of package statement:

package pkg_name;

Java uses file system directories to store packages. Remember that case is significant, and directory name must match the package name exactly. More than one file can include the same package statement.

You can create a hierarchy of packages. To do so, simply separate each package name from the one above it by use of a period. The general form of a multi-leveled package statement is shown here:

package pkg_name1 [.pkg_name2] [.pkg_name3];


A package hierarchy must be reflected in the file system of your Java development system.

For example a package declared as:

package java.awt.image;

needs to be stored in java/awt/image, java\awt\image, or java:awt:image on your Unix, Windows, or Macintosh file system, respectively.

A global naming scheme has been proposed to use the reverse Internet domain names to uniquely identify packages.

For example the apache’s domain name is www.apache.org. So to store classes in package tomcat, preferably you should use the package hierarchy:

org.apache.tomcat

which would be unique.

A package hierarchy represents an organization of Java classes and interfaces. It does not represent the source code organization of the classes and interfaces. Each Java source file (also called compilation unit) can contain zero or more definitions of classes and interfaces, but the compiler provides a separate class file containing the Java byte code for each of them. A class or interface can indicate that its java byte code be placed in a particular package, using a package declaration.

At most one package statement can appear in a source file, and it must be the first statement in the unit.

Note that this scheme has two consequences. First, all classes and interfaces in a source file will be placed in the same package. Secondly, several source files can be used to specify the contents of a package.

Finding packages and CLASSPATH

As discussed, packages are mirrored by directories. This raises an important question. How does the Java run-time system know where to look for packages that you create?

There can be two approaches:

First, by default, the Java run-time system uses the current working directory as its starting point. Thus, if your package is in the current directory, or a subdirectory of the current directory, it will be found.

Second, you can specify a directory path or paths by setting the CLASSPATH environment variable. For example, consider the following package specification:

package mypack;

In order for a program to find mypack, one of the two things must be true. Either the program is executed from a directory immediately above mypack, or CLASSPATH must be set to include the path to mypack.

Jar File

If you are developing a complex system or using third party libraries then instead of creating a directory hierarchy for class files you can use .jar files by including them in the CLASSPATH.

The JVM searches for the packages and classes in .jar file as it does searches in the file system.
Instead of .jar file you can also use a .zip file created by any popular software like winzip, winrar etc. Jar files can be created using jar utility that is part of JDK. To include the current directory and all the sub-directories below it in a jar file give the following command:

jar -cf myjar.jar *

here, c stands for creating a new .jar file.

         f stands for name of the .jar file.

The above command will create myjar.jar file in the current folder.

Example:

package mypack;

public class MyProg

{ public static void main(String args[])

{ System.out.println("Yes, Its working!");

}

}

To compile the following program give following command:

C:\totest>javac -d . MyProg.java

Here -d is used to create a directory ‘mypack’ in the current folder and put the class file in this folder automatically. When we compile the program, ‘mypack’ directory is created in the current folder (which is assumed to be c:\totest).

We can run above program in following different ways:

1. Running from the current directory: 

Give the following command from the directory where the package directory is created i.e from folder c:\totest.

java mypack.MyProg

This is because, MyProg file is part of package mypack.

Output:

Yes, Its working!

2. Running using classpath:

Give the following command at the command prompt:

SET CLASSPATH = %CLASSPATH%;C:\totest;

Then give the following command from any directory/folder:

java mypack.MyProg

3. Running by specifying classpath as parameter

Give the following command:

 java –classpath c:\totest mypack.MyProg

4. Running using jar file: Go to C:\totest folder and give the following command:

 jar –cf myjar.jar mypack (or jar -cf myjar.jar mypack)

and then give the following command:

java -classpath c:\totest\myjar.jar mypack.MyProg

After creating the .jar file, you can also set the classpath as follows:

set classpath=%classpath%;c:\totest\myjar.jar

Note: you can use –d option to copy the class file in any desired folder. For example, use the following command to create folder ‘mypack’ in C:\myclasses:

javac –d C:\myclasses MyProg.java

This will create a folder mypack below myclassses, if not already present and put the MyProg.class file in it.

Java Abstract Classes

There are situations in which you will want to define a super class that declares the structure of a given abstraction without providing a complete implementation of every method. That is, sometimes you will want to create a super class that only defines a generalized form that will be shared by all of its subclasses, leaving it to each sub class to fill in the details. Such a class determines the nature of the methods that the sub classes must implement. One way this situation can occur is when a super class is unable to create a meaningful implementation for a method.

This is the case with the class Shape used in the preceding example. The definition of area() is simply placeholder. It will not compute and display the area of any type of object. When you create your own class libraries, it is not uncommon for a method to have no meaningful definition in the context of its super-class.

You can handle this situation in two ways: 

One way, as shown in the previous example, is to simply have it report a warning message. While this approach can be useful in certain situations- such as debugging. It is not usually appropriate. You may have methods, which must be overridden by the sub class in order for the sub class to have any meaning.

Consider the class triangle. It has no meaning if area() is not defined. In this case, you want some way to ensure that a sub class does, indeed, override all necessary methods.

Java’s solution to this problem is the abstract method. You can require that certain methods be overridden by subclasses by specifying the abstract type modifier. These methods are sometimes referred to as subclass responsibility because they have no implementation specified in the super class. Thus a sub class must override them – it can not simply use the version defined in the super class. To declare an abstract method, use this general form:

abstract return_type name(parameter-list);

As you can see, no method body is present. Any class that contains one or more abstract methods must also be declared abstract. To declare a class abstract, you simply use the abstract keyword in front of the class keyword at the beginning of the declaration.

There can be no object of an abstract class. That is, an abstract class can not be directly instantiated with the new operator. Such objects would be useless, because an abstract class is not fully defined. Also you cannot declare abstract constructors or abstract static methods. Any subclass of an abstract class must either implement all of the abstract methods in super class, or be itself declared abstract. Here, is a simple example of a class with an abstract method, followed by a class which implements that method.

Example:

1 abstract class Shape //abstract class

2 { double puCost = 100;

3 abstract double area(); //abstract method.

4 double calCost()

5 {  return puCost * area();

6 }

7 }

1 class Triangle extends Shape

2 {

3 double s1,s2,s3;

4 Triangle(double a, double b, double c)

5 {

6   s1 = a; s2 = b; s3 = c;

7 }

8 double area()

9 {

10 double s = (s1+s2+s3)/2;

11 return Math.sqrt(s*(s-s1)*(s-s2)*(s-s3));

12 }

13 }

1 class Rectangle extends Shape

2 { double s1,s2;

3 Rectangle(double a, double b)

4 {

5  s1 = a; s2 = b;

6 }

7 double area()

8 {

9 return s1 * s2;

10 }

11 }

1 class Square extends Shape

2 {

3 double s;

4 Square(double a)

5 {

6   s = a;

7 }

8 double area()

9 {

10 return s * s;

11 }

12 }

1 class ShapeTest1

2 { static public void main(String args[])

3     { //Shape s = new Shape();

4   Shape s1 = new Triangle(3,4,5);

5   Shape s2 = new Rectangle(3,4);

6   Shape s3 = new Square(3);

7   //System.out.println(s.area());

8   System.out.println(s1.area());

9   System.out.println(s2.area());

10   System.out.println(s3.area());

11   //System.out.println(s.calCost());

12   System.out.println(s1.calCost());

13   System.out.println(s2.calCost());

14   System.out.println(s3.calCost());

15 }

16 }

Output:

6.0
12.0
9.0
600.0
1200.0
900

Java Method Overriding and Dynamic Binding

Method Overriding

In a class hierarchy, when a instance method in a subclass has the same signature as an instance method (non-private) in its super class, then the method in the sub-class is said to override the method in the super-class. When an overridden method is called from within a sub-class, it will always refer to the version of that method defined by the sub-class. The version of the method defined by the super-class will be hidden.

Please not that the concept of overriding is applicable only for instance methods. Static methods cannot be overridden. It is not possible to override even an instance method if its visibility is private.

While overriding a method, we cannot decrease the visibility. The visibility of the method in the child class should be same or higher. The visibility of a method overriding a public method can be public only. The visibility of a method overriding a protected method can be protected or public. Similarly the visibility of a method overriding a method with the package visibility can be package, protected or public.

Dynamic Method Binding (Dynamic Method Dispatch or Run-time Binding) 

Method overriding forms the basis for one of Java’s most powerful concepts. Dynamic method dispatch is the mechanism by which a call to an overridden instance method is resolved at run time, rather than compile time.

Dynamic method dispatch is important because this is how Java implements run-time polymorphism.
A super-class reference variable can refer to a sub-class object. Java uses this fact to resolve calls to overridden methods at run time. When an overridden method is called through a super-class reference, Java determines which version of that method to execute based upon the type of the object being referred to at the time the call occurs.

Thus, this determination is made at run time, when different types of objects are referred to; different versions of an overridden method will be called.

In other words, it is the type of the object being referred to (not the type of reference) that determines which version of an overridden method will be executed.

Why Overridden Methods?

Overridden methods allow Java to support run-time polymorphism. Polymorphism is essential for OOP for one reason: It allows a general class to specify methods that will be common to all of its derivatives, while allowing sub classes to define the specific implementation of some or all of these methods.

By combining inheritance with overridden methods, a super-class can define the general form of method that will be used by all of its sub classes.

The ability of existing code libraries to call methods on instances of new classes without recompiling while maintaining a clean abstract interface is a profoundly powerful tool.

Example: The following example illustrates the concept of method overriding and dynamic binding.

1 class A

2 { int i,j;

3 A(int a, int b)

4 {

5 i = a; j = b;

6 }

7 void show()

8 {

9 System.out.println(i);

10 System.out.println(j);

11 }

12 }

1 class B extends A

2 { int k = 5;

3 B(int a, int b, int c)

4 {

5 super(a,b);

6 k = c;

7 }

8 void show()

9 { System.out.println(k);

10 }

11 }

1 class OverridingDemo1

2 { static public void main(String args[])

3 { B b = new B(1,2,3); b.show();

4     A a = b;

5     a.show();

6   }

7 }

Output:
3
3

Example: The following example illustrates that the overridden method of the super class can be invoked through super keyword.

1 class A

2 { int i,j;

3 A(int a, int b)

4 { i = a; j = b;

5 }

6 void show()

7 { System.out.println(i);

8 System.out.println(j);

9 }

10 }

1 class B extends A

2 { int k = 5;

3 B(int a, int b, int c)

4 {

5 super(a,b);

6 k = c;

7 }

8 void show()

9 { super.show(); //this call’s the A’s show()

10 System.out.println(k);

11 }

12 }

1 class OverridingDemo2

2 { static public void main(String args[])

3 { B b = new B(1,2,3); b.show();

4 A a = b;

5 a.show();

6 }

7 }

Output:

1
2
3
1
2
3

Here, super.show() calls the super class version of show().

Method overriding occurs only when the signature of the two methods are identical. If not, then the two methods are simply overloaded.

Example: The following example illustrates that the show() method in the sub-class does not override the show() method in the super-class as their signatures are different. The show() method is just overloaded.

1 class A

2 { int i,j;

3 A(int a, int b)

4 { i = a; j = b;

5 }

6 void show()

7 { System.out.println(i);

8 System.out.println(j);

9 }

10 }

1 class B extends A

2 { int k = 5;

3 B(int a, int b, int c)

4 { super(a,b);

5 k = c;

6 }

7 void show(String msg)

8 { System.out.println(msg + k);

9 }

10 }

1 class OverridingDemo3

2 { static public void main(String args[])

3   { B b = new B(1,2,3); b.show("Value of k: "); b.show();

4     }

5 }

Output:

Value of k:

3
1
2

Example:

The stack class defined earlier can hold only ten elements in the stack. We want a dynamic stack, which can hold any number of elements in the stack. We can rewrite the push() method of the existing class Stack or ExtStack. But the better alternative is to define another class by extending the Stack or ExtStack class and overriding the push() method. This will not affect any existing code, which is using Stack or ExtStack class. The push() method in the derived class will have exactly same signature as the push() method in the base-class but the body of the method will be different so as to implement the dynamic stack.

1 class DynamicStack extends ExtStack 

2 { public void push(int x)

3 { int b[];

4 if(top == a.length-1)

5 { b = new int[2*a.length];

6 for(int i = 0; i < a.length; i++)

7 b[i] = a[i];

8 a = b; //a now points to a new array of double size

9 }

10 top = top + 1;

11 a[top] = x;

12 }

13 }

The following program makes use of the overridden method push(). It is now possible to push any number of elements till the JVM has free memory.

1 class StackDemo2

2 { public static void main(String args[])

3 { DynamicStack s = new DynamicStack();

4 for(int i = 0; i < 10; i++)

5 { s.push(100+i);

6 }

7 for(int i = 0; i < 10; i++)

8 { s.push(100+i);

9 }

10 for(int i = 0; i < 10; i++)

11 { s.push(100+i);

12 }

13 s.display();

14 }

15 }

Example: It is possible to access the overridden method through base class reference. This can be achieved by creating object of sub-class and assigning its reference to a reference variable of base-class.

The following example demonstrates this concept. But a base-class reference can be used to access only features defined in the base-class even if it points to an object of the sub-class. If a reference of base-class actually points to an object of sub-class, you can typecast it to get sub-class reference and then use it to access the features, which are specific to the sub-class.

Following example demonstrates these concepts.

1 class StackDemo3

2 { public static void main(String args[])

3 { Stack s = new DynamicStack();

4 for(int i = 0; i < 10; i++)

5 { s.push(100+i);

6 }

7 for(int i = 0; i < 10; i++)

8 { s.push(100+i);

9 }

10 //boolean b = s.isStackFull();

11 //s.display();

12 DynamicStack ds = (DynamicStack) s;

13 boolean b = ds.isStackFull();

14 ds.display();

15 }

16 }

We have created an object of type DynamicStack and assigned the reference in a reference variable of type Stack, which is valid as it is up-casting and takes place implicitly as discussed above. But we can access only the features of the base-class through the reference of type Stack.

Hence the call to methods s.isStackFull() and s.display() are commented as they are not valid. But observe that call s.push() actually calls push() method of the sub-class as it is over-ridden. This is why we are able to insert more than 10 elements in the stack.

Finally, in this program reference of type Stack (s) is typecasted back to reference of type DynamicStack (ds). This is down-casting so explicit typecast is needed. Typecasting will be valid only if the referred object is of type DynamicStack. We can now call ds.isStackFull() and ds.display() methods.

Example: The following example illustrates that it is possible to write generic code using inheritance, method over-riding and dynamic binding features.

1 class Shape

2 { double puCost = 100;

3 double area()

4 { System.out.println("Area is not defined");

5 return 0;

6 }

7 double calCost()

8 { return puCost * area();

9 }

10 }

1 class Triangle extends Shape

2 { double s1,s2,s3;

3 Triangle(double a, double b, double c)

4 {  s1 = a; s2 = b; s3 = c;

5 }

6 double area()

7 { double s = (s1+s2+s3)/2;

8 return Math.sqrt(s*(s-s1)*(s-s2)*(s-s3));

9 }

10 }

1 class Rectangle extends Shape

2 { double s1,s2;

3 Rectangle(double a, double b)

4 {  s1 = a; s2 = b;

5 }

6 double area()

7 { return s1 * s2;

8 }

9 }

1 class Square extends Shape

2 { double s;

3 Square(double a)

4 {  s = a;

5 }

6 double area()

7 { return s * s;

8 }

9 }

1 class ShapeTest

2 { static public void main(String args[])

3 { Shape s = new Shape();

4   Shape s1 = new Triangle(3,4,5);

5  Shape s2 = new Rectangle(3,4);

6 Shape s3 = new Square(3);

7 System.out.println(s.area());

8   System.out.println(s1.area());

9   System.out.println(s2.area());

10   System.out.println(s3.area());

11   System.out.println(s.calCost());

12   System.out.println(s1.calCost());

13   System.out.println(s2.calCost());

14   System.out.println(s3.calCost());

15 }

16 }

Output:

Area is not defined
0.0
6.0
12.0
9.0
Area is not defined
0.0
600.0
1200.0
900.0

Note: If an object is derived from Shape, then its area can be obtained by calling area() method.
The interface to this operation is the same no matter what type of Shape is being used.