Understanding Advance JAVA In One Article

Since Java is an object-oriented language, complete Java language is built on classes and object. Java is also known as a strong Object-oriented programming language(OOPS).

OOPS is a programming approach which provides a solution to problems with the help of algorithms based on the real world. It uses a real-world approach to solve a problem. So object oriented technique offers a better and easy way to write a program then procedural programming model such as C, ALGOL, PASCAL.

MAIN FEATURES OF OOPS

1. Inheritance

2. Polymorphism

3. Encapsulation

4. Abstraction

As an object orient language, Java supports all features given above. We will discuss all these features in detail later.

CLASS

In Java, everything is encapsulated underclass. The class is the core of Java language. The class can be defined as a template/blueprint that describes the behaviour of a particular entity. A class defines new data types. Once defined this new type can be used to create an object of that type. The object is an instance of a class. You may also call it as physical existence of a logical templates class.

A class is declared using class keyword. A class contain both data and code that operate on the data. The data or variables defined within a class are called instance variables and that code operates on that data. The data or variable defined within a class are called instance variables and the code that operates on this data is known as methods. Thus, the instance variable and methods are known as class members. A class is also known as a user-defined datatype.

RULES OF JAVA

1. A class can have only public or default access specifier.

2. It can be either abstract, final or concrete.

3. It must have the class keyword, and class must be followed by a legal identifier.

4. It may optionally extend one parent class. By default, it will extend java.lang.Object.

5. It may optionally implement any number of comma-separated interfaces.

6. The class’s variable and methods are declared within a set of curly braces {}.

7. Each .java source file may contain only one public class. A source file may contain any number of default visible classes.

8. Finally, the source file name must match the public class name and it must have a .java suffix.

A SIMPLE CLASS EXAMPLE

Suppose, a test is a class and student’s name, roll number, age will be the property. And down here is the code for it.

public class test {
String name;
int rollnumber;
int age;
}

when a reference is made to a particular student with its property then it becomes an object, physical existence of Student class.

student std= new student();

after the above statement, std is instance/object of student class. Here the new keyword creates an actual physical copy of the object and assigns it to the std variable. It will have physical existence and get memory in help area. The new operator dynamically allocates memory for an object.

METHODS IN JAVA

Methods describes behavior of an object. A method is a collection of statement that is group together to perform an operation.

return-type methodName(parameter-list)
{
// this is going to be the body
}

EXAMPLES OF METHODS

public string getName(String st) {
string name = “read”;
name = name +st;
return name;
}

MODIFIER: Modifier is access type of method. We will discuss it in detail later.

Return type: A method may return value. A data type of value return by a method is declared in method heading.

Method name: the actual name of the method.

Parameter: value passed to a method.

Method body: a collection of statement that defines what method does.

PARAMETER VS. ARGUMENT

While talking about the method, it is important to know the difference between the two terms parameter and argument.

The parameter is a variable defined by a method that receives value when the method is called. Parameter is always local to the method they don’t have scope outside the method. While argument is a value that is passed to a method when it is called.

public class sum (int x. int y){
System.out.println(x+y);
}
public static void main(String [] args) {
Test b = new Test();
b.sum(10,20);
}

here int x and int y are the parameters and the value 10 and 20 are the arguments.

There are two ways to pass an argument to a method.

1. Call-by-value: in this approach copy of an argument value is pass to a method. Changes made to the argument value inside the method will have no effect on the arguments.

2. Call-by-reference: in this reference of an argument is pass to a method. Any changes made inside the method will affect the argument value.

NOTE: there is only call by value in java, not call by reference.

EXAMPLE OF CALL-BY-VALUE

public class Test {
public void callbyvlaue(int x ) {
x = 100;
}
public static void main(String [] args) {
int x = 50;
Test t = new Test();
t.callbyvlaue(x); // here we call the function
System.out.println(x);
}
}
Output will be 50

METHOD OVERLOADING

If two or more methods in a class have the same name but different parameters, it is known as method overloading. Overloading always occurs in the same class (unlike method overloading). Method overloading is one of the ways through which java supports polymorphism. Method overloading can be done by changing number of arguments or by changing the data type of argument. If two or more method has the same name and same parameter list but differs in return type are not said to be overloaded method.

DIFFERENT WAYS OF METHOD OVERLOADING

There are two different ways of method overloading.

METHOD OVERLOADING BY CHANGING DATA TYPE OF ARGUMENTS

import com.sun.javafx.css.CalculatedValue;
public class calculate {
void sum (int a, int b) {
System.out.println(“sum is” +(a+b));
}
void sum (float a, float b) {
System.out.println(“sum is “ + (a + b));
}
public static void main(String [] args) {
CalculatedValue cal = new CalculatedValue();
cal.sum(8,5);
cal.sum(4.6f, 3.8f);
}
}
sum is 13
sum is 8.4

you can see that sum() method is overload two times. The first takes two integer arguments, the second takes two float arguments.

METHOD OVERLOADING BY CHANGING NUMBER OF ARGUMENT

Example

class Area
{
void find(int l, int b)
{
System.out.println(“Area is”+(l*b)) ;
}
void find(int l, int b,int h)
{
System.out.println(“Area is”+(l*b*h));
}
public static void main (String[] args)
{
Area ar = new Area();
ar.find(8,5); //find(int l, int b) is method is called.
ar.find(4,6,2); //find(int l, int b,int h) is called.
}
}
area is 40
area is 48

in this example that find () method is overloaded twice. The first takes two arguments to calculate area, and the second takes three arguments to calculate the area. When an overloaded method is called java look for a match between the argument to call the method and the method’s parameter. This match need not always be exact sometime when an exact match is not found, java automatic type conversion plays a vital role.

EXAMPLE OF METHOD OVERLOADING WITH TYPE PROMOTION

