Saturday, 30 May 2015

Java Variables

Java has three kinds of variables:


  • Local variables
  • Instance variables
  • Static Variables


We have already discussed about local variables. Local variables are used inside blocks or methods. The other two types of variables (also referred to as data members) are defined within the class but outside any method/block.

1. Instance Variables

A class provides the data encapsulation by declaring the variables within the class definition. For example, in the class Box defined above, the variables width, height and length are instance variables. Instance variables are declared in the same way as local variables except that they are declared outside the methods.

An instance variable occupies the memory on the per-object basis. For example, if you create two objects of type Box using operator new then both the objects will have different set of variables corresponding to instance variables width, height and length.

Initialization

The instance variables are initialized as soon as the object is created i.e. as soon as the memory is allocated with the new operator. The variables are initialized according to their types as shown in
the following tables.

For example, as soon as an object of type Box is created, the instance variables width, height and

length are initialized to 0 (Zero).

Accessing Instance Variables

The dot (.) operator is used to access the instance variables. The general form for accessing the
instance variables using the dot operator is:

<Object Reference>.<Variable Name>

Where <Object Reference> is some reference variable pointing to an object and <Variable
Name> is the name of an instance variable. For example, after creating an object of type Box and
storing its reference in the reference variable box, we can access the instance variables using dot
operator as follows:

box.width box.height box.length

Thus the way of accessing instance variables is very similar to the way in which we access the
members of structures in C or C++. But there is one significant difference. In C/C++, we can
access structure members directly as well as through pointers. But in Java program, we never
have access to an object directly. We always access an object through its reference. Thus the dot
(.) operator of Java is like -> operator of C/C++.

We can assign values to instance variables just like local variables as shown below:

box.width = 10; box.height = 20; box.length = 30;

We can use instance variables in expressions as shown below:

double vol =  box.width * box.height * box.length;

We can display the values of the instance variables, just like local variables as shown below:

System.out.println(box.height);

Example: The following program demonstrates the concepts discussed till now.

1 class Box

2 { double width;

3 double height;

4 double depth;

5 public static void main(String args[])

6   { Box b = new Box();

7 double vol;

8 b.width = 10;

9 b.height = 20;

10 b.depth = 15;

11 vol = b.width * b.height * b.depth;

12 System.out.println("volume is " + vol);

13 }

14 }

Example: The following program provides the same functionality as the previous one but it uses
two classes: Box and BoxDemo. Here it is assumed that both the classes are defined in different
files: Box.java and BoxDemo.java. It is also possible to define both the Java classes in one file.

Box.java

1 class Box

2 { double width;

3 double height;

4 double depth;

5 }

BoxDemo.java

1 class BoxDemo

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

3    { Box b = new Box();

4 double vol;

5 b.width = 10;

6 b.height = 20;

7 b.depth = 15;

8 vol = b.width * b.height * b.depth;

9 System.out.println("volume is " + vol);

10  }

11 }

Compiling Box.java will generate Box.class file and compiling BoxDemo.java will generate
BoxDemo.class file. After compiling these two files you should run the BoxDemo class, because
it contains the main() method.
It is not necessary for both the Box and BoxDemo classes to be in the different source file. For
example, both the classes might be defined in the source file Box.java but compiling this file will
also generate two different classes: Box.class and BoxDemo.class.

Example: The pervious example is modified so that the classes Box.java and BoxDemo.java
belong to the package p1.

Box.java

1 package p1;

2 class Box

3 { double width;

4 double height;

5 double depth;

6 }

BoxDemo.java

1 package p1;

2 class BoxDemo

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

4 { Box b = new Box();

5 double vol;

6 b.width = 10;

7 b.height = 20;

8 b.depth = 15;

9 vol = b.width * b.height * b.depth;

10 System.out.println("volume is " + vol);

11 }

12 }

To run the above program you should put both the classes in folder p1 in the working folder and
then give the following command from the working folder (parent of p1):

java p1.BoxDemo

The folder p1 will be created automatically (if it does not exist), in the working folder, if you
compile the above java files using the command:

javac  -d . Box.java

javac  -d . BoxDemo.java

