0% found this document useful (0 votes)
9 views42 pages

Java Packages and Exception Handling Guide

Module 4 covers Java packages, exception handling, and member access. It explains how to define and use packages, the importance of encapsulation, and how to handle naming conflicts with imports. Additionally, it discusses built-in and user-defined packages, static imports, and access control for class members.

Uploaded by

4al24cs038
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
9 views42 pages

Java Packages and Exception Handling Guide

Module 4 covers Java packages, exception handling, and member access. It explains how to define and use packages, the importance of encapsulation, and how to handle naming conflicts with imports. Additionally, it discusses built-in and user-defined packages, static imports, and access control for class members.

Uploaded by

4al24cs038
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Module 4 (updated)

Packages: Packages, Packages and Member Access, Importing Packages.


Exceptions: Exception-Handling Fundamentals, Exception Types, Uncaught Exceptions, Using
try and catch, Multiple catch Clauses, Nested try Statements, throw, throws, finally, Java’s Built-
in Exceptions, Creating Your Own Exception Subclasses, Chained Exceptions.

Defining a Package

The package statement in java is used to define a name space in which classes are stored. If you omit
the package statement, the class names are put into the default package, which has no name

This is the general form of the package statement:


package pkg;

Here, pkg is the name of the package. For example, the following statement creates a package called
mypackage:

package mypackage;

A Short Package Example

// A simple package
package mypack;

class AccountBalance {
public static void main(String[] args) {
Balance[] current = new Balance[3];

current[0] = new Balance("K. J. Fielding", 123.23);


current[1] = new Balance("Will Tell", 157.02);
current[2] = new Balance("Tom Jackson", -12.33);

for (int i = 0; i < 3; i++)


current[i].show();
}
}

package mypack;

class Balance {
String name;
double bal;
Balance(String n, double b) {
name = n;
bal = b;
}

void show() {
if (bal < 0)
[Link]("-->> ");
[Link](name + ": $" + bal);
}
}

o/p

K. J. Fielding: $123.23
Will Tell: $157.02
-->> Tom Jackson: $-12.33
Packages in Java

Package in Java is a mechanism to encapsulate a group of classes, sub packages and interfaces.
Packages are used for:

Preventing naming conflicts. For example there can be two classes with name Employee in two
packages, [Link] and [Link]

Making searching/locating and usage of classes, interfaces, enumerations and annotations easier

Providing controlled access: protected and default have package level access control. A protected
member is accessible by classes in the same package and its subclasses. A default member (without any
access specifier) is accessible by classes in the same package only.

Packages can be considered as data encapsulation (or data-hiding).

All we need to do is put related classes into packages. After that, we can simply write an import class
from existing packages and use it in our program. A package is a container of a group of related
classes where some of the classes are accessible are exposed and others are kept for internal purpose.
We can reuse existing classes from the packages as many time as we need it in our program.

How packages work?

Package names and directory structure are closely related. For example if a package name is
[Link], then there are three directories, college, staff and cse such that cse is present in staff
and staff is present college.

Package naming conventions : Packages are named in reverse order of domain names, i.e.,
[Link]. For example, in a college, the recommended convention is [Link],
[Link], [Link], etc.

Adding a class to a Package : We can add more classes to a created package by using package name at
the top of the program and saving it in the package directory. We need a new java file to define a public
class, otherwise we can add the new class to an existing .java file and recompile it.

Subpackages: Packages that are inside another package are the subpackages. These are not imported
by default, they have to imported explicitly. Also, members of a subpackage have no access privileges,
i.e., they are considered as different package for protected and default access specifiers.

Example :

import [Link].*;
util is a subpackage created inside java package.

Accessing classes inside a package

Consider following two statements :


// import the Vector class from util package.
import [Link];

// import all the classes from util package


import [Link].*;

First Statement is used to import Vector class only from util package which is contained inside java.

Second statement imports all the classes from util package.

// All the classes and interfaces of this package


// will be accessible but not subpackages.

import package.*;

// Only mentioned class of this package will be accessible.


import [Link];

// Class name is generally used when two packages have the same
// class name. For example in below code both packages have
// date class so using a fully qualified name to avoid conflict

import [Link];// in-built


import [Link]; // user defined

Built-in Packages

These packages consist of a large number of classes which are a part of Java [Link] of the
commonly used built-in packages are:

1) [Link]: Contains language support classes(e.g classed which defines primitive data types, math
operations). This package is automatically imported.
2) [Link]: Contains classed for supporting input / output operations.
3) [Link]: Contains utility classes which implement data structures like Linked List, Dictionary and
support ; for Date / Time operations.
4) [Link]: Contains classes for creating Applets.
5) [Link]: Contain classes for implementing the components for graphical user interfaces (like button
, ;menus etc).
6) [Link]: Contain classes for supporting networking operations.

User-defined packages

These are the packages that are defined by the user. First we create a directory myPackage (name
should be same as the name of the package). Then create the MyClass inside the directory with the first
statement being the package names.

Using Static Import

Static import is a feature introduced in Java programming language ( versions 5 and above ) that allows
members ( fields and methods ) defined in a class as public static to be used in Java code without
specifying the class in which the field is defined.
Following program demonstrates static import :
// Note static keyword after import.
import static [Link].*;

class StaticImportDemo
{
public static void main(String args[])
{
// We don't need to use '[Link]'
// as imported using static.
[Link]("AIET");
}
}
Output:

AIET

Handling name conflicts

The only time we need to pay attention to packages is when we have a name conflict . For example
both, [Link] and [Link] packages have a class named Date. So if we import both packages in
program as follows:

import [Link].*;
import [Link].*;

//And then use Date class, then we will get a compile-time error :

Date today ; //ERROR-- [Link] or [Link]?


The compiler will not be able to figure out which Date class do we want. This problem can be solved
by using a specific import statement:
import [Link];
import [Link].*;

If we need both Date classes then, we need to use a full package name every time we declare a new
object of that class.

For Example:

[Link] deadLine = new [Link]();


[Link] today = new [Link]();

Illustration of user-defined packages:

Creating our first package:


File name – [Link]

package package_one;

public class ClassOne {


public void methodClassOne() {
[Link]("Hello there I am ClassOne");
}
}

Creating our second package:


File name – [Link]
package package_two;

public class ClassTwo {


public void methodClassTwo(){
[Link]("Hello there I am ClassTwo");
}
}

Making use of both the created packages:


File name – [Link]

import package_one.ClassOne;
import package_two.ClassTwo;

public class Testing {


public static void main(String[] args){

ClassOne a = new ClassOne();


ClassTwo b = new ClassTwo();
[Link]();
[Link]();

}
}

Output:
Hello there I am ClassOne
Hello there I am ClassTwo

Important points:

 Every class is part of some package.


 If no package is specified, the classes in the file goes into a special unnamed package (the same
unnamed package for all files).
 All classes/interfaces in a file are part of the same package. Multiple files can specify the same
package name.
 If package name is specified, the file must be in a subdirectory called name (i.e., the directory
name must match the package name).
 We can access public classes in another (named) package using: [Link]-name

What’s the use of static imports?


Static imports are used to save your time and typing. If you hate to type same thing again and again
then you may find such imports interesting.

Lets understand this with the help of below examples:

Example 1: Without Static Imports

class Demo1{
public static void main(String args[])
{
double var1= [Link](5.0);
double var2= [Link](30);
[Link]("Square of 5 is:"+ var1);
[Link]("Tan of 30 is:"+ var2);
}
}

Output:

Square of 5 is:2.23606797749979
Tan of 30 is:-6.405331196646276

Example 2: Using Static Imports

import static [Link];


import static [Link].*;
class Demo2{
public static void main(String args[])
{
//instead of [Link] need to use only sqrt
double var1= sqrt(5.0);
//instead of [Link] need to use only tan
double var2= tan(30);
//need not to use System in both the below statements
[Link]("Square of 5 is:"+var1);
[Link]("Tan of 30 is:"+var2);
}
}

Output:

Square of 5 is:2.23606797749979
Tan of 30 is:-6.405331196646276

Points to note:
1) Package import syntax:

import static [Link];


import static [Link].*;

2) Note comments given in the above code.

When to use static imports?

If you are going to use static variables/methods a lot then it’s fine to use static imports. for
example if you wanna write a code with lot of mathematical calculations then you may want to
use static import.
Drawbacks
It makes the code confusing and less readable so if you are going to use static members very few
times in your code then probably you should avoid using it. You can also use wildcard(*) imports.

Packages and Member Access

Classes and packages are both means of encapsulating and containing the name
space and scope of variables and methods. Packages act as containers for classes and
other subordinate packages. Classes act as containers for data and code. The class is
Java’s smallest unit of abstraction. As it relates to the interplay between classes and
packages, Java addresses four categories of visibility for class members:

 Subclasses in the same package


 Non-subclasses in the same package
 Subclasses in different packages
 Classes that are neither in the same package nor subclasses
The three access modifiers, private, public, and protected, provide a variety of
ways to produce the many levels of access required by these categories. Table below
sums up the interactions.

An Access Example
The following example shows all combinations of the access control modifiers. This example has two
packages and five classes. Remember that the classes for the two different packages need to be stored
in directories named after their respective packages—in this case, p1 and p2.

The source for the first package defines three classes: Protection, Derived, and SamePackage. The first
class defines four int variables in each of the legal protection modes. The variable n is declared with the
default protection, n_pri is private, n_pro is protected, and n_pub is public.

Each subsequent class in this example will try to access the variables in an instance of this class. The
lines that will not compile due to access restrictions are commented out. Before each of these lines is a
comment listing the places from which this level of protection would allow access.

The second class, Derived, is a subclass of Protection in the same package, p1. This grants Derived
access to every variable in Protection except for n_pri, the private one. The third class, SamePackage,
is not a subclass of Protection, but is in the same package and also has access to all but n_pri.
This is file [Link]:
/ Demo package p1.
package p1;
// Instantiate the various classes in p1.
public class Demo {
public static void main(String[] args) {
Protection ob1 = new Protection();
Derived ob2 = new Derived();
SamePackage ob3 = new SamePackage();
}
}
package p1;

public class Protection {


public int n_pub = 4;
protected int n_pro = 3;
int n = 1;
private int n_pri = 2;

public Protection() {
[Link]("base constructor");
[Link]("n = " + n);
[Link]("n_private = " + n_pri);
[Link]("n_protected = " + n_pro);
[Link]("n_public = " + n_pub);
}
}

package p1;

class Derived extends Protection {


Derived() {

[Link]("derived constructor");
[Link]("n = " + n);

// class only
// [Link]("n_pri = " + n_pri);

[Link]("n_protected = " + n_pro);


[Link]("n_public = " + n_pub);
}
}