class Area {
void find (long l, long b) {
System.out.println(“area is” + (l*b));
}
void find (int l, int b, int h ) {
System.out.println(“area is” + (l*b*h));
}
public static void main (String [] args) {
Area ar = new Area();
ar.find(8,5);
ar.find(2,4,5);
}
}
area is 40
area is 48

CONSTRUCTORS IN JAVA

A constructor is a special method that is used to initialize an object. Every class has a constructor, if we don’t explicitly declare a constructor for any java class the compiler builds a default constructor for that class. A constructor does not have any return type. A constructor has the same name as the class in which it resides. The constructor in Java cannot be abstract, static, final or synchronized. These modifiers are not allowed for a constructor.

class car {
String name;
String model;
car () {
name = “”;
model = “”;
}
}

THERE ARE TWO TYPES OF CONSTRUCTOR

1. Default constructor

2. Parameterized constructor

Each time a new object is created at least one constructor will be invoked.

Car c = new Car() // deafult constructor invoked
Car c = new Car (name) ; // paramerterized constuctor invoked

CONSTRUCTOR OVERLOADING

Like methods, a constructor can also be overloaded. Overloaded constructor is differentiated on the basis of their type of parameter or number of parameter. Constructor overloading is not much different than method overloading. In case of method overloading you have multiple methods with the same name but different signature, whereas in constructor overloading you have multiple constructors with different signature but the only difference is that constructor doesn’t have a return type in java. In case if you are wondering that why do we overload constructor? Then constructor overloading is one to construct an object in different ways.

EXAMPLE OF CONSTRUCTOR OVERLOADING

class Cricketer
{
String name;
String team;
int age;
Cricketer () //default constructor.
{
name =””;
team =””;
age = 0;
}
Cricketer(String n, String t, int a) //constructor overloaded
{
name = n;
team = t;
age = a;
}
Cricketer (Cricketer ckt) //constructor similar to copy constructor of c++
{
name = ckt.name;
team = ckt.team;
age = ckt.age;
}
public String toString()
{
return “this is “ + name + “ of “+team;
}
}
Class test: {
public static void main (String[] args)
{
Cricketer c1 = new Cricketer();
Cricketer c2 = new Cricketer(“sachin”, “India”, 32);
Cricketer c3 = new Cricketer(c2 );
System.out.println(c2);
System.out.println(c3);
c1.name = “Virat”;
c1.team= “India”;
c1.age = 32;
System .out. print in (c1);
}
}
output: this is Sachin of india x3

What’s the difference between constructor and normal methods? Then there are the answer constructors must have the same name as the class and can not return a value. They are only called for a single object once for a single object while regular methods could be called many times and it can return a value or can be void.

THIS KEYWORD

1. This keyword is used to refer to a current object.

2. This is always a reference to the object on which method was invoked.

3. This can be used to invoke the current class constructor.

4. This can be passed as an argument to another method.

class Box a{
Double width, height, depth;
Box (double w, double h, double d)
{
this.width = w;
this.height = h;
this.depth = d;
}
}

Here the this is used to initialize a member of current object. Such as, this.width refers to the variable width of the current object that has invoked the constructor width only refers to the parameter received in constructor i.e the argument passed while calling the constructor.

A string is probably the most commonly used class in java library. String class is encapsulated under java.lang package. In Java, every string that you create is actually an object of type String. One important thing to notice about string object is that string objects are immutable that means once a string object is created it cannot be altered.

an object whose state cannot be changed after it is created is known as an immutable object. String, Integer, Byte, Short, Float, Double and all other wrapper classes objects are immutable.

public class string {
final String str;
string(String s) {
this.str = s;
}
public String get() {
return str;
}
}

In this example string is an immutable class. string’s state cannot be changed once it is created.

CREATING A STRING OBJECT

A string can be created in a number of ways, here are few ways of creating string object.

String literal is a simple string enclosed in double quotes “ ”. A string literal is treated as a string object.

String str1 = “hello”;

You can also make a string using another string.

String str2 = new String(str1);

You can also make it using a new keyword.

String str3 = new String(“Java”);

A string can be made using + operator(Concatenation).

String str4 = str1 + str2;
or
String str5 = “hello” + “java”;

Each time you create a String literal, the JVM checks the string pool first. If the string literal already exists in the pool, a reference to the pool instance is returned. If a string does not exist in the pool, a new string object is created and is placed in the pool. String object is stored in a special memory area known as string constant pool inside the heap memory.

CONCATENATING STRING

There are 2 methods to concatenate two or more string.

Using the concat() method.

string s = “hello”;
string str = “java”;
string str2 = s.concat(str);
String str1 = “hello”.concat(“java”); //works with string literals too.

Using the + operator.

string str = “donald”;
string str1 = “trump”;
string str2 = str + str2;
string st = “donald” + “trump”;

STRING COMPARISON

String comparison can be done in 3 ways:

Using the equal () method.

equals() method compares two strings for equality. Its general syntax is.

boolean equals (object str)

it compares the content of the string. it will return true if the string matches, else return false.

String s = “hell”;
String s1 = “hello”;
String s2 = “hello”;
s1.equals(s2); //true
s.equals(s1); //flase

USING == OPERATOR

== operator compares two object references to check whether they refer to the same instance. This also will return true on a successful match.

String s1 = “java”;
String s2 = “java”;
String s3 = new string (“java”);
test(s1 == s2) // true
test (s1 == s3) // false

The reason for this is because we are creating a new object using the new operator, and thus it gets created in a non-pool memory area of the heap. s1 is pointing to the String in string pool while s3 is pointing to the String in heap and hence, when we compare s1 and s3, the answer is false.

BY compareTo() METHOD

compareTo() method compares values and return an int which tells if the string compared is less than, equal to or greater than the other string. it compares the String based on natural ordering. It’s general syntax is.

int comapreTo(String str)

