Sunday, 7 June 2015

Java Modifiers

Introduction

Modifiers are Java keywords that give the compiler information about the nature of code, data, classes or interfaces. For example, we have been using visibility modifiers public, private, protected, package etc. to specify the visibility of class members.  Beside visibility we have also used the modifiers static and abstract.

Classification

  • For the purpose of clear understanding, modifiers can be categorized as:
  • Accessibility modifiers for top-level classes and interfaces.
  • Member accessibility/visibility modifiers for classes.
  • Member accessibility/visibility modifiers for interfaces.
  • Other modifiers for top-level classes.
  • Other modifiers for top-level interfaces.
  • Other modifiers for interface members.
  • Other modifiers for class members.

Java Creating user-defined Exception/Error sub-classes

This is quite easy to do, just define a sub class of Exception/Error class. Your sub-classes do not need to actually implement anything. It is their existence in the type system that allows you to use them as exceptions/errors. The Exception/Error class does not define any methods of its own.

It does, of course, inherit methods provided by Thorwable class.

Extending RunTimeException or any of its sub-classes will create a user-defined unchecked-exception and extending Exception and any other sub-class of exception will create a user-defined checked-exception.  

Example: The following example demonstrates the use of a user-defined checked-exception.

class InvalidMarksException extends Exception

{ InvalidMarksException(String msg)

{ super(msg);

}

}

class MyExceptionDemo

{ static void dispGrade(int marks) throws InvalidMarksException

{ if(marks < 0 || marks > 100)

throw new InvalidMarksException

if(marks >= 75) System.out.println("S");

else if(marks >= 60) System.out.println("A");

else if(marks >= 50) System.out.println("B");

else if(marks >= 33) System.out.println("C");

else System.out.println("F");

("Marks should be in the range 0 to 100");

}

public static void main(String args[])

{ try

{ int marks = Integer.parseInt(args[0]);

dispGrade(marks);

}

catch(InvalidMarksException e)

{ System.out.println(e);

}

}

}


Example: The following example is rewritten here so as to display the marks entered as command line argument along with the error message.

class InvalidMarksException extends Exception

{ int marks;

InvalidMarksException(int marks, String msg)

{ super(msg);

}

public String toString()

{

}

}

class MyExceptionDemo1

{ static void dispGrade(int marks) throws InvalidMarksException

{ if(marks < 0 || marks > 100)

this.marks = marks;

return("InvalidMarksException["+marks+"]:"+getMessage());

throw new InvalidMarksException

if(marks >= 75) System.out.println("S");

else if(marks >= 60) System.out.println("A");

else if(marks >= 50) System.out.println("B");

else if(marks >= 33) System.out.println("C");

else System.out.println("F");

(marks, "Marks should be in the range 0 to 100");

}

public static void main(String args[])

{ try

{ int marks = Integer.parseInt(args[0]);

dispGrade(marks);

}

catch(InvalidMarksException e)

{ System.out.println(e);

}

}

}

Chained Exceptions

The chained exception feature allows you to associate another exception with an exception. This second exception describes the cause of the first exception. For example, imagine a situation in which a method throws an ArithmeticException because of an attempt to divide by zero.

However, the actual cause of the problem was that an I/O error occurred, which caused the divisor to be set improperly.

Although the method must certainly throw an ArithmeticException, since that is the error that occurred. You might also want to let the calling code know that the underlying cause was an I/O error.

To allow chained exceptions, Java 2, version 1.4 added two constructors and two methods to Throwable class. The constructors are shown here:

Throwable(Throwable causeExc)

Throwable(String msg, Throwable causeExc)

In the first form, causeExc is the exception that causes the current exception. That is, causeExc is the underlying reason that an exception occurred. The second form allows you to specify a description at the same time that you specify a cause exception. These two constructors have also been added to the Error, Exception, and RuntimeException classes.

The chained exception methods added to Throwable class are getCause() and init Cause():

Throwable getCause()

Throwable initCause(Throwable causeExc)

The getCause() method return the exception that underlies the current exception. If there is no underlying exception, null is returned. The initCause() method associates causeExc with the invoking exception and returns a reference to the exception. Thus, you can associate a cause with an exception after the exception has been created. However, the cause exception can be set only once. Thus, you can call initCause() only once for each exception object. Furthermore, if the
cause exception was set by a constructor, then you cannot set it again using initCause() method.