package p1;
class SamePackage {
SamePackage() {
Protection p = new Protection();
[Link]("same package constructor");
[Link]("n = " + p.n);

// class only
// [Link]("n_private= " + p.n_pri);
[Link]("n_protected = " + p.n_pro);
[Link]("n_public = " + p.n_pub);
}
}

o/p of [Link] in package p1

n=1
n_private = 2
n_protected = 3
n_public = 4
base constructor
n=1
n_private = 2
n_protected = 3
n_public = 4
derived constructor
n=1
n_protected = 3
n_public = 4
base constructor
n=1
n_private = 2
n_protected = 3
n_public = 4
same package constructor
n=1
n_protected = 3
n_public = 4

/ Demo package p2.


package p2;

// Instantiate the various classes in p2.


public class Demo {
public static void main(String[] args) {
Protection2 ob1 = new Protection2();
OtherPackage ob2 = new OtherPackage();
}
}

package p2;

class Protection2 extends [Link] {


Protection2() {
[Link]("derived other package constructor");

// class or package only


// [Link]("n = " + n);

// class only
// [Link]("n_private = " + n_pri);

[Link]("n_protected = " + n_pro);


[Link]("n_public = " + n_pub);
}
}

package p2;

class OtherPackage {
OtherPackage() {
[Link] p = new [Link]();
[Link]("other package constructor");

// class or package only


// [Link]("n = " + p.n);

// class only
// [Link]("n_private = " + p.n_pri);

// class, subclass or package only


// [Link]("n_protected = " + p.n_pro);

[Link]("n_public = " + p.n_pub);


}
}

o/p of [Link] in package p2

base constructor
n=1
n_private = 2
n_protected = 3
n_public = 4
derived other package constructor
n_protected = 3
n_public = 4
base constructor
n=1
n_private = 2
n_protected = 3
n_public = 4
other package constructor
n_public = 4

Importing Packages

Given that packages exist and are a good mechanism for compartmentalizing diverse classes from each
other, it is easy to see why all of the built-in Java classes are stored in packages. There are no core Java
classes in the unnamed default package; all of the standard classes are stored in some named package.
Since classes within packages must be fully qualified with their package name or names, it could
become tedious to type in the long dot-separated package path name for every class you want to use.
For this reason, Java includes the import statement to bring certain classes, or entire packages, into
visibility. Once imported, a class can be referred to directly, using only its name. The import statement
is a convenience to the programmer and is not technically needed to write a complete Java program. If
you are going to refer to a few dozen classes in your application, however, the import statement will
save a lot of typing.

In a Java source file, import statements occur immediately following the package statement (if it exists)
and before any class definitions. This is the general form of the import statement:

import pkg1 [.pkg2].(classname | *);

Here, pkg1 is the name of a top-level package, and pkg2 is the name of a subordinate package inside
the outer package separated by a dot (.). There is no practical limit on the depth of a package hierarchy,
except that imposed by the file system. Finally, you specify either an explicit classname or a star (*),
which indicates that the Java compiler should import the entire package. This code fragment shows
both forms in use:

In a Java source file, import statements occur immediately following the package statement (if it exists)
and before any class definitions. This is the general form of the import statement:

import pkg1 [.pkg2].(classname | *);

Here, pkg1 is the name of a top-level package, and pkg2 is the name of a subordinate package inside
the outer package separated by a dot (.). There is no practical limit on the depth of a package hierarchy,
except that imposed by the file system. Finally, you specify either an explicit classname or a star (*),
which indicates that the Java compiler should import the entire package. This code fragment shows
both forms in use:All of the standard Java SE classes included with Java begin with the name java.
The basic language functions are stored in a package called [Link]. Normally, you have to import
every package or class that you want to use, but since Java is useless without much of the functionality
in [Link], it is implicitly imported by the compiler for all programs. This is equivalent to the
following line being at the top of all of your programs:

If a class with the same name exists in two different packages that you import using the star form, the
compiler will remain silent, unless you try to use one of the classes. In that case, you will get a
compile-time error and have to explicitly name the class specifying its package. It must be emphasized
that the import statement is optional. Any place you use a class name, you can use its fully qualified
name, which includes its full package hierarchy. For example, this fragment uses an import statement:

The same example without the import statement looks like this:

In this version, Date is fully-qualified.

Example program for explaining modules and packages

Create three packages namely Arith, Great and MainPack for storing the modules
ArithmeticOperations, GreatestFinder and MainClass respectively. Create different objects for the
classes ArithmeticOperations and GreatestFinder to access the methods which are defined in these
classes.
// File: Arith/[Link]

package Arith;

public class ArithmeticOperations {


public int add(int a, int b) {
return a + b;
}

public int subtract(int a, int b) {


return a - b;
}

public int multiply(int a, int b) {


return a * b;
}

public double divide(int a, int b) {


if (b == 0) {
throw new IllegalArgumentException("Division by zero is not allowed.");
}
return (double) a / b;
}
}

// File: Great/[Link]
package Great;

public class GreatestFinder {


// Method to find the greatest of two numbers
public int greatestOfTwo(int a, int b) {
return a > b ? a : b;
}

// Method to find the greatest of three numbers


public int greatestOfThree(int a, int b, int c) {
return [Link](a, [Link](b, c));
}

// Method to find the greatest of four numbers


public int greatestOfFour(int a, int b, int c, int d) {
return [Link]([Link](a, b), [Link](c, d));
}
}

