Java Notes
Java Notes
Evaluation Strategy
section .data
msg db 'Hello World!!',0
section .text
global _start
_start:
; Write the string to stdout
mov eax, 4 ; System call for "write"
mov ebx, 1 ; File descriptor for stdout
mov ecx, msg ; Pointer to the message
mov edx, 13 ; Length of the message
int 0x80 ; Call the kernel
What is Technology?
• Technology refers to the tools and techniques used to create and manipulate information. In
Simple words, we can develop application using technology.
• Example:
• Java
• Artificial Intelligence (AI)
• Blockchain
• Augmented Reality (AR)
• Internet of Things (IoT)
• Cloud Computing
• Note: Every language can be considered as technology but every technology can not be
considered as language.
• Reference: https://docs.oracle.com/javase/tutorial/getStarted/intro/definition.html
Contents of package
Sub package
Interface
Nested Type
Constant Fields
Abstract Methods
Default Methods
Static Interface Methods
Class
Nested Types( Interface / Class / Enum )
Fields
Constructor
Method
Enum
Exception
For students use only 11 / 363
Error
Annotation Type
Modifiers in Java
PUBLIC
PRIVATE
PROTECTED
STATIC
FINAL
SYNCHRONIZED
VOLATILE
TRANSIENT
NATIVE
INTERFACE
ABSTRACT
STRICT
Reference: https://docs.oracle.com/javase/8/docs/api/java/lang/reflect/Modifier.html
Access Modifiers
Modifiers which are used to control visibility of members of the class is called access modifier.
Access modifiers
private
Package level private( also called as default )
protected
public
More about main method
In java, main method is considered as entry point method.
With the help of main thread, JVM invoke main method.
Syntax:
public static void main(String args[] )
public static void main(String[] args )
public static void main(String... args )
We can define main method inside class as well as interface.
class Program{
public static void main(String[] args ) {
System.out.println("Hello World!!!");
}
}
interface Program{
public static void main(String[] args ) {
Reference: https://docs.oracle.com/javase/tutorial/getStarted/application/index.html
Java Comments
To maintain documentation of source code we should use comments:
Types of comments:
Implementation Comments
Block comments / multiline comments
class Program{
/* public static void main(String args[] ) {
System.out.println("Hello World!!!");
} */
public static void main(String[] args ) {
System.out.println("Hello World!!!");
}
}
class Program{
public static void main(String[] args ) {
//System.out.println("Hello World!!!");
System.out.println("Good Morning");
}
}
/**
Author is Sandeep Kulange
*/
class Program{
/**
Entry point method of class Program
*/
public static void main(String[] args ) {
System.out.println("Hello World!!!");
}
}
Reference: https://www.oracle.com/java/technologies/javase/codeconventions-comments.html
For students use only 13 / 363
Java OOPS concepts
Consider following code:
class Test{
//Fields
private int num1; //Instance variable
private static int num2; //Class level variable
//Methods
public void setNum1( int num1 ){ //Instance method
this.num1 = num1;
}
public static void setNum2( int num2 ){ //Class level method
this.num2 = num2;
}
}
In Java, to access static members ( class level members ) of the class, we must use class name and
dot operator.
To access non static members( instance members ) of the class, we must use instance of the class.
class Program{
public static void main(String[] args) {
System.out.println("Hello World!!");
}
}
A class from which we can not create child / sub class is called as final class.
We can instantiate final class.
Example:
java.lang.System
java.lang.String
If method in parent /super class is final then we can not redefine / override that method in child / sub
class.
What is System.out.println?
package java.lang;
public final class System {
//Fields
public final static InputStream in = null;
package java.io;
public class PrintStream extends FilterOutputStream implements
Appendable, Closeable{
class Program{
public static void main1(String[] args ) {
System.out.print("Hello ");
System.out.print(" World");
System.out.print("!!");
}
}
System.out.println method print output on console but it moves cursor to the next line.
class Program{
public static void main(String[] args ) {
System.out.println("Hello ");
System.out.println(" World");
System.out.println("!!");
}
}
Data Types
Data type of any variable describe following things:
( Memory ) How much memory is required to store the data.
( Nature ) Which type of data is allowed to store inside allocated memory.
( Range ) How much data is allowed to store inside allocated memory.
( Operation ) Which operations are allowed to perform / execute on the data stored inside
memory.
Types of data type
Primitive data type
Variable of primitive data type contains value. Hence primitive type is also called as value
type.
There are 8 primitive / value types in Java:
boolean
byte
char
short
int
float
double
long
Non Primitive data type
Variable of non primitive data type contains reference of the instance. Hence non
primitive type is also called as reference type.
There are 4 non primitive / reference types in Java
Interface
Class
Enum
Array
For students use only 18 / 363
If we declare variable inside method then it is called as method local variable.
In Java, we can not declare method local variable static.
class Program {
public static void main(String[] args) {
int number; //Non Static Method Local Variable //OK
}
}
class Program {
public static void main(String[] args) {
int number; //Non Static Method Local Variable
System.out.println( number ); //error: variable number might not
have been initialized
}
}
If we want to use any method local variable( primitive / non primive ) then we must store some value
inside it.
class Program {
public static void main(String[] args) {
int number = 10; //Initialization
System.out.println( number ); //OK
}
}
class Program {
public static void main(String[] args) {
int number;
number = 10; //Assignment
System.out.println( number ); //OK
}
}
If the string does not contain a parsable numeric value then parseXXX() method throws
NumberFormatException. Reference:
https://docs.oracle.com/javase/8/docs/api/java/lang/NumberFormatException.html
Commandline arguments
Consider code in C language
int sum( int num1, int num2 ){ //num1, num2 <= Function parameters
int result = num1 + num2;
return result;
}
int main( void ){
int result = sum( 10, 20 ); //10, 20 <= Function arguments
return 0;
}
class Program {
//args is a method parameter
public static void main(String[] args) {
System.out.println("Hello,"+args[ 0 ]);
}
}
class Program {
public static void main(String[] args) {
Stream
It is an abstraction( object /instance ) which is used to produce( write ) or consume( read )
information from source to destination.
Console = Keyboard + Monitor
Keyboard => Console Input
Monitor => Console Output
class Program{
public static void main( String[] args ){
java.util.Scanner sc = null; //reference
sc = new java.util.Scanner( System.in ); //Instance
}
}
class Program{
public static void main( String[] args ){
java.util.Scanner sc = new java.util.Scanner( System.in );
//Instance
}
}
import java.util.Scanner;
class Program{
public static void main( String[] args ){
Scanner sc = new Scanner( System.in ); //Instance
}
}
import java.util.Scanner;
class Program {
public static void main(String[] args) {
Scanner sc = new Scanner( System.in );
System.out.print("Name : ");
String name = sc.nextLine();
System.out.print("Empid : ");
int empid = sc.nextInt();
System.out.print("Salary : ");
float salary = sc.nextFloat();
Reference: https://docs.oracle.com/javase/8/docs/api/java/util/Scanner.html
Java language Features / buzzwords / ( Sun Microsystems Marketing Keywords )
Simple
Object oriented
Architecture neutral
Portable
Robust
Multithreaded
Dynamic
Secure
High Performance
Distributed
What is the meaning of Deprecated?
In Java, the term "Deprecated" is used to indicate that a particular method, class, or interface should
no longer be used because it is either obsolete, flawed, or has been replaced by a better alternative.
Instance creation in Java
In Java, we can create instance using 3 ways:
Using new operator
For students use only 29 / 363
Using factory method
Using reflection
Manipulating system date and time using Date, Calendar, LocalDate, LocalTime, LocalDateTime
System Date using java.util.Date class
import java.util.Date;
class Program {
public static void main(String[] args) {
Date date = new Date();
int day = date.getDate();
int month = date.getMonth() + 1;
int year = date.getYear() + 1900;
System.out.println(day+" / "+month+" / "+year);
}
}
The Calendar class should be used to convert between dates and time fields and the DateFormat
class should be used to format and parse date strings. The corresponding methods in Date are
deprecated.
Calendar is abstract class declared in java.util package.
LocalDate ld = LocalDate.now();
import java.time.LocalDate;
class Program {
public static void main(String[] args) {
LocalDate ld = LocalDate.now();
int day = ld.getDayOfMonth();
int month = ld.getMonthValue();
int year = ld.getYear();
System.out.println(day+" / "+month+" / "+year);
}
}
LocalTime lt = LocalTime.now();
import java.util.Date;
import java.text.SimpleDateFormat;
class Program {
public static void main(String[] args)throws Exception {
String pattern = "dd/MM/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat( pattern);
String source = "23/07/1983";
Date date = sdf.parse( source );
import java.util.Date;
import java.text.SimpleDateFormat;
class Program {
public static void main(String[] args) {
Date date = new Date( );
//SimpleDateFormat sdf = new SimpleDateFormat( "dd-MM-yyyy");
//SimpleDateFormat sdf = new SimpleDateFormat( "dd/MMM/yyyy");
SimpleDateFormat sdf = new SimpleDateFormat( "dd/MMMM/yyyy");
String strDate = sdf.format(date);
System.out.println( strDate );
}
}
Reference: https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html
Phases of software development life cycle
For students use only 32 / 363
Requirement
Analysis
Design
Coding / implementation
Testing
Deployment / installation
mentainance
Procedure orineted programming language
Write a program to accept, strore and print information of employeee
name : char[ 30 ]
empid : int
salary : float
A programming methodology in which we can solve real world problems using structure and global
function.
Object oriented programming in C++
//File Name: Main.cpp
#include<stdio.h>
class Employee{
private:
char name[ 30 ];
For students use only 33 / 363
int empid;
float salary;
public:
void acceept_record( /* struct Employee *this */ ){
printf("Name : ");
scanf("%s", this->name);
printf("Empid : ");
scanf("%d", &this->empid);
printf("Salary : ");
scanf("%f", &this->salary);
}
void print_record( /* struct Employee *this */ ){
printf("%-30s%-5d%-10.2f\n", this->name, this->empid, this->salary);
}
};
int main( void ){
Employee emp;
emp.accept_record( ); //emp.accept_record( &emp );
emp.print_record( ); //emp.print_record( &emp );
return 0;
}
A programming methodology, in which we can solve real world problem using class and object is
called object oriented programming.
Object oriented programming in Java
Write a program to strore and print date information.
day : int
month : int
year : int
Analyze problem statement and define the class.
class Date{
//TODO
}
Analyze the problem statement, decide and declare field inside class.
Variable declare inside class / class scope is called as field.
Variable declare inside method / method scope is called as method local variable.
class Date{
//Fields
int day;
int month;
int year;
}
new Date();
new Date();
new Date();
After instantiation, if we want to process( accept/print/get/set) state of the instance then we should
call method on instance.
class Date{
//TODO
}
Analyze the problem statement, decide and declare field inside class.
Variable declare inside class / class scope is called as field.
Variable declare inside method / method scope is called as method local variable.
class Date{
//Fields
int day;
int month;
int year;
}
new Date();
new Date();
new Date();
After instantiation, if we want to process( accept/print/get/set) state of the instance then we should
call method on instance.
String s1 = "";
String s2 = "Sandeep Kulange";
//"Sandeep Kulange" => String literal / literal
To access instance members of the class inside method, use of this keyword is optional.
For students use only 40 / 363
void acceptRecord( /*Employee this*/ ){
Scanner sc = new Scanner(System.in);
System.out.print("Name : ");
name = sc.nextLine(); //OK
System.out.print("Empid : ");
empid = sc.nextInt(); //Ok
System.out.print("Salary : ");
salary = sc.nextFloat(); //OK
}
Definition:
this reference is implicit reference variable which is available in every non static method /
instance method of class which is used to store reference of current / calling instance.
Consider code in C
In C/C++, if name of local & global variable is same then preference is always given to the local
variable.
Consider code in java:
class Date{
int day, month, year;
void setDay( /* Date this,*/int day ){
//day = day; //Assignment to self
this.day = day;
}
}
class Program{
public static void main(String[] args) {
Date date = new Date( );
date.setDay( 23 ); //date.setDay( date, 23 );
}
}
If name of method local variable / method paramater and name of field is same then preference is
always given to the local variable. In this case, If we want to give preference to field then we should
use this referene before field. For the reference consider above code.
enum ShapeType{
LINE, RECTANGLE, CIRLE, TRIANGLE
}
Characteristics of instance
State
Value stored inside instance is called as state of that instance.
Value stored inside field represents state of the instance.
Behavior
Number / set of operations( behaviors/methods) which are allowed to perform/call on instance
represents behavior of the instance.
Methods defined inside class represents behavior of the instance.
Identity
Value of any field which is used to indentify instance uniquely is called its identity.
Instance
Definition:
An entity which is having physical existance is called as instance.
In C++, physical entity is called as object and in Java it is called instance.
An entity which is having state, behavior and identity is called as instance.
For students use only 45 / 363
Example: Tata Nano, "Java Certification-Khalid Mughal", "MacBook Air", "iPhone-14"
Process of creating instance is called as instantiation.
By creating instance we are achieving abstraction.
null literal and NullPointerException
#define NULL ((void*)0) //C
#define NULL 0 //C++
If reference contains, null value then reference variable is called as null reference variable / null
object.
Consider following code:
class Program{
public static void main(String[] args) {
Employee emp;
emp.acceptRecord(); // error: variable emp might not have been
initialized
emp.printRecord();
}
}
Solution:
class Program{
public static void main(String[] args) {
Employee emp = null; //emp is null object
Using null object, if we try to access any instance member of the class then JVM throws
NullPointerException.
Reference: https://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html
Difference between value type and reference types
Reference: https://docs.oracle.com/javase/tutorial/reflect/class/index.html
Value type
Primitive type is also called as value type.
There are 8 value/primitive types in java.
boolean, byte, char, short, int, float, double, long
Variable of value type contains value.
class Date{
int day; //0
int month; //0
int year; //0
}
Variable of value type get space on Java stack( by considering it as method local variable ).
Reference type
Not primitive type is also called as reference type.
There are 4 reference/non primitive types in java.
interface, class, enum, array
Variable of reference type contains reference.
class Employee{
String name; //null
Date joinDate; //null
}
class Program {
static void sum( int num1, int num2 ){ // 2 method parameters
int result = num1 + num2;
System.out.println("Result : "+result);
}
static void sum( int num1, int num2, int num3 ){ // 3 method
parameters
int result = num1 + num2 + num3;
System.out.println("Result : "+result);
}
public static void main(String[] args) {
Program.sum( 10, 20 );
Program.sum( 10, 20, 30 );
}
}
If we want to give same name to methods and if number of parameters passed to the method
are same then type of at least one parameter must be different.
class Program {
static void sum( int num1, int num2 ){ // 2 method parameters
int result = num1 + num2;
System.out.println("Result : "+result);
}
static void sum( int num1, double num2 ){ // 2 method
parameters
double result = num1 + num2;
System.out.println("Result : "+result);
}
public static void main(String[] args) {
Program.sum( 10, 20 );
Program.sum( 10, 20.5 );
}
}
If we want to give same name to the methods and if number of parameters passed to the
method are same then order of type of parameters must be different.
class Program {
static void sum( int num1, float num2 ){ // 2 method
Only on the basis of different return type, we can not give same name to methods.
class Program {
static void sum( int num1, int num2 ){ // 2 method
parameters
int result = num1 + num2;
System.out.println("Result : "+result);
}
static int sum( int num1, int num2 ){ // 2 method parameters
int result = num1 + num2;
return result;
}
public static void main(String[] args) {
Program.sum( 10, 20 );
Program.sum( 10, 20 );
}
}
When we define multiple methods with same name using above rules then it is called as method
overloading.
In other words, process of defining methods with same name and different signature is called as
method overloading.
Methods, which are taking part in method overloading are called as overloaded methods.
If implementation of methods are functionally equivalilent / same then we should overload method i.e.
we should give same name to the methods.
Return type is not considered in method overloading.
return value from method as well as catching value from method is optional hence return type
is not considered in method overloading.
Constructor
Constructor chaining
Instance initialization block
For students use only 51 / 363
Need of getter and setter methods
Initialization( Revision )
Process of providing value to the variable during its declaration is called as initialization.
class Date{
int day;
int month;
int year;
Date( ){ //Constructor
LocalDate ld = LocalDate.now();
import java.time.LocalDate;
import java.util.Scanner;
class Date{
int day;
int month;
int year;
Date( ){ //Constructor
System.out.println("Inside constructor");
LocalDate ld = LocalDate.now();
this.day = ld.getDayOfMonth();
this.month = ld.getMonthValue();
this.year = ld.getYear();
}
}
class Program{
public static void main(String[] args) {
Date dt1 = new Date(); //Here constructor will call implicitly
//dt1.Date( ); //Not allowed
}
public static void main1(String[] args) {
//Date dt1 = null; //Here construcor will not be call
//new Date( ); //Here constructor will call on anonymous
instance
Date dt2 = new Date(); //Here constructor will call on only once
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/constructors.html
Types of constructor
There are 3 types of constructor in Java:
Parameterless constructor
Parameterized constructor
Default constructor
Parameterless constructor
It is also called as zero argument constructor / programmer defined default constructor.
For students use only 55 / 363
Consider example:
If we create instance without passing arguments( i.e. we are passing 0 arguments ) then
Parameterless constructor gets called.
Parameterized constructor
A constructor which take parameter is called as Parameterized constructor.
Consider example:
class Date{
int day;
int month;
int year;
Date( ){
System.out.println("Inside parameterless constructor");
class Date{
int day;
int month;
int year;
}
class Program{
public static void main(String[] args) {
Date dt1 = new Date( ); //OK
//Here on instance, default constructor will call
}
}
class Date{
int day;
int month;
int year;
class Date{
int day;
int month;
int year;
Date( ){
//Explicit call to the construcor
this( 1, 4, 2023); //Constructor chaining
}
Date( int day, int month, int year ){
this.day = day;
this.month = month;
this.year = year;
}
}
class Stack{
int top;
int[] arr;
Stack( ){
this( 5 ); //Constructor chaining
}
Stack( int size ){
this.top = -1;
this.arr = new int[ size ];
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/thiskey.html
Stack
Data structure describes two things:
How to organize data in ram.
Which operations should be used to organise data inside RAM.
Types of data structure:
Linear / sequential data structure
Array, Stack, Queue, LinkedList etc.
Non Linear data structure
Tree, Graph, Hashtable etc.
Stack is a linear data structure in which we can manage elements in Last In First Out order( LIFO ).
We can perform following operations on Stack:
boolean empty( );
void push( int element );
int peek( );
boolean full( );
void pop();
Value stored inside data structure is called element.
Consider syntax of array:
class Stack{
int top;
int[] arr;
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/initial.html
Access Modifier
In Java, parent class is called as super class and child class is called as sub class.
The modifiers, which are used to control visibility of the members of the class is called access
modifiers.
There are 4 access modifiers in Java:
private
package level private ( no modifier / default means --> package level private )
protected
public
Reference: https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html
Need of Getter and Setter method
Process of declaraing fields of the class private is called as data hiding.
class Student{
//Data hiding
private String name;
private int rollNumber;
private float marks;
}
class Student{
private String name;
private int rollNumber;
private float marks;
public void setMarks( float marks ){
if( marks > 100 )
throw new IllegalArgumentException("Invalid marks.");
this.marks = marks;
}
//acceptRecord
}
class Program{
public static void main(String[] args) {
Student s1 = new Student();
s1.setMarks( 101 );
}
}
Final modifier
Absolute path and relative path
Reference: https://www.redhat.com/sysadmin/linux-path-absolute-relative
Path and classpath
Reference: https://docs.oracle.com/javase/tutorial/essential/environment/paths.html
java.lang.Object class
Reference: https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html
Use below command on terminal to get more details:
javap java.lang.Object
toString method
Final Modifier
Final method local variable
class Program{
public static void main(String[] args) {
int number = 10; //Initialization
number = number + 5;
System.out.println("Number : "+number); //15
}
}
After storing value inside variable, if we dont want to modify its value then we should use final
modifier.
In java, we can declare local variable final.
class Program{
public static void main(String[] args) {
final int number = 10; //Initialization
number = number + 5; //error: cannot assign a value to final
variable number
System.out.println("Number : "+number);
class Program{
public static void main(String[] args) {
final int number;
number = 10; //Assignment
//number = number + 5; //error: variable number might already
have been assigned
System.out.println("Number : "+number); //10
}
}
class Program{
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
System.out.print("Number : ");
final int number = sc.nextInt(); // //Initialization
//number = 20; //error: cannot assign a value to final variable
number
System.out.println("Number : "+number); //10
}
}
We can provide value to final variable before compilation as well as after compilation.
Final field
We can declare fiel final.
After initialization, if we dont want to modify value of any field inside any method of the class
including constructor body then we should declare field final.
We must provide value to the final field either inside constructor body or at the time of declaration.
class Test{
//Field
private final int number; //NOT OK
}
class Test{
//Field
private final int number;
public Test( ){
this.number = 10; //OK
}
}
class Test{
//Field
private final int number = 10; //OK
public Test( ){
this.number = 20; //Not OK
}
}
class Test{
private final int NUMBER = 10; //Field
public void showRecord( ){
//this.NUMBER = this.NUMBER + 1; //Not OK
System.out.println("Number : "+this.NUMBER);
}
public void printRecord( ){
//this.NUMBER = this.NUMBER + 1; //Not OK
System.out.println("Number : "+this.NUMBER);
}
}
class Program{
public static void main(String[] args) {
Test t = new Test();
t.showRecord(); //10
t.printRecord(); //10
t.showRecord(); //10
}
}
class Complex{
private int real;
private int imag;
public Complex( ){
this( 0, 0);
}
public Complex( int real, int imag ){
this.real = real;
this.imag = imag;
}
public int getReal() {
return this.real;
}
public void setReal(int real) {
this.real = real;
}
public int getImag() {
return this.imag;
}
public void setImag(int imag) {
this.imag = imag;
}
}
class Program{
public static void main(String[] args) {
final Complex c1 = new Complex( 10, 20);
c1.setReal(100); //OK
c1.setImag(200); //OK
System.out.println("Real Number : "+c1.getReal()); //100
System.out.println("Imag Number : "+c1.getImag()); //200
In Java, parent class is called as super class and child class is called as sub class.
Object is a concrete class declared in java.lang package.
java.lang.Object do not extend any class or do not implement any interface. In other words, it is super
class of all the classes( not interfaces ) in core Java.
It is also called as ultimate base class / super cosmic base class / root of java class hierarchy.
There are 11 methods( 5 non final( 2 native + 3 non native ) + 6 final methods( 4 native + 2 non native
methods)) in java.lang.Object class.
Use following command to check signature of methods:
javap java.lang.Object
5 Non final methods of java.lang.Object class( we can override these methods inside sub class
)
public String toString( );
public boolean equals( Object obj );
public native int hashCode( );
protected native Object clone( )throws CloneNotSupportedException
protected void finalize( )throws Throwable
6 Final methods of java.lang.Object class
public final native Class<?> getClass()
public final void wait( ) throws InterruptedException
public final native void wait( long timeout ) throws InterruptedException
public final void wait( long timeout, int nanos ) throws InterruptedException
public final native void notify();
public final native void notifyAll();
Overriding toString method
toString is a non final method of java.lang.Object class
For students use only 70 / 363
public String toString( );
If we want to return state of the instance in String form then we should use toString method.
If we do not define toString() method inside class then super class's toString method will call. If any
super class do not contain toString() method then Object class's toString() method will call.
Consider definition of toString method from java.lang.Object class:
Hashcode is not an address / reference of the instance. It is a logical integer number which can
be generated by processing state of the instance.
According to client's requirement, If implementation of super class method is partially complete the
we should redefine/override method inside sub class.
If we dont want hashCode then we should override toString() method inside sub class.
The result in toString() method should be a concise but informative that is easy for a person to read.
Static Field
For students use only 71 / 363
If we create instance of the class then all the fields get space inside instance.
class Test{
private int num1;
private int num2;
private int num3;
public Test( int num1, int num2 ){
this.num1 = num1;
this.num2 = num2;
this.num3 = 500;
}
}
class Program {
public static void main(String[] args) {
Test t1 = new Test( 10, 20 ); //10,20,500
Test t2 = new Test( 30, 40 ); //30,40,500
Test t3 = new Test( 50, 60 ); //50,60,500
}
}
If we want to share, value of any field inside all the instances of same class then we should declare
field static.
A field of the class, which get space inside instance is called as instance variable. In other words, only
non static field get space inside instance. Hence non static field is also called as instance variable.
Instance variable get space once per instance on heap memory.
To use instance variable we must use object reference.
A field of the class which do not get space inside instance is called as class level variable. In other
words, static fields do not get space inside instance. Hence static field is also called as class level
variable.
For students use only 72 / 363
Class level variable get space during class loading once per class on method area.
To access class level variable we should use class name and dot operator.
class X{
private int num1;
private int num2;
private static int count = 500;
}
X x1 = new X(10,20); //10,20, 500
X x2 = new X(30,40);//30,40,500
X x3 = new X(50,60);//50,60,500
class Y{
private int num3;
private int num4;
private static int count = 600;
}
Y y1 = new Y(11,12); //11,12,600
Y y2 = new Y(13,14); //13,14,600
Y y3 = new Y(15,16); //15,16,600
class Z{
private int num5;
private int num6;
private static int count = 700;
}
Z z1 = new Z(21,22); //21,22,700
Z z2 = new Z(23,24); //23,24,700
Z z3 = new Z(25,26); //25,26,700
class Test{
private int num1;
private int num2;
private static int num3;
class Test{
private int num1;
private int num2;
private static int num3;
class Program{
public int num1 = 10;
public static int num2 = 20;
public static void main(String[] args) {
//System.out.println( num1 ); //Not OK
Program p = new Program();
System.out.println( p.num1 );
System.out.println( num2 ); //OK
}
}
Using instance, we can access non static members inside static method.
Count instances of the class
Singleton class
class Program{
/* public double power( double base, int index ){
double result = 1;
for( int count = 1; count <= index; ++ count )
result = result * base;
return result;
} */
public static double power( double base, int index ){
double result = 1;
for( int count = 1; count <= index; ++ count )
result = result * base;
return result;
}
public static void main(String[] args) {
//Program p = new Program();
//double result = p.power(2, 3);
If constructor is public then we can create instance of the class inside method of same class as well
as method of different class.
class Complex{
private int real;
private int imag;
public Complex( ){
System.out.println("Inside constructor.");
this.real = 10;
this.imag = 20;
}
public static void test( ){
Complex c2 = new Complex(); //OK
}
}
class Program{
public static void main(String[] args) {
Complex c1 = new Complex(); //OK
Complex.test();
class Complex{
private int real;
private int imag;
private Complex( ){
System.out.println("Inside constructor.");
this.real = 10;
this.imag = 20;
}
public static void test( ){
Complex c2 = new Complex(); //OK
}
}
class Program{
public static void main(String[] args) {
//Complex c1 = new Complex(); //NOT OK
Complex.test();
}
}
Instance Counter
class InstanceCounter{
private static int count;
public InstanceCounter( ){
InstanceCounter.count = InstanceCounter.count + 1;
}
public static int getCount() {
return InstanceCounter.count;
}
}
class Program{
public static void main(String[] args) {
InstanceCounter c1 = new InstanceCounter();
InstanceCounter c2 = new InstanceCounter();
System.out.println("Instance Count : "+InstanceCounter.getCount());
}
}
In Java, we can declate local variable final but we can not declare it static.
Static variable is also called as class level variable. According to oops, class level variable should be
declared inside class scope. Hence we can not declare local variable static. But we can declare field
static.
class Program{
private static int count = 0;
public static void printRecord( ){
count = count + 1;
System.out.println("Count : "+count);
}
public static void main(String[] args) {
Program.printRecord(); //1
Program.printRecord(); //2
Program.printRecord(); //3
}
}
Design pattern
Reusable solution which is used to solve common problems during development is called as design
pattern.
Creational
Abstract factory
Builder
Factory method
For students use only 78 / 363
Prototype
Singleton
Structural
Adapter
Bridge
Composite
Decorator
Facade
Flyweight
Proxy
Behavioral
Chain of responsibility
Command
Interpreter
Iterator
Mediator
Memento
Observer
State
Strategy
Template method
Visitor
Singleton class
A class from which we can create only one instance is called as singleton class.
Method 1:
class Singleton{
private Singleton( ){
//TODO
}
private static Singleton reference;
public static Singleton getReference( ){
if( reference == null )
reference = new Singleton( );
return reference;
}
}
class Program{
public static void main(String[] args) {
Singleton s1 = Singleton.getReference();
Singleton s2 = Singleton.getReference();
}
}
class Singleton{
private int num1;
private int num2;
private static Singleton reference;
static{
reference = new Singleton();
}
public static Singleton getReference() {
return reference;
}
private Singleton( ){
this.num1 = 10;
this.num2 = 20;
}
}
class Program{
public static void main(String[] args) {
Singleton s1 = Singleton.getReference();
Singleton s2 = Singleton.getReference();
}
}
Package
java.util.Date
java.sql.Date
java.lang.Object
//java : main package
//lang : sub package
//Object : Type name( interface, class....etc)
In Java
class Complex{
//TODO: Member declaration
};
package p1; //Not OK
If we do not define any class inside package then it is considered as a member of default
package.
class Complex{
//TODO: Member declaration
};
If we do not specify access modifier then default modifier of class is always package level private.
If access modifier of type is package level private then we can not access it outside the package.
If we want to use any type outside the package then type must be public.
According to Java Language Specification(JLS), name of the public class and name of the .java file
must be same.
Since name of the public class and name of the .java file must be same, we can not define multiple
public classes in single .java file.
We can not declare class private or protected. In other words, access modifier of a class can be
either package level private or public only.
Demo 1
Consider code in Complex.java
import p1.Complex;
class Program{
public static void main(String[] args) {
//p1.Complex c1 = new p1.Complex();
Complex c1 = new Complex();
System.out.println( c1.toString());
}
}
Compile Program.java
set classpath=.\bin;
javac -d .\bin .\src\Program.java
java Program
Demo 2
Consider Complex.java
Compile Complex.java
Consider Program.java
package p1;
class Program{
public static void main(String[] args) {
Complex c1 = new Complex();
Compile Program.java
set classpath=.\bin;
javac -d .\bin .\src\Program.java //error: cannot find symbol Complex
If we define any class without package then it is considered as a member of default package.
Conclusion: Since we can not import default package, It is impossible to use unpackged class inside
packaged class.
Demo 3
Consider Complex.java
package p1;
public class Complex {
public String toString() {
return "Complex.toString( )";
}
}
Compile Complex.java
Consider Program.java
package p2;
import p1.Complex;
class Program{
public static void main(String[] args) {
Complex c1 = new Complex();
System.out.println( c1.toString());
}
}
Compile Program.java
java Program //Error: Could not find or load main class Program
java p2.Program //OK
Demo 4
Consider Complex.java
package p1;
public class Complex {
public String toString() {
return "Complex.toString( )";
}
}
Compile Complex.java
package p1;
//import p1.Complex; //Optional
class Program{
public static void main(String[] args) {
Complex c1 = new Complex();
System.out.println( c1.toString());
}
}
Compile Program.java
set classpath=.\bin;
javac -d .\bin .\src\Program.java
java p1.Program
Demo 5
For students use only 88 / 363
Consider Complex.java
package p1.p2;
public class Complex {
public String toString() {
return "Complex.toString( )";
}
}
Compile Complex.java
Consider Program.java
package p1.p3;
import p1.p2.Complex;
class Program{
public static void main(String[] args) {
Complex c1 = new Complex();
System.out.println( c1.toString());
}
}
Compile Program.java
set classpath=.\bin;
javac -d .\bin .\src\Program.java
java p1.p3.Program
Without class name, if we want to access static members of the class then we should use static
import.
If we want to use any type( interface, class, enum, error, exception, annotation) outside package then
we should use import statement.
If we want to use static members of the class, without class outside class name, then we should use
static import.
naming conventions for package
org.example.main
in.cdac.acts.utils
java.lang.reflect
oracle. jdbc. driver.
com.mysql.jdbc
Reference: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html
For students use only 90 / 363
Eclipse introduction
Second approach
Instantiation of array
length is a property of array data structure which returns size/length of the array.
int[] arr3 = new int[ ]{ 10, 20, 30, 40, 50, 60, 70 }; //OK
Program.printRecord( arr3 );
}
Program.acceptRecord( arr );
Program.printRecord(arr);
}
}
Using illeagal index, if we try to access elements of array then JVM throws
ArrayIndexOutOfBoundsException.
package org.example.main;
import java.time.LocalDate;
import java.util.Arrays;
class Date{
private int day;
private int month;
private int year;
public Date() {
LocalDate ld = LocalDate.now();
this.day = ld.getDayOfMonth();
this.month = ld.getMonthValue();
this.year = ld.getYear();
}
@Override
public String toString() {
return this.day+" / "+this.month+" / "+this.year;
}
For students use only 100 / 363
}
public class Program {
public static void main(String[] args) {
Date[] arr = new Date[ 3 ]; //Array of references
System.out.println( Arrays.toString(arr)); //[null, null,
null]
}
}
//int a = x;
//int b = y;
void swap( int a, int b ){
int temp = a;
a = b;
b = temp;
}
int main( void ){
int x = 10;
int y = 20;
//int *a = &x;
//int *b = &y;
void swap( int *a, int *b ){
int temp = *a;
*a = *b;
*b = temp;
}
In Java, we can pass any argument( primitive / non primitive ) to the method by value only.
Consider code:
package org.example.main;
public class Program {
If we want to simulate pass by reference mechanisam then we should use array in Java.
Consider following code:
Program.swap( arr );
x = arr[ 0 ];
y = arr[ 1 ];
import java.util.Scanner;
public class Program {
private static Scanner sc = new Scanner(System.in);
public static void acceptRecord( int[] number ) {
System.out.print("Enter number : ");
number[ 0 ] = sc.nextInt();
}
private static void printRecord(int[] number) {
System.out.println("Number : "+number[ 0 ]);
}
public static void main(String[] args) {
int[] number = new int[ 1 ];
Program.acceptRecord( number );
Program.printRecord( number );
}
}
Instantiation:
import java.util.Scanner;
Reference declaration:
Instantiation
import java.util.Scanner;
Program.sum( 10, 20 );
Program.sum( 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 );
}
}
Enum
If we want to improve readability of the source code then we should use enum in C/C++/java.
Consider code in C programming language:
#include<stdio.h>
enum ArithmeticOperation{
EXIT, SUM, SUB,MULTIPLICATION, DIVISION // Enum Constants
//EXIT = 0, SUM = 1, SUB = 2,MULTIPLICATION = 3, DIVISION = 4 //
Enum Constants
};
enum Day{
MON = 1, TUES = 2, WED = 3, THURS = 4, FRI = 5, SAT = 6, SUN = 7
}
enum Day{
MON( 1 ), TUES( 2 ), WED( 3), THURS ( 4 ), FRI( 5 ), SAT( 6 ),
SUN( 7 );
// 1,2,3,4,5,6,7 : Literals
//MON, TUES, WED, THURS, FRI, SAT, SUN : Name of enum constants
//0,1,2,3,4,5,6 : Ordinals
}
enum Color{
RED( 255,0,0), GREEN(0,255,0), BLUE(0,0,255)
//RED = 0, GREEN = 1, BLUE = 2
}
//(255,0,0),(0,255,0),(0,0,255)
//RED, GREEN, BLUE : Name of enum constants
//0,1,2 : Ordinals
enum Day{
MON( 1, "Monday"), SUN( 7, "SunDay");
}
//( 1, "Monday"), ( 7, "SunDay"); //Literals
//MON, SUN : Name of enum constants
//0, 1 : Ordinal values
enum Color{
Since enum is implicitly considered as final class, we can not extend enum. In other words we can not
create sub type of enum.
Consider code to demonstrate name()/ordinal() and values() method.
enum Color{
RED, GREEN, BLUE
}
public class Program {
public static void main(String[] args) {
Color[] colors = Color.values();
for( Color color : colors )
System.out.println( color.name()+" "+color.ordinal());
}
public static void main4(String[] args) {
Color color = Color.RED;
System.out.println( color.name()+" "+color.ordinal());
color = Color.GREEN;
System.out.println( color.name()+" "+color.ordinal());
color = Color.BLUE;
System.out.println( color.name()+" "+color.ordinal());
}
package org.example.main;
enum Day {
MON("Monday"), TUES("TuesDay"), WED("WednesDay");
enum Day {
MON(1), TUES(2), WED(3);
enum Day {
MON(1, "MonDay"), TUES(2,"TuesDay"), WED(3,"WednesDay");
System.out.println(day.getDayNumber());//1
System.out.println(day.getDayName()); //MonDay
}
}
package org.example.main;
import java.util.Arrays;
import java.util.Scanner;
enum ArithmeticOperation{
EXIT, SUM, SUB, MULTIPLICATION, DIVISION
}
class ArithmeticOperationTest{
public static int sum( int num1, int num2 ) {
return num1 + num2;
}
public static int sub( int num1, int num2 ) {
return num1 - num2;
}
public static int multiplication( int num1, int num2 ) {
return num1 * num2;
}
public static int division( int num1, int num2 ) {
return num1 / num2;
}
public static void printRecord( int result ) {
System.out.println("Result : "+result);
}
private static Scanner sc = new Scanner(System.in);
public static ArithmeticOperation menuList( ) {
System.out.println("0.Exit");
System.out.println("1.Sum");
System.out.println("2.Sub");
For students use only 118 / 363
System.out.println("3.Multiplication");
System.out.println("4.Division");
System.out.print("Enter choice : ");
int choice = sc.nextInt();
return ArithmeticOperation.values()[ choice ];
}
}
public class Program {
public static void main(String[] args) {
ArithmeticOperation choice;
while( ( choice = ArithmeticOperationTest.menuList( ) ) !=
ArithmeticOperation.EXIT ) {
int result = 0;
switch( choice ) {
case SUM:
result = ArithmeticOperationTest.sum(100, 20);
break;
case SUB:
result = ArithmeticOperationTest.sub(100, 20);
break;
case MULTIPLICATION:
result = ArithmeticOperationTest.multiplication(100, 20);
break;
case DIVISION:
result = ArithmeticOperationTest.division(100, 20);
break;
}
ArithmeticOperationTest.printRecord(result);
}
}
}
OOPS
Object oriented programming structure/system
OOPS is not a syntax. It is a programming methodology which is used to solve real world problems
using classes and objects.
Dr Alan kay is inventor of OOPS.
Grady Booch is inventor of UML.
Author of "Object Oriented Analysis and Design with Applications"
According to Grady Booch there should be some major and minor features in the oops.
4 Major Elements / Features / Parts /Pillars
By major, we mean that a language without any one of these elements is not object oriented.
Abstraction - To achive simplicity
For students use only 119 / 363
Encapsulation - To hide data and to achieve security
Modularity - To reduce module dependency
Hierarchy - To achieve reusability
Types of hierarchy
Has-a - represents Association( Specialized form => Composition/Aggregation)
Is-a - represents generalization( also called as inheritance )
Use-a - represents dependency
Creates-a - represents instantiation
3 Minor Elements / Features / Parts /Pillars
By minor, we mean that each of these elements is a useful, but not essential.
Typing / Polymorphism - To reduce maintenance of the system
Concurrency - To utilize h/w resources( Memory/CPU ) efficiently
Persistance - To maintain state of the instance of secondary storage.
Abstraction
Abstraction is a major element / pillar of oops.
Process of getting essesntials things from object/instance is called as abstraction.
Abstraction focuses on outer behavior of an instance.
Abstraction in java:
class Program{
public static void main(String[] args) {
For students use only 120 / 363
Complex c1 = new Complex( );
c1.acceptRecord();
c1.PrintRecord();
}
}
import java.util.Scanner;
class Program{
public static void main(String[] args) {
Scanner sc = new Scanner( System.in );
String name = sc.nextLine( );
}
}
interface Printtable{
void print();
}
class Complex{
private int real;
private int imag;
public Complex( ){
this.real = 0;
this.imag = 0;
}
public void acceptRecord( ){
Scanner sc = new Scanner( System.in );
System.out.print("Real Number : ");
this.real = sc.nextInt();
System.out.print("Imag Number : ");
this.imag = sc.nextInt();
}
public void printRecord( ){
System.out.println("Real Number : "+this.real);
System.out.println("Imag Number : "+this.imag);
}
}
Abstraction and encapsulation are complementary concepts: Abstraction focuses on the observable
behavior of an object, whereas encapsulation focuses on the implementation that gives rise to this
behavior.
class Program{
public static void main(String[] args) {
Complex c1 = new Complex( );
c1.acceptRecord( );
c1.printRecord( );
}
}
Encapsulation
Definition:
Binding of data and code together is called as encapsulation.
Implementation of abstraction is called as encapsulation.
Abstraction and encapsulation are complementry concepts. In other words abstraction focuses on
external behavior whereas encapsulation focuses internal behavior.
Using encapsulation:
We can achieve abstraction
We can hide data from user:
Process of declararing fields private is called as data hiding. Data hiding is also called as
data encapsulation.
Data hiding helps us to achive data security.
To achive encapsulation we should define class. Hence class is considered as a basic unit of
encapsulation.
For Example:
class Complex{
private int real;
private int imag;
public Complex( ){
this.real = 0;
this.imag = 0;
}
For students use only 123 / 363
public void acceptRecord( ){
//TODO
}
public void printRecord( ){
//TODO
}
}
Modularity
It is a major pillar of oops.
It is the process of developing complex system using small parts.
Modularity helps us to minimize module dependency.
In Java, we can achieve Modularity using packages and .jar file.
Hiearchy
It is a major pillar of oops.
class Engine{
//Fields
//Constructors
//Methods
}
class Car{
//Car has a engine
private Engine e = new Engine(); //Association
}
class Wheel{
//TODO
}
class Engine{
}
class Car{
private Wheel[] wheels; //Association --> Composition
private Engine e; //Association --> Composition
}
class Student{
//TODO
}
class University{
private Stundet[] students; //Association --> Aggregation
//TODO
}
class Employee{
private String name;
private int age;
private int empid;
private float salary;
public Employee() {
this("",0,0,0.0f);
}
}
class Employee extends Person{ //Child class / Sub class
//Here Employee class can reuse fields/constructors/methods and
nested types of Person class
}
}
class Employee extends Person {
Now class Person is direct super class of class Employee and class Object is indirect super
class of class Employee.
In Java, any class can extend only one class.
class A{ } //OK
class B{ } //OK
class C extends B{ } //OK
class D extends A, B{ } //Not OK
During inheritance, members of sub class do not inherit into super class. Hence using super class
instance, we can access members of super class only.
}
}
During inheritance, members of super class inherit into sub class. Hence using sub class instance, we
can access members of super class as well as sub class.
int empid;
float salary;
If we create instance of sub class then all the non static fields declared in super class and sub class
get space inside it. In other words, non static fields of super class inherit into sub class.
Using sub class name, we can use/access static fields of super class. It means that static field of
super class inherit into sub class.
For students use only 132 / 363
All( static and non static ) the fields of super class inherit into sub class but only non static fields get
space inside instance of sub class.
We can call/invoke, non static method of super class on instance of sub class. In other words, non
static method of super class inherit into sub class.
We can invoke, static method of super class on sub class name. In other words, static method of
super class inherit into sub class.
Except constructor, all(static and non static ) the methods of super class inherit into sub class.
If we create instance of sub class then first super class constrcutor gets called and then sub class
constructor gets called.
From any constructor of sub class, by default, super class's parameterless constructor gets called.
If we want to call any constructor of super class from constructor of sub class then we should use
super statement.
super is keyword in java.
super statement must be first statement inside constructor body.
Except constrcutor, all the members of super class inherit into sub class.
Definition of Inheritance
Journey from generalization to specialization is called inheritance.
Process of acquiring/accessing members of parent class into child class is called as
inheritance.
Interface inheritance:
During inheritance, if super type and sub types are interfaces then it is called as interface
inheritance.
Implementation inheritance
During inheritance, if super type and sub type is class then it is called as implementation
inheritance.
interface A{ }
interface B{ }
interface C extends A, B{ } //OK: Multiple interface inheritance
interface A{ }
interface B{ }
class C implements A, B{ } //OK: Multiple interface implementation
inheritance
class A{ }
class B{ }
class C extends A, B{ } //Not OK: Multiple Implementation inheritance
In C++, combination of two or more than two types of inheritance is called hybrid inheritance.
If we combine hierarchical inheritance and multiple inheritance then it becomes diamond
inheritance, which creates some problems.
To avoid diamond problem, Java do not support multiple implementation inheritance / multiple
class inheritance.
Conclusion: In Java, class can extend only one class.
Consider following code:
class Object{
public String toString( );
public boolean equals( Object obj )
public native int hashCode( );
protected native Object clone( )throws CloneNotSupportedException;
protected void finalize()throws Throwable;
public final native Class<?> getClass( );
public final void wait( )throws InterruptedException;
public final native void wait( long timeOut )throws
InterruptedException;
public final void wait( long timeOut, int nanos )throws
InterruptedException;
public final void notify();
In above code, class Person will extend java.lang.Object class and class Employee will extend
only Person class( Not java.lang.Object class ).
class Person is direct super class and class java.lang.Object is indirect super class of Employee
class.
Types of inheritance
Single inheritance
In case of inheritance, if single super type is having single sub type then it is called as single
inheritance.
For example: Car is a vehicle.
Syntax:
class Vehicle{
//TODO
}
class Car extends Vehicle{ //Single inheritance( implementation
inheritance )
//TODO
}
Multiple inheritance
In case of inheritance, If multiple super types are having single sub type then it is called multiple
inheritance.
For Example: Fax-Copier machine is a fax machine and Fax-Copier machine is also Copier machine.
Syntax:
interface List<E>{ }
interface Queue<E>{ }
class LinkedList implements List<E>, Queue<E>{ } //OK: Multiple
Inheritance
Hierarchical inheritance
In case of inheritance, If single super type is having multiple sub types then it is called as hierarchical
inheritance.
For students use only 139 / 363
For Example: SavingsAccount is Account, CurrentAccount is a Account.
Syntax:
//Hierarchical inheritance
class Account{ }
class SavingsAccount extends Account{ } //Single inheritance
class CurrentAccount extends Account{ } //Single inheritance
interface Collection<E>{ }
interface List<Collection> extends <Collection<E>{ }
interface Queue<E> extends Collection<E>{ }
interface Set<E> extends Collection<E>{ }
Multilevel inheritance
In case of inheritance, if single inheritance is having multiple levels then it is called as multilevel
inheritance.
Syntax:
//Multilevel inheritance
class Person{ };
class Employee extends Person{ } //Single inheritance
class Manager extends Employee{ } //Single inheritance
class SalesManager extends Manager{ } //Single inheritance
//Multilevel inheritance
interface Iterable<T>{ }
interface Collection<E> extends Iterable<T>{ }
interface Queue<E> extends Collection<E>{ }
interface Deque<E> extends Queue<E>{ }
Reference: https://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
Private members( fields/methods/nested types ) inherit into sub class. If we want to access value of
private field inside sub class then we should use getter and setter methods of super class.
class A{
private int num1;
public A( ) {
this.num1 = 10;
}
public int getNum1() {
return this.num1;
}
}
class B extends A{
}
public class Program {
public static void main(String[] args) {
B b = new B();
//System.out.println(b.num1); //The field A.num1 is not visible
System.out.println( b.getNum1() ); //10
}
public static void main1(String[] args) {
A a = new A();
//System.out.println(a.num1); //The field A.num1 is not visible
System.out.println( a.getNum1() );
}
}
If name of super class method and sub class method is same and if we try to invoke such
method on instance of sub class then preference will be given to the sub class method. It is
called as method shadowing.
class Complex{
private int real;
private int imag;
public Complex( ) {
this.real = 10;
this.imag = 20;
}
public void setReal(int real) {
real = real; //Shadowing : Local variable is assigned to itself
}
public void setImag(int imag) {
this.imag = imag;
}
@Override
public String toString() {
return this.real+" "+this.imag;
}
}
public class Program {
public static void main(String[] args) {
Complex c1 = new Complex( ); //10,20
In case of fields
class A{
int num1 = 10;
int num3 = 30;
}
class B extends A{
int num2 = 20;
int num3 = 40;
public void printRecord( ) {
System.out.println("Num1 : "+num1); //OK: 10
System.out.println("Num1 : "+this.num1); //OK: 10
System.out.println("Num1 : "+super.num1); //OK: 10
In case method
class A{
public void showRecord( ) {
System.out.println("A.showRecord()");
}
public void printRecord( ) {
System.out.println("A.printRecord()");
}
}
class B extends A{
public void displayRecord( ) {
System.out.println("B.displayRecord()");
Since members of super class inherit into sub class, using sub class instance we can access
members of super class as well as sub class.
Final conclusion:
Person p = new Person(); //OK
Person p = new Employee(); //OK
Employee emp = new Employee(); //OK
Employee emp = new Person(); //Not OK
Upcasting
Super class reference can contain reference of sub class instance. It is also called as
upcasting.
If we want to minimize object/instance dependency in the code then we should use upcasting.
Downcasting
In case of upcasting, explicit type casting is optional but in case of dowcasting explicit typecasting is
manadatory.
class Person{
public void printRecord( ){
System.out.println("Person.printRecord");
}
}
class Employee extends Person{
public void printRecord( ){
System.out.println("Person.printRecord");
}
}
class Program{
public static void main(String[] args) {
Person p = new Employee(); //Upcasting
p.printRecord(); //Dynamic method dispatch
}
}
Note: In case of upcasting we can not access fields and non overriden methods of sub class. If we
want to access it the we should do downcasting.
Rules of method overriding
Below are the rules of method overriding
Access modifier of sub class method should be same or it should be wider.
Return type in sub class method should be same or it should be sub type.
Method name, number of paramaters and type of parameters in sub class method must be
same.
Checked exception list in sub class method should be same or it should be sub set.
Override is annotation declared in java.lang package. It helps developer to override method using
above rules. If we make any mistake then it generates metadata for the compiler to generate error.
instanceof operator
ArrayStoreException
operator== versus equals method
process of calling method of sub class on reference of super class is called as dynamic method
dispatch.
Boxing:
Process of converting value of primitive type into non primitive type is called as boxing.
For example:
If we want to compare state/value of variable of primitive type then we should use operator ==.
If we do not define equals() method inside class then super class's equals method will call.
Consider implementation of equals method from java.lang.Object class:
class Employee{
private String name;
private int empid;
private float salary;
public Employee(String name, int empid, float salary) {
this.name = name;
this.empid = empid;
this.salary = salary;
}
}
public class Program {
public static void main(String[] args) {
Employee emp1 = new Employee("Sandeep", 3778, 45000.50f );
Employee emp2 = new Employee("Sandeep", 3778, 45000.50f );
if( emp1.equals(emp2) )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Not Equal
}
public static void main1(String[] args) {
Employee emp1 = new Employee("Sandeep", 3778, 45000.50f );
For students use only 157 / 363
Employee emp2 = new Employee("Sandeep", 3778, 45000.50f );
if( emp1 == emp2 ) //OK: Comparing state of references
System.out.println("Equal");
else
System.out.println("Not Equal");
//Not Equal
}
}
class Employee{
private String name;
private int empid;
private float salary;
public Employee(String name, int empid, float salary) {
this.name = name;
this.empid = empid;
this.salary = salary;
}
//Employee this = emp1;
//Object obj = emp; //Upcasting
@Override
public boolean equals( Object obj ) {
if( obj != null ) {
Employee other = (Employee) obj; //Downcasting
if( this.empid == other.empid )
return true;
}
return false;
}
}
public class Program {
public static void main(String[] args) {
Employee emp1 = new Employee("Sandeep", 3778, 45000.50f );
Employee emp2 = new Employee("Sandeep", 3778, 45000.50f );
//Employee emp2 = null;
if( emp1.equals(emp2) )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Equal
}
}
int num2;
cout<<"Enter number : ";
cin>>num2;
try{
if( num2 == 0 ){
//throw 0; //OK
//throw ArithmeticException( "Divide by zero exception");
//OK
throw "Divide by zero exception"; //OK
}else
int result = num1 / num2;
cout<<"Result : "<<result<<endl;
}
}catch( string &ex ){
cout<<ex<<endl;
}
return 0;
}
class MyException{
private String message;
public MyException(String message) {
this.message = message;
}
}
public class Program {
public static void main(String[] args){
int num1 = 10;
int num2 = 0;
try {
if( num2 == 0 )
//throw 0; //No exception of type int can be thrown; an
exception type must be a subclass of Throwable
//throw "/ by 0"; //No exception of type String can be
thrown; an exception type must be a subclass of Throwable
throw new MyException("/ by 0");//No exception of type
MyException can be thrown; an exception type must be a subclass of
Throwable
int result = num1 / num2;
System.out.println("Result : "+result);
}catch( Exception ex ) {
//TODO
}
}
}
}
}
}
}
}
Constructor Summary
public Throwable()
Method Summary
public String getMessage()
public Throwable initCause(Throwable cause)
public Throwable getCause()
public final void addSuppressed(Throwable exception)
public void printStackTrace()
public void printStackTrace(PrintStream s)
public void printStackTrace(PrintWriter s)
public StackTraceElement[] getStackTrace()
Error versus Exception
Error and Exception are direct sub classes of java.lang.Throwable class.
Error
We can write try-catch block to handle errros. But we can not recover from errors hence it is not
recommended to use try catch block for the errors.
Example:
OutOfMemoryError
StackOverflowError
VirtualMachineError
Exception
The class Exception and its subclasses are a form of Throwable that indicates conditions that a
reasonable application might want to catch.
Runtime error which gets generated due to application is considered as exception in java
programming language.
We can use try-catch block to handle exception.
Example:
CloneNotSupportedException
InterrupedException
NumberFormatException
NullPointerExcption
NegativeArraySizeException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
ArithmeticException
Checked versus unchecked exception
import java.io.Closeable;
import java.io.IOException;
import java.util.Scanner;
}
public class Program {
public static void main(String[] args) {
try {
Test t = new Test();
t.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void close() throws Exception {
this.sc.close();
}
}
public class Program {
public static void main(String[] args) {
try {
Test t = new Test(); //new Test() => Resource
Any class which implements AutoCloseable / Closeable interface is called as resource type and its
instance is called resource.
If we use try with resource then close() method gets called automatically.
Exception handling using try catch throw throws and finally
If we want to handle exception then we should use 5 keywords in java:
try
catch
throw
throws
finally
While performing arithmetic operation, if we get any exception condition like "divide by zero" then
JVM throws ArithmeticException.
try
It is a keyword in Java.
If we want to keep watch on single statement or group of statements for exception then we should
use try block / handler.
we can not define try block after catch/finally block.
Try block must have at least one catch block or finally block or resource statement.
Consider following syntax:
throw
It is a keyword in java.
If we want to generate new exception then we should use throw keyword.
Only objects that are instances of Throwable class (or one of its subclasses) are thrown by the JVM
or can be thrown by the Java throw statement.
System.out.print("Num1 : ");
int num1 = sc.nextInt();
System.out.print("Num2 : ");
int num2 = sc.nextInt();
if( num2 == 0 )
throw new ArithmeticException("Divide by zero exception");
int result = num1 / num2;
System.out.println("Result : "+result);
}catch ( ArithmeticException ex) {
ex.printStackTrace();
}catch ( RuntimeException ex) {
ex.printStackTrace();
}catch ( Exception ex) {
ex.printStackTrace();
}
}
try{
//TODO
}catch( Exception ex ){ //Generic catch block
ex.printStackTrace();
}
Generally, generic catch block comes after all specific catch blocks.
finally
It is a keyword in Java.
If we want to close or release local resources then we should use finally block.
For given try block we can provide only one finally block.
We can define block after all try and catch blocks.
JVM always execute finally block.
try with resource
public static void main(String[] args) {
//try ( Program p = new Program()) { //Not Ok: The resource
type Program does not implement java.lang.AutoCloseable
try( Scanner sc = new Scanner(System.in)){
System.out.print("Num1 : ");
int num1 = sc.nextInt();
System.out.print("Num2 : ");
int num2 = sc.nextInt();
if( num2 == 0 )
throw new ArithmeticException("Divide by zero exception");
int result = num1 / num2;
System.out.println("Result : "+result);
throws
It is a keyword in Java
If we want delegate exception from method to the caller method then we should use throws
keyword/clause.
Exception chaining
package org.example;
abstract class A{
public abstract void print( );
}
class B extends A{
@Override
public void print() throws RuntimeException{
try {
for( int count = 1; count <= 10; ++ count ) {
System.out.println("Count : "+count);
Thread.sleep(250);
}
} catch (InterruptedException cause) {
throw new RuntimeException(cause); //Exception Chaining
}
}
}
public class Program {
public static void main(String[] args) {
try {
A a = new B();
a.print();//Dynamic method dispatch
} catch (RuntimeException e) {
//e.printStackTrace();
Throwable cause = e.getCause();
System.out.println(cause);
}
}
}
class Super{
public static void showRecord( ) {
System.out.println("Super.showRecord()");
}
}
class Sub extends Super{
@Override
public static void showRecord( ) { //Compiler Error
System.out.println("Sub.showRecord()");
}
}
class Super{
public void printRecord( ) {
System.out.println("Super.printRecord()");
}
}
class Sub extends Super{
@Override
public void printRecord( ) { //Overrided method
System.out.println("Sub.printRecord()");
}
}
public class Program {
public static void main(String[] args) {
//Super s1 = new Super();
//s1.printRecord();
class A{
public void f2( ) {
System.out.println("A.f2");
}
public final void f3() {
System.out.println("A.f3");
}
}
class B extends A{
@Override
public final void f2() {
System.out.println("B.f2");
}
}
public class Program {
public static void main(String[] args) {
B b = new B();
b.f2();
}
}
abstract class A{
public abstract void f1( );
}
class B extends A{
@Override
public void f1() {
//TODO
}
}
abstract class A{
public abstract void f1( );
}
abstract class B extends A{
abstract class A{
public abstract void f1( );
public abstract void f2( );
public abstract void f3( );
}
abstract class B extends A{
@Override
public void f1() { }
@Override
public void f2() { }
@Override
public void f3() { }
}
class C extends B {
@Override
public void f1() {
System.out.println("C.f1");
}
}
class D extends B {
@Override
public void f2() {
System.out.println("D.f2");
}
}
class E extends B{
@Override
public void f3() {
System.out.println("E.f3");
}
}
public class Program {
a = new C();
a.f1();
a = new D();
a.f2();
a = new E();
a.f3();
}
}
Sole constructor
A constructor of super class which is designed to call from constructor of only sub class is called sole
constructor.
abstract class A{
private int num1;
private int num2;
public A( int num1, int num2) { //Sole Constructor
this.num1 = num1;
this.num2 = num2;
}
public void printRecord( ) {
System.out.println("Num1 : "+this.num1);
System.out.println("Num2 : "+this.num2);
}
}
class B extends A{
private int num3;
public B( int num1, int num2, int num3 ) {
super( num1, num2 );
this.num3 = num3;
}
@Override
public void printRecord() {
super.printRecord();
System.out.println("Num3 : "+this.num3);
}
}
public class Program {
public static void main(String[] args) {
Process of converting value of variable of primitive type into non primitive type is called as boxing.
We can directly store reference of sub class instance into super class reference variable. It is
called as upcasting.
If we want to reduce object/instance dependency in the code then we should use upcasting.
In case of upcasting, using super class reference variable we can access:
non private fields of super class.
non private methods of super class.
overriden methods of sub class.
Downcasting definition
We can convert reference super class into reference of sub class. It is called as downcasting.
In case of upcasting, using super class reference variable, we can not access non private fields and
non overriden methods of sub class. If we want to access it then we should do downcasting.
class A{
public void print( ){
System.out.println("A.print");
}
public void display( ){
System.out.println("A.display");
}
}
class B extends A{
@Override
public void print( ){
System.out.println("B.print");
}
public void show( ){
System.out.println("B.show");
}
}
class Program{
public static void main( String[] args ){
A a1 = new A(); //OK
a1.print(); //A.print
B b1 = new B( ); //OK
b1.print(); //B.print => Due to shadowing preference will be given
to B.print
Generic Programming
Let us define stack to store boolean elements
class Stack{
private int top = -1;
private boolean[] arr;
public Stack( ) {
this( 5 );
}
public Stack( int size ) {
this.arr = new boolean[ size ];
}
public boolean empty( ) {
return this.top == -1;
}
public boolean full( ) {
return this.top == this.arr.length - 1;
}
public void push( boolean element ) throws StackOverflowException
{
if( this.full())
throw new StackOverflowException("Stack is full");
this.top = this.top + 1;
this.arr[ this.top ] = element;
}
public boolean peek( ) throws StackUnderflowException {
if( this.empty())
throw new StackUnderflowException("Stack is empty");
return this.arr[ this.top ];
}
public void pop( ) throws StackUnderflowException {
if( this.empty())
throw new StackUnderflowException("Stack is empty");
this.top = this.top - 1;
}
}
class Stack{
private int top = -1;
private double[] arr;
public Stack( ) {
this( 5 );
}
public Stack( int size ) {
this.arr = new double[ size ];
}
public boolean empty( ) {
return this.top == -1;
}
public boolean full( ) {
return this.top == this.arr.length - 1;
}
public void push( double element ) throws StackOverflowException {
For students use only 188 / 363
if( this.full())
throw new StackOverflowException("Stack is full");
this.top = this.top + 1;
this.arr[ this.top ] = element;
}
public double peek( ) throws StackUnderflowException {
if( this.empty())
throw new StackUnderflowException("Stack is empty");
return this.arr[ this.top ];
}
public void pop( ) throws StackUnderflowException {
if( this.empty())
throw new StackUnderflowException("Stack is empty");
this.top = this.top - 1;
}
}
class Box{
private Object reference;
public Object getReference() {
return reference;
}
public void setReference(Object reference) {
this.reference = reference;
b1.setReference(new Date());
System.out.println(date);
}
}
Why Generics
Generics gives us stronger typechecking at compile time. In other words, using generics we can write
type-safe generic code.
It completly eliminates need of explict typecasting.
It helps developer to define generic algorithms and data structures.
Generics Syntax:
We can specify type argument during declaration of reference as well as instantiation.
If we specify type argument during reference declaration then specifying type argument during
instantiation is optional. It is called as type inference.
If we use parameterized type without type argument then it is called as raw type.
For students use only 192 / 363
Box b = new Box(); //OK: Here Box is called as raw type
//Box<Object> b1 = new Box< Object>( );
During instantiation of parameterized type, type argument must be non primitive type.
If we want to store primitive values inside instance of parameterized type then type argument must
be Wrapper class.
ArrayList demo
import java.util.ArrayList;
Wild Card
In Generics ? is called as wild card which represents unknown type.
Types of wild card
Unbouned wild card
Upper Bouned wild card
Lower Bounded wild card.
Consider following code
In above code, list will contain reference of ArrayList which can contain any type of element.
In the above code, list will contain reference of ArrayList which can containf Number and its sub type
of elements
In above code, list will contain reference of ArrayList which can contain Integer and its super type of
elements.
Restrictions on Generics
Reference: https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html
Type Erasure
Consider generic type without upper bound.
class Box<T>{
private T data;
public Box() {
}
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return this.data.toString();
}
}
class Box{
private Object data;
public Box() {
}
public Box(Object data) {
public Box() {
}
public Box(T data) {
this.data = data;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return this.data.toString();
}
}
class Box{
private Number data;
public Box() {
}
public Box(Number data) {
this.data = data;
}
public Number getData() {
return data;
}
Bridge method
Consider following code:
class Box<T>{
private T data;
public Box() {
}
public Box(T data) {
this.data = data;
}
public void setData(T data) {
this.data = data;
}
@Override
public String toString() {
return this.data.toString();
}
}
class Sample extends Box<Integer>{
public Sample() {
super();
}
public Sample(Integer data) {
super(data);
}
/*
//Method added by compiler to achive dynamic method dispatch
public void setData(Object data) { //Bridge method
super.setData((Integer)data);
} */
@Override
public void setData(Integer data) {
super.setData(data);
}
}
Restrictions on Generics
Cannot Instantiate Generic Types with Primitive Types
class Box<T>{
private static T data; //Not OK
//TODO: Getter and Setter
}
A class cannot have two overloaded methods that will have the same signature after type erasure.
class Program{
private Program( ){
//TODO
}
public void main( String[] args ){
//TODO
}
}
class Program{
public Program( String s1, int i1, float f1, double d1 ){
//TODO
}
public void main( String[] args ){
//TODO
}
}
interface Printable{
//int value; //Error: The blank final field value may not have been
initialized
int value = 123;
//public static final int value = 123;
}
interface Printable{
//void print( ) { } //Error: Abstract methods do not specify a
body
void print( );
//public abstract void print( );
}
void print( );
//public abstract void print( );
}
class Test implements Printable{ //Service Provider
@Override
public void print() {
System.out.println("Value : "+Printable.value);
}
}
public class Program { //Service Consumer
public static void main(String[] args) {
Printable p = null; //OK
p = new Test( ); //Upcasting
p.print();//Dynamic method dispatch
}
}
System.out.println("Num2 : "+B.num2);
System.out.println("Num2 : "+C.num2);
System.out.println("Num3 : "+C.num3);
}
}
interface A{
void f1();
}
interface B{
void f2();
}
interface C extends A, B{
void f3();
}
class D implements C{
@Override
public void f1() {
System.out.println("D.f1");
}
@Override
public void f2() {
System.out.println("D.f2");
}
@Override
public void f3() {
System.out.println("D.f3");
}
}
public class Program {
public static void main(String[] args) {
D d = new D();
d.f1();//OK
A a = new D();
a.f1();//OK
B b = new D();
b.f2();//OK
C c = new D();
c.f1(); //OK
c.f2(); //OK
c.f3(); //Ok
}
}
interface A{
void f1();
void f3();
}
interface B{
void f2();
B b = new C();
b.f2();
b.f3();
}
}
interface Printable{
void f1();
void f2();
void f3();
void f4();
}
abstract class AbstractPrintable implements Printable{
@Override public void f1() { }
@Override public void f2() { }
@Override public void f3() { }
}
class A extends AbstractPrintable{
@Override
public void f1() {
System.out.println("A.f1");
}
}
class B extends AbstractPrintable{
@Override
public void f2() {
System.out.println("B.f2");
p = new A();
p.f1(); //A.f1
p = new B();
p.f2(); //B.f2
p = new C();
p.f3(); //C.f3
}
}
Types of inheritance
Interface inheritance
Single inheritance( Allowed in java )
Multiple inheritance( Allowed in java )
Hierarchical inheritance( Allowed in java )
Multilevel inheritance( Allowed in java )
implementation inheritace
Single inheritance( Allowed in java )
Multiple inheritance( Not Allowed in java )
Hierarchical inheritance( Allowed in java )
Multilevel inheritance( Allowed in java )
Default interface method
If we want to make changes in the interface at runtime then we should use default method.
We can not provide body to the abstact method but it is mandatory to provide body to the default
method.
It is mandatory to override abstract method but it is optional to override default method.
interface A{
void f1( );
default void f2( ){
//TODO
}
interface A{
void f1( );
default void f2( ){
//TODO
}
}
interface B{
void f1( );
default void f3( ){
//TODO
}
}
class C implements A, B{
@override
public void f1( ){
//TODO
}
}
interface A{
void f1( );
default void f2( ){
//TODO
}
}
interface B{
void f1( );
default void f2( ){
//TODO
}
}
class C implements A, B{
@override
public void f1( ){
//TODO
}
@Override
public void f2( ){ //mandatory to override
//TODO
}
}
interface Collection {
void acceptRecord();
int[] toArray();
void printRecord();
public Array() {
this(5);
}
@Override
public void acceptRecord() {
try (Scanner sc = new Scanner(System.in)) {
for (int index = 0; index < this.arr.length; ++index) {
System.out.print("Enter element : ");
this.arr[index] = sc.nextInt();
}
}
}
@Override
public void sort() {
for( int i = 0; i < this.arr.length - 1; ++ i ) {
for( int j = i + 1; j < this.arr.length; ++ j ) {
if( this.arr[ i ] > this.arr[ j ] ) {
int[] temp = new int[ ] { arr[ i ], arr[ j ]};
Collection.swap(temp);
arr[ i ] = temp[ 0 ];
arr[ j ] = temp[ 1 ];
}
}
}
}
@Override
public void printRecord() {
System.out.println(Arrays.toString(this.arr));
}
}
Static interface methods are helper methods that we can use inside default method as well as inside
sub class. But we can not override it inside sub class.
Functional interface
An interface which can contain Single Abstract Method (SAM) is called as Functional interface / SAM
interface.
Example:
java.lang.Runnable
java.util.Comparator
java.util.function.Predicate
java.util.function.Consumer
java.util.function.Supplier
java.util.function.Function
Consider following code:
For students use only 214 / 363
@FunctionalInterface
interface A{
void f1();
}
@FunctionalInterface
interface A{
void f1();
default void f2( ){
}
}
@FunctionalInterface
interface A{
void f1();
default void f2( ){
}
static void f3( ){
}
}
@FunctionalInterface
interface A{
void f1();
default void f2( ){
}
default void f3( ){
}
static void f4( ){
}
static void f5( ){
}
}
If we want to create new instance from existing instance then we should use clone method.
clone is non final and native method of java.lang.Object class:
Syntax:
protected native Object clone( )throws CloneNotSupportedException
Inside clone method, if we want to create shallow copy of instance then we should use super.clone();
Without implementing Cloneable interface, if we try to create clone() of the instane then clone
method throws CloneNotSupportedException.
Marker interface:
An interface which do not contain any member is called as marker / tagging interface.
Marker interface are used to generate metadata. It helps JVM to perform some operations e.g
to do clone, serializing state of java instance etc.
Example:
java.lang.Cloneable
java.util.EventListener
java.util.RandomAccess
java.rmi.Remote
@Override
public String toString() {
return this.day+" / "+this.month+" / "+this.year;
}
}
System.out.println(dt1);
System.out.println(dt2);
Shallow Copy
If we want to sort array/collection of non primitive type using Arrays.sort() method then non primitive
type must implement Comparable interface.
Comparable is interface declared in java.lang package.
T -> the type of objects that this object may be compared to
Method:
int compareTo(T other)
Returns a negative integer(-1) : current/calling object is less than the specified object.
Returns zero(0): current/calling object is equal to the specified object.
Returns a positive integer(1) : current/calling object is greater than the specified object.
Comparable interface provides natural ordering( default ordering ) of elements inside same class.
This interface imposes a total ordering on the objects of each class that implements it. This ordering
is referred to as the class's natural ordering, and the class's compareTo method is referred to as its
natural comparison method.
@NoArgsConstructor
@AllArgsConstructor
@Getter @Setter
//@ToString
@Override
public int compareTo(Employee other) {
return this.empNumber - other.empNumber;
}
@Override
public String toString() {
return String.format("%-5d%-10s%-10s%-5d%-15s%-10.2f%-10.2f%-5d",
this.empNumber, this.empName, this.job, this.manager, this.hireDate,
this.salary, this.commision, this.deptNumber);
}
}
import java.util.Comparator;
import java.util.Comparator;
public class IdComparator implements Comparator<Person>{
@Override
public int compare(Person p1, Person p2) {
if( p1 instanceof Student && p2 instanceof Student ) {
Student s1 = (Student) p1;
Student s2 = (Student) p2;
return s1.getRollNumber() - s2.getRollNumber();
}else if( p1 instanceof Employee && p2 instanceof Employee ) {
Employee e1 = (Employee) p1;
Employee e2 = (Employee) p2;
return e1.getEmpid() - e2.getEmpid();
}else if( p1 instanceof Student && p2 instanceof Employee ) {
Student s1 = (Student) p1;
Employee e2 = (Employee) p2;
return s1.getRollNumber() - e2.getEmpid();
}else {
Employee e1 = (Employee) p1;
Student s2 = (Student) p2;
return e1.getEmpid() - s2.getRollNumber();
}
}
}
import java.util.Iterator;
import java.util.LinkedList;
We can use foreach loop on Array and any instance which implements java.lang.Iterable interface.
Iterable is interface declared in java.lang package.
T -> the type of elements returned by the iterator
Implementing this interface allows an object to be the target of the "for-each loop" statement.
It is introduced in JDK 1.5
Methods:
java.util.Iterator iterator()
default Spliterator spliterator()
default void forEach(Consumer<? super T> action)
Iterator is interface declared in java.util package.
E -> the type of elements returned by this iterator
It is introduced in JDK 1.2
Methods:
boolean hasNext()
E next()
default void remove()
default void forEachRemaining(Consumer<? super E> action)
Super class of abstract class can be either concrete class / abstract class. Abstract class can extend
only one abstract class / concrete class.
We can define constructor inside abstract class.
Abstract may/may not contain abstract method.
When state is involved in super type then it should be abstract class
Interface
If "is-a" relationship is not exist between super type & sub type( "can-do" relationship is exist ) and if
we want to use same method design in all the sub classes then super type should be interface.
Super type of interface must be interface. Interface can extend multiple interfaces.
We can not define constructor inside interface.
Interface methods are by default public and abstract.
When state is not involved in super type then it should be interface.
Nested class
We can define class inside scope of another class. It is called as nested class.
Consider following code:
Access modifier of top level class can be either package level private or public only but we can use
any access modifier on nested class.
Types of nested class
Non static nested class / Inner class
For students use only 229 / 363
Static nested class
Inner class
In Java, non static nested class is called as inner class.
If implementation of nested class depends on top level class then we should declare nested class non
static.
@Override
public Iterator<Integer> iterator() {
Iterator<Integer> itr = new LinkedListIterator( this.head );
//Upcasting
return itr;
}
Note: For the simplicity, consider non static nested class a non static method of the class.
Consider following code:
class Outer{
class Inner{
//TODO
}
}
Inside non static nested class i.e inner class, we can not define static members( fields & methods ).
But if we want to declare any static field then it must be final.
Using instance, we can access members of non static nested class inside method of top level class.
Consider following example:
class Outer{
private int num1 = 10; //OK
private static int num2 = 20; //OK
class Inner{
private int num3 = 30; //OK
//private static int num4 = 40; //Not OK
private final static int num4 = 40; //OK
}
Without instance, we can access all the members of top level class inside method of non static
nested class i.e inner class.
Consider following code:
class Outer{
private int num1 = 10;
private static int num2 = 20;
class Outer{
private int num1 = 10;
class Inner{
private int num1 = 20;
public void print( ) {
int num1 = 30;
System.out.println("Num1 : "+Outer.this.num1); //10
System.out.println("Num1 : "+this.num1); //20
System.out.println("Num1 : "+num1); //30
}
}
}
public class Program {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner();
in.print();
}
}
In Java, we can not declare top level class static but we can declare nested class static.
Note: For simplicity, consider static nested class as a static method of the class.
Instantiation of Top level class:
We can access static members of the top level class inside method of static nested class directly. But
to access non static member of the class we must use instance of the class.
class Outer{
private int num1 = 10;
private static int num2 = 20;
interface Printable{
void print( );
}
public class Program {
public static void main(String[] args) {
Printable p = new Printable() {
@Override
public void print() {
System.out.println("Hello World!!");
}
};
Reflection
Annotation
class Date{
//TODO: Member definition
}
class Address{
//TODO: Member definition
}
class Person{
//TODO: Member definition
When class loader loads Program, String, Date, Address, Person class for execution then it create
instance of java.lang.Class per loaded type on Method area. Instance contains metadata of the
loaded type.
java.lang.Class class
Class class is a final class declared in java.lang package.
The entry point for all reflection operations is java.lang.Class.
Instances of the class java.lang.Class represent classes and interfaces in a running Java application.
Class has no public constructor. Instead Class objects are constructed automatically by the Java
Virtual Machine.
Methods of java.lang.Class:
public static Class<?> forName(String className) throws ClassNotFoundException
public Annotation[] getAnnotations()
public Annotation[] getDeclaredAnnotations()
public ClassLoader getClassLoader()
public Constructor<?>[] getConstructors() throws SecurityException
public Constructor getConstructor(Class<?>... parameterTypes) throws
NoSuchMethodException, SecurityException
public Field getDeclaredField(String name) throws NoSuchFieldException, SecurityException
public Field[] getDeclaredFields() throws SecurityException
public Field getField(String name) throws NoSuchFieldException, SecurityException
public Field[] getFields() throws SecurityException
public Class<?>[] getInterfaces()
public Method[] getMethods() throws SecurityException
For students use only 240 / 363
public Method[] getDeclaredMethods()throws SecurityException
public String getName()
public String getSimpleName()
public Package getPackage()
public InputStream getResourceAsStream(String name)
public String getTypeName()
public T newInstance() throws InstantiationException, IllegalAccessException
Retrieving Class Objects
Using getClass() method:
int i = 123;
Class<?> c = i.getClass( ); //Not OK
Class<?> c = i.class; //OK
Class<?> c = Number.class; //OK
It is convenient to use .class syntax with primitive type and abstract class.
Using Class.forName() method
If the fully-qualified name of a class is available, it is possible to get the corresponding Class
using the static method Class.forName().
Class<?> c = Double.TYPE;
Class<?> c = Void.TYPE; //OK
Class<?> c = Void.class; //OK
import java.lang.reflect.Modifier;
Class<?> sc = c.getSuperclass();
String superClassName = sc.getName();//Returns the name of the
super class
Class<?>[] si = c.getInterfaces();
StringBuffer sb = new StringBuffer();
for (Class<?> i : si) {
sb.append(i.getName());//Returns the name of the super
interfaces
}
}
}
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
For students use only 242 / 363
public class Program {
public static void main(String[] args) {
Class<?> c = Integer.class;
Field[] fields = c.getFields(); //Returns an array of public
fields that are declared in the class or its superclasses
Field[] declaredFields = c.getDeclaredFields(); //Returns an array
of all the fields declared in the class
for (Field field : declaredFields) {
String modifiers = Modifier.toString(field.getModifiers());
String typeName = field.getType().getSimpleName();
String fieldName = field.getName();
System.out.println( modifiers+" "+typeName+" "+fieldName);
}
}
}
getFields() returns an array of public fields that are declared in the class or its superclasses. This
includes fields inherited from the superclass or any interface that the class implements. This method
does not return any private or protected fields, regardless of whether they are inherited or declared in
the class.
getDeclaredFields() returns an array of all the fields declared in the class. This includes public,
private, and protected fields. It does not include any fields inherited from a superclass or an interface.
Examine Method Metadata
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
getMethods(): This method returns an array of Method objects that represent all the public methods
of the class (including inherited methods) and the public methods declared in any interfaces
implemented by the class.
getDeclaredMethods(): This method returns an array of Method objects that represent all the
methods declared explicitly by the class, including both public and non-public methods. It does not
include any inherited methods or the methods declared in any interfaces implemented by the class.
Accessing private fields using Reflection
import java.lang.reflect.Field;
class Complex{
private int real;
private int imag;
public Complex() {
this.real = 10;
this.imag = 20;
}
public int getReal() {
return this.real;
}
public int getImag() {
return this.imag;
}
}
public class Program {
public static void main(String[] args) {
try {
Class<?> c = complex.getClass();
Field field = null;
field = c.getDeclaredField("real");
field.setAccessible(true);
field.setInt(complex, 50);
field = c.getDeclaredField("imag");
field.setAccessible(true);
field.setInt(complex, 60);
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
class Complex {
private int real;
private int imag;
Middleware Application
//Calculator.java
public class Calculator {
public double sum( int num1, float num2, double num3) {
return num1 + num2 + num3;
}
public int sub( int num1, int num2 ) {
return num1 + num2;
}
}
//Convert.java
class Convert{
public static Object changeType( String type, String value ) {
switch( type ) {
case "int":
return Integer.parseInt(value);
case "float":
return Float.parseFloat(value);
case "double":
return Double.parseDouble(value);
}
return null;
}
}
//Program.java
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Scanner;
Advantages of Reflection:
Dynamic class loading: Reflection allows classes to be loaded and instantiated dynamically, which
can be useful when the class to be used is not known at compile time.
Introspection: Reflection allows the properties and methods of a class to be inspected at runtime.
This can be useful for building tools like debuggers or IDEs, where we need to be able to examine the
structure of a program while it is running.
Frameworks and libraries: Many Java frameworks and libraries make use of reflection to provide
powerful features like dependency injection, ORM, and serialization.
Testing: Reflection can be useful for testing by allowing access to private methods and fields, and for
mocking objects.
For students use only 247 / 363
Drawbacks of Reflection:
Performance overhead: Reflection operations are slower than direct method calls because they
involve additional runtime checks and lookups.
Security risks: Reflection can be used to bypass access controls and security measures, allowing
malicious code to access private fields and methods or modify the behavior of a program in
unexpected ways.
Complexity and readability: Reflection code can be harder to read and understand, especially for
developers who are not familiar with the language's reflection APIs.
Proxy Design Pattern( Assignment )
The official Java documentation on the Proxy pattern:
https://blogs.oracle.com/javamagazine/post/the-proxy-pattern
Reference: The Gang of Four (GoF) book: The GoF book "Design Patterns: Elements of Reusable
Object-Oriented Software".
Multithreading
Singletasking versus multitasking
Process Definition:
Program in execution is called as process.
Running instance of a program is called as process.
Process is also called as task.
Term Singletasking and multitasking is always used in the context of Operating System
An ability of operating system to execute single task at a time is called as Singletasking.
Example: MS DOS is singletasking operating system.
An ability of operating system to execute multiple task at a time is called as Multitasking.
Example: MS Windows, Linuxm Mac OS etc.
Before transfering control of CPU from one process to another, schedular must save state of the
process into process control block. Then another process get access of CPU. It is called context
switching.
Since context switching is a heavy task, proess based multitasking is called as heavy weight
multitasking.
Nested Type
Thread.State is enum declared inside Thread class.
import java.lang.Thread.State;
NEW 0
RUNNABLE 1
BLOCKED 2
WAITING 3
TIMED_WAITING 4
TERMINATED 5
Fields:
public static final int MIN_PRIORITY //1
public static final int NORM_PRIORITY //5
public static final int MAX_PRIORITY //10
For students use only 252 / 363
Constructors
public Thread()
public Thread(String name)
public Thread(Runnable target)
public Thread(Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name)
Methods
public static Thread currentThread()
public final String getName()
public final void setName(String name)
public final int getPriority()
public final void setPriority(int newPriority)
public Thread.State getState()
public final boolean isAlive()
public final boolean isDaemon()
public final void join() throws InterruptedException
public final void setDaemon(boolean on)
public static void sleep(long millis) throws InterruptedException
public void start()
public static void yield()
Thread creation using java.lang.Thread class and Runnable interface
User Thread versus Daemon Thread
Thread termintation
Blocking calls in Thread
Race condition and synchronized keyword
Inter thread communication using wait,notify/notifyAll
Synchronization using consumer/producer
Thread life cycle.
Thread is non Java resource. In other words, it is unmanaged resource. Hence developer must take
care of its creation as well as termination / dispose.
Instance of java.lang.Thread is not a operating system thread. Rather it represents operating system
thread.
package java.lang;
public class Thread extends Object implements Runnable{
public static enum State{
NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED;
}
}
package java.lang;
public class Thread extends Object implements Runnable{
@FunctionalInterface
public static interface UncaughtExceptionHandler {
void uncaughtException(Thread t, Throwable e);
}
}
Output is:
class Sample{
public Sample( ) {
System.out.println("Inside constructor of
"+this.getClass().getSimpleName());
}
public void print( ) {
System.out.println("Inside print method of
"+this.getClass().getSimpleName());
}
@Override
protected void finalize() throws Throwable {
System.out.println("Inside finalize method of
"+this.getClass().getSimpleName());
Output is
finalize
It is non final method of java.lang.Object class.
If we want to release class level( which is declared as field ) resources then we should
use finalize method.
class Sample{
private Scanner sc; //Field
public Sample( ) {
this.sc = new Scanner( System.in);
}
//TODO
@Override
protected void finalize() throws Throwable {
this.sc.close();
}
}
public class Program {
public static void main(String[] args) {
Sample sample = null;
sample = new Sample();
sample.print();
sample = null;
System.gc
}
}
If we call start() method on already started thread then start() method throws
IllegalThreadStateException
When control come out of run method then thread gets terminated. In this case thread is considered
in TERMINATED state.
In following cases, control can come out of run method and thead can terminate:
Successful completion of run method.
Getting exception during execition of run method.
Execution of jump statement( return statement ) inside run method.
If we want to suspend execution of running thread then we should use sleep() method. It is a static
method of java.lang.Thread class.
Thread.sleep( 250 )
@Override
public void run() {
//TODO: Business Logic
}
}
public class Program {
public static void main(String[] args) {
Task th1 = new Task("User Thread#1");
Task th2 = new Task("User Thread#2");
}
}
Day 20
What will happen if we call run method instead of start method on thread instance
class Task extends Thread{
public Task( String name ) {
super( name );
}
@Override
If we call start() method on thread instance then JVM starts execution of new Thread. But if we call
run() method on thread instance then JVM do not start execution of new Thread. In above code, main
therad is calling main method and main method is calling run() method. In directly main thread is
calling run() method.
What is the difference between creating thread using Runnable and Thread class
Runnable
Consider Thread creation using Runnable interface:
class B extends A{
public B( ){
}
@Override
public void run( ){
//TODO: Write business logic here
}
}
class D extends C{
public D( ){
}
@Override
public void run( ){
//TODO: Write business logic here
}
}
If create instance of class B then first A class and then B class constructor will call. In class A, Thread
registration process will start and when OS thread will get CPU then B class run method will call.
Same is the case of class C and D. In simple words, If class implement Runnable interface then that
class and all its sub classes must participate in Threading behavior.
Thread
Consider Thread creation by extending Thread class:
In Java, class can extend more than one class. So here we can not extend another class / if
class already sub class of another class then we can not extend Thread.
Let us try to create sub class of class A
class B extends A{
public B( ){
}
class C extends B{
public C( ){
}
@Override
public void run( ){
//TODO: Write business logic here
}
}
class D extends C{
public D( ){
}
@Override
public synchronized void start() {
//Keep Empty
}
}
In above code class A, B and C must participate into Threading behavior. But by overriding
start( ) method class D can come out of threading behavior.
Types of Thread in java:
User Thread
It is also called as non daemon thread.
If we create any thread from main method / another user thread then it is by default considered
as user thread.
Default Properties of main thead:
Type: User Thread
Priority: 5
Thread group: main
Daemon Thread
It is also called as background thread.
If we create any thread from finalze method / another deamon thread then it is by default
considered as daemon thread.
Default Properties of GC thead:
Type: Daemon Thread
Priority: 8
Thread group: system
For students use only 267 / 363
Using "public final boolean isDaemon()" method we can check type of thread.
Using "public final void setDaemon(boolean on)" method we can marks thread as either a daemon
thread or a user thread.
When the interrupt signal is sent to the thread, it will set an interrupted flag on the thread. We can
check that flag using isInterrupted() method.
isInterrupted() method only check interrupted status but do not reset the status.
Using interrupted() method we can check interrupted status but it reset interrupted status. In other
words, if this method were to be called twice in succession, the second call would return false
while (!Thread.interrupted()) {
for (int count = 100; count <= 120; ++count)
System.out.println("Count : " + count);
}
}
}
Thread Priority
OS schedular is responsible for assigning CPU to the thread.
On the basis of thread priority schedular assign CPU to the thread.
Thread priorities of Java and OS are different.
Thread priorities in Java:
Thread.MIN_PRIORITY = 1;
Thread.NORM_PRIORITY = 5;
Thread.MAX_PRIORITY = 10;
How will you read thread priority in Java?
If we set priority of a thread in Java then OS map it differently on differnt system. Hence Same Java
application produces different behavior on different OS.
Which features of Java makes Java application platform dependent:
Abstract Window Toolkit(AWT) Components
AWT components implicitly use peer classes and these classes has been written into
C++ which are OS specific.
Thread priorities
Thread Join
If we call join method on thread instance then it blocks execution of all other threads
For students use only 271 / 363
Consider following code:
Race Condition
A race condition is a situation that occurs in a concurrent system when two or more threads or
processes access a shared resource or variable in an uncontrolled order, resulting in unpredictable
and often incorrect behavior.
To prevent race conditions, concurrency control mechanisms such as locks, semaphores, and
monitors can be used to ensure that only one thread at a time can access and modify a shared
resource.
In Java,we can use synchronized keyword with block/method to avoid race condition.
For students use only 272 / 363
If threads are waiting to get monitor object associated with shared resource then it is consider in
BLOCKED state.
In Java, inter-thread communication is achieved using the wait(), notify() and notifyAll() methods,
which are defined in the Object class.
wait() : This method causes the current thread to wait until another thread invokes the notify()
or notifyAll() method for the same object. The thread will release the lock it holds on the object
and wait until it's notified by another thread.
notify() : This method wakes up a single thread that is waiting on the object. If there are
multiple threads waiting, only one thread will be awakened. The awakened thread will not be
For students use only 273 / 363
able to proceed until it regains the lock on the object.
notifyAll() : This method wakes up all the threads that are waiting on the object. All the threads
will then compete for the lock on the object.
The JVM throws the IllegalMonitorStateException when a thread attempts to call the wait(), notify(),
or notifyAll() methods on an object without holding the object's monitor.
class TickTock{
public void tick() throws InterruptedException {
synchronized( this ) {
System.out.print("Tick ");
this.notify();
this.wait( 1000 ); //To avoid deadlock pass time
}
}
public void tock() throws InterruptedException {
synchronized( this ) {
System.out.println(" Tock");
this.notify();
this.wait( 1000 ); //To avoid deadlock pass time
}
}
}
@Override
public void run() {
try {
while (true) {
String order = "Burger"; // produce food
kitchen.addOrder(order);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@Override
public void run() {
try {
while (true) {
String order = kitchen.getOrder();
serve(order); // consume food
Thread.sleep(1000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void serve(String order) {
System.out.println("Serving " + order);
}
}
Volatile Fields:
Computers with multiple processors can temporarily hold memory values in registers or local memory
caches. As a consequence, threads running in different processors may see different values for the
class SharedInstance{
int counter = 0;
}
Here we assume that there are two threads are working on SharedInstance.
If these two threads run on different processors then each thread will have its own local copy
of counter.
If we modifies value of one thread, then its value might not reflect in the original one in the
main memory instantly. It is totally depends on the write policy of cache.
Now the other thread is not aware of the modified value which leads to data inconsistency.
If the counter variable is not declared volatile there is no guarantee about when the value of the
counter variable is written from the CPU cache back to main memory. This means, that the
counter variable value in the CPU cache may not be the same as in main memory.
volatile is a keyword in Java which is applicable only for fields.
"DAC";
//{'D','A','C','\0'}
In Java, String is collection of character instances which do not end with '\0' character.
If we want to manipulate String in Java then we can use following classes:
java.lang.String
java.lang.StringBuffer
java.lang.StringBuilder
java.util.StringTokenizer
java.text.Pattern
java.text.Matcher
org.apache.commons.lang3.StringUtils
java.lang.String
If we create String instance using new operator then it gets space on heap section.
String s1 = "CDAC";
//s1 : String reference
//"CDAC" : String literal
If we create String without new operator the it gets space on String literal on method area.
In Java, String do not ends with '\0' character. Using illegal index, if we try to access character from
String then String methods throws StringIndexOutofBoundsException.
Strings are constant; their values cannot be changed after they are created. In other words, String
instances are immutable.
Consider following code:
System.out.println(s1.concat("ACTS")); //CDAC,ACTS
String s2 = s1.concat("ACTS");
System.out.println(s2); //CDAC,ACTS
}
The Java language provides special support for the string concatenation operator ( + ), and for
conversion of other objects to strings.
Using + operator, we can contact any(primitive/non primitive) value to the String but using
concat method we can concat onluy String.
Constant expressions always gets evaluated at compile time. Hence "CDAC,"+"ACTS" will be
considered as "CDAC,ACTS" at compile time.
if( s1 == s2 )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Output: Not Equal
}
if( s1.equals(s2) )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Output: Equal
}
if( s1 == s2 )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Output: Equal
}
if( s1.equals(s2) )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Output: Equal
}
Reference: https://learn.microsoft.com/en-us/previous-
versions/windows/desktop/ms762271(v=vs.85)
StringTokenizer
www.cdac.in
www cdac in //Tokens
. //Delimiter
Constructor Summary
public StringTokenizer(String str)
public StringTokenizer(String str, String delim)
public StringTokenizer(String str, String delim, boolean returnDelims)
Method Summary
public int countTokens()
public boolean hasMoreTokens()
public String nextToken()
public String nextToken()
Regular Expression
regular expression to validate a 10-digit mobile number:
^\d{10}$
^[A-Za-z]+(\s[A-Za-z]+)*$
^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$
class Date{ }
class Addresss{ }
class Person{
private String name = new String();
private Date birthDate = new Date();
private Address currentAddress = new Address();
}
class Program{
public static void main(String[] args) {
Person p = new Person( );
}
}
In Java, instance do not get space inside another instance. Rather instance contains reference of
another instance.
Library
In Java, .jar file is a library file.
It can contain, menifest file, resources, packages.
Package can contain sub package, interface, class, enum, exception, error, annotation types
Example: rt.jar
Framework
framework = collection of libraries + tools + rules/guidelines
It is a development platform which contain reusable partial code on the top of it we can develop
application.
Examples:
For students use only 297 / 363
JUnit: Unit testing framework which is used to write test case.
Apache Log4j2: Logging framework which is used to record activities.
AWT/Swing/Java-FX: GUI framework.
JNI: Framework to access native code
Struts: Readymade MVC based web application framework.
Hibernate: ORM based automatic persistence framework
Spring: Enterprise framework
Collection
Any instance which contains multiple elements is called as collection.
In java, data structure is also called as collection.
Collection Framework
Collection framework is a library of data structure classes on the top of it we can develop Java
application.
In Java, collection framework talk about use not about implementation.
In Java, when we use collection to store instance then it doesnt contain instance rather it contains
reference of the instance.
To use collection framework, we should import java.util package.
Iterable
It is interface declared in java.lang package.
It is introduced in jDK 1.5.
Implementing this interface allows an object to be the target of the "for-each loop" statement.
Methods:
Iterator iterator()
default Spliterator spliterator()
default void forEach(Consumer<? super T> action)
For students use only 298 / 363
Collection
Reference: https://docs.oracle.com/javase/8/docs/technotes/guides/collections/overview.html
Value stored inside any collection( Array, Stack, Queue, LinkedList etc.) is called as element.
It is interface declared in java.util package.
It is root interface in the collection framework interface hierarchy.
The JDK does not provide any direct implementations of Collection interface.
Direct implementation classes of Collection interface are AbstractList, AbstractQueue, AbstractSet.
List, Queue, Set are sub interfaces of java.util.Collection interface.
Abstract methods of java.util.Collection interface:
boolean add(E e)
boolean addAll(Collection<? extends E> c)
void clear()
boolean contains(Object o)
boolean containsAll(Collection<?> c)
boolean isEmpty()
boolean remove(Object o)
boolean removeAll(Collection<?> c)
boolean retainAll(Collection<?> c)
int size()
Object[] toArray()
T[] toArray(T[] a)
Default methods of java.util.Collection interface:
default Stream stream()
default Stream parallelStream()
default boolean removeIf(Predicate<? super E> filter)
List
This interface is a member of the Java Collections Framework and introduced in JDK 1.2
//Object[] elementData;
private static int capacity(List<Integer> list) throws Exception{
Class<?> c = list.getClass();
Field field = c.getDeclaredField("elementData");
field.setAccessible(true);
Object[] elementData = (Object[]) field.get(list);
return elementData.length;
}
public static void main(String[] args) {
try {
List<Integer> list = Program.getList();
System.out.println("Size : "+list.size()); //5
How will you search and remove single element from ArrayList?
During traversing, without iterator, if we try to make changes in underlying collection and if we do not
get ConcurrentModificationException then such iterator is called as fail-safe Iterator. Such iterators
works by creating copy of the Collection.
LinkedList
Deque
It is sub interface of Queue interface.
The name deque is short for "double ended queue" and is usually pronounced "deck".
This interface is a member of the Java Collections Framework.
It is introduced in JDK 1.6
Set
Day 22
Set
set.add(50);
For students use only 318 / 363
set.add(10);
set.add(30);
set.add(20);
set.add(40);
System.out.println( set );
}
Algorithm
In Computer science algorithm and data structure are two different branches.
Data structure describes 2 things:
How to organize data inside RAM?
Which operations should be used to organize data inside RAM.
Data structure can be linear / non linear.
Well defined set of statements that we can use to solve real world common problems is called as
algorithms.
In the context of data structure algorithms can be searching / sorting algorithms.
Searching
Searching refers to the process of finding location( index / reference ) of an element in Collection.
The collection of data may be in array, list, database, or any other data structure.
There are several searching algorithms, each with its own strengths and weaknesses:
For students use only 319 / 363
Linear search
Binary search
Hashing
Interpolation search
Exponential search
Linear Search
Linear search is a simple searching algorithm that sequentially searches each element in a collection
until the desired item is found.
Consider following code:
Hashing is a technique used to store and retrieve data in a fast and efficient manner.
Hashing searching is based on hash code.
Hashcode is not an index / address / reference. It is a logical integer number that can be generated by
processing state of the instance.
To generate hash code we should use hash function. Consider following example
In the context of hashing, a slot refers to a location in the hash table where a key-value pair can be
stored.
By Processing state of the instance, if we get same slot then it is called as collision.
To avoid collision, we can maintain one collection(LinkedList/BST) per slot. It is called as bucket.
Note: If we want to store any element of non primitive type inside Hashcode based collection then we
should override equals and hashCode method inside non primitive type.
Pros of Hashing
Fast retrieval: Hashing allows for constant-time retrieval of data, regardless of the size of the
data set. This makes it a very efficient searching algorithm.
Flexibility: Hashing can be used to search for any type of data, including strings, numbers, and
custom objects.
Easy to implement
Supports dynamic resizing: Hash tables can be resized dynamically to accommodate more
data, without having to recreate the entire data structure.
Cons of Hashing:
Hash collisions: Hash collisions occur when two different keys are mapped to the same hash
value. This can result in slower lookup times and may require additional processing to resolve
the collision.
Memory usage: Hash tables can consume a lot of memory, particularly if the data set is large.
This can lead to performance issues if the available memory is limited.
Hash functions: The efficiency of hashing depends on the quality of the hash function used.
Poor hash functions can lead to more collisions, slower retrieval times, and other issues.
equals and hashCode are non final methods of java.lang.Object class.
If we do not override equals method then super class's equals method will call. equals method of
Object class do not compare state of instances. It compares state of references.
Consider equals method definition of Object class:
hashCode() method of java.lang.Object class convert memory address of instance into integer value.
Hence even though state of the instances are same we get different hashCode. If we want hashCode
based on state of the instance then we should override hashCode method inside class.
Consider implementation:
@Override
public int hashCode() {
int prime = 31;
int result = 1;
result = result * prime + this.empid;
return result;
}
HashSet
It is hashCode based collection whose implementation is based on Hashtable.
In HashSet elements get space according its hash code hence It doesn't give any gurantee about
order of the elements.
Since it is Set collection, it doesn't contain duplicate elements.
HashSet can contain null element.
It is unsynchronized collection. Using Collections.synchronizedSet() method we can consider it
synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.2
If we want to use any element of non final type inside HashSet then non final type should override
equals() and hashCode() method.
Instantiation of HashSet:
set.add(101);
set.add(125);
set.add(13);
set.add(314);
set.add(215);
set.add(null);
System.out.println(set); //[null, 101, 215, 314, 125, 13]
}
LinkedHashSet
It is hashCode based collection whose implementation is based on Hashtable and LinkedList.
During traversing it maintains order of lements.
Since it is Set collection, it doesn't contain duplicate elements.
HashSet can contain null element.
It is unsynchronized collection. Using Collections.synchronizedSet() method we can consider it
synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.4
If we want to use any element of non final type inside HashSet then non final type should override
equals() and hashCode() method.
For students use only 326 / 363
Dictionary<K,V>
Dictionary<K,V> is abstract class declared in java.util package.
We can use it store elements in key value pair format.
Hashtable is sub class of Dictionary<K,V> class.
It was introduced in JDK 1.0
Method Summary
public abstract V put(K key, V value)
public abstract int size()
public abstract V get(Object key)
public abstract V remove(Object key)
public abstract boolean isEmpty()
public abstract Enumeration keys()
public abstract Enumeration elements()
Consider example of Dictionary class:
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
public class Program {
public static Dictionary<Integer, String> getDictionary( ){
Dictionary<Integer, String> d = new Hashtable<>(); //Upcasting
d.put(1,"PreDAC");
d.put(2,"DAC");
d.put(3,"DMC");
d.put(4,"DIVESD");
d.put(5,"DESD");
d.put(6,"DBDA");
return d;
}
private static void countAndPrintEntries(Dictionary<Integer, String>
d) {
System.out.println("Count of entries : "+d.size());
}
private static void printKeys(Dictionary<Integer, String> d) {
Enumeration<Integer> keys = d.keys();
Integer key = null;
while( keys.hasMoreElements()) {
key = keys.nextElement();
System.out.println( key );
}
}
private static void printValues(Dictionary<Integer, String> d) {
Enumeration<String> values = d.elements();
String value = null;
while( values.hasMoreElements()) {
value = values.nextElement();
System.out.println(value);
}
}
private static void printValue(Dictionary<Integer, String> d, int
For students use only 327 / 363
courseId) {
Integer key = new Integer( courseId );
String value = d.get(key);
if( value != null )
System.out.println(key+" "+value);
else
System.out.println("Invalid key");
}
private static void removeEntry(Dictionary<Integer, String> d, int
courseId) {
Integer key = new Integer( courseId );
String value = d.remove(key);
if( value != null )
System.out.println(key+" "+value+" is removed");
else
System.out.println("Invalid key");
}
public static void main(String[] args) {
Dictionary<Integer, String> d = Program.getDictionary();
//Program.countAndPrintEntries( d );
//Program.printKeys( d );
//Program.printValues( d );
//Program.printValue( d, 2 );
Program.removeEntry( d, 200);
}
}
This class is obsolete. New implementations should implement the Map interface, rather than
extending this class.
Map<K,V>
import java.util.ArrayList;
import java.util.Collection;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
For students use only 329 / 363
import java.util.Set;
Consider example:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
For students use only 332 / 363
result = prime * result + number;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Account other = (Account) obj;
if (number != other.number)
return false;
return true;
}
@Override
public String toString() {
return String.format("%-10d%-15s%8.2f", this.number, this.type,
this.balance);
}
}
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.example.domain.Account;
import org.example.domain.Customer;
import java.util.Hashtable;
import java.util.Scanner;
import org.example.domain.Account;
import org.example.domain.Customer;
import org.example.test.MapTest;
HashMap<K,V>
It is a sub class of AbstractMap<K,V> class and it implements Map<K,V>
Its implementation is based on Hash table.
For students use only 336 / 363
Since it is Map collection, we can not insert duplicate keys but we can insert duplcate value.
In HashMap<K,V> key and value can be null.
It is unsynchronized collection. Using Collections.synchronizedMap() method we can consider it
synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.2.
If we want to use any element of non final type inside Hashtable then non final type should override
equals and hashCode method.
Instantiation:
LinkedHashMap<K,V>
It is a sub class of HashMap<K,V>.
Its implementation is based on Hash table and linked list.
During traversing it maintains order of elements.
Since it is Map collection, we can not insert duplicate keys but we can insert duplcate value.
In HashMap<K,V> key and value can be null.
It is unsynchronized collection. Using Collections.synchronizedMap() method we can consider it
synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.2.
If we want to use any element of non final type inside Hashtable then non final type should override
equals and hashCode method.
Instantiation:
TreeMap<K,V>
It is a sub class of AbstractMap<K,V> class and it implements NavigableMap<K,V>
Its implementation is based on Red Black Tree.
TreeMap store entries in sorted order.
Since it is Map collection, we can not insert duplicate keys but we can insert duplcate value.
In TreeMap<K,V> key can not be null but value can be null.
It is unsynchronized collection. Using Collections.Collections.synchronizedSortedMap() method we
can consider it synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.2.
File I/O
Variable
It is temporary conrainter which is used to store record in primary memory( RAM ).
File
It is permenant conrainter which is used to store record on HDD.
Text File
Examples: .c, .cpp, .java. .cs, .html, css. .js, .txt, .doc, .docs, .xml, .json etc.
We can read text file using any text editor.
It requires more processing than binary file hence it is slower in performance.
If we want to save data in human readable format then we should create text file.
Binary File
Examples: .jpg, .jpeg, .bmp, .gif, .mp3, .mp4, .obj, .class etc.
To read binary file, we must use specific program.
It requires less processing than text file hence it is faster in performance.
If we dont want to save data in human readable format then we should create
binary file.
Stream
It is an abtraction( instane ) which either consume( read) or produce( write ) information from
source to destination.
Stream is always associated with resource.
Standard stream instances of Java programming languages which are associated with
Console( Keyboard / Monitor ):
System.in
System.out
System.err
If we want to save data in file the we should use types declared in java.io package.
java.io.Console class reprsents Console.
Interfaces:
FileFilter
FilenameFilter
Closeable
Flushable
DataInput
DataOutput
ObjectInput
ObjectOutput
Serializable
Externalizable
If we want to read/write data into binary file then we should use InputStream, OutputStream and their
sub classes.
If we want to read/write data into text file then we should use Reader, Writer and their sub classes.
Process of converting state of Java instance into binary data is called as serialization.
To serialize Java instance type of instance must implement Serializable interface otherwise we get
NotSerializableException.
If class contains fields of non primitive type then its type must implement Serializable interface.
Consider following example:
transient is modifier in Java. If we declare any field transient then JVM do not serialize its state.
Process of converting binary data into Java instance is called as deserialization.
import java.io.*;
class Sample implements Serializable {
private static final long serialVersionUID = 1L;
private int data;
In the above example, the Sample implements the Serializable interface, indicating that its objects
can be serialized. The class also defines a seriserialVersionUIDalVersionUID as 1L. When an object
of Sample is serialized, the serialVersionUID is included in the serialized byte stream. During
deserialization, the serialVersionUID is checked to ensure compatibility between the serialized
object and the class definition.
It's important to note that if you make any changes to a serialized class, such as adding or removing
fields or changing their types, you should update the serialVersionUID accordingly to maintain
compatibility between different versions of the class.
Text file manipulation
If we/you want to manipulate text file then we should use Reader/writer classes and their sub classes.
Consider Writer hierarchy:
The FileWriter class is used to write characters to a file. It extends the Writer class and provides
methods to write characters or character arrays to a file. It handles the underlying low-level
operations required for writing characters to a file, such as opening the file, writing the data, and
closing the file.
The FileReader class is used to read characters from a file. It extends the Reader class and provides
methods to read characters into a buffer from a file. It handles the low-level operations required for
reading characters from a file, such as opening the file, reading the data, and closing the file.
The BufferedWriter class is used to write characters to a character stream with buffering
capabilities. It wraps an existing Writer and improves the performance of writing characters by
buffering them in memory before writing them to the underlying stream.
The BufferedReader class is used to read characters from a character stream with buffering
capabilities. It wraps an existing Reader and improves the performance of reading characters by
buffering them in memory before accessing the underlying stream.
For students use only 350 / 363
In Java, InputStreamReader and OutputStreamWriter are classes that provide a bridge between byte
streams and character streams. They are used to convert bytes to characters (for input) and
characters to bytes (for output) while reading from or writing to streams.
The InputStreamReader class is used to read bytes from an InputStream and decode them into
characters using a specified character encoding. It converts a stream of bytes into a stream of
characters.
Consider following code:
import java.io.*;
public class Program {
public static void main(String[] args) {
String inputFile = "input.txt";
// Reading from a file using InputStreamReader
try (FileInputStream fileInputStream = new
FileInputStream(inputFile);
InputStreamReader inputStreamReader = new
InputStreamReader(fileInputStream)) {
char[] buffer = new char[1024];
int length;
while ((length = inputStreamReader.read(buffer)) != -1)
{
System.out.println(new String(buffer, 0, length));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
The OutputStreamWriter class is used to write characters to an output stream of bytes. It wraps an
existing OutputStream and provides methods to write characters to the output stream using a
specified character encoding.
Consider following example:
For students use only 351 / 363
import java.io.*;
public class Program {
public static void main(String[] args) {
String outputFile = "output.txt";
// Writing to a file using OutputStreamWriter
try (FileOutputStream fileOutputStream = new
FileOutputStream(outputFile);
OutputStreamWriter outputStreamWriter = new
OutputStreamWriter(fileOutputStream)) {
String data = "Hello, World!";
outputStreamWriter.write(data);
System.out.println("Data written to the file.");
} catch (IOException e) {
e.printStackTrace();
}
}
}
How to serialize and deserialize state of Java instance into text file?
Socket Programming
A URL stands for Uniform Resource Locator.
It is a standardized address used to locate resources on the internet.
Web Page.
Image files.
For students use only 353 / 363
Audio/video files.
Document files etc.
A URL has the following components:
Protocol: It specifies the protocol used to access the resource, such as HTTP, HTTPS, FTP, etc.
Host: It specifies the domain name or IP address of the server hosting the resource.
Port: (Optional) It specifies the port number on the server to connect to. If not specified, it
defaults to the default port for the specified protocol (e.g., 80 for HTTP, 443 for HTTPS).
Ports are identified by numbers ranging from 0 to 65535.
In networking, certain port numbers are reserved for specific services and protocols.
These reserved ports are standardized and commonly used for well-known services.
Here are some examples of reserved ports:
Well-Known Ports (0-1023):
Port 80: Hypertext Transfer Protocol (HTTP)
Port 443: Hypertext Transfer Protocol Secure (HTTPS)
Port 21: File Transfer Protocol (FTP)
Port 22: Secure Shell (SSH)
Port 25: Simple Mail Transfer Protocol (SMTP)
Port 110: Post Office Protocol (POP3)
Port 143: Internet Message Access Protocol (IMAP)
Port 3389: Remote Desktop Protocol (RDP)
Port 53: Domain Name System (DNS)
Registered Ports (1024-49151):
Port 3306: MySQL Database System
Port 5432: PostgreSQL Database System
Port 8080: Hypertext Transfer Protocol (HTTP) alternative port
Port 8443: Hypertext Transfer Protocol Secure (HTTPS) alternative port
Dynamic and/or Private Ports (49152-65535):
These ports are typically used for dynamic or private purposes and are not
assigned to specific services.
When developing network applications, it's recommended to use port numbers above
1023 for custom services to avoid conflicts with reserved ports.
Path: It specifies the path to the resource on the server. It can include directories and
subdirectories leading to the specific file or resource.
Parameters: (Optional) It specifies additional parameters passed to the server as part of the
URL. Parameters are typically key-value pairs used to provide information or customize the
request.
Fragment: (Optional) It specifies a specific location within the resource, such as an anchor or
section identifier within an HTML page.
An example of a URL:
https://www.example.com:8080/path/to/resource?
key1=value1&key2=value2#section1
Port number is logical integer number which is used to identify process running on server.
A physical memory which is allocated client and server through which client/server can
send/receive data is called as socket.
In java, If we want to do socket programming then we should import java.net package.
In Java, the InetAddress class is used to represent IP addresses and perform various operations
related to network communication. Consider following code:
import java.net.InetAddress;
import java.net.UnknownHostException;
public class Program {
public static void main(String[] args) {
try {
// Get the local host's IP address
InetAddress localHost = InetAddress.getLocalHost();
System.out.println("Local Host IP Address: " +
localHost.getHostAddress());
// Checking reachability
boolean isReachable = googleAddress.isReachable(5000); // 5
seconds timeout
System.out.println("Is Google Reachable: " + isReachable);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
}
In Java, Inet4Address and Inet6Address are subclasses of the InetAddress class and represent IP
addresses in the IPv4 and IPv6 formats, respectively. Consider following code:
import java.net.InetAddress;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.UnknownHostException;
public class Program {
public static void main(String[] args) {
try {
// Retrieve an IPv4 address
InetAddress ipv4Address =
Inet4Address.getByName("192.168.0.1");
System.out.println("IPv4 Address: " +
ipv4Address.getHostAddress());
package org.example.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
while (true) {
// Accept client connections
Socket clientSocket = serverSocket.accept();
System.out.println("Client connected: " +
clientSocket.getInetAddress().getHostAddress());
In Java, the Socket class is a fundamental component of network communication and is used to
establish a connection between a client and a server.
The Socket class provides the following functionalities:
Creating a Socket
Communicating with the Server
Sending and Receiving Data
Closing the Socket
For students use only 357 / 363
A simple example that demonstrates the usage of Socket in a client-server scenario:
package org.example.client;
import java.io.*;
import java.net.*;
try {
// Create a socket and connect to the server
Socket socket = new Socket(serverHostname, serverPort);
package org.example.server;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
String message;
do {
System.out.print("S:Server : ");
message = sc.nextLine();
outputStream.writeUTF(message);
outputStream.flush();
message = inputStream.readUTF();
System.out.println("S:Client : "+message);
}while( !message.equalsIgnoreCase("end"));
}catch( Exception ex ) {
ex.printStackTrace();
}finally {
try {
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Client
package org.example.client;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Scanner;
System.out.print("C:Client : ");
message = sc.nextLine();
outputStream.writeUTF(message);
outputStream.flush();
}while( !message.equalsIgnoreCase("end"));
}catch( Exception ex ) {
ex.printStackTrace();
}finally {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
A lambda expression consists of three main components: parameter list, arrow token, and
body.
Here's a breakdown of the components:
Parameters: The input parameters to the function. They can be omitted if the function
takes no arguments or inferred if there is only one parameter.
Arrow Token: The arrow token -> separates the parameter list from the body of the
lambda expression.
Expression/Body: The implementation of the lambda function, which can be a single
expression or a block of code enclosed in curly braces {}.
Lambda Expression with No Parameters
Method Reference
Method references in Java provide a way to refer to methods without executing them. They can be
seen as a shorthand notation for writing lambda expressions that invoke a single method.
There are four different types of method references in Java:
Reference to a Static Method:
class MathUtils {
public static int add(int a, int b) {
return a + b;
}
}
Reference to a Constructor