Full Core Java
Full Core Java
Full Core Java
[email protected]
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
• Reference: https://docs.oracle.com/javase/tutorial/getStarted/intro/definition.html
Application Programming Interface
Day 2
Java Documentation
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
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 ) {
System.out.println("Hello World!!!");
}
}
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
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
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
}
}
Reference: https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
Wrapper classes
In Java, primitive types are not classes. But Sun/Oracle developers has written classes for it. Such
classes are called as Wrapper classes.
All the Wrapper classes are final and declared in java.lang package.
Class Hierarchy
java.lang.Object
java.lang.Boolean
java.lang.Character
java.lang.Number
java.lang.Byte
java.lang.Short
java.lang.Integer
java.lang.Float
java.lang.Double
java.lang.Long
Initialization
Process of storing value inside variable during its declaration is called initialization.
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) {
int num1 = Integer.parseInt(args[ 0 ]);
float num2 = Float.parseFloat(args[ 1 ]) ;
double num3 = Double.parseDouble(args[ 2 ]) ;
double result = num1 + num2 + num3;
System.out.println("Result : "+result);
}
public static void main1(String[] args) {
int num1 = Integer.parseInt(args[ 0 ]);
int num2 = Integer.parseInt(args[ 1 ]) ;
int result = num1 + num2;
System.out.println("Result : "+result);
}
}
Day 3
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
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
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 ];
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;
}
To store values, create instance of the class.
Process of creating instance of a class is called as instantiation.
A class from which we can create instance is called as concrete class. In other words, we can
instantiate concrete class.
In Java, to create instance, we should use new operator.
If we use new operator to allocate memory then it gets space of heap memory area.
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.
• Object oriented
Ø This feature helps to break complex code into easy to understand classes.
Ø It also helps to manage high complexity programs in distributed team environment.
• Memory management
Ø In traditional programming language like C, C++ user has to manage memory by allocating and deallocating memory
which leads to memory leaks in the program.
Ø In Java, memory management is taken care by the Java Virtual Machine and safe from memory crashes. All the
allocation and deallocation of the memory is done automatically.
• Exception Handling
Ø In Java, developers are forced to handle the exception during the development time. All the possible exception are
errored out during the compilation of the program. This way when the exception occurs during runtime, there is proper
exception handling mechanism already coded in the program.
Multithreaded
• If we start execution of Java application then Java Virtual Machine start execution of main thread and
garbage collector.
• Main Thread
1. It is a user thread( also called as non daemon thread ).
2. It is responsible for invoking main method.
3. Its priority in Java is 5( It means Thread.NORM_PRIORITY )
• Garbage Collector( Also called as finalizer )
1. It is a daemon thread( also called as background thread )
2. It is responsible for deallocating memory of unused objects.
3. Its priority in Java is 8( It means Thread.NORM_PRIORITY + 3 )
• Due to main thread and garbage collector, every Java application is multithreaded.
Multithreaded
• The Java platform supports multithreading at the language level.
Multithreaded
• If we want to utilize hardware resources concurrently and efficiently then we should use thread.
• Thread is non Java resource. In other words it is operating system resource.
• Java Native Interface( JNI ) is a Java language feature, which allows us to use operating system
thread into Java program.
• Sun/Oracle came with Thread class and other frameworks, which implicitly use JNI and reduces
developers effort. Now Instead of thinking about OS thread ,JNI and multitasking solution, Java
application developer can think about logic only.
• Java’s libraries are also thread safe.
Secure
• Java technology is designed to operate in distributed environments, which means that security is of
paramount importance.
• When Java applications are executed they don’t instruct commands to the machine directly. Instead
Java Virtual machine reads the program and convert it into the machine instructions. This way any
program tries to get illegal access to the system will not be allowed by the JVM.
• Allowing Java application to be executed by the JVM makes Java application fully secured.
• Java security technology includes a large set of APIs, tools, and implementations of commonly used
security algorithms, mechanisms, and protocols. The Java security APIs span a wide range of areas,
including cryptography, public key infrastructure, secure communication, authentication, and access
control.
Dynamic
• In java, except constructor and non static method, all the methods are by default virtual.
• It was designed to adapt to an evolving environment( Operating System and Hardware).
• While the Java Compiler is strict in its compile-time static checking, the language and run-time
system are dynamic in their linking stages. Classes are linked only as needed.
• Libraries can freely add new methods and instance variables without any effect on their clients.
• In Java, finding out runtime type information is straightforward.
High Performance
• Performance of Java application is slower then C/C++ application.
• The Java platform achieves superior performance by adopting a scheme by which the interpreter can
run at full speed without needing to check the run-time environment. The automatic garbage
collector runs as a low-priority background thread, ensuring a high probability that memory is
available when required, leading to better performance.
• Applications requiring large amounts of compute power can be designed such that compute-
intensive sections can be rewritten in native machine code as required and interfaced with the Java
platform.
• In general, users perceive that interactive applications respond quickly even though they're
interpreted.
Distributed
Distributed
• A distributed application consists of one or more local or remote clients that communicate with one or
more servers on several machines linked through a network. With this type of application, business
operations can be conducted from any geographical location.
• Remote Method Invocation (RMI) is a Java language feature.
• RMI system allows an object running in one Java virtual machine to invoke methods on an object
running in another Java virtual machine.
• Due to RMI Java is considered as distributed.
Questions?
Day 4
How to find size of instance in Java?
Reference: https://www.baeldung.com/java-size-of-object
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.
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.
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.
Static method do not get this reference.
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.
Reference:
https://zjnu2017.github.io/OOAD/reading/Object.Oriented.Analysis.and.Design.with.Applications.3rd.E
dition.by.Booch.pdf
What is class and instance?
Class
Definition:
Class is a collection of fields and methods.
Structure and behavior of the instance depends on class hence class is considered as a
template model or blueprint for an insrance.
Class represents set of instances which is having common structure and common behavior.
Example: Car, Book, Laptop, Mobile Phone etc.
Class is imaginary / logical entity.
Class implementation represents encapsulation.
Reference:
https://zjnu2017.github.io/OOAD/reading/Object.Oriented.Analysis.and.Design.with.Applications.3rd.E
dition.by.Booch.pdf
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.
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
emp.acceptRecord(); //java.lang.NullPointerException
emp.printRecord();
}
}
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
parameters
float result = num1 + num2;
System.out.println("Result : "+result);
}
static void sum( float num1, int num2 ){ // 2 method
parameters
float result = num1 + num2;
System.out.println("Result : "+result);
}
public static void main(String[] args) {
Program.sum( 10, 20.2f );
Program.sum( 10.1f, 20 );
}
}
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
Need of getter and setter methods
Day 5
Coding conventions:
Camel Case
Camel case is a naming convention in which the first letter of each word in a compound word is
capitalized, except for the first word.
Example: showInputDialog
Pascal Case
Pascal case is a naming convention in which the first letter of each word in a compound word is
capitalized.
Example: ArrayIndexOutOfBoundsException
Snake Case
Snake case combines words by replacing each space with an underscore (_).
Example:MAX_VALUE
Kebab Case
Kebab case is the way to write compound words separated by hyphens (-) instead of using
space. Generally, everything is written in lowercase.
Example: “what-is-kebab-case”
Declaration and Definition
According to Dennis Ritchie, declaration refers to the place where nature of the variable is stated but
no storage is allocated.
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();
this.day = ld.getDayOfMonth();
this.month = ld.getMonthValue();
this.year = ld.getYear();
}
}
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.
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");
this.day = 0;
this.month = 0;
this.year = 0;
}
Date( int day, int month, int year ){ //Constructor
System.out.println("Inside parameterized constructor");
this.day = day;
this.month = month;
this.year = year;
}
}
class Program{
public static void main(String[] args) {
Date dt1 = new Date( 23, 7, 1983 );
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;
{//Instance initialization block
this.top = -1;
}
Stack( ){
//this.top = -1;
this.arr = new int[ 5 ];
}
Stack( int size ){
//this.top = -1;
this.arr = new int[ size ];
}
}
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
Day 6
class Employee{
//TODO : Fields
//TODO : Ctor
//TODO : Getters and Setters
}
class EmployeeTest{
/* Employee emp;
public EmployeeTest(){
emp = new Employee();
} */
private Employee emp = new Employee( );
//TODO: acceptRecord()
//TODO: printRecord()
}
class Program{
public static void main(String[] args) {
EmployeeTest test = new EmployeeTest( );
//TODO: accept and print
}
}
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 = 10; //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
}
}
We will discuss final method and final class in inheritance.
We can declare method final.
We can not redfine/override final method inside sub class.
We can declare class final.
We can not create sub class of final class.
What is the meaning of "final Complex c1 = new Complex( 10, 20);" statement?
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
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
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.
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
Day 7
static method
Inside method, if there is need to use this reference then method should be non static otherwise
method should be static.
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
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();
}
}
Method 2
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
It is a Java language feature which is used:
To avoid name clashing/collision/ambiguity/conflict
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
};
Java compiler maps pakage name with the folder.
If we want to use any type(class/interface) in different package then
Either we should use import statement
Or fully qualified type name
Consider following code:
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
Conclusion: we can access packaged class inside unpackaged class.
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();
System.out.println( c1.toString());
}
}
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
set classpath=.\bin;
javac -d .\bin .\src\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
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
Eclipse introduction
Day 8
Which are non primitive types in Java?
Interface
Class
Enum
Array
Array
How will you store 3 integer values in Java program?
First approach
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 );
}
How will accept and print record of array
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;
}
}
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;
}
int main( void ){
int x = 10;
int y = 20;
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
Using enum, we can give name to the single literal as well group of literals of same type / different
type.
java.lang.Enum is considered as super class of all the enums in Core Java language.
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());
}
public static void main3(String[] args) {
System.out.println( Color.BLUE.name()); //BLUE
System.out.println( Color.BLUE.ordinal()); //2
}
public static void main2(String[] args) {
System.out.println( Color.GREEN.name()); //GREEN
System.out.println( Color.GREEN.ordinal()); //1
}
public static void main1(String[] args) {
System.out.println( Color.RED.name()); //RED
System.out.println( Color.RED.ordinal()); //0
}
}
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
}
}
Menu driven code using enum
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");
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
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) {
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);
}
}
Class definition represents encapsulation.
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.
Day 10
Major and minor elements / pillars /parts of oops
Abstraction
It is a major pillar of oops.
Process of getting essential things from instance / system is called as abstraction.
Abstraction focuses on external behavior of the instance.
Abstraction changes from entity to entity.
Abstraction helps to achive simplicity.
In Java, if we want to achieve abstraction then we should create instance and invoke method on it.
For Example:
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;
}
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.
Level / order / ranking of abstraction is called as hierarchy.
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.
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();
public final void notifyAll();
}
class Person extends Object{
//TODO
}
class Employee extends Person{
//TODO
}
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
}
interface Iterable<T>{
//TODO
}
interface Collection<E> extends Iterable<T>{ //Single inheritance(
interface 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 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.
For Example: Employee is a Person; Manager is a Employee; Salesanager is a Manager;
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() );
}
}
Accessing members using super keyword
According, clients requirement, if implementation of super class method is logically incomplete /
partially complete then we should redefine method inside sub class. In other words, we should
override method inside sub class.
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.
If we want to use any member of super class inside method of sub class then we should use super
keyword.
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
c1.setReal(50);
System.out.println(c1.toString()); //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()");
}
public void printRecord( ) {
System.out.println("B.printRecord()");
}
}
public class Program {
public static void main(String[] args) {
B b = new B();
b.showRecord(); //A.showRecord()
b.displayRecord(); //B.displayRecord()
b.printRecord(); //B.printRecord() => Shadowing
}
}
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
Definition
Process of converting reference of sub class into reference of super class is called as
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
Process of converting reference of super class into reference of sub class is called as 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.
class Person{
public void printRecord( ){
System.out.println("Person.printRecord");
}
}
class Employee extends Person{
@Override
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
}
}
instanceof operator
ArrayStoreException
operator== versus equals method
Day 12
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 :
. Fields of super class( if it is non private )
. Methods of super class
. Overriden method of sub class
In case of upcasting, if we want to access fields of sub class and non overriden method of sub class
then we should do downcasting.
instanceof
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 );
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
}
}
Day 13
Project Lombok
Reference https://projectlombok.org/
External system resources
Following are the operating system resources that we can use for the application development:
Memory
Processor
Input and Output devices
File
Socket
Network Connections
Database connections
Operating System API
In the context of Java, all above resources are non Java resources. These are also called as
unmanaged resources(except memory).
In the context of Java, resource is any external system resource that we can use in the application.
Since operating system resources are limited, we should use it carefully.
Exception Concept
Definition
Exception is an issue / unexpected event / instance which occurs during execution of
application.
Exception is an instance which is used to acknowledge user of the system if any exeption
situation occurs in the code.
If we want to manages OS resources carefully then we should use exception handling in Java.
Throwable class Hierarchy
java.lang.Object is ultimate super class of all the classes in Java language.
Methods of java.lang.Object class:
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 native notify( );
public final native notifyAll( );
java.lang.Throwable:
The Throwable class is the superclass of all errors and exceptions in the Java language.
Only objects that are instances of Throwable class (or one of its subclasses) are thrown by the Java
Virtual Machine or can be thrown by the Java throw statement.
Consider code in C++
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;
}
Consider code in Java
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
}
}
}
}
}
Similarly, only Throwable class or one of its subclasses can be the argument type in a catch clause.
Consider following code:
}
}
}
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
An Error is a subclass of Throwable that indicates serious problems that a reasonable application
should not try to catch.
Most such errors are abnormal conditions.
Runtime error which gets generated due to environmental condition( hardware failure / OS failure /
JVM failure etc ) is considered as error in java programming language.
Consider following code:
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
Checked exception and unchecked exception are types of exception in Java, which are designed for
Java compiler( Not for JVM ).
Unchecked Exception
java.lang.RuntimeException is considered as super class of all the unchecked exception.
java.lang.RuntimeException and all its sub classes are considered as unchecked exception.
Examples of unchecked exception
RuntimeException
NumberFormatException
NullPointerExcption
NegativeArraySizeException
ArrayIndexOutOfBoundsException
ArrayStoreException
ClassCastException
ArithmeticException
Compiler do not force developer to handle or to use try-catch block for unchecked exception.
Checked Exception
java.lang.Exception is considered as super class of all the checked exception.
java.lang.Exception and all its sub classes except java.lang.RuntimeException(and its sub classes )
are considered as checked exceptions
Examples of checked exception
java.lang.CloneNotSupportedException
java.lang.InterruptedException
java.io.IOException
java.sql.SQLException
Compiler force developer to handle or to use try-catch block for checked exception.
AutoCloseable and Closeable
Closeable is an interface which is delcared in java.io package.
Method: void close() throws IOException
It is introduced in JDK 1.5
Consider following code:
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
t.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
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();
}
}
Using java.lang.Exception class we can define catch block which can handle any checked as well as
uncheked exception.
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.
public class Program {
public static void displayRecord( ) throws InterruptedException {
for( int count = 1; count <= 10; ++ count ) {
System.out.println("Count : "+count);
Thread.sleep(500);
}
}
public static void main(String[] args) {
try {
Program.displayRecord();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Exception chaining
Process of handling exception by throwing new type of exception is called as exception chaining.
Consider following code:
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);
}
}
}
Day 14
class A extends Exception{ }
class B extends Exception{ }
class C extends Exception{ }
public class Program {
//public static void print( int number ) throws A, B, C {
public static void print( int number ) throws Exception {
if( number == 10 )
throw new A();
if( number == 20 )
throw new B();
if( number == 30 )
throw new C();
System.out.println("Number : "+number);
}
public static void main(String[] args) {
try {
Program.print(50);
} catch (Exception e) {
e.printStackTrace();
}
}
}
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();
}
}
According business requirement, if implementation of class is logically 100% complete then we
should declare such class final.
We can not extend final class. In other words, we can not create sub class of final class.
Examples of final class:
java.lang.System
java.lang.String
java.lang.StrinBuffer
java.lang.StringBuilder
All the wrapper classes
java.lang.Math
java.util.Scanner
Abstract method an abstract class
According business requirement, if implementation of super class method is logically 100%
incomplete then we should declare super class method abstract.
abstract is modifier in java.
We can not provide body to the abstract method.
If we declare method abstract then we must declare class abstract.
We can not instantiate abstract class. In other words, we can not create instance of abstract class but
we can create reference of abstract class.
Abstract class may/may not contain abstract method.
If super class contains abstract method then sub class must override it otherwise sub class will be
considered as abstract.
Consider following code:
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 {
public static void main(String[] args) {
A a = null;
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.
Consider following code:
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 {
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;
}
}
Using java.lang.Object class, we can write generic code but we can not write type-safe generic code.
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.
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.
public static void main(String[] args) {
ArrayList<Integer> integerList = Program.getIntegerArrayList();
Program.printRecord( integerList );
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.
public static void main(String[] args) {
ArrayList<Integer> integerList = Program.getIntegerArrayList();
Program.printRecord( integerList ); //OK
Restrictions on Generics
Reference: https://docs.oracle.com/javase/tutorial/java/generics/restrictions.html
Day 16
Synthetic Constructs in Java
Reference: https://www.baeldung.com/java-synthetic
Generic Method
We can define generic method using java.lang.Object class.
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) {
this.data = data;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
@Override
public String toString() {
return this.data.toString();
}
}
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;
}
public void setData(Number data) {
this.data = data;
}
@Override
public String toString() {
return this.data.toString();
}
}
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);
}
}
public static void main3(String[] args) {
Sample s = new Sample();
Box b = s; //Upcasting
b.setData(123); //OK
System.out.println(b.toString()); //123
}
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 method syntax:
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();
void f3();
}
class C implements A, B{
@Override
public void f1() {
System.out.println("C.f1");
}
@Override
public void f2() {
System.out.println("C.f2");
}
@Override
public void f3() {
System.out.println("C.f3");
}
}
public class Program {
public static void main(String[] args) {
A a = new C();
a.f1();
a.f3();
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");
}
}
class C extends AbstractPrintable{
@Override
public void f3() {
System.out.println("C.f3");
}
}
public class Program {
public static void main(String[] args) {
Printable p = null;
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
}
}
class B implements A{
@override
public void f1( ){
//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
}
}
Consider following code:
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 int[] toArray() {
return this.arr;
}
@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:
@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);
} catch (CloneNotSupportedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Shallow Copy
Deep 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
public class Employee implements Comparable<Employee>{
private int empNumber;
private String empName;
private String job;
private int manager;
private LocalDate hireDate;
private float salary;
private float commision;
private int deptNumber;
@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)
import java.util.Iterator;
class Node{
int data;
Node next = null;
public Node( int data ) {
this.data = data;
}
}
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.
Consider following diagram
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
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 Inner{
private int num3 = 30;
private final static int num4 = 40;
public void print( ) {
System.out.println("Num1 : "+num1); //OK
System.out.println("Num2 : "+num2); //OK
System.out.println("Num3 : "+this.num3);
System.out.println("Num4 : "+Inner.num4);
}
}
}
public class Program {
public static void main(String[] args) {
Outer.Inner in = new Outer().new Inner();
in.print();
}
}
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!!");
}
};
p.print();
}
}
Reflection
Annotation
Day 18
What is Metadata?
Data about data is called as metadata. In other words, metadata refers to data that provides
information about other data.
For example, metadata for a photo might include:
The date and time it was taken
The location where it was taken
The camera used to take it
The resolution of the image.
In the case of digital media, metadata can include information about:
the artist
title
genre and album of a particular song or video.
In a file management application, metadata such as:
file name
size
creation date and modification date are commonly used to organize and search for files.
Metadata of Interface
What is the name of interface?
In which package it is declared?
Which is the access modifier of interface?
Which annotations are used on interface?
Which are the super interfaces of interface?
Which are the members declared inside interface?
Metadata of Class
What is the name of class?
In which package it is declared?
Which are the modifiers used on class?
Which are the annotations used on class?
Which is the super class of class?
Which are the super interfaces of the class?
Which are the members declared inside class?
Metadata of the Field
What is the name of the field?
Which is the type of field?
Which are the modifiers of field?
Which annotations has been used on the field?
Whether field is declared or inherited field?
Metadata of the method
What is the name of method?
Which are the modifiers used with method?
Which is the return type of method?
Which are the parameters of the methods?
Which exceptions method throws?
Which annotations has been used on the method.
Whether method is declared or inerhited method?
Application of Metadata
Metadata removes the need for native C/C++ header and library files when compiling.
Integrated Development Environment(IDE) uses metadata to help us write code. Its IntelliSense
feature parses metadata to tell us what fields and methods a type offers and in the case of a method,
what parameters the method expects.
Metadata allows an objectʼs fields to be serialized into a memory block, sent to another machine, and
then deserialized, re-creating the objectʼs state on the remote machine.
The Garbage Collector uses metadata to keep track of each object's lifecycle, from creation to
destruction.
Reflection
Reflection in Java is a feature that allows a program to examine or modify the behavior of a class,
method, or object at runtime.
It is a relatively advanced feature and should be used only by developers who have a strong grasp of
the fundamentals of the language.
reflection is a powerful technique and can enable applications to perform operations which would
otherwise be impossible.
using reflection, we can:
Obtain information about the class at runtime, such as its name, superclass, implemented
interfaces, constructors, methods, and fields.
Create new objects of a class dynamically, without knowing the class name at compile time.
Access and modify the values of fields in an object, even if they are declared as private.
Invoke methods on an object dynamically, without knowing the method names at compile time.
How to use reflection in Java?
Consider following code:
class Date{
//TODO: Member definition
}
class Address{
//TODO: Member definition
}
class Person{
//TODO: Member definition
}
class Program{
public static void main(String[] args) {
Date birthDate = new Date( 23, 7, 1983 );
Date joinDate = new Date( 1, 1, 2007 );
Address curAddress = new Address( "Pune-46");
Person person = new Person("Sandeep", currentAddress, birthDate );
}
}
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
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;
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 {
Complex complex = new Complex();
System.out.println("Real Number : "+complex.getReal());
System.out.println("Imag Number : "+complex.getImag());
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;
public class Program {
public static void main(String[] args) {
try( Scanner sc = new Scanner(System.in)){
System.out.print("Enter F.Q. Class Name : ");
String className = sc.nextLine();
//org.example.domain.Calculator
Class<?> c = Class.forName(className);
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.
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.
Thread concept
Thread Definition
Lightweight process is called as thread.
According to Java, thread is a seperate path of execution which runs independently
Therad always resides in process.
If we want to utilize H/W resources( memory, cpu) efficiently then we should use thread.
If any application take help of single thread for the execution then such application is called as single
threaded application.
If any application take help of multiple threads for the execution then such application is called as
multi threaded application.
Thread is Non Java resource. It is also called unmanged resource.
process based versus thread based multitasking
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.
Threads always reside into process. Hence to access the resources thread do not require context
switching. So thread based multitasking is called as lightweight multitasking
Java is multithreaded
When we start execution of Java application, JVM starts execution of main thread and Garbage
collector. Due to these threads, every Java application is multithreaded.
Main Thread
It is called as user thread / Non dameon thread.
Main thread is responsible for invoking main method.
In Java, priority of main thread is 5( Thread.NORM_PRIORITY ).
Garbage Collector
It is called as daemon thread / background thread.
Garbage collector is responsible for invoking finalize method and deallocating / releasing
memory of unused objects.
Garbage collector is also called as finalizer.
In Java, priority of garbage collector is 8( Thread.NORM_PRIORITY + 3).
Multithreading in Java
If we want to use threads in Java then we should use Types declared in java.lang package.
Interface(s)
Runnable
Class(es)
Thread
ThreadGroup
ThreadLocal
Enum:
Thread.State
Exception
IllegalThreadStateException
IllegalMonitorStateException
InterruptedException
Runnable
It is functional interface declared in java.lang package.
Method:
void run() //Business logic method of thread
To create thread, we can use Runnable interface.
Thread
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
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.
Day 19
Why Java is multi-threaded
When we start execution of Java application then JVM starts execution of main thread and garbage
collector( GC ). Due to these two threads every java application is multithreaded.
Main Thread
It is user thread / non daemon thread.
It is responsible for calling/invoking main method.
Its default priority in 5( In Java, Thread.NORM_PRIORITY ).
Garbage Collector / Finalizer
It is daemon thread / backgrounf thread.
It is responsible for releasing / reclaiming / deallocating memory of unused( whose
reference count is 0 ) instances.
Before releasing memory of unused instance, GC invoke finalize( similar to destructor in
C++) method on instance.
Its default priority in 8( In Java, Thread.NORM_PRIORITY + 3 ).
If we want to use non java resource into Java then we must use Java Native Interface framework.
Thread is non Java resource and to access it we require JNI. But Java application developer need not
to worry avout it. Because SUN/ORACLE developers has already written logic to access OS thread in
Java. In other words, Java has built-in support to thead. Hence java is considered as multithreaded
programming langauge.
Runnable
It is a functional interface declared in java.lang pckage.
"void run( )" is a method of java.lang.Runnable interface. In the context of multi-threading, run()
method is called as business logic method.
If we want to create thread in Java then we should use Runnable interface.
Thread
java.lang.Thread class is a sub class of java.lang.Object class and it implements java.lang.Runnable
interface.
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");
}
}
what is the relation between start and run method?
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");
}
}
what is the relation between start and run method?
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
public void run() {
System.out.println("Inside run method :
"+Thread.currentThread().getName());
}
}
public class Program {
public static void main(String[] args) {
Thread thread = new Task( "Thread#1");
//thread.start(); //Inside run method : Thread#1
thread.run();//Inside run method : main
}
}
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 C extends B{
public C( ){
}
@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( ){
}
@Override
public void run( ){
//TODO: Write business logic here
}
}
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
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);
}
}
}
public class Program {
public static void main(String[] args) throws Exception {
Thread thread = new Thread(new Task());
thread.start();
}
}
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
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.
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
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
same memory location.
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.
String s1 = "CDAC";
//char[] data = {'C','D','A','C'};
//String s1 = new String( data );
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
}
public static void main(String[] args) {
String s1 = "CDAC,ACTS";
String str = "ACTS";
String s2 = "CDAC,"+str;
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
}
intern() method returns reference of the String from String pool.
if( s1.equals(s2) )
System.out.println("Equal");
else
System.out.println("Not Equal");
//Output: Equal
}
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:
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)
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
It is sub interface of Collection interface. It means that all the methods of Collection interafce will be
inherited into List interface.
Direct implementation classes of List interfaces are AbstractList, ArrayList, Vector, Stack, LinkedList.
These collection classes are called as List collections.
Inside List collection we can store data in sequential fashion.
We can store duplicate elements inside any List collection.
We can store multiple null values inside List collection.
With the help of integer index, we can access elements from List collection.
We can traverse elements of any List collection using Iterator as well as ListIterator.
This interface is a member of the Java Collections Framework.
Abstract methods of java.util.List interface:
void add(int index, E element)
boolean addAll(int index, Collection<? extends E> c)
E remove(int index)
E get(int index)
E set(int index, E element)
int indexOf(Object o)
int lastIndexOf(Object o)
ListIterator listIterator()
ListIterator listIterator(int index)
List subList(int fromIndex, int toIndex)
Default methods of java.util.List interface:
default void sort(Comparator<? super E> c)
default void replaceAll(UnaryOperator operator)
Note: If we want to manage elements of non final type inside any List collection then we should
override at least equals methods inside non final type.
ArrayList
Array is collection of fixed elements. ArrayList is resizeable array.
Implementation of ArrayList is based of array.
ArrayList is List collection.
Since ArrayList is List collection we can store elements sequentially.
Since ArrayList is List collection, we can store duplicate elements as well as null elements inside
ArrayList.
Since ArrayList is List collection, we can access its elements using integer index.
Since ArrayList is List collection, we can traverse its elements using Iterator as well as ListIterator.
ArrayList implementation is unsynchronized. Using Collections.synchronizedList() method we can
make it synchronized.
If ArrayList is full then its capacity gets increased by half of existing capacity.
This class is a member of the Java Collections Framework and introduced in JDK 1.2.
Constructor Summary of ArrayList class:
public ArrayList()
//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?
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:
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)
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
It is sub interface of Collection interface. It means that all the methods of Collection interafce will be
inherited into List interface.
Direct implementation classes of List interfaces are AbstractList, ArrayList, Vector, Stack, LinkedList.
These collection classes are called as List collections.
Inside List collection we can store data in sequential fashion.
We can store duplicate elements inside any List collection.
We can store multiple null values inside List collection.
With the help of integer index, we can access elements from List collection.
We can traverse elements of any List collection using Iterator as well as ListIterator.
This interface is a member of the Java Collections Framework.
Abstract methods of java.util.List interface:
void add(int index, E element)
boolean addAll(int index, Collection<? extends E> c)
E remove(int index)
E get(int index)
E set(int index, E element)
int indexOf(Object o)
int lastIndexOf(Object o)
ListIterator listIterator()
ListIterator listIterator(int index)
List subList(int fromIndex, int toIndex)
Default methods of java.util.List interface:
default void sort(Comparator<? super E> c)
default void replaceAll(UnaryOperator operator)
Note: If we want to manage elements of non final type inside any List collection then we should
override at least equals methods inside non final type.
ArrayList
Array is collection of fixed elements. ArrayList is resizeable array.
Implementation of ArrayList is based of array.
ArrayList is List collection.
Since ArrayList is List collection we can store elements sequentially.
Since ArrayList is List collection, we can store duplicate elements as well as null elements inside
ArrayList.
Since ArrayList is List collection, we can access its elements using integer index.
Since ArrayList is List collection, we can traverse its elements using Iterator as well as ListIterator.
ArrayList implementation is unsynchronized. Using Collections.synchronizedList() method we can
make it synchronized.
If ArrayList is full then its capacity gets increased by half of existing capacity.
This class is a member of the Java Collections Framework and introduced in JDK 1.2.
Constructor Summary of ArrayList class:
public ArrayList()
//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
Day 22
Collection Framework
Consider following example:
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:
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)
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
It is sub interface of Collection interface. It means that all the methods of Collection interafce will be
inherited into List interface.
Direct implementation classes of List interfaces are AbstractList, ArrayList, Vector, Stack, LinkedList.
These collection classes are called as List collections.
Inside List collection we can store data in sequential fashion.
We can store duplicate elements inside any List collection.
We can store multiple null values inside List collection.
With the help of integer index, we can access elements from List collection.
We can traverse elements of any List collection using Iterator as well as ListIterator.
This interface is a member of the Java Collections Framework.
Abstract methods of java.util.List interface:
void add(int index, E element)
boolean addAll(int index, Collection<? extends E> c)
E remove(int index)
E get(int index)
E set(int index, E element)
int indexOf(Object o)
int lastIndexOf(Object o)
ListIterator listIterator()
ListIterator listIterator(int index)
List subList(int fromIndex, int toIndex)
Default methods of java.util.List interface:
default void sort(Comparator<? super E> c)
default void replaceAll(UnaryOperator operator)
Note: If we want to manage elements of non final type inside any List collection then we should
override at least equals methods inside non final type.
ArrayList
Array is collection of fixed elements. ArrayList is resizeable array.
Implementation of ArrayList is based of array.
ArrayList is List collection.
Since ArrayList is List collection we can store elements sequentially.
Since ArrayList is List collection, we can store duplicate elements as well as null elements inside
ArrayList.
Since ArrayList is List collection, we can access its elements using integer index.
Since ArrayList is List collection, we can traverse its elements using Iterator as well as ListIterator.
ArrayList implementation is unsynchronized. Using Collections.synchronizedList() method we can
make it synchronized.
If ArrayList is full then its capacity gets increased by half of existing capacity.
This class is a member of the Java Collections Framework and introduced in JDK 1.2.
Constructor Summary of ArrayList class:
public ArrayList()
//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
It is sub interface of java.util.Collection interface.
HashSet, LinkedHashSet, TreeSet, EnumSet are Set collections.
Set Collections do not contain duplicate elements.
This interface is a member of the Java Collections Framework.
It is introduced in JDK 1.2
Method names of Collection and Set interface are same. No new method is added in Set interafce.
What is the difference between List and Set?
ArrayList, Vector, LinkedList are List Collections and HashSet, LinkedHashSet, TreeSet are Set
collections
List collections can contain duplicate elements but Set collections do not contain duplicate elements.
List collections can contain null elements but not all Set collections contain null elements.
We can traverse elements of List collection using ListIterator as well as Iterator but we can we can
traverse elements of Set collection using Iterator only.
All List collections are sequential collections but we can not give gurantee of order of elements in Set
collection.
TreeSet
It is a Set collection.
It can not contain duplicate elements.
It can not contain null elements.
It contains data in sorted order.
TreeSet implementation is based on TreeMap<K,V>.
It is unsynchronized collection. Using Collections.synchronizedSortedSet() method we can make it
synchronized.
This class is a member of the Java Collections Framework.
It is introduced in JDK 1.2
Note: If we want to use TreeSet to store elements of non final type then non final type should
implement Comparable interface.
How to create instance of TreeSet
set.add(50);
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:
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.
In other words, hash code is required to generate index which is called as slot in hashing.
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.
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
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;
import java.util.Set;
Consider example:
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
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.
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.
If we want to use any element of non final type inside TreeMap then non final type should implement
Comparable interface.
Instantiation:
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.
Types of files:
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.
import java.io.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.
Consider OutputStream hierarchy:
If we want to read/write data into text file then we should use Reader, Writer and their sub classes.
Consider Writer hierarchy:
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.
Day 24
SerialVersionUID
In Java, the serialVersionUID is a special static variable that is used to control the serialization and
deserialization process of objects. It is a version number associated with a serialized class, and it
serves as a unique identifier for the class.
When an object is serialized, its state is converted into a byte stream. The serialVersionUID is
included in this byte stream. During deserialization, the JVM checks if the serialVersionUID of the
serialized object matches the serialVersionUID of the corresponding class in the local environment.
If the serialVersionUID values match, the deserialization process proceeds successfully. However, if
the serialVersionUID values don't match, a InvalidClassException is thrown, indicating a version
mismatch between the serialized object and the class definition.
The serialVersionUID is used for versioning purposes to ensure that the serialized object and the
class definition are compatible. It helps to maintain compatibility between different versions of a class
when objects are serialized and deserialized.
Here's an example that demonstrates the usage of serialVersionUID:
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:
Consider Reader 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.
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:
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.
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
In this example:
Protocol: HTTPS
Host: www.example.com
Port: 8080
Path: /path/to/resource
Parameters: key1=value1, key2=value2
Fragment: section1
Let us understand concept of socket. Consider following diagram:
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
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