//File: MainPack/[Link]
package MainPack;

//File: [Link]

import [Link];
import [Link];

public class MainClass {


public static void main(String[] args) {
// Creating objects of the classes
ArithmeticOperations arith = new ArithmeticOperations();
GreatestFinder great = new GreatestFinder();

// Arithmetic operations
int num1 = 10, num2 = 5;
[Link]("Addition: " + [Link](num1, num2));
[Link]("Subtraction: " + [Link](num1, num2));
[Link]("Multiplication: " + [Link](num1, num2));
[Link]("Division: " + [Link](num1, num2));

// Finding greatest numbers


int a = 12, b = 24, c = 36, d = 48;
[Link]("Greatest of two: " + [Link](a, b));
[Link]("Greatest of three: " + [Link](a, b, c));
[Link]("Greatest of four: " + [Link](a, b, c, d));
}
}

o/p

Addition: 15
Subtraction: 5
Multiplication: 50
Division: 2.0
Greatest of two: 24
Greatest of three: 36
Greatest of four: 48

Name conflics and


its solution using
Fully Qualified
Names
Solution of the name conflicts occuring during importing using Fully Qualified Names

package Modules_Packages;

public class Person {


public void display() {
[Link]("Hi!, I am Person class in Modules_Packages");
}
}

package package1;

public class Utility {


public void display() {
[Link]("Hi!, I am Utility Class from package1");
}
}

package package2;

public class Utility {


public void display() {
[Link]("Hi!, I am Utility Class from package2");
}
}

package Modules_Packages1;

//File: Main_Class.java
import Modules_Packages.Person;
import [Link];
//import [Link]; // conflicts occurs here as [Link] collides with another import
command

public class Main_Class{


public static void main(String[] args) {
Person p = new Person();
[Link]();
Utility u= new Utility();
[Link]();

}
}

o/p
Hi!, I am Person class in Modules_Packages
Hi!, I am Utility Class from package2

How can I make use of both the Utility classes in the main module.? The solution is Fully qualified
Name

Example for Fully qualified Name

import Modules_Packages.Person;

// Remove the ambiguous Utility imports


// import [Link]; (avoiding direct importing the modules)
// import [Link]; (avoiding direct importing the modules)

public class Main_Class {


public static void main(String[] args) {
Person p = new Person();
[Link]();

// Instantiate Utility from package1 using fully qualified name


[Link] u1 = new [Link]();
[Link]();

// Instantiate Utility from package2 using fully qualified name


[Link] u2 = new [Link]();
[Link]();
}
}
o/p

Hi!, I am Person class in Modules_Packages


Hi!, I am Utility Class from package1
Hi!, I am Utility Class from package2

Summary of what to do:

Remove the ambiguous import statements for Utility.


Fully qualify the class names when creating instances ([Link] and [Link]).
This approach clearly distinguishes between the two classes and allows you to use both in your code.

Exception-Handling Fundamentals

What is an exception?
An Exception can be anything which interrupts the normal flow of the program. It is a run time error.
When an exception occurs in a program, the processing gets terminated and doesn’t continue further.
In such cases we get a system generated error message. The good thing about exceptions is that they
can be handled.

Java exception handling is managed via five keywords: try, catch, throw, throws, and finally. Briefly,
here is how they work. Program statements that you want to monitor for exceptions are contained
within a try block. If an exception occurs within the try block, it is thrown. Your code can catch this
exception (using catch) and handle it in some rational manner. System-generated exceptions are
automatically thrown by the Java run-time system. To manually throw an exception, use the
keyword throw. Any exception that is thrown out of a method must be specified as such by a
throws clause. Any code that absolutely must be executed after a try block completes is put in a
finally block.
An example of Try catch in Java

class Example1 {
public static void main(String args[]) {
int num1, num2;

// Try block to handle code that may cause exception


try {
num1 = 0;
num2 = 62 / num1;
[Link]("Try block message");
}
catch (ArithmeticException e)
{
// This block is to catch divide-by-zero error
[Link]("Error: Don't divide a number by zero");
}
[Link]("I'm out of try-catch block in Java.");
}
}

custom exception
Output:
Error: Don't divide a number by zero
I'm out of try-catch block in Java.

When an exception can occur?


Exception can occur at runtime (known as runtime exceptions) as well as at compile-time (known
Compile-time exceptions).

Reasons for Exceptions


There can be several reasons for an exception. For example, following situations can cause an
exception –Opening a non-existing file, Network connection problem, Operands being manipulated are
out of prescribed ranges, class file missing which was supposed to be loaded and so on.

Difference between error and exception


Errors indicate serious problems and abnormal conditions that most applications should not try to
handle. Error defines problems that are not expected to be caught under normal circumstances by our
program. For example memory error, hardware error, JVM error etc.

Exceptions are the conditions within code which a developer can handle and take necessary corrective
actions. Few examples –
 DivideByZero exception
 NullPointerException
 ArithmeticException
 ArrayIndexOutOfBoundsException

Advantages of Exception Handling


 Exception handling allows us to control the normal flow of the program by using exception
handling in program.
 It throws an exception whenever a calling method encounters an error providing that the calling
method takes care of that error.
 It also gives us the scope of organizing and differentiating between different error types using a
separate block of codes. This is done with the help of try-catch blocks.

Why to handle exception?


