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 }

Java defining a class

A Java class represents a user-defined data type. It acts like a template using which we can create multiple objects. The objects are like variables /instances of the data type represented by the class. To begin with you can think of a class as struct of C with the difference that a struct data type can have only data as members whereas the class can have data as well as methods as its members.

The general form of a class is

modifiers class <classname>
{
      <body of the class>
}

The body of the class can consist of data members as well as methods.
The general form is expanded below to show the fact that the class body can contain data members (variables) as well as methods.

modifiers class <classname>
{
modifiers type variable1;
modifiers type variable2;
.

.

modifiers type methodname1(parameter-list)
{
     <body of the method>
}

modifiers type methodname2(parameter-list)
{
     <body of the method>
}

.

.

}

Friday, 29 May 2015

Basic Concepts of OOP (Object-Oriented Programming)

Some of the essential elements of the object-oriented programming are mentioned below:


  • Abstraction
  • Objects and Classes
  • Three OOP Principle
                   Encapsulation
                   Inheritance
                   Polymorphism

  • Persistence
  • Genericity
  • Composition/Aggregation
1. Abstraction

The abstraction is one of the essential elements of any programming language including the procedural languages. The concept of built-in data type is also an abstraction. The feature of defining own data type using struct in C language further extends this abstraction.

The basic purpose of abstraction is to reduce complexity by hiding details. For example, people do not think of car as a set of hundreds of components. They think of it as a well-defined object having some unique properties and behavior.

Abstraction can be defined as an act for identifying the essential properties and behaviors of an object without going into details. The properties and behaviors of an object differentiate it from other objects of similar type and also help in classifying/grouping the objects.

The object-oriented programming languages model abstractions using classes and objects.

2. Objects and Classes

Object

An object is a physical or abstract entity or thing, which can be distinguished from other objects of similar types. An object has three characteristics:

(i) Identification
(ii) Properties (Attributes)
(iii) Behaviors (Methods/Operations/Functions)

The object can also be thought of as an instance of class, where class is like a built-in data type and object is a variable.

Class

A class represents a category of objects with similar properties and behaviors. A class can be thought of as a blueprint for creating objects. An object has the properties and behaviors defined by its class. The class can be thought of as a user-defined data type and object as a variable/instance of the data type represented by the class.

The properties/attributes of an object are defined by data members/fields in Java. A data member/field in a class is a variable that can hold data. The behaviors/operations of an object are defined using methods in Java. Both data members and methods are referred to as members of the class.

A class may also be thought of as a user-defined data type and an object as a variable of that data type. Once a class has been defined we can create any number of objects belonging to that class.

3. Three OOP Principles

3.1 Encapsulation

Encapsulation is the mechanism that binds code and data on which the code acts. Java classes support this as they allow us to define the code and data together. Encapsulation also helps in achieving data hiding by declaring some of the class members as private so that they cannot be accessed from the code that does not belong to the class.

3.2 Inheritance

In object-oriented programming, inheritance refers to the properties of a class being available to other classes called sub-classes or derived-classes. A sub-class or derived class is one that is derived from an existing class. It inherits all the features of the existing class which is also referred as the base-class or super-class. So inheritance can be defined as the process of deriving a class from a super-class or a base-class. Inheriting a class does not introduce any changes in the base-class/super-class. The derived-class/sub-class has a larger set of properties and behaviors as compared to the base-class.

The major advantage of the inheritance is code reusability. If the base class is in use for a long time and there is a need to add some extra attributes and methods, we can do so by deriving another class. The derived class will be able to use code of the base class without debugging as it is in use for a long time

Class Hierarchy

All the classes derived from a common base class belong to a family and form a class hierarchy. The class hierarchy can be compared with a tree structure where one base class is at the root and does not have a super-class. All other classes are either derived from the class at the root of the hierarchy or from some other class, which is derived from the root class directly or indirectly.

More features are added as we go down the tree. The classes that are represented by the leaf nodes do not have any sub-classes. The following examples show some class hierarchies.

Example 1: You can derive classes Saving Account and Current Account from the class Account. Here Account is the Base/Super Class and Saving Account and Current Account are Derived/Sub classes.

Example 2: The following diagram shows the classes derived from the Base class Vehicle.

3.3 Polymorphism

Polymorphism is a feature that allows same interface to be used for a general class of actions.

Most of the object-oriented languages use polymorphism in the following situations:

  • Operator Overloading
  • Method Overloading
  • Method Overriding

Operator Overloading

Most of the languages use this form of polymorphism for the built-in operations. For example, all the arithmetic operators in C/C++ or Java can be used with many types of operands (int, long, float, double etc.). So same addition operator can be used to add two integers as well as to add

two floating-point numbers. 

The C++ allows the user to overload the built-in operators. For example, you can overload the 

arithmetic operators to handle the complex numbers also. Although Java uses operator 

overloading for built-in operators but does not allow the user to overload the operators.

Method Overloading

This feature allows us to write more than one methods with the same name. Both C++ and Java have this feature. The methods (functions in C++) with same name are differentiated based on the parameters. The overloaded methods must either have different number of parameters or the types of the parameters must differ if their number is same.

