Saturday, 30 May 2015

Java Recursive Methods

This feature is not specific to object-oriented languages. The concept is exactly same as in case of a procedural language. Using this feature a method can call itself.

Example: The following programs make use of the recursive method fact to calculate the factorial of a given positive integer.

1 class Factorial

2 { long fact (int n)

3 { if(n == 1)

4 return 1;

5 else

6 return n*fact(n-1);

7 }

8 public static void main(String args[])

9 { Factorial f=new Factorial();

10 System.out.println("Factorial of 4 = "+f.fact(4));

11 }

12 }

1 class Factorial

2 { static long fact (int n)

3 { if(n == 1)

4 return 1;

5 else

6 return n*fact(n-1);

7 }

8 public static void main(String args[])

9 { System.out.println("Factorial of 4 = "+fact(4));

10 }

11 }

Java Argument Passing Mechanism (call by value)

When a primitive type is passed to a method, it is done by use of call-by-value approach. In case of objects what is actually passed is an object reference. As a point of interest, an object reference is also passed by using call-by-value approach. However, since the value being passed refers to an object, the copy of that value will still refer to the same object that its corresponding argument does.

Example: The following example illustrates that Java uses call-by-value when passing primitive data types.

1 class Args1

2 { void swap(int a, int b)

3 { int t= a;

4 a = b; b = t;

5 }

6 public static void main(String args[])

7 { int x = 5, y = 7;

8 System.out.println("x = " + x + " y = " + y);

9 Args1 obj = new Args1(); obj.swap(x,y);

10 System.out.println("x = " + x + " y = " + y);

11 }

12 }

Output:

x = 5 y = 7

x = 5 y = 7

Example: The following example also illustrates that Java uses call-by-value when passing primitive data types.

1 class Args2

2 { static void swap(int a, int b)

3 { int t= a;

4 a = b; b = t;

5 }

6 public static void main(String args[])

7 { int x = 5, y = 7;

8 System.out.println("x = " + x + " y = " + y);

9 //Args2.swap(x,y);

10 swap(x,y);

11 System.out.println("x = " + x + " y = " + y);

12 }

13 }

Output:

x = 5 y = 7

x = 5 y = 7

Example: The following example illustrates that Java uses call-by-value even when passing reference types.

1 class Args3

2 { int a,b;

3 Args3(int x, int y)

4 { a = x;

5 b = y;

6 }

7 static void swap(Args3 ob1, Args3 ob2)

8 { Args3 t;

9 t = ob1;

10 ob1 = ob2;

11 ob2 = t;

12 }

13 public static void main(String args[])

14 { Args3  obj1 = new Args3(5,7);

15 Args3  obj2 = new Args3(4,6);

16 System.out.print("obj1.a = " + obj1.a + " obj1.b = " + obj1.b);

17 System.out.println(" obj2.a = " + obj2.a + " obj2.b = " + obj2.b);

18 swap(obj1,obj2);

19 System.out.print("obj1.a = " + obj1.a + " obj1.b = " + obj1.b);

20 System.out.println(" obj2.a = " + obj2.a + " obj2.b = " + obj2.b);

21 }

22 }

Output:

obj1.a = 5 obj1.b = 7 obj2.a = 4 obj2.b = 6

obj1.a = 5 obj1.b = 7 obj2.a = 4 obj2.b = 6

Example: The following example illustrates that although Java uses call-by-value when passing reference types but we can still modify the object referred to by the argument inside the called method, as what is actually passed is a reference.

1 class Args4

2 { int a,b;

3 Args4(int x, int y)

4 { a = x;

5 b = y;

6 }

7 static void swap(Args4 ob1, Args4 ob2)

8 { int x,y;

9 x = ob1.a; y = ob1.b; ob1.a = ob2.a; ob1.b = ob2.b;

10 ob2.a = x; ob2.b = y;

11 }

12 public static void main(String args[])

13 { Args4  obj1 = new Args4(5,7);

14 Args4  obj2 = new Args4(4,6);

15 System.out.print("obj1.a = " + obj1.a + " obj1.b = " + obj1.b);

16 System.out.println(" obj2.a = " + obj2.a + " obj2.b = " + obj2.b);

17 swap(obj1,obj2);

18 System.out.print("obj1.a = " + obj1.a + " obj1.b = " + obj1.b);

19 System.out.println(" obj2.a = " + obj2.a + " obj2.b = " + obj2.b);

20 }

21 }