STRING CLASS FUNCTION

The following methods are some of the most commonly used methods of String class.

charAt() function returns the character located at the specified index.

String str = “followme”;
Systrm.out.println(str.charAt(2));
output will be: l

Index of a String starts from 0, hence str.charAt(2) means the third character of the String str.

equalsIgnoreCase() determines the equality of two strings, ignoring their cases (upper or lower case doesn’t matter with this function).

String str = “java”;
System.out.println(str.equalsIgnorCase(“JAVA”));
output: true

indexOf()

indexOf() function returns the index of the first occurrence of a substring or a character. indexOf() method has four forms:

  • int indexOf(String str): It returns the index within this string of the first occurrence of the specified substring.
  • int indexOf(int ch, int fromIndex): It returns the index within this string of the first occurrence of the specified character, starting the search at the specified index.
  • int indexOf(int ch): It returns the index within this string of the first occurrence of the specified character.
  • int indexOf(String str, int fromIndex): It returns the index within this string of the first occurrence of the specified substring, starting at the specified index.
public class StudyTonight {
public static void main(String[] args) {
String str="StudyTonight";
System.out.println(str.indexOf('u')); //3rd form
System.out.println(str.indexOf('t', 3)); //2nd form
String subString="Ton";
System.out.println(str.indexOf(subString)); //1st form
System.out.println(str.indexOf(subString,7)); //4th form
}
}
output: 2, 11, 5, -1

length()

length() function return the number of character in a String.

String str = “Count me”;
System.out.println(str.length());
output: 8

replace()

replace() method replaces occurrences of a character with a specified new character.

String str = "Change me";
System.out.println(str.replace('m','M'));
output: Change Me

substring()

substring() the method returns a part of the string. substring() the method has two forms,

public String substring(int begin);
public String substring(int begin, int end);
/*
character of begin index is inclusive and character of end index is exclusive.
*/

The first argument represents the starting point of the substring. If the substring() method is called with only one argument, the substring returned, will contain characters from specified starting point to the end of the original string.

But, if the call to substring() method has two arguments, the second argument specifies the endpoint of the substring.

String str = "0123456789";
System.out.println(str.substring(4));
output: 456789
System.out.println(str.substring(4,7));
output: 456

toLowerCase ()

This method returns a string with all lowercase character changed to uppercase.

String str = "abcdef";
System.out.println(str.toUpperCase());
output : ABCDEF

toString()

toString() the method returns the string representation of the object used to invoke this method. toString() is used to represent any Java Object into a meaningful string representation. It is declared in the Object class, hence can be overridden by any java class. (Object class is a superclass of all java classes.)

public class Car {
public static void main(String args[])
{
Car c = new Car();
System.out.println(c);
}
public String toString()
{
return "This is my car object";
}
}
output: This is my car object

Whenever we will try to print an object of class Car, its toString() function will be called. toString() can also be used with normal string objects.

String str = "Hello World";
System.out.println(str.toString());
output: Hello World

NOTE: If we don’t override the toString() method and directly print the object, then it would print the object id.

Example:

public class Car {
public static void main(String args[])
{
Car c = new Car();
System.out.println(c);
}
}
studytonight.Car@15db9742 (here studytonight is a user-defined package).

valueOf()

Overloaded version of valueOf() method is present in String class for all primitive data types and for the type object.

valueOf() a function is used to convert primitive data types into Strings.

public class Example{
public static void main(String args[]){
int num = 35;
String s1 = String.valueOf(num); //converting int to String
System.out.println(s1+"IAmAString");
}
}
output: 35IAmAString

But for objects, valueOf() method calls toString() function.

toString() with Concatenation

Whenever we concatenate any other primitive data type, or object of other classes with a String object, toString() function or valueOf() function is called automatically to change the other object or primitive type into a string, for successful concatenation.

int age = 10;
String str = "He is" + age + "years old.";

In the above case, 10 will be automatically converted into a string for concatenation using the function.

trim()

This method returns a string from which any leading and trailing whitespaces has been removed.

String str = "   hello  ";
System.out.println(str.trim());
output: hello

NOTE: If the whitespaces are between the string, for example: String s1 = "study tonight"; then System.out.println(s1.trim());will output "study tonight".

trim() method removes only the leading and trailing whitespaces.

StringBuffer class

StringBuffer class is used to create a mutable string object that its state can be changed after it is created. It represents growable and writeable character sequence. As we know that String objects are immutable, so if we do a lot of changes with String objects, we will end up with a lot of memory leak.

So StringBuffer class is used when we have to make a lot of modifications to our string. it is also threaded safe that is multiple threads cannot access it simultaneously.

  1. StringBuffer()
  2. StringBuffer(int size)
  3. StringBuffer(String str)
  4. StringBuffer(charSequence []ch)
  • StringBuffer() creates an empty string buffer and reserves room for 16 characters.
  • stringBuffer(int size) creates an empty string and takes an integer argument to set capacity of the buffer.

DIFFERENCE BETWEEN STRING AND StringBuffer

class Test {
public static void main(String args[])
{
String str = "donald";
str.concat("trump");
System.out.println(str); // Output: donald
StringBuffer strB = new StringBuffer("donald");
strB.append("trump");
System.out.println(strB); // Output: donaldtrump
}
}

Reason:

The output is such because String objects are immutable objects. Hence, if we concatenate on the same String object, it won’t be altered(Output: donald). But StringBuffer creates mutable objects. Hence, it can be altered(Output: donaldtrump)

append()

This method will concatenate the string representation of any type of data to the end of the invoking StringBuffer object. append() method has several overloaded forms.

StringBuffer append(String str)
StringBuffer append(int n)
StringBuffer append(Object obj)

The string representation of each parameter is appended to the StringBuffer object.

StringBuffer str = new StringBuffer("test");
str.append(123);
System.out.println(str);
output: test123