If an exception is raised, which has not been handled by programmer then program execution can get
terminated and system prints a non user friendly error message.

Exception Types
All exception types are subclasses of the built-in class Throwable. Thus, Throwable is at the top of the
exception class hierarchy. Immediately below Throwable are two subclasses that partition exceptions
into two distinct branches.

One branch is headed by Exception. This class is used for exceptional conditions that user programs
should catch. This is also the class that you will subclass to create your own custom exception types.
There is an important subclass of Exception, called RuntimeException. Exceptions of this type are
automatically defined for the programs that you write and include things such as division by zero and
invalid array indexing.

The other branch is topped by Error, which defines exceptions that are not expected to be caught under
normal circumstances by your program. Exceptions of type Error are used by the Java run-time system
to indicate errors having to do with the run-time environment, itself. Stack overflow is an example of
such an error. Thischapter will not be dealing with exceptions of type Error, because these are typically
created in response to catastrophic failures that cannot usually be handled by your program.

The top-level exception hierarchy is shown here:

Uncaught Exceptions
Before you learn how to handle exceptions in your program, it is useful to see what happens when you
don’t handle them. This small program includes an expression that intentionally causes a divide-by-
zero error:
Using try and catch

o/p
Notice that the call to println( ) inside the try block is never executed. Once an exception is thrown,
program control transfers out of the try block into the catch block. Put differently, catch is not “called,”
so execution never “returns” to the try block from a catch. Thus, the line "This will not be printed." is
not displayed. Once the catch statement has executed, program control continues with the next line in
the program following the entire try / catch mechanism.

A try and its catch statement form a unit. The scope of the catch clause is restricted to those statements
specified by the immediately preceding try statement.
A catch statement cannot catch an exception thrown by another try statement (except in the case of
nested try statements, described shortly). The statements that are protected by try must be surrounded
by curly braces. (That is, they must bewithin a block.) You cannot use try on a single statement.
The goal of most well-constructed catch clauses should be to resolve the exceptional condition and then
continue on as if the error had never happened. For example, in the next program each iteration of the
for loop obtains two random integers. Those two integers are divided by each other, and the result is
used to divide the value 12345. The final result is put into a. If either division operation causes a
divide-by-zero error, it is caught, the value of a is set to zero, and the program continues.

// Handle an exception and move on.

import [Link];

class HandleError {
public static void main(String[] args) {
int a,b,c;
Random r = new Random();

for (int i = 0; i < 10; i++) {


try {
b = [Link]();
c = [Link]();
a = 12345 / (b / c);
} catch (ArithmeticException e) {
[Link]("Division by zero.");
a = 0; // set a to zero and continue
}
[Link]("a: " + a);
}
}
}

o/p

a: -4115
a: -12345
Division by zero.
a: 0
Division by zero.
a: 0
Division by zero.
a: 0
Division by zero.
a: 0
a: -12345
Division by zero.
a: 0
a: 6172
a: -12345

Displaying a Description of an Exception

Throwable overrides the toString( ) method (defined by Object) so that it returns a string containing a
description of the exception. You can display this description in a println( ) statement by simply passing
the exception as an argument. For example, the catch block in the preceding program can be rewritten
like this:

When this version is substituted in the program, and the program is run, each divide- by-zero error
displays the following message:

While it is of no particular value in this context, the ability to display a description of an exception is
valuable in other circumstances—particularly when you are experimenting with exceptions or when
you are debugging.

Multiple catch Clauses

In some cases, more than one exception could be raised by a single piece of code. To handle this type
of situation, you can specify two or more catch clauses, each catching a different type of exception.
When an exception is thrown, each catch statement is inspected in order, and the first one whose type
matches that of the exception is executed. After one catch statement executes, the others are bypassed,
and execution continues after the try / catch block. The following example traps two different exception
types

// This is updated code


package Exception;
//Demonstrate multiple catch statements with finally
class MultipleCatches {
public static void main(String[] args) {
try {

int a = [Link];
[Link]("a = " + a);
int b = 42 / 2;

int[] c = {1};
c[5] = 99;

int num = [Link] ("akki") ;

String a2 = "This is like chipping "; // length is 22


char c2 = [Link](24); // accessing 25th element
[Link](c); */

}
catch (ArithmeticException e) {
[Link]("Divide by 0: " + e);
}
catch (ArrayIndexOutOfBoundsException e) {
[Link]("\nArray index out of boundary: " + e);
}

catch (NumberFormatException e) {
[Link]("\nNumber Format Exception occurs: " + e);
}

catch (StringIndexOutOfBoundsException e){


[Link]("\nString Index out of Bounds Exception occurs: " + e);
}

finally{ {
[Link]("\nAfter exectuing the concerned try/catch block.");
}
}
}
}

o/p

a=0
Array index out of boundary: [Link]: Index 5 out of bounds for
length 1

After exectuing the concerned try/catch block.

When you use multiple catch statements, it is important to remember that exception subclasses must
come before any of their superclasses. This is because a catch statement that uses a superclass will
catch exceptions of that type plus any of its subclasses. Thus, a subclass would never be reached if it
came after its superclass. Further, in Java, unreachable code is an error. For example, consider the
following program:

If you try to
compile this program, you will receive an error message stating that the second catch statement is
unreachable because the exception has already beencaught. Since ArithmeticException is a subclass of
Exception, the first catch statement will handle all Exception-based errors, including
ArithmeticException.