Output:

obj1.a = 5 obj1.b = 7 obj2.a = 4 obj2.b = 6

obj1.a = 4 obj1.b = 6 obj2.a = 5 obj2.b = 7

Java Constructors

It is very common requirement to initialize an object immediately after creation. We can define instance methods for this purpose but they have to be invoked explicitly. Java has a solution for this requirement. Java allows objects to initialize themselves when they are created using constructors.

The syntax of the constructors is very similar to that of instance methods. They have the same name as the class and do not have any return type. This is because the implicit return type of a class’s constructor is the class itself. Constructors can be overloaded just like methods.

When operator new is used to create an instance/object of a class, JVM allocates memory for the object, then initializes the instance variables to their default initial values, and then calls the appropriate constructor to initialize the instance variables.

We have not explicitly used constructors so far. But every class has a default constructor that does not take any argument and its body does not have any statements. The compiler generates the default constructor automatically. The compilers stops generating default constructor as soon as you add your own constructor.

Note: The name constructor is a bit confusing. It appears as if the purpose of the constructor is to create an object/instance. The object is created and instance variables and static variables are initialized to their default initial values before constructor is called. So the purpose of the constructor is to initialize the instance variables after the object has been created.

1. Default Constructor

Example: The following program does not define any constructor so it uses the default constructor, which does not take any parameters.

1 class Box

2 { float width;

3 float height;

4 float depth;

5 public static void main(String args[])

6 { Box b = new Box();

7 float volume = b.width * b.height * b.depth;

8 System.out.println("Volume = " + volume);

9 }

10 }

The compiler would automatically generate the following default constructor while compiling the above program:

Box()

{

}

The output of the above program will be 0 (Zero) as constructor is not doing any initialization and default initial value of float type instance variables is 0 (Zero).

2. No Argument Constructor

You can replace the default constructor with your own no argument constructor. This will allow you to initialize the instance variables to any value.

Example: The following program defines a no argument constructor, which is called immediately after creation of object.

1 class Box

2 { private double width, height, depth; //data hiding

3 double volume()

4 { double vol = width * height * depth;

5 return vol;

6 }

7 Box() // No argument constructor

8 { System.out.println("Initializing Box");

9 width = 10;

10 height = 10;

11 depth = 10;

12 }

13 }

1 class BoxDemo7

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

3  { Box b1 = new Box();

4 Box b2 = new Box();

5 double volume = b1.volume();

6 System.out.println(volume);

7 volume = b2.volume();

8 System.out.println(volume);

9 }

10 }

The user-defined no argument constructor would be called immediately after the object creation and would initialize the values of the instance variables width, height and depth to 10. Thus the output of the above program would be 1000 instead of 0 (Zero).

3. Parameterized Constructors

The no argument constructor defined in the previous example is not of much use as it always initializes with the same value. A constructor, which can take parameters, will be more useful.

this keyword:

Sometimes a method will need to refer to the object that invoked it. To allow this, Java defines this keyword. It can be used inside any method to refer to the current object. That is, this is always a reference to the object on which the method was invoked. You can use this anywhere a reference to an object of the current class’s type is permitted. To better understand what this refers to, consider the following example.

Instance Variable Hiding

As you know, it is illegal in Java to declare two local variables with the same name inside the same or enclosing scopes. Interesting, you can have local variables, including formal parameter to methods, which overlap with the name of the class’s instance variables. However, when a local variable has the same as an instance variable, the local variable hides the instance variable.

This is why width, height, and depth were not used as the names of the parameters to the Box() constructor inside the box class. If they had been, then width would have referred to the formal parameter, hiding the instance variable width.

While it is usually easier to simply use different names, there is another way around this situation. Because this lets you refer directly to the object, you can use it to resolve any name space collisions that might occur between instance variables and local variables.