insert()

This method inserts one string into another. Here are a few forms of the insert() method.

StringBuffer insert(int index, String str)
StringBuffer insert(int index, int num)
StringBuffer insert(int index, Object obj)

Here the first parameter gives the index at which position the string will be inserted and a string representation of the second parameter is inserted into StringBuffer object.

StringBuffer str = new StringBuffer("test");
str.insert(4, 123);
System.out.println(str);
output: test123

reverse()

This method reverses the characters within a StringBuffer object.

StringBuffer str = new StringBuffer("Hello");
str.reverse();
System.out.println(str);
output: olleH

replace()

This method replaces the string from the specified start index to the end index.

StringBuffer str = new StringBuffer("Hello World");
str.replace( 6, 11, "java");
System.out.println(str);
output: Hello java

capacity()

This method returns the current capacity of the StringBuffer object.

StringBuffer str = new StringBuffer();
System.out.println( str.capacity() );
output: 16

Note: Empty constructor reserves space for 16 characters. Therefore the output is 16.

ensureCapacity()

This method is used to ensure a minimum capacity of StringBuffer object.

If the argument of the ensureCapacity() method is less than the existing capacity, then there will be no change in existing capacity.

If the argument of the ensureCapacity() method is greater than the existing capacity, then there will be a change in the current capacity using the following rule: newCapacity = (oldCapacity*2) + 2.

StringBuffer str = new StringBuffer();
System.out.println( str.capacity()); //output: 16 (since empty constructor reserves space for 16 characters)
str.ensureCapacity(30); //greater than the existing capacity
System.out.println( str.capacity()); //output: 34 (by following the rule - (oldcapac

Exception Handling is the mechanism to handle runtime malfunctions. We need to handle such exceptions to prevent abrupt termination of the program. The term exception means an exceptional condition, it is a problem that may arise during the execution of the program. A bunch of things can lead to exceptions, including programmer error, hardware failure, files that need to be opened cannot be found, resource exhaustion etc.

EXCEPTION

A JAVA exception is an object that describes that occurs in a program. When an exceptional event occurs in Java, an exception is said to be thrown. The code that’s responsible for doing something about the exception is called an exception handler.

All exception types are subclasses of class Throwable, which is at the top of the exception class hierarchy.

  1. Exception class is for exceptional conditions that the program should catch. This class is extended to create user-specific exception classes.
  2. RuntimeException is a subclass of Exception. Exceptions under this class are automatically defined for programs.
  3. An exception of type Error is used by the Java run-time system to indicate errors having to do with the run-time environment, itself.

EXCEPTIONS ARE CATEGORIZED INTO 3 CATEGORY

  1. Checked Exception: The exception that can be predicted by the programmer at the compile time.
  2. Unchecked Exception: Unchecked exceptions are the class that extends RuntimeException. An unchecked exception is ignored at compile time.
  3. Error: Errors are typically ignored in code because you can rarely do anything about an error.

Uncaught Exceptions

When we don’t handle the exceptions, they lead to unexpected program termination. Let’s take an example for a better understanding.

class UncaughtException
{
public static void main(String args[])
{
int a = 0;
int b = 7/a; // Divide by zero, will lead to exception
}
}

This will lead to an exception at runtime, hence the Java run-time system will construct an exception and throw it. As we don’t have any mechanism for handling an exception in the above program, hence the default handler will handle the exception and will print the details of the exception on the terminal.

EXCEPTION HANDLING MECHANISM

In JAVA, exception handling is done using five keywords,

  1. try
  2. catch
  3. throw
  4. throws
  5. finally

Exception handling is done by transferring the execution of a program to an appropriate exception handler when an exception occurs.

USING TRY AND CATCH

Try is used to guard a block of code in which exception may occur. This block of code is called the guarded region. A catch statement involves declaring the type of exception you are trying to catch. If an exception occurs in guarded code, the catch block that follows the try is checked, if the type of exception that occurred is listed in the catch block then the exception is handed over to the catch block which then handles it.

class Excp
{
public static void main(String args[])
{
int a,b,c;
try
{
a=0;
b=10;
c=b/a;
System.out.println("This line will not be executed");
}
catch(ArithmeticException e)
{
System.out.println("Divided by zero");
}
System.out.println("After exception is handled");
}
}
output:
Divided by zero
After exception is handled

An exception will be thrown by this program as we are trying to divide a number by zero inside try block. The program control is transferred outside try block. This the line “this line will not be executed” is never parsed by the compiler. The exception thrown is handled in the catch block. Once the exception is handled, the program control continues with the next line in the program that is after the catch block. Thus the line “after an exception is handled” is printed.

MULTIPLE CATCH BLOCKS

A try block can be followed by multiple catch blocks. You can have any number of catch blocks after a single try block. If an exception occurs in the guarded code the exception is passed to the first catch block in the list. If the exception type of exception, matches with the first catch block it gets caught if not the exception is passed down to the next catch block. This continues until the exception is caught or falls through all catches.

class Excep
{
public static void main(String[] args)
{
try
{
int arr[]={1,2};
arr[2]=3/0;
}
catch(ArithmeticException ae)
{
System.out.println("divide by zero");
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("array index out of bound exception");
}
}
}
output:
divide by zero

Although both ArrayIndexOutOfBoundsException and ArithmeticException occurred, since the first catch is of Arithmetic Exception, it will be caught there and program control will be continued after the catch block. At a time, only once the exception is processed and only one respective catch block is executed.

While using multiple catch statement, it is important to remember that subclasses of class Exception inside catch must come before any of their superclasses otherwise it will lead to compile time error. This is because in Java, if any code is unreachable, then it gives compile time error.