If the call to an overloaded method can be resolved at compile time i.e. if the compiler can decide which of the overloaded method will be called then this is called static binding, which is an example of compile time polymorphism. 

If the call to an overloaded method cannot be resolved at compile time i.e. if the compiler cannot 
decide which of the overloaded method will be called then this is called dynamic binding, which 
is an example of run-time polymorphism. 

In general Java resolves calls to overloaded methods at run-time but there are many situations 
where the calls to overloaded methods are resolved at compile-time.

Method Overriding

The sub-class can define a method with the same name as in the super-class, and same number and type of parameters. This is called method overriding. 

The compiler can not resolve call to an overridden method. Java normally uses dynamic binding to resolve calls to overridden methods i.e. the decision takes place at run-time.

4. Persistence

Some object-oriented languages allow you to store/retrieve the state of a program to/from a persistent storage media i.e. a permanent storage media like secondary storage. This is called persistence.

Java allows you to store any object on the secondary storage and to retrieve it later on. If you attempt to store an object at the top of an object graph, all of the other referenced objects are recursively located and saved. Similarly when the object is retrieved later on, all of the objects and their references i.e. the entire object graph is correctly created in the main memory.

For example, it is possible to save an entire tree structure by just saving the root of the tree. At a
later stage it is possible to recreate the entire tree structure in the memory by just retrieving the root.
The C++ does not support this feature.

5. Genericity

The concept of defining an algorithm once, independently of any specific type of data, and then 
applying that algorithm to a wide variety of data types without any additional effort is called Genericity. 

C++ supports this feature using templates. Java also supports this feature through Object class, 
which is at the top of any class hierarchy in Java.

For example, using this feature, we can implement a generic data type stack so that it is possible 
to store element of any type in the stack.

This feature increases the degree of reusability to a large extent.

6. Composition/Aggregation

An object might be made up of other objects. Such an object is called Composite or Aggregate 
object. For example, it is appropriate if an object of class vehicle is defined as a composite object 
made up of objects like Engine, Body, Axle, Seats etc.

Inheritance v/s Composition

There are two basic mechanisms for deriving new classes from the existing ones: Inheritance and 
Composition. 

The class Bus can be derived by inheriting properties of class vehicle. Here Bus is a kind of vehicle which has some additional properties / behaviors beside the properties and behaviors which are common for all the vehicles. In other words class Bus has is-a relationship with the class vehicle as we can say that Bus is a vehicle.

The class vehicle itself might be derived from many other classes using composition. For example, an object of class vehicle might be composed of objects belonging to classes like Engine, Gear Box, Seats, Driver’s Seat, Body, Steering Wheel etc. The derived class in this case has whole-part relationship with the classes representing parts of the composite object. We can not say that Vehicle is an Engine or Vehicle is a Gear Box as Vehicle is made up of a number of parts.

Object-Oriented Programming v/s Procedural Programming

All the programs consist of two elements: process and data.  There can be two different approaches depending upon whether our main focus is on processing or data. The procedural programming languages (C, FORTRAN, PASCAL, COBOL etc.) focus on the processing part i.e. they give more importance to “what is happening” in the system and less importance to data.

The object-oriented languages (Java, C++) focus on the data i.e. they give more importance to “who is being affected”. The procedural approach becomes less and less suitable as the programs become large and complex. The object-oriented programming languages were developed to overcome the limitations of the procedural programming languages. The object-oriented programs are relatively far less complex as compared to the similar programs written in procedural languages.

Object-oriented programs are organized around data (i.e. objects) and a set of well-defined
interfaces (public methods) to that data. Java is based on object-oriented paradigm. Java is almost pure object-oriented programming language. We have used the term “almost” as Java also supports Primitive Data Types due to performance reasons. The C++ is not a pure object-oriented language. C++ is an extension to C so it uses an approach, which is a mix of procedure-oriented approach and object-oriented approach.

The basic differences in the two approaches are summarized below:

(i) The object-oriented programs are data centric while the programs written in procedural
languages are process centric.

(ii) The object-oriented programs are organized around data (objects) so they model the real
world objects in a better way.

(iii) The degree of reusability and extensibility of code is very high in case of object-
oriented approach as compared to procedural approach. So code size is less.

(iv) The object-oriented programs are easier to maintain, as they are relatively less complex
and smaller in size.

(v) The object-oriented programs are based on the bottom-up design methodology while
the procedural programs are based on the top-down design methodology.

Java return Statement

The return statement is used to immediately return control from a called method to the calling method.

The syntax of the return statement is as follows:

return;

or

return expression;

The first form of return statement is used to simply transfer control from the called method to the calling method. The second form returns control as well as returns a value to the calling method as specified by the expression following the return statement.

Java continue Statement

The general form of simple continue statement is:

continue;

The unlabeled continue statement can be used inside loops (for, while and do-while) only. It prematurely stops the current iteration of the loop body and proceeds with the next iteration, if possible.