Example: The following program defines a parameterized constructor, which is used for initializing the object.

1  class Box

2  { private double width, height, depth; //data hiding

3 double volume()

4 { double vol = width * height * depth;

5 return vol;

6 }

7 Box(double w, double h, double d) //Parameterized constructor

8 { System.out.println("Initializing Box");

9 width = w; height = h; depth = d;

10 }

11 /* Box(double width,  double height, double depth)  //Parameterized constructor

12 { System.out.println("Initializing Box");

13 this.width = width;

14 this.height = height;

15 this.depth = depth;

16 }*/

17  }

1   class BoxDemo8

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

3   { Box b1 = new Box(10,20,15);

4 Box b2 = new Box(3,6,9);

5 double vol;

6 double volume = b1.volume(); System.out.println(volume);

7 volume = b2.volume(); System.out.println(volume);

8 }

9  }

The parameterized constructor allows you to initialize the box with any dimensions.

4. Overloading Constructors

It is possible to overload the constructor just like methods. For example, the constructor of class Box can be overloaded to initialize different types of boxes. If we have a cube then we need to pass just one argument as all the sides of the cube would be of same dimension.

Example: The following program makes use of overloaded constructor to create and initialize the different type of boxes.

1  class Box

2  { private double width, height, depth; //data hiding

3 double volume()

4 { double vol = width * height * depth;

5 return vol;

6 }

7 Box(double w, double h, double d)

8 { width = w; height = h; depth = d;

9 }

10 Box()

11 { width = -1; height = -1; depth = -1;

12 }

13 Box(double len)

14 { width = height = depth = len;

15 }

16 Box(Box ob)  // Copy Constructor

17 { width = ob.width; height = ob.height; depth = ob.depth;

18 }

19  }

1 class BoxDemo9

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

3  { Box b1 = new Box(10,20,15);

4 Box b2 = new Box();

5 Box b3 = new Box(5);

6 Box b4 = new Box(b1);

7 double vol;

8 vol = b1.volume();

9 System.out.println(vol);

10 vol = b2.volume();

11 System.out.println(vol);

12 vol = b3.volume();

13 System.out.println(vol);

14 vol = b4.volume();

15 System.out.println(vol);

16 }

17 }

Java Method Overloading

We can have more than one method with the same name as long as they differ either in number of parameters or type of parameters. This is called method overloading as discussed earlier.

While calling an overloaded method it is possible that type of the actual parameters passed may not match exactly with the formal parameters of any of the overloaded methods. In that case parameters are promoted to next higher type till a match is found. If no match is found even after promoting the parameters then a compilation error occurs.

Example: The following program overloads the method area() to find the area of a circle, square, rectangle and  a triangle.

1  class Area

2  { static final double PI = 3.1415;

3  static double area(double radius) //area of circle

4 { return PI * radius * radius;

5 }

6 static float area(float size) // area of square

7 { return size * size;

8 }

9 static float area(float length, float width) // area of rectangle

10 { return length * width;

11 }

12 static float area(float a, float b, float c) // area of triangle

13 { float s = (a+b+c)/2;

14 float  area = (float) Math.sqrt(s * (s-a) * (s-b) * (s-c));

15 return area;

16 }

17 public static void main(String a[])

18 { double carea = area(3.0); //Circle’s area() method is invoked

19 System.out.println(carea);

20 float sarea = area(3.0f); //Square’s area() method is invoked

21 System.out.println(sarea);

22 float rarea = area(3.0f,4.0f); //Rectangle’s area() method is invoked

23 System.out.println(rarea);

24 float tarea = area(3.0f,4.0f,5.0f); //Triangle’s area() method is invoked

25 System.out.println(tarea);

26 // next higher type matching with the parameter is float

27 float area = area(3);  //Squares’s area() method is invoked

28 System.out.println(area);

29 area = area(3,4);  //Rectangle’s area() method is invoked

30 System.out.println(area);

31 area = area(3,4,5);  //Triangles’s area() method is invoked

32 System.out.println(area);

33 }

34 }

Java Methods