class Excep
{
public static void main(String[] args)
{
try
{
int arr[]={1,2};
arr[2]=3/0;
}
catch(Exception e) //This block handles all Exception
{
System.out.println("Generic exception");
}
catch(ArrayIndexOutOfBoundsException e) //This block is unreachable
{
System.out.println("array index out of bound exception");
}
}
}
output:
Generic exception

NESTED TRY STATEMENT

try statement can be nested inside another block of try. The nested try block is used when a part of the block may cause one error while the entire block may cause another error. In case of the inner try block does not have a catch handler for a particular exception then the outer try-catch block is checked for a match.

class Excep
{
public static void main(String[] args)
{
try
{
int arr[]={5,0,1,2};
try
{
int x=arr[3]/arr[1];
}
catch(ArithmeticException ae)
{
System.out.println("divide by zero");
}
arr[4]=3;
}
catch(ArrayIndexOutOfBoundsException e)
{
System.out.println("array index out of bound exception");
}
}
}
output:
divide by zero 
array index out of bound exception

Try WITH RESOURCE STATEMENT

JDK 7 introduces a new version of a try statement known as a try-with-resources statement. This feature adds another way to exception handling with resources management. It is also referred to as automatic resource management.

syntax:

try(resource-specification(there can be more than one resource))
{
//use the resource
}catch()
{...}

This try statement contains a parenthesis in which one or more resources declared. Any object that implements java.lang.AutoCloseable or java.io.Closeable can be passed as a parameter to try a statement. A resource is an object that is used in a program and must be closed after the program is finished. The try-with-resources statement ensures that each resource is closed at the end of a statement of the try block. You do not have to explicitly close the resources.

Example without using try with Resource Statement

import java.io.*;
class Test
{
public static void main(String[] args)
{
try{
String str;
//opening file in read mode using BufferedReader stream
BufferedReader br=new BufferedReader(new FileReader("d:\\myfile.txt"));
while((str=br.readLine())!=null)
{
System.out.println(str);
}
br.close(); //closing BufferedReader stream
}catch(IOException ie)
{ System.out.println("exception"); }
}
}

Example using try with Resource statement

import java.io.*;
class Test
{
public static void main(String[] args)
{
try(BufferedReader br=new BufferedReader(new FileReader("d:\\myfile.txt")))
{
String str;
while((str=br.readLine())!=null)
{
System.out.println(str);
}
}catch(IOException ie)
{ System.out.println("exception"); }
}
}

POINTS TO REMEMBER

  1. A resource is an object in a program that must be closed after the program has finished.
  2. Any object that implements java.lang.AutoCloseable or java.io.Closeable can be passed as a parameter to try a statement.
  3. All the resources declared in the try-with-resources statement will be closed automatically when the try block exits. There is no need to close it explicitly.
  4. We can write more than one resources in the try statement.
  5. In a try-with-resources statement, any catch or finally block is run after the resources declared have been closed.

THROW KEYWORD

throw keyword is used to throw an exception explicitly. The only object is Throwable class or its subclasses can be thrown. Program execution stops on encountering throw statement, and the closes catch statement is checked for matching the type of exception.

Syntax: throw ThrowableInstance

CREATING INSTANCE OF THROWABLE CLASS

There are two possible ways to create an instance of class Throwable,

  1. Using a parameter in the catch block.
  2. Creating an instance with a new operator.
new NullPointerException("test");

This constructs an instance of NullPointerException with name test.

EXAMPLE DEMONSTRATING THROW KEYWORD

Class Test
{
static void avg()
{
try
{
throw new ArithmeticException("demo");
}
catch(ArithmeticException e)
{
System.out.println("Exception caught");
}
}
 public static void main(String args[])
{
avg();
}
}

In the above example, the avg() method throws an instance of ArithmeticException, which is successfully handled using the catch statement and thus, the program outputs “Exception caught”.

throws Keyword

Any method that is capable of causing exceptions must list all the exceptions, possible during its execution so that anyone calling that method gets a prior knowledge about which exceptions are to be handled. A method can do so by using the throws keyword.

Syntax:

type method_name(parameter_list) throws exception_list
{
//definition of method
}

Example demonstrating throws keyword:

class Test
{
static void check() throws ArithmeticException
{
System.out.println("Inside check function");
throw new ArithmeticException("demo");
}
 public static void main(String args[])
{
try
{
check();
}
catch(ArithmeticException e)
{
System.out.println("caught" + e);
}
}
}
output:
Inside check function
caught java.lang.ArithmeticException: demo

DIFFERENCE BETWEEN THROW AND THROWS

  1. throw keyword is used to throw an exception explicitly, throws keyword is used to declare an exception possible during its execution.
  2. throw keyword is followed by an instance of Throwable class or one of its sub-classes. throws keyword is followed by one or more Exception class names separated by commas.
  3. throw keyword is declared inside a method body, throws keyword is used with method signature(method declaration).
  4. We cannot throw multiple exceptions using throw exception, we can declare multiple exceptions (separated by comms) using throws keyword.

FINALLY CLAUSE

A finally keyword is used to create a block of code that follows a try block. A finally block of code is always executed whether an exception has occurred or not. Using a finally block, it lets you run any cleanup type statement that you want to execute, no matter what happens in the protected code. A finally block appears at the end of the catch block.

Class ExceptionTest
{
public static void main(String[] args)
{
int a[]= new int[2];
System.out.println("out of try");
try
{
System.out.println("Access invalid element"+ a[3]);
/* the above statement will throw ArrayIndexOutOfBoundException */
}
finally
{
System.out.println("finally is always executed.");
}
}
}
output: 
Out of try
finally is always executed
Exception in thread main java.Lang. exception array Index out of bound ex

You can see in the above example even if the exception is thrown by the program, which is not handled by the catch block, still finally block will get executed.

USER DEFINED EXCEPTION SUBCLASS

You can also create your own exception subclass simply by extending java Exception class. You can define a constructor for your Exception subclass and you can override the toString() function to display your customized message on a scatch.