In the case of while and do-while loops, the rest of the body is skipped and the execution continues with the loop condition. In the case of for loop, the rest of the body is skipped and the execution continues with the increment/decrement expression.

This is similar to continue statement in C/C++.

Example: The linear search program is rewritten to make use of the continue statement.

import java.util.*;

class LinearSearch

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

{ int n, x, a[]; boolean found = false; String number;

Buffered Reader in

= new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter the number of elements in the array: ");

number = in.readLine(); n = Integer.parseInt(number);

a = new int[n];

for(int i = 0; i < n; i++)// read the array elements

{ number = in.readLine();

a[i] = Integer.parseInt(number);

}

System.out.print("Enter the element to be searched in the array: ");

number = in.readLine(); x = Integer.parseInt(number);

int i = 0;

while(i < n && !found) // search the specified element

{

if(x = =  a[i]) // simple if statement

{

found = true;

continue;

}

i++;

}

if(found) // if-else statement

System.out.println("The number " + x + " is present in the list");

else

System.out.println("The number " + x + " is not in the list");
}
}

labeled continue Statement

The syntax of the labeled continue statement is as follows:

continue  <label>;

The labeled continue statement specifies the label of the enclosing loop to continue. The label need not correspond to the closest enclosing loop.

Example: The matrix search program is rewritten here to make use of the continue statement.

import java.util.*;

class SearchMatrix1

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

{

int i, j, x, row, col , matrix[][];  String number;  boolean found = false;

Buffered Reader in = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter the number of rows in the matrix: ");

number = in.readLine(); row = Integer.parseInt(number);

System.out.print("Enter the number of columns in the matrix: ");

number = in.readLine(); col = Integer.parseInt(number);

matrix = new int[row][col];

for(i = 0; i < row; i++) //enter one element in one line

{

System.out.println("enter the elements of row " + (i+1));

for(j = 0; j < col; j++)

{ number = in.readLine();

}

}

System.out.print("Enter the element to be searched in the matrix: ");

number = in.readLine();

x = Integer.parseInt(number);

outerloop: for(i = 0; i < row && !found; i++)

{ for(j = 0; j < col; j++)

{ if(matrix[i][j] == x)

{ found = true;

continue outerloop;

}

}

}

// break will transfer control to the following statement

if(found)

System.out.println("The number "+ x + " is present in the matrix");

else

System.out.println("The number " + x + " is not in the matrix");

}

}

Java Jump Statements

Jump statements are used for breaking the control flow. Java supports the following jump statements:

  • break
  • labeled break
  • continue
  • labeled continue
  • return
Beside this the constructs used for exception handling can also be put into this category but they are discussed in a separate chapter.

break Statement

The general form of simple break statement is:

break;

The unlabeled break statement can be used inside loops (for, while and do-while) and switch statements. It terminates the containing statement and transfers the control outside the closest enclosing loop or switch statement. The rest of containing statement body is skipped and the execution continues after the containing statement.

This is similar to break statement in C/C++. Refer to examples of simple-if statement and switch statement discussed above for the use of break statement.

labeled break Statement

The syntax of the labeled break statement is as follows:

break  <label>;

The labeled beak statement is used to terminate the block whose label is specified in the break statement. Unlike simple break statement, you can terminate any block. For example, it is possible to terminate the outermost loop from inside a deeply nested for loop.

The break statement can also be used to terminate a simple block (i.e. the block need not be a loop or switch statement)

Example: The following program searches for a given element inside a matrix (2-D array) and makes use of the labeled break statement to come out of the outermost for loop as soon as the element is found.

import java.util.*;

class SearchMatrix

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

{ int i, j, x, row, col , matrix[][];

String number;

boolean found = false;

Buffered Reader in

= new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter the number of rows in the matrix: ");

number = in.readLine();

row = Integer.parseInt(number);

System.out.print("Enter the number of columns in the matrix: ");

number = in.readLine();

col = Integer.parseInt(number);

matrix = new int[ row][col];

for(i = 0; i < row; i++) //enter one element in one line

{ System.out.println("enter the elements of row " + (i+1));

for(j = 0; j < col; j++)

{ number = in.readLine();

}

}

System.out.print("Enter the element to be searched : ");

number = in.readLine();

x = Integer.parseInt(number);

outerloop: for(i = 0; i < row; i++)

matrix[i][j]= Integer.parseInt(number);

{

for(j = 0; j < col; j++)

{

if(matrix[i][j] == x)

{ found = true;

}

 break outerloop;
}

}
}
if(found)

System.out.println("The number "+ x + " is present");

else

System.out.println("The number " + x + " is not present");
}
}

The use of labeled break statement in the above program is a substitute of the labeled goto statement of C/C++. This is a better alternative, as the program is more readable hence the labeled break is referred to as the civilized form of goto statement.

Java Iteration Statements (Loop Control Structure)

The Java supports the while, do-while and for iteration/loop control statements. The syntax is similar to C/C++. With JDK1.5, a second form of for was added that implements a “for-each” style loop.

while Statement