This means that the second catch statement will never execute. To fix the problem, reverse the order of
the catch statements.

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
statementssucceeds, 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

// This is an updated notes


// An example nested try statements.
package Exception;

//An example nested try statements.


class NestTry {
public static void main(String[] args) {
try {
int a = [Link];

/* If no command line args are present,


the following statement will generate
a divide-by-zero exception. */
[Link]("a = " + a);
iCustom exceptionf (a == 2) {
int b = 42 /(a-a);
//int b = 42 /a;
}

try { // nested try block

/* If three command line args are used


then generate an out-of-bounds exception. */
if (a == 3) {
int[] c = {1};
c[42] = 99; // generate an out-of-bounds exception
}
} catch (ArrayIndexOutOfBoundsException e) {
[Link]("Exception occurs at inner [Link] index out-of-bounds: " + e);
}

} catch (ArithmeticException e) {
[Link]("Exception occurs at outer [Link] by 0: " + e);
}
}
}

o/p

if one argument is given by Run-> Run configurations -> Arguments


a=1

if two arguments are given by Run-> Run configurations -> Arguments


a=2
Exception occurs at outer [Link] by 0: [Link]: / by zero

if three arguments are given by Run-> Run configurations -> Arguments


a=3
Exception occurs at inner [Link] index out-of-bounds:
[Link]: Index 42 out of bounds for length 1

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 with one command-line argument generates a divide-by-zero


exceptionfrom 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:

throw

So far, you have only been catching exceptions that are thrown by the Java run-time system.
However, it is possible for your program to throw an exception explicitly, using the throw
statement. The general form of throw is shown here:

throw ThrowableInstance;

Here is a sample program that creates and throws an exception. The handler that
catches the exception rethrows it to the outer handler.
// This is the updated code

package Exception;

class ThrowsDemo2 {
static void throwOne() throws IllegalAccessException {
[Link]("Inside throwOne.");
throw new IllegalAccessException("demonstrating Illegal Access Exception");
}

public static void main(String[] args) {


try {
throwOne();
} catch (IllegalAccessException e) {
[Link]("Caught " + e);
}
}
}
o/p

Inside throwOne.
Caught [Link]: demonstrating Illegal Access Exception

In Java, throw and throws are both used in the context of exception handling, but they serve
different purposes. Let's explore the differences between the two, followed by examples.
1. throw Keyword
The throw keyword is used to explicitly throw an exception in your code. It is followed by an
instance of Throwable (which includes both Exception and Error). When the throw
statement is executed, the control is immediately transferred to the nearest matching catch
block.
 Purpose: To explicitly throw an exception at runtime.
 Example: throw new Exception("Error message");

2. throws Keyword
The throws keyword is used in a method declaration to indicate that the method can throw exceptions
of the specified type. It informs the caller of the method that it must handle or declare these exceptions.
 Purpose: To declare that a method might throw certain exceptions.
 Example: public void myMethod() throws IOException { }

Differences Between throw and throws:


Feature throw throws
Used to explicitly throw an Used in method signatures to
Usage
exception declare exceptions
Position Inside the method body In the method declaration
Requires an instance of Specifies one or more exception
Exception Type Throwable
types
Causes the immediate transfer of Declares that the method might
Control Flow
control throw an exception
Number of Can be used multiple times in a Can only be used once in the
Occurrences method method signature
Example Program for throw
In this example, we’ll explicitly throw an ArithmeticException when division by zero is
attempted.

public class ThrowExample {


public static void main(String[] args) {
try {
divide(10, 0);
} catch (ArithmeticException e) {
[Link]("Exception caught: " + [Link]());
}
}

// Method that throws an exception explicitly using 'throw'


public static void divide(int a, int b) {
if (b == 0) {
throw new ArithmeticException("Division by zero is not allowed");
} else {
[Link]("Result: " + (a / b));
}
}
}

o/p

Exception caught: Division by zero is not allowed

Example Program for throws


In this example, we will declare that a method might throw an IOException when trying to read
a file that doesn’t exist.
import [Link].*;

public class ThrowsExample {


public static void main(String[] args) {
try {
readFile("[Link]");
} catch (IOException e) {
[Link]("Caught IOException: " + [Link]());
}
}

// Method that declares it throws an IOException


public static void readFile(String fileName) throws IOException {
File file = new File(fileName);
FileReader fr = new FileReader(file); // This will throw FileNotFoundException (which is a
subclass of IOException)
[Link]("File opened successfully");
[Link]();
}
}
o/p

Caught IOException: [Link] (No such file or directory)

Explanation:
1. throw Example:

 The divide() method explicitly throws an ArithmeticException when division


by zero is detected. This exception is caught in the main() method, demonstrating how
throw is used for raising exceptions explicitly.
2. throws Example:

 The readFile() method declares that it may throw an IOException. When


attempting to open a file that doesn't exist, a FileNotFoundException (a subclass
of IOException) is thrown. The main() method handles this exception by catching
it in a try-catch block.

Key Takeaways:
 Use throw when you want to explicitly raise an exception from a specific point in your
code.
 Use throws to declare that a method might throw an exception, allowing the caller to
handle or declare it.

Finally