class MyException extends Exception
{
private int ex;
MyException(int a)
{
ex=a;
}
public String toString()
{
return "MyException[" + ex +"] is less than zero";
}
}
  class Test
{
static void sum(int a,int b) throws MyException
{
if(a<0)
{
throw new MyException(a); //calling constructor of user-defined exception class
}
else
{
System.out.println(a+b);
}
}
   public static void main(String[] args)
{
try
{
sum(-10, 10);
}
catch(MyException me)
{
System.out.println(me); //it calls the toString() method of user-defined Exception
}
}
}
output:
MyException[-10] is less than zero

METHOD OVERRIDING WITH EXCEPTION HANDLING

There are few things to remember when overriding a method with exception handling. If the superclass method does not declare any exception, then subclass overridden method cannot declare checked exceptions but it can declare unchecked exceptions.

example of subclass overridden Method declaring Checked Exception

import java.io.*;
class Super
{
void show() { System.out.println("parent class"); }
}
public class Sub extends Super
{
void show() throws IOException //Compile time error
{ System.out.println("parent class"); }
 public static void main( String[] args )
{
Super s=new Sub();
s.show();
}
}

As the method show() doesn’t throw any exception while in the superclass, hence it has overridden version also cannot throw any checked exception.

example of subclass overridden method declaring unchecked exception:

import java.io.*;
class Super
{
void show(){ System.out.println("parent class"); }
}
public class Sub extends Super
{
void show() throws ArrayIndexOutOfBoundsException //Correct
{ System.out.println("child class"); }
 public static void main(String[] args)
{
Super s=new Sub();
s.show();
}
}
output:
child class

Because ArrayIndexOutOfBoundsException is an unchecked exception hence, overridde show() method can throw it.

MORE ABOUT OVERRIDEN METHOD AND EXCEPTIONS

If the Super class method throws an exception, then the subclass overridden method can throw the same exception or no exception, but must not throw parent exception of the exception thrown by the Super class method.

It means, if the Super class method throws an object of NullPointerException class, then the subclass method can either throw the same exception or can throw no exception, but it can never throw an object of the Exception class.

example of subclass overridden method with the same Exception

import java.io.*;
class Super
{
void show() throws Exception
{ System.out.println("parent class"); }
}
public class Sub extends Super {
void show() throws Exception //Correct
{ System.out.println("child class"); }
 public static void main(String[] args)
{
try {
Super s=new Sub();
s.show();
}
catch(Exception e){}
}
}
output:
child class

example of subclass overridden method with no exception:

import java.io.*;
class Super
{
void show() throws Exception
{ System.out.println("parent class"); }
}
public class Sub extends Super {
void show() //Correct
{ System.out.println("child class"); }
 public static void main(String[] args)
{
try {
Super s=new Sub();
s.show();
}
catch(Exception e){}
}
}
output:
child class

The exception of the subclass overridden method with parent Exception:

import java.io.*;
class Super
{
void show() throws ArithmeticException
{ System.out.println("parent class"); }
}
public class Sub extends Super {
void show() throws Exception //Cmpile time Error
{ System.out.println("child class"); }
 public static void main(String[] args)
{
try {
Super s=new Sub();
s.show();
}
catch(Exception e){}
}
}

CHAINED EXCEPTION

Chained Exception was added to Java in JDK 1.4. This feature allows you to relate one exception with another exception, that is one exception describes the cause of another exception. For example, consider a situation in which a method throws an ArithmeticException because of an attempt to divide by zero bu the actual cause of exception was an input-output error which caused the divisor to be zero. The method will throw only Arithmetic Exception to the caller. So the caller would not come to know about the actual cause of the exception. The chained exception is used in such type of situation.

Two new constructor and two new methods were added to the Throwable class to support chained exception:

  1. Throwable (Throwable cause)
  2. Throwable (String str, Throwable cause)

In the first form, the parameter cause specifies the actual cause of the exception. In the second form, it allows us to add an exception description in string form with the actual cause of the exception.

getCause() and initCause() are the two methods added to Throwable class.

  1. getCause() method return the actual cause associated with the current exception.
  2. initCause() set an underlying cause with invoking the exception.

EXAMPLE:

import java.io.IOException;
public class ChainedException
{
public static void divide(int a, int b)
{
if(b==0)
{
ArithmeticException ae = new ArithmeticException("top layer");
ae.initCause( new IOException("cause") );
throw ae;
}
else
{
System.out.println(a/b);
}
}
 public static void main(String[] args)
{
try {
divide(5, 0);
}
catch(ArithmeticException ae) {
System.out.println( "caught : " +ae);
System.out.println("actual cause: "+ae.getCause());
}
}
}
OUTPUT:
caught: java.lang.ArithmeticException: top layer
actual cause: java.io.IOException: cause

INTRODUCTION TO MULTITHREADING

A program can be divided into a number of small process. Each small process can be addressed as a single thread. You can think of a lightweight process as a virtual CPU that exceeds code or system calls. You usually do not need to concern yourself with lightweight processess to program with threads. Multithreaded programs contain two or more threads that can run concurrently and each thread defines a separate path of execution. This means that single program can perform two task or more tasks simultaneously. For example, one thread is writing content on a file at the same time another thread is performing spelling check.

In Java, the word thread means two different things:

1. An instance of Thread class.

2. Or, A thread of execution.

An instance of Thread class is just an object, like any other object in JAVA. But a thread of execution means an individual “lightweight” process that has its own call stack. In java each thread has its own call stack.

THE main THREAD

When we run any java program, the program begins to execute its code starting from the main method. Therefore, the JVM creates to start executing the code present in main methods. This thread is called a main thread. Although the main thread is automatically created, you can control it by obtaining a reference to it by calling currentThread() method.

Two important things to know about main thread are,

1. It is the thread from which other threads will be produced.