Example: The pervious example is modified so that the classes Box.java and BoxDemo.java
belong to package p1 and p2 respectively.

Box.java

1 package p1;

2 public class Box

3 { public double width; //instance variables

4 public double height;

5 public double depth;

6 }

BoxDemo.java

1 package p2;

2 import p1.*;

3 class BoxDemo

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

5    { Box b = new Box();

6 double vol;

7 b.width = 10; b.height = 20; b.depth = 15;

8 vol = b.width * b.height * b.depth;

9 System.out.println("volume is " + vol);

10   }

11 }

The folder p1 and p2 will be created automatically (if do not exist), in the working folder, if you
compile the above java files using the commands:

javac  -d . Box.java

javac  -d . BoxDemo.java

To run the above program you should give the following command from the working folder

(parent of p1 and p2):

java  p2.BoxDemo

Note that the class Box is declared public as it used in class BoxDemo that belongs to a different
package.  Similarly all the data members of the class Box are also declared public as they are
being accessed in class BoxDemo.

Also note that the class BoxDemo imports class Box so that it can use the class without
qualifying with the package name.

Example: Creating two instances of Box class
If you have two Box objects, each has its own copy of depth, width, and height. It is important to
understand that changes to the instance variables of one object have no effect on the instance
variables of another.

Box.java

1 class Box

2 { double width; //instance variables

3 double height;

4 double depth;

5 }

BoxDemo2.java

1 class BoxDemo2

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 b2.width = 3;

10 b2.height = 6;

11 b2.depth = 9;

12 vol = b1.width * b1.height * b1.depth;

13 System.out.println("volume is " + vol);

14 vol = b2.width * b2.height * b2.depth;

15 System.out.println("volume is " + vol);

16    }

17 }

2. Static Variables

Static variables are also declared outside methods/blocks like instance variables. But the static
variables make use of the modifier static before the data type. For example, the variable width in
the previous example can be made static variable if declared as:

static double width;

The static variables are global to a class and all of its instances (objects). They are useful for
keeping track of global states. For example, a static variable count in a class can store the
number of instances/objects of the class created in the program at any instance of time. The
objects can communicate using static variables just like C functions communicate through global
variables.

For static variables there is only one copy of the variable irrespective of number of instances/objects created in the program, which is shared across all the instances.

The dot (.) operator is used to access the static variables also. The general form for accessing the static variables using the dot operator is:

<Class Name>.<Variable Name>

Where <Class Name> refers to the name of the class in which the static variable is declared and
<Variable Name> is the name of a static variable. For example, if we declare the variables width,
height and depth as static then we can access them using dot operator as follows:

Box.width

Box.height

Box.length

We can also access the static variables through object reference and dot operator as follows but any reference will point to the same copy:

box.width

box.height

box.length

Example: The following example illustrates that for static variables there is only one copy of the
variable irrespective of number of instances/objects created in the program, which is shared across all the instances.

Initialization

The static variables are initialized as soon as the class is loaded/used. The variables are initialized with default values according to their types. The default values are same as those for instance variables.

Box.java

1 class Box

2 { static double width;

3 static double height;

4 static double depth;

5 }

BoxDemo.java

1 class BoxDemo3

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.width * b1.height * b1.depth;

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

15 vol = b2.width * b2.height * b2.depth;

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

17  }

18 }

Java assigning object reference variables

The following example explains what happens when we assign one object reference to another object reference.

Example: 

Box b1 = new Box();

Box b2 = b1;

You might think that b2 is being assigned a reference to a copy of the object referred to by b1. That is, you might think that b1 and b2 refer to separate and distinct objects. However, this would be wrong.

Instead, after this fragment executes, b1 and b2 will both refer to the same object. The assignment of b1 to b2 did not allocate any memory or copy any part of the original object. It simply makes b2 refer to the same object, as does b1. Thus, any changes made to the object through b2 will effect the object to which b1 is referring, since they are the same object.

Although b1 and b2 both refer to the same object, they are not linked in any other way. For example, a subsequent assignment of null to b1 will simply unhook b1 from the original object without affecting the object or b2:

Box b1 = new Box();

Box b2 = b1;

.

b1 =null;

Here, b1 has been set to null, but b2 still points to the original object.