In general, initCause() is used to set a cause for legacy exception classes which do not support the two additional constructors described earlier. Most of Java's built-in exceptions do not define the additional constructors. Thus, you will use initCause() if you need to add an exception chain to these exceptions.

Chained exceptions are not something that every program will need. However, in chases in which knowledge of an underlying cause is useful, they offer an elegant solution.

Example:

class ChainExecDemo

{

static void demoproc()

{

NullPointerException e = new NullPointerException("top layer");

e.initCause(new ArithmeticException("Cause"));

throw e;

}

public static void main(String agrs[])

{

char a = 'a';

try

{

demoproc();

}

catch(NullPointerException e)

{

System.out.println(a);

System.out.println(e);

System.out.println("Original Cause : " +e.getCause());

}

}

}

Output:


Note: The NullPointerException constructor is not overloaded to receive cause so the only way to associate cause with it is to make use of initCause() method.

Java finally clause

finally creates a block of code that will be executed after a try/catch block has completed and before the code following the try/catch block.

The finally block will execute whether or not exception is thrown. If an exception is thrown, the finally block will execute even if no catch statement matches the exception.

Any time a method is about to return to the caller from inside a try/catch block, via an uncaught exception or an explicit return statement, the finally clause is also executed just before the method returns. This can be useful for closing file handlers and freeing up any other resources that might have been allocated at the beginning of a method with the intent of disposing of them before returning.

The finally clause is optional. However, each try statement requires at least one catch or a finally clause.

Example:

class FinallyDemo

{ static void procA()

{ try

{ System.out.println("inside procA()");

throw new RuntimeException("Demo");

}

finally

{ System.out.println("procA()'s finally"); }

}

static int procB()

{ try

{ System.out.println("inside procB()");

return(5);

}

finally

{ System.out.println("procB()'s finally"); return(10);

}

}

static void procC()

{ try

{ System.out.println("inside procC()"); }

finally

{ System.out.println("procC()'s finally"); }

}

public static void main(String args[])

{ try

{ procA(); }

catch(Exception e)

{ System.out.println("! Exception caught:"+e); }

int x = procB();

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

procC();

}

}

Output:

inside procA()

procA()'s finally

! Exception caught:java.lang.RuntimeException: Demo

inside procB()

procB()'s finally

x= 10

inside procC()
procC()'s finally

Java throw statement

Example: Normally built-in exceptions are thrown by the JVM but user can also create and throw any exception although this is normally not done. The throw statement is needed for throwing user-defined exceptions, which is discussed in a later section.

The following program creates and throws an exception

class ThrowDemo {

static void demoproc() {

try {

int c = 0, a = 0;

if (a == 0)

int b = c / a;

} catch (ArithmeticException e) {

System.out.println("Caught inside demporoc.");

throw e;

}

throw new ArithmeticException("Division by zero");

}

public static void main(String args[]) {

try {

demoproc();

} catch (ArithmeticException e) {

System.out.println("Recaught: " + e);

}

}

}

Output:

Caught inside demporoc.

Recaught: java.lang.ArithmeticException: Division by zero

Example: The following example demonstrates that if a checked-exception is thrown using throw statement then it must either be caught or declared in the throws clause.

import java.io.*;

class ThrowsDemo {

static void throwOne() throws IOException {

System.out.println("inside throwOne");

throw new IOException("Demo");

}

public static void main(String args[]) {

}

}

Output: above program will not compile and result in following compile time error.

throwOne();


Example: The above example is re-written such that the method throwOne() is called in a try block.

import java.io.*;

class ThrowsDemo

{ static void throwOne() throws IOException

{ System.out.println("inside throwOne");

}

public static void main(String args[])

{ try

throw new IOException("Demo");

{ throwOne();

}

catch(IOException e)

{ e.printStackTrace();

}

}

}

Output: results in an exception at run-time.


Friday, 5 June 2015

Java Handling Checked Exceptions

Example: This program also handles the Checked Exceptions. The following program takes names of two files as input and copies the file specified by the first argument to the file specified by the second argument. The number of bytes copied are displayed in the finally block. So number of bytes copied will be displayed even if some abnormal condition terminates the program. The files are also closed in the finally block so that they will always be closed.