2. main thread must be always the last thread to finish execution.

class MainThread
{
public static void main(String[] args)
{
Thread t=Thread.currentThread();
t.setName(“MainThread”);
System.out.println(“Name of thread is “+t);
}
}
Output:
Name of thread is[MainThread,5,main]

LIFE CYCLE OF A THREAD

1. New: A thread begins its life cycle in the new state. It remains in this state until the start() method is called on it.

2. Runnable: After invocation of start() method on new thread, the thread becomes runnable.

3. Running: A thread is in running state if the thread scheduler has selected it.

4. Waiting: A thread is in waiting state if it waits for another thread to perform a task. In this stage the thread is still alive.

5. Terminated: A thread enter the terminated state when it completes its task.

THREAD PRIORITIES

Every thread has a priority that helps the operating system determine the order in which threads are scheduled for execution. In Java thread priority ranges between 1 to 10.

1. MIN-PRIORITY (a constant of 1 )

2. MAX-PRIORITY(a constant of 10)

By default every thread is given a NORM-PRIORITY(5). The main thread always have a non-priority.

THREAD CLASS

Thread class is the main class on which Java’s Multithreading system is based. Thread class, along with its companion interface Runnable will be used to create and run threads for utilizing Multithreading feature of JAVA.

CONSTRUCTOR OF THREAD CLASS

1. Thread ()

2. Thread (String str)

3. Thread(Runnable r)

4. Thread(Runnable r, string str)

You ca create new thread, either by extending Thread class or by implementing Runnable interface. Thread class also defines many methods for managing threads. Some of them are,

1. setName(): to give thread a name

2. getName(): return thread’s name

3. getPriority(): return thread’s priority

4. isAlive(): checks if thread is still running or not

5. join(): wait for a thread to end

6. run(): entry point for a thread

7. sleep(): suspend thread for a specified time

8. start(): start a thread by calling run() method

SOME IMPORTANT POINTS TO REMEMBER

1. when we execute Thread class, we cannot override setName() and getName() functions, because they are declared final in Thread class.

2. While using sleep(), always handle the exception it throws.

static void sleep(long milliseconds) throws InterruptedException

CREATING A THREAD

Java defines two ways by which a thread can be created.

1. By implementing the Runnable interface.

2. By extending the Thread class.

IMPLEMENTING THE RUNNABLE INTERFACE

The easiest way to create a thread is to create that implements the runnable interface. After implementing runnable interface, the class needs to implement the run() method, which is of form.

Public void run()

1. Run() method introduces a concurrent thread into your program. This thread will end when run() method terminates.

2. You must specify the code that your thread will execute inside run() method.

3. Run() method can call other methods, can use other classes and declare variables just like any other normal method.

class MyThread implements Runnable
{
public void run()
{
System.out.println("concurrent thread started running..");
}
}
class MyThreadDemo
{
public static void main( String args[] )
{
MyThread mt = new MyThread();
Thread t = new Thread(mt);
t.start();
}
}
Output:
Concurrent thread started running..

To call the run() method, start() method is used. On calling start(), a new stack is provided to the thread and run() method is called to introduce the new thread into the program. If you are implementing runnable interface in your class, then you need to explicitly create a thread class object and need to pass the Runnable interface implemented class object as a parameter in its constructor.

EXTENDING THREAD CLASS

This is another way to create a thread by a new class that extends Thread class and create an instance of that class. The extending class must override run() method which is the entry point of new thread.

class MyThread extends Thread
{
public void run()
{
System.out.println("concurrent thread started running..");
}
}
classMyThreadDemo
{
public static void main( String args[] )
{
MyThread mt = new  MyThread();
mt.start();
}
}
Output:
Concurrent thread started running..

In this case also, we must override the run() and then use the start() method to run the thread. Also, when you create MyThread class object, thread class constructor will also be invoked, as it is the super class, hence MyThread class object acts as Thread class object.

What if we call run() method directly without using start() method?

In above program if we directly call run() method, without using start() method.

public static void main( String args[] )
{
MyThread mt = new MyThread();
mt.run();
}

Doing so, the thread won’t be allocated a new call stack, and it will start running in the current call stack, that is the call stack of the main thread. Hence Multithreading won’t be there.

CAN WE START THREAD TWICE?

No, a thread cannot be started twice. If you try to do so.

IllegalThreadException will be thrown.

public static void main( String args[] )
{
MyThread mt = new MyThread();
mt.start();
mt.start();     //Exception thrown
}

When a thread is in running stable, and you try to start it again, or any method try to invoke that thread again using start() method, exception is thrown.

JOINING THREADS

Sometimes one thread needs to know when other thread is terminating. In JAVA, isAlive() and join() are two different methods that are used to check whether a thread has finished its execution or not.

This isAlive() method returns true if the thread upon which it is called is still running otherwise it returns false.

final boolean isAlive()

but, join() method is used more commonly that isAlive(). This method waits until the thread on which it is called terminates.

final void join() throws InterruptedException

Using join() method, we tell our thread to wait until the specified thread completes its execution. There are overloaded versions of join() method, which allows us to specify time for which you want to wait for the specified thread to terminate.

final void join(long milliseconds) throws InterruptedException

As we have seen in the introduction, the main thread must always be the last thread to finish its execution. Therefore, we can use thread join() method to ensure that all the threads created by the program has been terminated before the execution of the main thread.

Example of isAlive()

public class MyThread extends Thread
{
public void run()
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}
catch(InterruptedException ie) { }
System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
t2.start();
System.out.println(t1.isAlive());
System.out.println(t2.isAlive());
}
}
Output:
r1
true
true
r1
r2
r2

example of thread without join() method

public class MyThread extends Thread
{
public void run()
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}
catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
t2.start();
}
}
Output:
r1
r1
r2
r2