The general form of a while statement is:

while(condition)

loop body

Loop body may contain one or more statements. If loop body contains more than one statement then they must be enclosed between braces.

Example: The following program accepts one natural number say n as command line argument and then calculates and displays the sum of first n natural numbers.

class SumNaturalNumbers

{

public static void main(String a[])

{ int n, sum=0;

n = Integer.parseInt(a[0]); //command line argument

int i = 1;

sum = 0;

while (i <= n)

{

sum = sum + i;

i  = i + 1;

}

System.out.println("Sum of first " + n + " natural numbers is " + sum);

}

}

do-while Statement

The general form of a do-while statement is:

do

{

} while (condition)

loop body

Example: The following program accepts one integer number say n as command line argument and then calculates and displays the sum of its digits.

class SumOfDigits

{ public static void main(String a[])

{ int n, m, sum, digit;

n = Integer.parseInt(a[0]); //command line argument

m = n;

if(m < 0)

m = -m;

sum = 0;

do

{ digit = m % 10;

sum = sum + digit;

m = m / 10;

}while (m > 0);

System.out.println("Sum of digits of number " + n + " is: " + sum);

}

}

for Statement

The general form of a for statement is:

for(initialization; condition; increment/decrement)

loop body

Loop body may contain one or more statements. If loop body contains more than one statement then they must be enclosed between braces.

Example: The following program accepts one natural number say n as command line argument

and then calculates and displays the sum of first n natural numbers.

class SumNaturalNumbers1

{ public static void main(String a[])

{ int i, n, sum;

n = Integer.parseInt(a[0]); //command line argument

for(i = 1, sum = 0; i <= n; i++)

{

sum = sum + i;

}

System.out.println("Sum of first " + n + " natural numbers is " + sum);
}
}


Java Selection Statements (Decision Control Structure)

Java supports the following selection statements:

  • simple if Statement
  • if-else Statement
  • nested-if Statement
  • if-else-if Ladder
  • switch Statement

The syntax of these statements is same as in C/C++ so we will be discussing in details only if there is some difference from C/C++.

Simple if Statement

The syntax of the simple if statement is:

if (condition)
Statement;

if-else Statement

The syntax of the if-else statement is

if(condition)
   Statement1;
else
   Statement2;

Example: The following program illustrates the use of simple if statement as well as if-else statement. The program reads elements in an array of type int, followed by the element to be searched in the array using the linear search method. The program then displays the suitable message according to the search result.

import java.util.*;

class LinearSearch

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

{ int n, x, a[]; boolean found = false;

String number;

Buffered Reader in

System.out.print("Enter the number of elements in the array: ");

number = in.readLine();

n = Integer.parseInt(number);

a = new int[n];

for(int i = 0; i < n; i++) // read the array elements

{ number = in.readLine(); // enter only one element in one line

}

System.out.print("Enter the element to be searched in the array: ");

number = in.readLine();

x = Integer.parseInt(number);

for(int i = 0; i < n; i++) // search the specified element

{

}

if(found) // if-else statement

else

}

}

nested-if Statement

Any type of if statement may appear in the if or else part of another if statement. The rules for nesting are same as in C/C++. The following example illustrates the use of nested-if statement.

Example: The following program finds the largest among three given numbers.

import java.util.*;

class LargestOfThree

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

{ int a,b,c,max;  String number;

Buffered Reader in

System.out.print("Enter the first number : ");

number = in.readLine(); a = Integer.parseInt(number);

System.out.print("Enter the second number : ");

number = in.readLine(); b = Integer.parseInt(number);

System.out.print("Enter the third number : ");

number = in.readLine(); c = Integer.parseInt(number);

if(a > b)

else

System.out.println("Maximum among "+a+","+b+","+c+" is:"+max);

}

}

if-else-if Ladder

The syntax of the if-else-if ladder statement is as follows:

if(condition)
  Statement;
else if (condition)
  Statement;
else if (condition)
  Statement;
else
  Statement;

Example: The following program demonstrates the use of if-else-if ladder. The program reads

the weekday as an integer and displays corresponding weekday.

import java.util.*;

class DisplayWeekDay

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

{ int weekDay;

Buffered Reader in = new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter the day of week (1 to 7) : ");

number = in.readLine(); weekDay = Integer.parseInt(number);

if (weekDay == 1)

System.out.println("Sunday");

else if(weekDay == 2)

System.out.println("Monday");

else if(weekDay == 3)

System.out.println("Tuesday");

else if(weekDay == 4)

System.out.println("Wednesday");

else if(weekDay == 5)

System.out.println("Thursday");

else if(weekDay == 6)

System.out.println("Friday");

else if(weekDay == 7)

System.out.println("Saturday");

else

System.out.println("Valid values are from 1 to 7");

}

}

switch Statement

The switch statement is a multi-way branch statement. Its syntax is as follows:

switch(expression)

{ case label-1: Statement Sequence

case label-2 : Statement Sequence

[break;]

[break;]

case label-n: Statement Sequence

default: Statement Sequence

[break;]

[break;]

}