It has three handlers to handle the abnormal conditions:

  • One handler will print the usage of the program when the user does not provide both input and output file names.
  • The next handler will notify the user when the input file does not exist.
  • Another handler will print an error message when other I/O exceptions occur.
import java.io.*;

class MyCopy

{ public static void main(String args[])

{ int byte_count = 0;

byte buffer[] = new byte[512];

String input_file = null;

String output_file = null;

FileInputStream fin = null;

FileOutputStream fout = null;

try

{ input_file  = args[0];

output_file = args[1];

fin  = new FileInputStream(input_file);

fout = new FileOutputStream(output_file);

int bytes_in_one_read;

while((bytes_in_one_read = fin.read(buffer)) != -1)

{ fout.write(buffer,0,bytes_in_one_read);

}

}

catch(ArrayIndexOutOfBoundsException e)

{ System.out.println("Use:java MyCopy source target");

}

catch(FileNotFoundException e)//Checked Exception

{ System.out.println("Can't open input file:"+input_file);

}

byte_count = byte_count + bytes_in_one_read;

catch(IOException e) //Checked Exception

{ System.out.println("I/O Exception occurs");

}

finally

{ if(byte_count > 0)

if(fin != null)

if(fout != null)

}

System.out.println(byte_count + " bytes written");

fin.close();

fout.close();

} // end main

} // end class

Note:

1. FileNotFoundException and IOException are checked exceptions and must be handled.

2. It is possible that we handle only IOException as this will also indirectly handle the FileNotFoundException, which is its sub-class.

3. If both IOException and FileNotFoundException are handled then FileNotFoundException must be caught before IOException as it is sub-class of IOException.

Example: The previous example is rewritten to use method:

int copyFile(String input-file, String output-file)

We want that caller of this method should handle the abnormal conditions by itself. Method will not have any error handler for I/O Exception. A throws clause is added to the method declaration to indicate that method can throw exception and caller has to handle this exception. The caller can also throw the exception if it does not want to handle itself.

import java.io.*;

class MyCopy1

{ static FileInputStream fin = null;

static FileOutputStream fout = null;

public static int CopyFile(String input_file, String output_file)

{ int byte_count = 0;

throws IOException, FileNotFoundException

 fout = new FileOutputStream(output_file);

int bytes_in_one_read;

byte buffer[] = new byte[512];

fin  = new FileInputStream(input_file);

while((bytes_in_one_read = fin.read(buffer)) != -1)

{ fout.write(buffer,0,bytes_in_one_read);

byte_count = byte_count + bytes_in_one_read;

import java.io.*;

class MyCopy1

{ static FileInputStream fin = null;

static FileOutputStream fout = null;

public static int CopyFile(String input_file, String output_file)

{ int byte_count = 0;

throws IOException, FileNotFoundException

 fout = new FileOutputStream(output_file);

int bytes_in_one_read;

byte buffer[] = new byte[512];

fin  = new FileInputStream(input_file);

while((bytes_in_one_read = fin.read(buffer)) != -1)

{ fout.write(buffer,0,bytes_in_one_read);

byte_count = byte_count + bytes_in_one_read;

{ int a = args.length;

int b = 42/a;

System.out.println("a = " + a);

try

{ if(a == 1)

a = a/(a-a);

if(a == 2)

{

int c[] = {1};

c[42] = 99;

}

}

catch(ArrayIndexOutOfBoundsException e)

{ System.out.println("Array index out-of-bounds:"+e);

}

System.out.println("Outer Try");

}

catch(ArithmeticException e)

{ System.out.println(e);

}

System.out.println("After Outer Try");

}

}

Note: Nesting of try statement 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.

Example: Previous program is re-written so that the nested try block is moved inside the method nesttry().

class NestTry1

{ static void nesttry(int a)

{ try

{ if(a == 1)

if(a == 2)

{ int c[] = {1};

}

}

catch(ArrayIndexOutOfBoundsException e)

{

System.out.println("Array index out-of-bounds:" + e);

}

a = a/(a-a);

c[42] = 99;

}

public static void main(String args[])

{ try

{ int a = args.length;

int b = 42/a;

System.out.println("a = " + a);

nesttry(a);

}

catch(ArithmeticException e)

{

System.out.println(e);

}

}

}