Note: When you assign one object reference variable to another object reference variable, you are not creating a copy of the object, you are only making a copy of the reference.

Java Allocating Memory using Operator new

The memory for Java objects is always allocated dynamically with the help of new operator. For
example, an instance/object of the class Box can be created as follows:

Box box = new Box();

For the sake of understanding we can compare new operator with the malloc() of C. In the above
example, new operator will allocate memory for an object of class Box and return its reference, which is then assigned to reference type variable box. The reference type variable box will now refer to an object of type Box as shown below:

The new Operator


It is important to understand that new allocates memory for an object during runtime. Since memory is finite, it is possible that new may not be able to allocate memory for an object because in-sufficient memory exists. If this happens, a run-time error will occur.

Java Declaring Objects

You can declare object of class Box as follows:

Box box;

Normally we say that box is an object of type Box. This is correct in C++ but this is not fully correct in Java. Because box is simply a variable that can hold reference to an object of type Box.

This is like pointer to a structure in C/C++. The reference box will store garbage or null reference unless we assign reference of some object of class Box to it.

After the above declaration variable box will contain garbage or null reference as shown below:

This indicates that variable box is not pointing to any object.

If the variable box is defined in a method or block it will contain garbage, as local variables are not initialized by default. To make sure that it contains null unless some valid reference (conceptually same as pointer of C/C++) is assigned to it, you must declare and initialize the box as follows:

Box box = null;

If the above declaration of box is outside any method/block then it is an instance variable and there is no need not initialize it with null as an instance/reference variables are always initialized with null.

Java Access/Visibility Modifiers

Access/visibility modifiers control access to a class, interface, data member or method. There are four levels of visibility in Java:


  • public
  • protected
  • package
  • private

1. Access/Visibility Modifiers for Top-Level Classes.

Visibility of a top-level class can be either public or package.

public

The keyword public is the only modifier, which can be used with a top-level class. If a class is to 
be visible to all the classes irrespective of their package, then it must be declared as public by specifying the modifier public, which should appear before the keyword class.

package

There is no keyword package for visibility control. In the absence of any access/visibility modifier before the top-level class, its visibility is only within the package in which it is defined. The concept of package is somewhat similar to the concept of friend classes in C++.

2. Access/Visibility Modifiers for Data Members and Methods.

When used in the variable or method declarations, access/visibility modifiers control access to the variable or method i.e. they decide who can access the variables and methods. These modifiers are not applicable for local variables as their visibility/scope is anyhow limited to the method/block in which they are declared.

public

Any method or variable is always visible in the class in which it is declared. The instance methods of a class can access any other method (instance as well as static method) or variable (instance as well as static variable) declared in the class. Similarly a static method of a class can access any other static method or static variable declared in the same class. 

If a method or variable is to be visible to all the classes, then it must be declared as public by specifying the modifier public, which should appear before the data type. For example, main() method is always declared as public. The reason is that main() method is accessed by the code which is part of JVM i.e. it is outside the class in which main() method is declared. Similarly an instance or static variable can be declared public by specifying modifier public as shown below:

public float width;
public static float width;

A variable or method declared as public has the widest possible visibility. It can be accessed from any class.

private

If you want that a method or variable should not be visible outside the class in which it is declared then its access modifier should be private. We use this modifier to hide the variable or method so that it cannot be accessed from outside the class. 

A variable declared as private has the least possible visibility but it is the most commonly used modifier to encourage data encapsulation and data hiding.  

package 

There is no keyword package. In the absence of any access/visibility modifier before a data member or method, its visibility is only within the package in which it is defined.

protected

A variable declared as protected can be accessed from all the classes belonging to the same package as that of the class in which member is declared. This visibility is similar to the package scope. But in addition to this a protected member can be accessed from any child class irrespective of the package in which it is declared.

Example: A simple class Box is defined below.

1 class Box
2 {
3    double width;
4    double height;
5    double length;
6 }

Example: The class Box is redefined here to include one method volume().

1 class Box
2 {
3    double width;
4    double height;
5    double length;
6    void volume()
7    {
8        double vol = width * height * length;
9        System.out.println(vol);
10  }
11 }