The syntax is same as in C/C++, with the following differences:

(i) In Java, switch expression can be any integer expression except long i.e. the type of the switch expression can be byte, short, char or int. But the Java’s int is of 4 bytes which is same as size of long in C/C++.

(ii) The case labels are constant expressions as in C/C++ but the values of the case labels must be in the range of the type of the switch expression otherwise the program will not compile. For example, if switch expression is of type byte then the valid values for case labels are from –128 to 127.

Example: The following program demonstrates the use of switch statement. The program reads the weekday as an integer and displays the corresponding weekday in character form.

import java.util.*;

class DisplayWeekDay1

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

{ int weekDay;

String number;

Buffered Reader in

= new BufferedReader(new InputStreamReader(System.in));

System.out.print("Enter the day of week (1 to 7) : ");

number = in.readLine();

weekDay = Integer.parseInt(number);

switch(weekDay)

{

case 1: System.out.println("Sunday");

case 2: System.out.println("Monday");

case 3: System.out.println("Tuesday");

case 4: System.out.println("Wednesday");

case 5: System.out.println("Thursday");

case 6: System.out.println("Friday");

break;

break;

break;

break;

break;

break;

case 7: System.out.println("Saturday");

break;

default:

System.out.println("Valid values are from 1 to 7");

}
}
}

Java Control Statements

Control statements are used to change the flow of execution. Java’s control statements can be classified into three categories:

  • Selection Statements (Decision Control Structure)
  • Iteration Statements (Loop Control Structure)
  • Jump statements

Most of the statements have same syntax as the corresponding statements in C/C++. However there are some significant differences:

(i) The conditional expressions used in the if, for, while and do statements must be valid boolean expressions i.e. their values should be either true or false. You cannot use 0 (Zero) instead of false or a non-zero value instead of true that is valid in C/C++.

(ii) Java does not have any goto statement although goto is a reserved word in the language. Java provides labeled break and labeled continue statements, which are often referred to as the civilized form of goto as they are supposed to be better substitutes of goto statement.

Thursday, 28 May 2015

Java Type Conversions during Assignments

Types of the left hand side variable and right hand side expression in an assignment may differ from each other as long as they are type-compatible with each other. For example all the primitive types excluding boolean are type-compatible with each other. When value of an expression is assigned to a variable, it should be converted to the type of the variable on the left hand side. The type conversion may take place automatically or we may have to convert the type explicitly using typecast operator.

Type conversions can be classified as:

  • Widening (or Broadening or UpCasting) Type Conversions
  • Narrowing (or DownCasting) Type Conversions
Widening Conversions

Widening conversion takes place when we assign a lower type expression to a higher type. There is no possibility of any data/precision loss in a widening conversion so it takes place implicitly/automatically.

Examples: The following examples will clarify this.

Suppose following variables are declared in a method/block:

int i ; byte b= 3; short s = 16; char c = 65; long l; float f; double d;

The following expressions are valid as widening conversion takes place automatically:

i  = b; l = s; f = b; d = c;

Narrowing Conversions


Narrowing conversion takes place when we assign a higher type expression to a lower type.

There is possibility of data/precision loss in a narrowing conversion. So normally a narrowing conversion does not take place implicitly/automatically. The programmer needs to explicitly typecast the higher type to lower type so that he/she is aware of the possibility of data/precision loss. However, there are some cases where even narrowing conversion takes place automatically.

Simple assignments always need explicit type conversion.

Examples: The following examples will clarify this.

Suppose following variables are declared in a method/block:

int i = 10 ; byte b; short s; char c; long l = 23; float f = 18.1f; double d = 5.77;

The following expressions are not valid, as narrowing conversions need explicit typecast:

b = i; s  = l; b = f; c = d;

To use these expressions you need to do explicit typecasting as follows:

b = (byte) i; s = (short) l; b = (byte) f; c = (char) d;

Java Arithmetic Expressions

Arithmetic expressions are formed by combining numeric types (constants, variables and expressions) using arithmetic operators. The basic concepts are same as in case of C/C++ although there are some differences.

1. Type Conversions in Expressions

Automatic type promotion takes place in arithmetic expressions according to the following rules:

  • An operand of type byte, short or char is always converted to int. This is true even if unary operator is used.  This implies that the type of the result will always be int or some higher type.
  • If the higher type between two operands is long the other is converted to long.
  • If the higher type between two operands is float the other is converted to float.
  • If the higher type between two operands is double the other is converted to double.
  • If both the operands are of same type (after byte, short  or char has been promoted to int) then no conversion takes place.
Examples: The following examples will clarify these rules.

Suppose following variables are declared in a method/block:

int i = 10; byte b= 3; short s = 16; char c = 65; long l = 100;

float f = 10.3f; double d = 4.88;

The following table demonstrates some expressions formed using above variables, their result type and the value calculated using the conversion rules defined above:

2. Integer Expressions

An Integer expression is one where all the operands are of integer type. The result of such an expression will always be integer as in case of C/C++. The fractional part is simply ignored. For example the result of expression 5/3 is 1.

