MC0078 – Java Programming
Assignment - 2
1. With the help of a simple program demonstrate the compilation and execution of Java Programs.
Ans:
A program is a set of instructions. In order to execute a program, the operating system needs to
understand the language. The only language an operating system understands is in terms of 0’s and 1’s
i.e. the binary language. Programs written in language such as C and C++ are converted to binary code
during the compilation process. However, that binary code can be understood only by the operating
system for which the program is compiled. This makes the program or application operating system
dependent.
In Java, the program is compiled into bytecode (.class file) that run on the Java Virtual Machine, which
can interpret and run the program on any operating system. This makes Java programs platform-
independent.
At the command prompt, type
javac <filename>.java
When the code is compiled and error-free, the program can be executed using the command:
java <filename>
2. Write a complete program for each of the following:
Ans:
There are two types of decision making statements in Java. They are:
if statements
switch statements
The if Statement:
An if statement consists of a Boolean expression followed by one or more statements.
Syntax:
The syntax of an if statement is:
if(Boolean_expression)
{
//Statements will execute if the Boolean expression is true
}
If the boolean expression evaluates to true then the block of code inside the if statement will be
executed. If not the first set of code after the end of the if statement(after the closing curly brace) will
be executed.
Example:
public class Test {
public static void main(String args[]){
int x = 10;
if( x < 20 ){
System.out.print("This is if statement");
}
}
}
This would produce following result:
This is if statement
The if...else Statement:
An if statement can be followed by an optional else statement, which executes when the Boolean
expression is false.
Syntax:
The syntax of a if...else is:
if(Boolean_expression){
//Executes when the Boolean expression is true
}else{
//Executes when the Boolean expression is false
}
Example:
public class Test {
public static void main(String args[]){
int x = 30;
if( x < 20 ){
System.out.print("This is if statement");
}else{
System.out.print("This is else statement");
}
}
}
This would produce following result:
This is else statement
The switch Statement:
A switch statement allows a variable to be tested for equality against a list of values. Each value is called
a case, and the variable being switched on is checked for each case.
Syntax:
The syntax of enhanced for loop is:
switch(expression){
case value :
//Statements
break; //optional
case value :
//Statements
break; //optional
//You can have any number of case statements.
default : //Optional
//Statements
}
The following rules apply to a switch statement:
The variable used in a switch statement can only be a byte, short, int, or char.
You can have any number of case statements within a switch. Each case is followed by the value
to be compared to and a colon.
The value for a case must be the same data type as the variable in the switch, and it must be a
constant or a literal.
When the variable being switched on is equal to a case, the statements following that case will
execute until a break statement is reached.
When a break statement is reached, the switch terminates, and the flow of control jumps to the
next line following the switch statement.
Not every case needs to contain a break. If no break appears, the flow of control will fall through
to subsequent cases until a break is reached.
A switch statement can have an optional default case, which must appear at the end of the
switch. The default case can be used for performing a task when none of the cases is true. No
break is needed in the default case.
Example:
public class Test {
public static void main(String args[]){
char grade = args[0].charAt(0);
switch(grade)
{
case 'A' :
System.out.println("Excellent!");
break;
case 'B' :
case 'C' :
System.out.println("Well done");
break;
case 'D' :
System.out.println("You passed");
case 'F' :
System.out.println("Better try again");
break;
default :
System.out.println("Invalid grade");
}
System.out.println("Your grade is " + grade);
}
}
Compile and run above program using various command line arguments. This would produce following
result:
$ java Test a
Invalid grade
Your grade is a a
$ java Test A
Excellent!
Your grade is a A
$ java Test C
Well done
Your grade is a C
$
There may be a situation when we need to execute a block of code several number of times, and is often
referred to as a loop.
Java has very flexible three looping mechanisms. You can use one of the following three loops:
while Loop
do...while Loop
for Loop
As of java 5 the enhanced for loop was introduced. This is mainly used for Arrays.
The while Loop:
A while loop is a control structure that allows you to repeat a task a certain number of times.
Syntax:
The syntax of a while loop is:
while(Boolean_expression)
{
//Statements
}
When executing, if the boolean_expression result is true then the actions inside the loop will be
executed. This will continue as long as the expression result is true.
Here key point of the while loop is that the loop might not ever run. When the expression is tested and
the result is false, the loop body will be skipped and the first statement after the while loop will be
executed.
Example:
public class Test {
public static void main(String args[]){
int x= 10;
while( x < 20 ){
System.out.print("value of x : " + x );
x++;
System.out.print("\n");
}
}
}
The do...while Loop:
A do...while loop is similar to a while loop, except that a do...while loop is guaranteed to execute at least
one time.
Syntax:
The syntax of a do...while loop is:
do
{
//Statements
}while(Boolean_expression);
Notice that the Boolean expression appears at the end of the loop, so the statements in the loop
execute once before the Boolean is tested.
If the Boolean expression is true, the flow of control jumps back up to do, and the statements in the
loop execute again. This process repeats until the Boolean expression is false.
The for Loop:
A for loop is a repetition control structure that allows you to efficiently write a loop that needs to
execute a specific number of times.
A for loop is useful when you know how many times a task is to be repeated.
Syntax:
The syntax of a for loop is:
for(initialization; Boolean_expression; update)
{
//Statements
}
Here is the flow of control in a for loop:
1. The initialization step is executed first, and only once. This step allows you to declare and
initialize any loop control variables. You are not required to put a statement here, as long as a
semicolon appears.
2. Next, the Boolean expression is evaluated. If it is true, the body of the loop is executed. If it is
false, the body of the loop does not execute and flow of control jumps to the next statement
past the for loop.
3. After the body of the for loop executes, the flow of control jumps back up to the update
statement. This statement allows you to update any loop control variables. This statement can
be left blank, as long as a semicolon appears after the Boolean expression.
4. The Boolean expression is now evaluated again. If it is true, the loop executes and the process
repeats itself (body of loop, then update step,then Boolean expression). After the Boolean
expression is false, the for loop terminates.
3. Write a program to demonstrate the concept of various possible exceptions arising in a Java
Program and the ways to handle them.
Common Exceptions
Java has several predefined exceptions. The most common exceptions that you may encounter are
described below.
· Arithmetic Exception
This exception is thrown when an exceptional arithmetic condition has occurred. For example, a division
by zero generates such an exception.
· NullPointer Exception
This exception is thrown when an application attempts to use null where an object is required. An object
that has not been allocated memory holds a null value. The situations in which an exception is thrown
include:
- Using an object without allocating memory for it.
- Calling the methods of a null object.
- Accessing or modifying the attributes of a null object.
· ArrayIndexOutOfBounds Exception
The exception ArrayIndexOutOfBounds Exception is thrown when an attempt is made to access an array
element beyond the index of the array. For example, if you try to access the eleventh element of an
array that’s has only ten elements, the exception will be thrown.
Exception Handling Techniques
When an unexpected error occurs in a method, Java creates an object of the appropriate exception
class. After creating the exception objects, Java passes it to the program, by an action called throwing an
exception. The exception object contains information about the type of error and the state of the
program when the exception occurred. You need to handle the exception using exception-handler and
process the exception.
You can implement exception-handling in your program by using following keywords:
· try
· catch
· finally
The try Block
You need to guard the statements that may throw an exception in the try block. The following skeletal
code illustrates the use of the try block
try
{
// statement that may cause an exception
}
The try block governs the statements that are enclosed within it and defines the scope of the exception
handlers associated with it. In other words, if an exception occurs within try block, the appropriate
exception-handler that is associated with the try block handles the exception. A try block must have at
least one catch block that follow it immediately.
Nested try Statements
The try statement can be nested. That is, a try statement can be inside the block of another try. Each
time a try statement is entered, the context of that exception is pushed on the stack. If an inner try
statement does not have a catch handler for a particular exception, the stack is unwound and the next
try statement’s catch handlers are inspected for a match. This continues until one of the catch
statements succeeds, or until all of the nested try statements are exhausted. If no catch statement
matches, then the Java run-time system will handle the exception. Here is an example that uses nested
try
statements:
// An example of nested try statements.
class NestTry {
public static void main(String args[ ]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[ ] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
}
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
As you can see, this program nests one try block within another. The program works as follows. When
you execute the program with no command-line arguments, a divide-by zero exception is generated by
the outer try block. Execution of the program by one command-line argument generates a divide-by-
zero exception from within the nested try block. Since the inner block does not catch this exception, it is
passed on to the outer try block, where it is handled. If you execute the program with two command-
line arguments, an array boundary exception is generated from within the inner try block. Here are
sample runs that illustrate each case:
C:\>java NestTry
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One
a = 1
Divide by 0: java.lang.ArithmeticException: / by zero
C:\>java NestTry One Two
a = 2
Array index out-of-bounds:
java.lang.ArrayIndexOutOfBoundsException: 42
Nesting of try statements can occur in less obvious ways when method calls are involved. For example,
you can enclose a call to a method within a try block. Inside that method is another try statement. In this
case, the try within the method is still nested inside the outer try block, which calls the method. Here is
the previous program recoded so that the nested try block is moved inside the method nesttry( ):
/* Try statements can be implicitly nested via
calls to methods. */
class MethNestTry {
static void nesttry(int a) {
try { // nested try block
/* If one command-line arg is used,
then a divide-by-zero exception
will be generated by the following code. */
if(a==1) a = a/(a-a); // division by zero
/* If two command-line args are used,
then generate an out-of-bounds exception. */
if(a==2) {
int c[ ] = { 1 };
c[42] = 99; // generate an out-of-bounds exception
}
} catch(ArrayIndexOutOfBoundsException e) {
System.out.println("Array index out-of-bounds: " + e);
}
}
public static void main(String args[ ]) {
try {
int a = args.length;
/* If no command-line args are present,
the following statement will generate
a divide-by-zero exception. */
int b = 42 / a;
System.out.println("a = " + a);
nesttry(a);
} catch(ArithmeticException e) {
System.out.println("Divide by 0: " + e);
}
}
}
The output of this program is identical to that of the preceding example.
The catch Block
You associate an exception-handler with the try block by providing one or more catch handlers
immediately after try block. The following skeletal code illustrates the use of the catch block.
try
{
//statements that may cause an exception
}
catch ()
{
// error handling code
}
The catch statement takes an object of an exception class as a parameter. If an exception is thrown, the
statements in the catch block are executed. The scope of the catch block is restricted to the statements
in the preceding try block only.
The finally Block
When an exception is raised, the rest of the statements in the try block are ignored. Sometimes, it is
necessary to process certain statements irrespective of whether an exception is raised or not. The finally
block is used for this purpose.
try
{
openFile();
writeFile(); //may cause an exception
}
catch (…)
{
//process the exception
}
In the above example, the file has to be closed irrespective of whether an exception is raised or not. You
can place the code to close the file in both the try and catch blocks. To avoid duplication of code, you
can place the code in the finally block. The code in the finally block is executed regardless of whether an
exception is thrown or not. The finally block follows the catch blocks. You have only one finally block for
an exception-handler. However, it is not mandatory to have a finally block.
finally
{
closeFile ();
}
4. Write a program to show the various ways of creating and running threads in Java.
Ans:
Creating a Thread
In the most general sense, you create a thread by instantiating an object of type Thread.
Java defines two ways in which this can be accomplished:
• You can implement the Runnable interface.
• You can extend the Thread class, itself.
The following two sections look at each method, in turn.
Implementing Runnable
The easiest way to create a thread is to create a class that implements the Runnable interface.
Runnable abstracts a unit of executable code. You can construct a thread on any object that implements
Runnable. To implement Runnable, a class need only implement a single method called run( ), which is
declared like this:
public void run( )
Inside run( ), you will define the code that constitutes the new thread. It is important to understand that
run( ) can call other methods, use other classes, and declare variables, just like the main thread can. The
only difference is that run( ) establishes the entry point for another, concurrent thread of execution
within your program. This thread will end when run( ) returns. After you create a class that implements
Runnable, you will instantiate an object of type Thread from within that class. Thread defines several
constructors. The one that we willuse is shown here:
Thread(Runnable threadOb, String threadName)
In this constructor, threadOb is an instance of a class that implements the Runnable interface. This
defines where execution of the thread will begin. The name of the new thread is specified by
threadName. After the new thread is created, it will not start running until you call its start( ) method,
which is declared within Thread. In essence, start( ) executes a call to run( ). The start() method is
shown here:
void start( )
Here is an example that creates a new thread and starts it running:
Inside NewThread’s constructor, a new Thread object is created by the following statement:
t = new Thread(this, "Demo Thread");
Passing this as the first argument indicates that you want the new thread to call the run() method on
this object. Next, start( ) is called, which starts the thread of execution beginning at the run( ) method.
This causes the child thread’s for loop to begin. After calling start( ), NewThread’s constructor returns to
main( ). When the main thread resumes, it enters its for loop. Both threads continue running, sharing
the CPU, until their loops finish. The output produced by this program is as follows:
Child thread: Thread[Demo Thread,5,main]
Main Thread: 5
Child Thread: 5
Child Thread: 4
Main Thread: 4
Child Thread: 3
Child Thread: 2
Main Thread: 3
Child Thread: 1
Exiting child thread.
Main Thread: 2
Main Thread: 1
Main thread exiting.
As mentioned earlier, in a multithreaded program, the main thread must be the last thread to finish
running. If the main thread finishes before a child thread has completed, then the Java run-time system
may "hang." The preceding program ensures that the main thread finishes last, because the main thread
sleeps for 1,000 milliseconds between iterations, but the child thread sleeps for only 500 milliseconds.
This causes the child thread to terminate earlier than the main thread. Shortly, you will see a better way
to ensure that the main thread finishes last.
5. Write a simple program in Java to display a string message using Servlets. List out the steps
involved in Compiling and Running Servlets.
Ans:
Servlet Life Cycle
Now that you have seen the basic structure of a servlet, let’s review the process by which a server
invokes a servlet. This process can be broken down into the nine steps as follows:
1. The server loads the servlet when it is first requested by the client or if configured to do so, at server
start-up. The servlet may be loaded from either a local or a remote location using the standard Java class
loading facility.
This step is equivalent to the following code:
Class c=Class.forName(“com.sourcestream.MyServlet”);
It should be noted that when referring to servlets, the term load often refers to the process of both
loading and instantiating the servlet.
2. The server creates one or more instances of the servlet class. Depending on implementation. The
server may create a single instance that services all requests through multiple threads or create a pool
of instances from which one chosen to service each new request. This step is equivalent to the following
Java code:
Servlet s=(Servlet) c.newInstance (); where ‘c’ is the same Class object created in previous step.
3. The server constructs a ServerConfig object that provides initialization information to the servlet.
4. The server calls the servlet’s init () method, passing the object constructed in step 3 as a parameter.
The init () method is guaranteed to finish execution prior to the servlet processing the first request. If
the server has created multiple servlet instances (step 2), the init () method is called one time for each
instance.
5. The server constructs a ServletRequest or HttpServletRequest object from the data included in the
client’s request. It also constructs a ServletResponse or HttpServletResponse object that provides
methods for customizing the server’s response. The type of object passed in these two parameters
depends on whether the servlet extends the GenericServlet class or the HttpServlet class, respectively.
6. The server calls the servlet’s service() method passing the objects constructed in step 5 as
parameters. When concurrent requests arrive, multiple service() methods can run in separate threads.
7. The service () method processes the client request by evaluating the ServletRequest or
HttpServletRequest object and responds using ServletResponse or HttpServletResponse object.
8. If the server receives another request for this servlet, the process begins again at step 5.
9. When instructed to unload the servlet, perhaps by the server administrator or programmatically by
the servlet itself, the server calls the servlet’s destroy() method. The servlet is then eligible for garbage
collection.
The above mentioned nine steps illustrate the entire lifecycle of a servlet. The following figure shows the
flow of the servlet lifecycle.
6. Write a program in Java to demonstrate the complete life cycle of a Servlet.
Ans:
Servlet Life Cycle
Now that you have seen the basic structure of a servlet, let’s review the process by which a server
invokes a servlet. This process can be broken down into the nine steps as follows:
1. The server loads the servlet when it is first requested by the client or if configured to do so, at server
start-up. The servlet may be loaded from either a local or a remote location using the standard Java class
loading facility.
This step is equivalent to the following code:
Class c=Class.forName(“com.sourcestream.MyServlet”);
It should be noted that when referring to servlets, the term load often refers to the process of both
loading and instantiating the servlet.
2. The server creates one or more instances of the servlet class. Depending on implementation. The
server may create a single instance that services all requests through multiple threads or create a pool
of instances from which one chosen to service each new request. This step is equivalent to the following
Java code:
Servlet s=(Servlet) c.newInstance (); where ‘c’ is the same Class object created in previous step.
3. The server constructs a ServerConfig object that provides initialization information to the servlet.
4. The server calls the servlet’s init () method, passing the object constructed in step 3 as a parameter.
The init () method is guaranteed to finish execution prior to the servlet processing the first request. If
the server has created multiple servlet instances (step 2), the init () method is called one time for each
instance.
5. The server constructs a ServletRequest or HttpServletRequest object from the data included in the
client’s request. It also constructs a ServletResponse or HttpServletResponse object that provides
methods for customizing the server’s response. The type of object passed in these two parameters
depends on whether the servlet extends the GenericServlet class or the HttpServlet class, respectively.
6. The server calls the servlet’s service() method passing the objects constructed in step 5 as
parameters. When concurrent requests arrive, multiple service() methods can run in separate threads.
7. The service () method processes the client request by evaluating the ServletRequest or
HttpServletRequest object and responds using ServletResponse or HttpServletResponse object.
8. If the server receives another request for this servlet, the process begins again at step 5.
9. When instructed to unload the servlet, perhaps by the server administrator or programmatically by
the servlet itself, the server calls the servlet’s destroy() method. The servlet is then eligible for garbage
collection.
The above mentioned nine steps illustrate the entire lifecycle of a servlet. The following figure shows the
flow of the servlet lifecycle.
A Simple Servlet
To become familiar with the key servlet concepts, we will begin by building and testing a simple servlet.
The basic steps are the following:
1. Create and compile the servlet source code.
2. Start the servletrunner utility.
3. Start a Web browser and request the servlet.
The following sections examine each of these steps in detail.
Create and Compile the Servlet Source Code
To begin, create a file named HelloServlet.java that contains the following program:
import java.io.*;
import javax.servlet.*;
public class HelloServlet extends GenericServlet {
public void service(ServletRequest request,
ServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter pw = response.getWriter();
pw.println("<B>Hello!");
pw.close();
}
}
First, note that this program imports the javax.servlet package, which contains the classes and
interfaces required to build servlets. You will learn more about these classes and interfaces later in this
chapter. Next, the program defines HelloServlet as a subclass of GenericServlet. The GenericServlet
class provides functionality that makes it easy to handle requests and responses.
Inside HelloServlet, the service( ) method (which is inherited from GenericServlet) is overridden. This
method handles requests from a client. Notice that the first argument is a ServletRequest object. This
enables a servlet to read data that is provided via the client request. The second argument is an
ServletResponse object. This enables a servlet to formulate a response for the client.
The call to setContentType( ) establishes the MIME type of the HTTP response. In this program, the
MIME type is text/html, which indicates that the browser should interpret the content as HTML source
code.
Next, the getWriter( ) method obtains a PrintWriter. Anything written to this stream is sent to the client
as part of the HTTP response. Then, println( ) is used to write some simple HTML source code as the
HTTP response.
Compile this source code and place the HelloServlet.class file in the directory named
c:\\Jsdk2.0\\examples. This ensures that it can be located by the servletrunner utility.
Start the servletrunner Utility
Open a command prompt window and type servletrunner to start that utility. This tool listens on port
8080 for incoming client requests.
Start a Web Browser and Request the Servlet
Start a Web browser and enter the URL shown here:
http://localhost:8080/servlet/HelloServlet
Alternatively, you may enter the URL shown here:
http://127.0.0.1:8080/servlet/HelloServlet
This can be done because 127.0.0.1 is defined as the IP address of the local machine.
You should observe the output of the servlet in the browser display area. It should contain the string
Hello! in bold type.
Note
The examples in this chapter assume that the servletrunner and the Web browser execute on the same
machine. However, these two applications can be installed on different machines. In that case, the URLs
must be changed to identify the machine on which servletrunner is executing.