Java methods are equivalent to C++ functions. Objects can communicate with each other using methods. Java’s methods can be classified in the two categories:


  • Instance Methods
  • Static Methods 


Just like static variables and instance variables, there are static methods and instance methods.

1. Instance Methods

The general form of an instance method is:

<return-type> <method-name> (parameter-list)

{

<method-body>

}

Method definition has four parts:


  • Name
  • Return Type
  • List of Parameters
  • Method Body

The return type can be a primitive data type or reference data type. In case, the method returns a 
reference, the return type will be the name of the class to which the object referred to by the returned reference belongs. It is must to declare the return type even if the method does not return any value. In this case, the return type should be declared as void.

The method’s formal parameters/arguments are specified within the parenthesis after the method name. The syntax is same as in C/C++.

The method body may contain any valid Java statement. If the method has a return type, then a value must be returned through return statement.

Invoking/Calling Instance Methods

The dot (.) operator is used to invoke/call the instance methods. The general form for calling the 

instance methods using the dot operator is: 

<object-reference>.<method-name>(paremeter-list)

Where <object-reference> is some reference variable pointing to an object and <method-  name> is the name of an instance method. For example, after creating an object of type Box and storing its reference in the reference variable b1, we can call the instance method  volume() using dot operator as follows: 

Box b1 = new Box();

b1.volume();

Instance methods can access the instance variables as well as static variables.

Example: The following program demonstrates how to call a instance method.

1 class Box 

2 { double width; //instance variables

3 double height;

4 double depth;

5 void volume() //instance method

6 { System.out.println("volume is:" + width * height * depth); 

7 }

8 }

1 class BoxDemo_4

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

3   { Box b = new Box();

4 b.width = 10; 

5 b.height = 20;

6 b.depth = 15;

7 b.volume();

8 }

9 }

In the main() method an instance of the class Box is created, its instance variables are initialized and then the instanced method is called. The instance method volume() calculates and displays the volume of the Box.

While accessing an instance variable inside main() method, we have used object reference. It is required, as we can not access an instance variable directly inside a static method. However, when an instance variable is accessed by a method that is defined in the same class as the instance variable, the instance variable can be referred directly. 

In fact we cannot specify the object reference in the method volume(), in the above example. This is due to the fact that unlike instance variables, there is only one copy of the instance methods. The instance methods use the copy of the instance variables of the object through which they are called. So the same method called through different object references will use different copy of the instance variables and hence the name instance method.

Implicitly an instance variable referred directly in a method uses this reference. For example, in the above program the direct reference to variables width, height and length is equivalent to this.width, this.height and this.length. The reference this inside a method refers to the current object (i.e. the object on which the method is called). The reference this is replaced by the reference of the invoking object at run-time. Hence the same instance method invoked through different objects will use different set of instance variables and hence will normally give different results.

Example: The following program demonstrates that calling non-static/instance method on different objects results in different output. 

1 class Box 

2 { double width; //instance variables

3 double height;

4 double depth;

5 void volume() //instance method

6 { System.out.println("volume is "+width*height*depth); 

7 }

8 }

1 class BoxDemo4

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

3   { Box b1 = new Box();

4 Box b2 = new Box();

5 b1.width = 10; b1.height = 20; b1.depth = 15;

6 b2.width = 3; b2.height = 6;  b2.depth = 9;
7 b1.volume();

8 b2.volume();

9   }

10 }

The first call to method volume() displays the volume of the box b1 correctly as 6000 and the 
second call to method volume() displays the volume of the box b2 as 162.

Method Returning a value

Example: The following program demonstrates use of method, which returns a value i.e. its 
return type, is not void.

1 class Box 

2 { double width;

3 double height;

4 double depth;

5 double volume()

6 { return width * height * depth; 

7 }

8 }

1 class BoxDemo5

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

3   { Box b1 = new Box();

4 Box b2 = new Box();

5 double vol;

6 b1.width = 10;

7 b1.height = 20;

8 b1.depth = 15;

9

10 b2.width = 3;

11 b2.height = 6;

12 b2.depth = 9;

13 vol = b1.volume();

14 System.out.println("Volume is : " + vol);

15 vol = b2.volume();

16 System.out.println("Volume is : " + vol);

17 }