While evaluating an integer expression, the following rules are applied:

1. An operand of type byte, short or char is converted to int before evaluation of the expression. This is true for unary as well as binary operators. So the operands will always be of type int or long.

2. While evaluating expressions the operators are applied according to precedence rules, which are same as in C/C++.

3. If both the operands of an operator are of type int then result will also be of type int.

4. If both the operands of an operator are of type long then result will also be of type long.

5. If one of the operands of an operator is of type int and the other is of type long then the int would be converted to long and the result will also be of type long.

Integer division including modulo (%) operator may result in an ArithmeticException (run time error).

Example: The following example illustrates what happens on division by zero.

class ZeroDivision
{
   public static void main(String args[])

  {
     int i;

     int x = 5;

      i = x / 0;  // x % 0 will also lead to exception.

      int y = i + 3;

      System.out.println(y);

  }

}

On execution of the above program, the following exception (run time error) occurs at statement

i = x/0; and the program terminates:

Exception in thread "main" java.lang.ArithmeticException: / by zero

        at ZeroDivision.main(ZeroDivision.java:5)

The reason is that division by zero is not defined in Java when both the operands are integer. In Java, it is possible to recover from a run time error and continue the execution. This is done by using exception-handling mechanism that will be discussed later.

Overflow in Integer Expressions

Except division no other integer calculations result in any exception although the result might be arithmetically incorrect. On evaluation of an operator (or complex integer expression), the result may be outside the range of the result data type. Such a situation is called overflow.  The actual result is obtained by truncating the extra bits in the result. For example, if the type of the result is
int and the result contains more than 32 bits, then 32 least significant bits in the result are kept and rest are simply truncated to obtain the result. Thus the result will not be correct and in some cases result may be of the wrong sign.

Example:

int tooBig = Integer.MAX_VALUE + 1;

MAX_VALUE is a static final constant defined in the class Integer. Its value represents the maximum positive value that can be stored in a variable of type int, which is, 2147483647. The result of the above expression will be of type int as both the operands are of type int. But the expression would lead to overflow as we are adding one to highest integer value.

In fact, on displaying value of variable tooBig, you will find that it holds the value -2147483648, which is the minimum value that an integer can hold.  The only solution to the overflow problem is to use higher data type i.e. use long type if you expect the result to exceed the limit of the int.

3. Floating-Point Expressions

These are the expressions involving floating-point types. A floating-point expression may also have integer types i.e. a mix of integer and floating-point types. If a floating-point expression has an operator whose both the operands are integer then its result will be calculated as per integer arithmetic rules. For example the expression 3.1 + 5/3 is a floating-point expression but its result will be 4.1 (3.1 + 1) and not 4.76 (3.1 + 1.66) as one might expect because the result of the expression 5/3 would still be int.

While evaluating a floating-point expression, the following rules are applied:

  • An operand of type byte, short or char type is converted to int before evaluation of the expression. This is true for unary as well as binary operators. So the integer operands will always be of type int or long.
  • While evaluating expressions the operators are applied according to precedence rules, whichare same as in C/C++.
  • If operands of an operator are of different types then the lower type operand will be promoted to the type of the higher type operand and the type of the result will be the higher type.
There are three special floating-point values infinity, minus infinity and not a number to represent out-of-range values.

In case of float type these values are represented by constants Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY and Float.NaN respectively defined in the class Float.

Similarly in case of double type these values are represented by constants
Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY and Double.NaN respectively defined in the class Double.

No exception occurs on division by zero as this is defined in case of floating point expressions.

The result of division by zero is either Infinity or –Infinity. Similarly no error occurs if the floating-point expression involves non-determinant forms like 0/0, 0/, /, /0, complex numbers etc. The result of such an expression is NaN (Not a Number).

Examples: 
The following code segments demonstrate the use of three special values.

(i) double d = 10.0/0;

System.out.println(d);

The output of the above println() statement would be Infinity.

(ii) double d = -10.0/0;

System.out.println(d);

The output of the above println() statement would be Infinity.

(iii) double d = 0.0/0;

System.out.println(d);

The output of the above println() statement would be NaN.

(iv) double d = Math.sqrt(-25);

System.out.println(d);

The output of the above println() statement would be NaN.

Note: The result will be same if we substitute the type double with float.

Overflow in Floating-Point Expressions

If the result of a floating-point expression exceeds the maximum value (magnitude) it is represented by +Infinity or –Infinity depending on the sign of the result.

Examples:

(i) double d = 1.0E+308 * 10;

System.out.println(d);
The output of the above println() statement would be Infinity. The result exceeds the

maximum value (magnitude) and its sign is positive hence it is represented as positive

Infinity.

(ii) double d = -1.0E+308 * 10;

System.out.println(d);

The output of the above println() statement would be Infinity. The result exceeds the maximum value (magnitude) and its sign is negative hence it is represented as negative Infinity.

Note: The result will be same if we substitute the type double with float and the result exceeds the maximum float value.

Underflow in Floating-Point Expressions