In this above program two thread t1 and t2 are created. t1 starts first and after printing “r1” on console thread t1 goes to sleep for 500 ms. At the same time Thread t2 will start its process and print “r1” on console and then go into sleep for 500 ms. Thread t1 will wake up from sleep and print “r2” on console similarly thread t2 will wake up from sleep and print “r2” on console. So you will get output like r1 r1 r2 r2

Example of thread with join() method

public class MyThread extends Thread
{
public void run()
{
System.out.println("r1 ");
try {
Thread.sleep(500);
}catch(InterruptedException ie){ }
System.out.println("r2 ");
}
public static void main(String[] args)
{
MyThread t1=new MyThread();
MyThread t2=new MyThread();
t1.start();
try{
t1.join();      //Waiting for t1 to finish
}catch(InterruptedException ie){}
t2.start();
}
}
Output:
r1
r2
r1
r2

In this above program join() method on thread t1 ensures that t1 finishes it process before thread t2 starts.

Specifying time with join()

If in the above program, we specify time while using join() with t1, then t1 will execute for that time, and then t2 will join it.

t1.join(1500);

Doing so, initially t1 will execute for 1.5 seconds, after which t2 will join it.

SYNCHRONIZATION

At times when more than one thread try to access a shared resource, we need to ensure that resource will be used by only one thread at a time. The process by which this is achieved is called synchronization. The synchronization keyword in java creates a block of code referred to as critical section.

General syntax:

synchronized (object)
{
//statement to be synchronized
}

Every java object with a critical section of code gets a lock associated with the object. To enter critical section a thread need to obtain the corresponding object’s lock.

WHY WE USE SYNCHRONIZATION?

If we do not use syncronization, and let two or more threads access a shared resource at the same time, it will lead to distorted results.

Consider an example, suppose we have two different threads T1 and T2, T1 starts execution and save certain values in a file temporary.txt which will be used to calculate some result when T1 returns. Meanwhile, T2 starts and before T1 returns, T2 changes the value saved by T1 in the file temporary.txt. Now obviously T1 will return wrong result.

To prevent such problem, synchronization was introduced. With synchronization in above case, once T1 starts using temporary.txt file, this file will be locked, and no other thread will be locked, and no other thread will be able to access or modify it until T1 returns.

USING SYNCHRONIZED METHODS

Using synchronized methods is a way to accomplish synchronization. But lets first see what happens when we do not use synchronization is our program.

Example with no synchronization

class First
{
public void display(String msg)
{
System.out.print ("["+msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
start();
}
public void run()
{
fobj.display(msg);
}
}
public class Syncro
{
public static void main (String[] args)
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second (fnew,"new");
Second ss2 = new Second(fnew, "programmer");
}
}
Output:
[welcome [ new [ programmer]
]
]

In the above, object fnew of class First is shared by all three running threads(ss, ss1 and ss2) to call the shared method(void display). Hence the result is unsynchronized and such situation is called Race condition.

SYNCHRONIZED KEYWORD

To synchronized above program, we must synchronize access to the shared display() method, making it available to only one thread at a time. This is done by using keyword synchronized with display() method.

As synchronized void display(String msg)

USING SYNCHRONIZED BLOCK

If you have to synchronized access to an object of a class or you only want a part of a method to be synchronized to an object then you can use synchronized block for it.

class First
{
public void display(String msg)
{
System.out.print ("["+msg);
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
System.out.println ("]");
}
}
class Second extends Thread
{
String msg;
First fobj;
Second (First fp,String str)
{
fobj = fp;
msg = str;
start();
}
public void run()
{
synchronized(fobj)       //Synchronized block
{
fobj.display(msg);
}
}
}
public class Syncro
{
public static void main (String[] args)
{
First fnew = new First();
Second ss = new Second(fnew, "welcome");
Second ss1= new Second (fnew,"new");
Second ss2 = new Second(fnew, "programmer");
}
}
Output:
[welcome]
[new]
[programmer]

Because of the synchronized block, this program gives the expected output.

DIFFERENCE BETWEEN SYNCHRONIZED KEYWORD AND SYNCHRONIZED BLOCK

When we use synchronized keyword with a method, it acquires a lock in the object for the whole method. It means that no other thread can use any synchronized method until the current thread, which has invoked it’s synchronized method, has finished its execution.

Synchronized block acquires a lock in the object only between parentheses after the synchronized keyword. This means that no other thread can acquire a lock on the locked object until the synchronized block exists. But other threads can access the rest of the code of the method.

INTERHREAD COMMUNICATION

Java provide benefits of avoiding thread pooling using inter-thread communication. The wait(), notify() and notifyAll() methods of Object class are used for this purpose. These methods are implemented as final methods in Object, so that all classes have them. All the three methods can be called only from within a synchronized context.

1. Wait() tells calling thread to give up monitor and go to sleep until some other thread enters the same monitor and call notify.

2. Notify() wakes up a thread that called wait() on same object.

3. notifyAll() wakes up the thread that called wait() on same object.

DEADLOCK

Deadlock is a situation of complete lock, when no thread can complete its execution because of lack of resources.

Example of deadlock

class Pen{}
class Paper{}
public class Write {
public static void main(String[] args)
{
final Pen pn =new Pen();
final Paper pr =new Paper();
Thread t1 = new Thread(){
public void run()
{
synchronized(pn)
{
System.out.println("Thread1 is holding Pen");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
synchronized(pr)
{  System.out.println("Requesting for Paper"); }
}
}
};
Thread t2 = new Thread(){
public void run()
{
synchronized(pr)
{
System.out.println("Thread2 is holding Paper");
try{
Thread.sleep(1000);
}catch(InterruptedException e){}
synchronized(pn)
{  System.out.println("requesting for Pen"); }
}
}
};
t1.start();
t2.start();
}
}
Output:
Thread1 is holding Pen
Thread2 is holding Paper