When exceptions are thrown, execution in a method takes a rather abrupt, nonlinear path that alters the
normal flow through the method. Depending upon how the method is coded, it is even possible for an
exception to cause the method to return prematurely. This could be a problem in some methods. For
example, if a method opens a file upon entry and closes it upon exit, then you will not want the code
that closes the file to be bypassed by the exception-handling mechanism. The finally keyword is
designed to address this contingency. 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 an 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 handles
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. Here is an example
program that shows three methods that exit in various ways, none without executing their finally
clauses:
// Demonstrate finally.
class FinallyDemo {
// Throw an exception out of the method.
static void procA() {
try {
[Link]("inside procA");
throw new RuntimeException("demo");
} finally {
[Link]("procA's finally");
}
}

// Return from within a try block.


static void procB() {
try {
[Link]("inside procB");
return;
} finally {
[Link]("procB's finally");
}
}

// Execute a try block normally.


static void procC() {
try {
[Link]("inside procC");
} finally {
[Link]("procC's finally");
}
}

public static void main(String[] args) {


try {
procA();
} catch (Exception e) {
[Link]("Exception caught");
}
procB();
procC();
}
}
o/p

inside procA
procA's finally
Exception caught
inside procB
procB's finally
inside procC
procC's finally

This is an updted notes

final keyword in Java as a non-access modifier

In Java, the final keyword is a non-access modifier that prevents users from changing or modifying
entities. It can be used with variables, methods, and classes to ensure that they are immutable and
cannot be inherited or overridden:

Final variables: A final variable is a constant, meaning that its value cannot be changed after it has
been initialized. For example, final int MAX_VALUE = 100.

Final methods: A final method cannot be overridden by subclasses, ensuring that the method's
implementation remains unchanged.

Final classes: A final class cannot be subclassed, preventing inheritance.


The final keyword can help ensure thread safety, security, error prevention, code optimization, and
design intent. For example, the String class in Java uses final to ensure immutability, which is
important for security and string pool functionality.

Finalize() in Java

The Java finalize() method of Object class is a method that the Garbage Collector always calls just
before the deletion/destroying the object which is eligible for Garbage Collection to perform clean-up
activity. Clean-up activity means closing the resources associated with that object like Database
Connection, Network Connection, or we can say resource de-allocation.