If the result of a floating-point expression is less than the minimum value (magnitude), it is represented by 0 (Zero).

Examples:

(i) double d = 3E-324 – 1.0E-324;

System.out.println(d);

The output of the above println() statement would be 0 (Zero). The result is less than the minimum value (magnitude) hence it is treated as 0 (Zero).

(ii) double d =  -3E-324 – 1.5E-324;

System.out.println(d);

The output of the above println() statement would be 0 (Zero). The result is less than the minimum value (magnitude) hence it is treated as 0 (Zero).

Note: The result will be same if we substitute the type double with float and the result is less than the minimum float value.

Java Shift Operators

The Java supports the following bit-wise shift operators:

<< (left shift)

>> (right shift with sign fill)

>>> (right shift with zero fill)

Both the operands must be of integer type. The type promotion rule is applied to each operand before performing the shift operation. The type of the result is same as the promoted type of the left hand operand. This means that type of result will be either int or long.

The shift distance should be in the range 0 to 31 if the promoted type of the left hand operand is int. This means you can shift the bits to left or right by at the most 31 places.

If the shift distance is more than 31 then it will be converted to a value in the range 0 to 31 by obtaining mod with 32. So shifting by 32 is equivalent to shifting by 0 i.e. no shifting al all;

shifting by 33 is equivalent to shifting by 1, and so on.

If the shift distance is negative then actual shift distance is obtained by adding some multiple of 32 to the shift distance such that it falls in the range 0 to 31. For example, if shift distance is –30

then the actual shift distance will be 2 (-30 + 1*32); if the shift distance is –44 then the actual shift distance will be 20 (-44 + 2 * 32).

The shift distance should be in the range 0 to 63 if the promoted type of the left hand operand is long. This means you can shift the bits to left or right by at the most 63 places. If the shift distance is more than 63 then it will be converted to a value in the range 0 to 63 by obtaining mod with 64. So shifting by 64 is equivalent to shifting by 0 i.e. no shifting at all; shifting by 65 is equivalent to shifting by 1, and so on.

If the shift distance is negative then actual shift distance is obtained by adding some multiple of 64 to the shift distance such that it falls in the range 0 to 63. For example, if shift distance is –60

then the actual shift distance will be 4 (-60 + 1*64); if the shift distance is –88 then the actual shift distance will be 40 (-88 + 2 * 64).

Left Shift (<<) Operator

To obtain the result of << operator, the bits in the left hand side operand (which can be any integer expression) are shifted to the left as specified by the right hand operand (which can also be any integer expression) and the empty bit positions to the right are filled with zero.  Left shifting by 1 is equivalent to multiplication by 2. It is possible that sign of the result may differ from the sign of the left hand side operand. This may happen because the sign depends on the
left-most bit, which can change from 0 to 1 or 1 to 0 hence the change in sign.

Example:

y = x << 4

To obtain the value of y, shift the bits in x by 4 positions to the left and fill the 4 right bits with zero.

Right Shift with sign fill (>>) Operator

To obtain the result of >> operator, the bits in the left hand side operand (which can be any integer expression) are shifted to the right as specified by the right hand operand (which can also be any integer expression) and the empty bit positions to the left are filled with sign bit. Right shifting by 1 is equivalent to division 2. This operator never changes the sign of the result i.e. it will be same as the sign of the left hand operand.

Example:

y = x >> 4

To obtain the value of y, shift the bits in x by 4 positions to the right and fill the 4 left bits with sign bit (i.e. with 0 if the leftmost bit before shifting is 0 or 1 if the leftmost bit before shifting is 1).

Right Shift with zero fill (>>>) Operator

To obtain the result of >>> operator, the bits in the left hand side operand (which can be any integer expression) are shifted to the right as specified by the right hand operand (which can also be any integer expression) and the empty bit positions to the left are filled with 0.  Right shifting by 1 is equivalent to division 2. If shifting tales place then result will always be positive, as the rightmost bit would become zero.

Example:

y = x >>> 4

To obtain the value of y, shift the bits in x by 4 positions to the right and fill the 4 left bits with 0.

Java Bit-wise operators

The Java supports the following bit-wise operators:

~ (1’s complement or bit-wise complement)| (bit-wise OR)

& (bit-wise AND)

^ (bit-wise exclusive OR or XOR)

The operands of these operators must be of integer type only. If any of the operand of a bit-wise operator is of type byte, short or char then it is promoted to int before being used. If one operand is of type long then other is also promoted to long. So the type of the result will always be int or long.

Note: The operators |, & and ^ behave like boolean logical operators if both the operands are of boolean type.

Bit-wise Assignment Operators

The Java supports the following Bit-wsie Assignment Operators:

&=, |=, ^=

An assignment operator has the following syntax:

<variable><operator> = <expression>

The above assignment is equivalent to:

<variable> = <variable>  <operator> (<expression>)

For example the assignment:

 i &= i1 is equivalent to i = i & i1

Here i is an integer type variable and i1 is an integer expression.

Java Assignment Operator (=)

The assignment operator has the following syntax:

<variable> = <expression>

Here variable can be of primitive type or reference type. Similarly expression may result in a primitive data value or object reference:

Example: Assignment involving primitives.

x = 10;

Example: Assignment involving reference data type.

int x[];

x = new int [100];

Here new is an operator that returns an object reference.

Multiple Assignments

The assignment operator = may be used like any other operator to form a compound expression.

The operator can appear more than once in an assignment statement as shown below:

Example:

int x = 5, y = 6 , z = 7;

x = y = z; //multiple assignment statement

Here = behaves like an operator. It is a right associative operator, hence after the execution of the assignment statement, the value of variables x, y and z will be 7.

Example:

int  x[], y[];

x = y = new int[20];

Here new operator returns reference to an array, which can hold 20 int values. The reference is first assigned to y and then to x as the = operator is right associative.

Note: Assigning a reference does not create a copy of the object. So both x and y refer to the same array in this example.

Java Ternary Conditional Operator (? :)

The ternary conditional operator has the following syntax:

<condition> ? <expr1> : <expr2>

If condition (boolean expression) is true then <expr1> is evaluated otherwise <expr2> is evaluated.

For example, the following code segment, will store the maximum of x and y into variable max:

max = (x > y) ? x : y;

Here it is assumed that the variables x, y and max are of numeric type. The type of the variable max should be higher or same as the higher type among types of x and y.

Java Conditional Operators (or Short-Circuit Logical Operators)

The Java supports the following conditional operators:

|| (conditional OR)

&& (conditional AND)

The conditional operators && and || can be used to perform logical OR or AND operations on boolean operands. The operators are similar to boolean logical operators. The only difference is that if the result is definitely known after evaluating the first operand then second operand is not evaluated as discussed in the previous section. Hence these operators are also known as short-circuit logical operators. Sometimes this proves to be very useful in avoiding run-time exceptions.

For example, the following piece of code may result in a run-time exception, if the value of x is zero (assuming that x and y are integers), as it will lead to division by zero:

x = 0;

if( x != 0 & y/x > 5)

{

----

----

}

The possibility of the run-time exception can be avoided if we use the short-circuit operator && instead of boolean logical operator & as shown below:

x = 0;

if( x != 0 && y/x > 5)

{

----

----

}

Java Boolean Logical Operators

The Java supports the following boolean logical operators:

! (logical complement)

| (logical OR)

& (logical AND)

^ (logical exclusive OR)

Logical Complement ( ! ) Operator

This is a unary operator and the operand must always be a boolean expression. This acts as the negation operator, which negates a boolean expression as shown in the following table:

Boolean Expression(b) Logical Complement(!b)
true false
false true

Logical OR ( | ) Operator

The logical OR operator is used to combine two boolean expressions to form a compound boolean expression. The value of any boolean expression in Java is either true or false no matter how complex it is. The following table shows the value of boolean expression obtained by combining two boolean expressions using logical OR operator.

Boolean Expression(b1) Logical Complement(b2) Logical Complement(b1 | b2)
false false false
false true true
true false true
true true true

If first boolean expression is true then value of the compound expression will be true irrespective of the value of the second boolean expression. Even then the second boolean expression is always evaluated. This is different from the conditional (short-circuit) OR operator where the second boolean expression is not evaluated if the result of the first boolean expression is true.

If both the operands of the | operator are of integer type then this operator behaves like bit-wise OR operator.

Logical AND ( & ) Operator

The logical AND operator is used to combine two boolean expressions to form a compound boolean expression. The value of any boolean expression in Java is either true or false no matter how complex it is. The following table shows the value of boolean expression obtained by combining two boolean expressions using logical AND operator.

Boolean Expression(b1) Logical Complement(b2) Logical Complement(b1 & b2)
false false false
false true false
true false false
true true true

If first boolean expression is false then value of the compound expression will be false irrespective of the value of the second boolean expression. Even then the second boolean expression is always evaluated. This is different from the conditional (short-circuit) AND operator where the second boolean expression is not evaluated if the result of the first boolean expression is false.

If both the operands of the & operator are of integer type then this operator behaves like bit-wise AND operator.

Logical Exclusive OR or XOR ( ^ ) Operator

The logical exclusive OR operator is used to combine two boolean expressions to form a compound boolean expression. The value of any boolean expression in Java is either true or false no matter how complex it is. The following table shows the value of boolean expression obtained by combining two boolean expressions using logical exclusive operator.

Boolean Expression(b1) Logical Complement(b2) Logical Complement(b1 ^ b2)
false false false
false true true
true false true
true true false

If both the operands of the ^ operator are of integer type then this operator behaves like bit-wise exclusive OR operator.

Boolean Logical Assignment Operators

The Java supports the following Boolean Logical Assignment Operators:

&=, |=, ^=

An assignment operator has the following syntax:

<variable><operator> = <expression>

The above assignment is equivalent to:

<variable> = <variable>  <operator> (<expression>)

For example the assignment:

 b &= b1 is equivalent to b = b & b1

Here b is a boolean variable and b1 is a boolean expression