18 }

Passing Arguments to Methods.

In the previous examples using class BoxDemo5, we initialized the instance variables directly to 
keep the things simple. This should not be done as it defeats the purpose of data encapsulation.

Moreover the instance variables can be made private so that they cannot be accessed from other 
classes. In that case it would not be possible to access the instance variables directly. The only 
alternative in that case is to define a method that takes width, height, and length as arguments 
and then initializes the instance variables.

Example: The following program defines two classes: Box and BoxDemo6. The class Box has a 
method that takes arguments. The classes may be defined in same source file or in two different 
source files. But in both the cases you will get two classes after compilation: Box.class and 

BoxDemo6.class. You can execute only class BoxDemo6.class as only this class has main() 
method. It also makes use of class Box for creating an instance/object and calling methods.

1. class Box

2. { private double width, height, depth; //data hiding

3. double volume()

4. { double vol = width * height * depth;

5. return vol;

6. }

7. void setDimensions(double w, double h, double d)

8. { width = w;

9. height = h;

10. depth = d; 

11. }

12. /* Instance Variable Hiding 

13. void setDimensions(double width,double height,double depth)

14. { width = width;

15. height = height;

16. depth = depth; 

17. }

18. */

19. /* Instance Variable Hiding 

20. void setDimensions(double width,double height,double depth)

21. { this.width = width;

22. this.height = height;

23. this.depth = depth; 

24. }

25. */

26. }

1 class BoxDemo6

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

3    { Box b1 = new Box();

4 Box b2 = new Box();

5 b1.setDimensions(10, 20, 30);

6 double volume = b1.volume();

7 System.out.println(volume);

8 b2.setDimensions(5, 10, 15);

9 volume = b2.volume();

10 System.out.println(volume);

11 }

12 }

You cannot access the instance variables of class Box though object reference in the class 
BoxDemo6 as instance variables are declared private. The private instance variables can be 
accessed only in the class in which they are declared.

Nesting of Instance Methods

One instance method can invoke the other instance method of the same class without qualifying 
i.e. by just specifying the method name. For example, in the following program, calCost() 
method, which is an instance method, can call the instance method area() of the same class 
simply by its name.

1 class Circle

2 { static final float  PI = 3.1415f;

3 float puCost; // say cost of painting unit area

4 float radius;

5 float area()

6 { return PI * radius * radius;

7 }

8 float calCost()

9 {

10 float cost = puCost * area();

11 return cost;

12 }

13 public static void main(String args[])

14 { Circle circle = new Circle();

15 circle.puCost = 100;

16 circle.radius = 3;

17 float area = circle.calCost();

18 System.out.println(area); 

19 }

20 }

2. static Methods 

The static methods can be accessed like static variables through the class name without creating 
any instance/object. The static methods can also be called using the object reference. The static 
methods can directly access only static variables irrespective of the fact that they are invoked 
through class name or object reference.

The general form of a static method is:

static <return-type> <method-name> (parameter-list)


<method-body>


The general form is same as that of a instance method with the only difference that the modifier 
static is used before the return type.

Invoking/Calling static Methods

Example: The following program demonstrates the use of static method. The method area() 
takes one argument representing the radius of the circle and calculates its area. The method area() does not use any instance variable so it is declared as static and can be invoked through class name without creating any instance/object.

1 class Circle

2 { static final float  PI = 3.1415f;

3 static float area(float radius)

4 { return PI * radius * radius;

5 }

6 public static void main(String args[])

7 { int r = 4;

8 float area = Circle.area(r); 

9 //float area = area(r); //Nesting of static methods 

10 System.out.println("Area: "+area); 

11 }

12 }

Here the static variable PI is declared to be constant by putting modifier before the type. This is 
equivalent to const of C/C++.

Nesting of Class Methods

One class method can invoke the other class method of the same class without qualifying i.e. by 
just specifying the method name. For example, in the above program main() method, which is 
static can call the static method area() of the same class simply by its name: 

float area = area(r);

This nesting can go to any depth.