public class FinalizeExample {


public static void main(String[] args)
{
FinalizeExample obj = new FinalizeExample();

obj = null;
// calling the garbage collector using gc()
[Link]();
[Link]("End of the garbage collection");
}
// defining the finalize method
protected void finalize()
{
[Link]("Called the finalize() method automatically by garbage collector just before
deleting an object");
}

Output:
End of the garbage collection
Called the finalize() method automatically by garbage collector just before deleting an object

Java’s Built-in Exceptions

Inside the standard package [Link], Java defines several exception classes. A few have been used by
the preceding examples. The most general of these exceptions are subclasses of the standard type
RuntimeException.
As previously explained, these exceptions need not be included in any method’s throws list. In the
language of Java, these are called unchecked exceptions because the compiler does not check to see if
a method handles or throws these exceptions. The unchecked exceptions defined in [Link] are listed
in Table 10-1. Table 10-2 lists those exceptions defined by [Link] that must be included in a
method’s throws list if that method can generate one of these exceptions and does not handle it itself.
These are called checked exceptions. In addition to the exceptions in [Link], Java defines several
more that relate to its other standard packages.

Table 10-1

Table
10-2
Creating Your Own Exception Subclasses

Although Java’s built-in exceptions handle most common errors, you will probably want to create your
own exception types to handle situations specific to your applications. This is quite easy to do: just
define a subclass of Exception (which is, of course, a subclass of Throwable). Your subclasses don’t
need to actually implement anything—it is their existence in the type system that allows you to use
them as exceptions. The Exception class does not define any methods of its own. It does, of course,
inherit those methods provided by Throwable. Thus, all exceptions, including those that you create,
have the methods defined by Throwable available to them. They are shown in Table 10-3. You may also
wish to override one or more of these methods in exception classes that you create.
Table 10-3

Creating Your Own Exception Subclasses

Concept: Creating Your Own Exception Subclasses in Java

In Java, exceptions are objects that represent abnormal conditions during program execution. By
default, Java provides many standard exception classes like IOException, NullPointerException, etc.
However, sometimes the built-in exceptions are not specific enough for certain conditions in your
programs. In such cases, you can create your own custom exception classes by extending the Exception
class (or RuntimeException if you want unchecked exceptions).
Key Steps in Creating Your Own Exception Subclasses:

Extend a Java Exception class:


If the exception needs to be checked (i.e., it must be caught or declared), extend the Exception class.
For unchecked exceptions (which don't need to be caught or declared), extend RuntimeException.

Provide Constructors:
Typically, custom exceptions should have constructors that allow passing in error messages and other
relevant details, like a cause.

Throw and Handle the Exception:


You can then throw your custom exception in relevant places in your code using the throw keyword.
You can also handle the exception using the try-catch block as you would with any standard exception.
Example: Creating a Custom Exception in Java
In this example, we’ll create a custom exception called InsufficientBalanceException to represent a
situation where a user tries to withdraw more money than is available in their bank account.

Step-by-Step Code:
// Step 1: Create a Custom Exception by extending Exception class
class InsufficientBalanceException extends Exception {
// Constructor to allow error message
public InsufficientBalanceException(String message) {
super(message);
}
}

// Step 2: Create a BankAccount class that throws the custom exception


class BankAccount {
private double balance;

// Constructor to initialize account balance


public BankAccount(double balance) {
[Link] = balance;
}

// Method to withdraw money, throwing custom exception if balance is insufficient


public void withdraw(double amount) throws InsufficientBalanceException {
if (amount > balance) {
throw new InsufficientBalanceException("Insufficient funds! You have only $" + balance + " in
your account.");
} else {
balance -= amount;
[Link]("Withdrawal successful! New balance: $" + balance);
}
}
// Method to display balance
public void displayBalance() {
[Link]("Current balance: $" + balance);
}
}

// Step 3: Create a test class to use the custom exception


public class CustomExceptionExample {
public static void main(String[] args) {
// Create a bank account with an initial balance of $500
BankAccount account = new BankAccount(500.00);

// Attempt to withdraw money


try {
[Link]();
[Link](600.00); // This will cause the custom exception to be thrown
} catch (InsufficientBalanceException e) {
// Catch and handle the custom exception
[Link]("Exception: " + [Link]());
}

// Try another withdrawal


try {
[Link](200.00); // This will succeed
} catch (InsufficientBalanceException e) {
[Link]("Exception: " + [Link]());
}
}
}

o/p

Current balance: $500.0


Exception: Insufficient funds! You have only $500.0 in your account.
Withdrawal successful! New balance: $300.0

Explanation:
InsufficientBalanceException: This is a custom exception class that extends Exception. It has a
constructor that takes an error message as a parameter, which can be displayed when the exception is
thrown.

BankAccount class: This class represents a bank account with a balance. It has a method withdraw()
that checks if the withdrawal amount is greater than the current balance. If it is, it throws the
InsufficientBalanceException.

CustomExceptionExample: This is the main class where we test the functionality of the custom
exception. It tries to withdraw amounts from the account, handling the exception if it is thrown.
In this program, when an attempt is made to withdraw more money than available, the
InsufficientBalanceException is thrown and caught in the catch block, displaying the custom error
message.

Chained Exceptions

Concept: Chained Exceptions in Java

Chained exceptions in Java allow you to relate one exception to another. This is particularly useful
when one exception causes another, providing a way to keep track of the root cause of an error. The
idea is to throw one exception and associate it with the original exception that caused it,
maintaining a "chain" of exceptions that help in understanding the flow of errors.

Why Chained Exceptions Are Useful:

Root Cause Identification: Helps in tracing the original cause of the problem.

Detailed Error Reporting: When higher-level methods catch and throw exceptions, the lower-level
details are not lost.

Simplified Debugging: Multiple exceptions can be tied together, improving debugging in complex
programs.

Key Methods for Chaining Exceptions:

[Link](Throwable cause): This method is used to set the cause of an exception.

[Link](): This method returns the cause of the current exception.


You can also pass the cause directly into the constructor of many exception types, as most exceptions
provide constructors that accept a Throwable as an argument.

Example: Chained Exceptions in Java

Let’s create an example where a FileNotFoundException is thrown at a lower level, which causes a
CustomDatabaseException to be thrown at a higher level, using chained exceptions to link the two.

Step-by-Step Code:
import [Link].*;

// Step 1: Create a custom exception that supports exception chaining


class CustomDatabaseException extends Exception {
// Constructor accepting message and cause (chaining the root cause)
public CustomDatabaseException(String message, Throwable cause) {
super(message, cause);
}
}

public class ChainedExceptionExample {


// Method simulating a file operation that throws FileNotFoundException
public static void readFile() throws FileNotFoundException {
// Simulate file not found scenario
throw new FileNotFoundException("File not found while reading the database config file.");
}

// Method that interacts with the database, catching and chaining the exception
public static void connectToDatabase() throws CustomDatabaseException {
try {
// Attempt to read a file that does not exist
readFile();
} catch (FileNotFoundException e) {
// Chain the FileNotFoundException to a higher-level custom exception
throw new CustomDatabaseException("Database connection failed due to a file issue.", e);
}
}

public static void main(String[] args) {


try {
// Attempt to connect to the database, which will trigger exception chaining
connectToDatabase();
} catch (CustomDatabaseException e) {
// Catch the custom exception and print details
[Link]("Caught Exception: " + [Link]());

// Use getCause() to retrieve the original exception


Throwable cause = [Link]();
if (cause != null) {
[Link]("Caused by: " + cause);
}
}
}
}

o/p

Caught Exception: Database connection failed due to a file issue.


Caused by: [Link]: File not found while reading the database config file.

Explanation:
1. CustomDatabaseException: This is a custom exception that supports exception chaining. It
has a constructor that accepts a message and a Throwable cause, allowing the chaining of
exceptions.
2. readFile(): This method simulates a scenario where a FileNotFoundException is thrown
(e.g., when trying to read a non-existent configuration file).
3. connectToDatabase(): This method attempts to call readFile() but catches the
FileNotFoundException. It then throws a higher-level exception,
CustomDatabaseException, and chains the original exception using the constructor.

4. main(): In the main method, we attempt to connect to the database and catch the
CustomDatabaseException. The original exception is retrieved using the getCause()
method, showing the chain of exceptions.
Flow of Exceptions:
1. The program attempts to read a file in readFile(), which throws a
FileNotFoundException.
2. connectToDatabase() catches this exception and throws a new
CustomDatabaseException, chaining the FileNotFoundException as its cause.
3. The CustomDatabaseException is caught in main(), and the original
FileNotFoundException is accessed using getCause().

This approach makes it easy to track the sequence of events leading to an exception, helping developers
debug issues efficiently.

You might also like