Core Java PDF
Core Java PDF
Table of Contents
Introduction: ................................................................................................................................................. 1
Java Development Kit (JDK): ..................................................................................................................... 1
Java Runtime Environment (JRE): ............................................................................................................. 1
Java Virtual Machine (JVM): ..................................................................................................................... 2
Just-In-Time (JIT) compiler: ....................................................................................................................... 2
Java Environment Setup: .............................................................................................................................. 3
Setup temporary path:.............................................................................................................................. 3
Setup permanent path: ............................................................................................................................. 3
Features of Java: ........................................................................................................................................... 4
Variables and Datatypes in Java.................................................................................................................... 7
Variables: .................................................................................................................................................. 7
Datatypes: ................................................................................................................................................. 7
byte: ...................................................................................................................................................... 9
short: ..................................................................................................................................................... 9
int: ......................................................................................................................................................... 9
long: ...................................................................................................................................................... 9
float: ...................................................................................................................................................... 9
double: ................................................................................................................................................ 10
boolean: .............................................................................................................................................. 10
char: .................................................................................................................................................... 10
String: .................................................................................................................................................. 11
Arrays: ................................................................................................................................................. 17
Identifiers: ............................................................................................................................................... 28
Modifiers: ................................................................................................................................................ 29
Operators: ................................................................................................................................................... 36
Assignment Operators: ........................................................................................................................... 37
Arithmetic Operators: ............................................................................................................................. 39
Relational Operators: .............................................................................................................................. 39
i
Bitwise Operators: .................................................................................................................................. 41
Logical Operators: ................................................................................................................................... 42
Conditional Operator ( ? : ): .................................................................................................................... 42
Casting:.................................................................................................................................................... 43
Order of operators: ................................................................................................................................. 44
Precedence order:............................................................................................................................... 44
Associativity: ....................................................................................................................................... 44
Precedence and associativity of Java operators: ................................................................................ 44
Order of evaluation of subexpressions: .............................................................................................. 46
Short circuiting: ................................................................................................................................... 46
Precedence order gone awry: ............................................................................................................. 46
Control Flow Statements: ........................................................................................................................... 48
Selection Statements: ............................................................................................................................. 48
The if statement: ................................................................................................................................. 48
The if-else Statement: ......................................................................................................................... 49
The switch statement: ........................................................................................................................ 50
Iteration Statements: .............................................................................................................................. 51
The while Loop: ................................................................................................................................... 51
Do-while Loop ..................................................................................................................................... 52
For Loops ............................................................................................................................................. 54
Transfer Statements................................................................................................................................ 57
Continue Statement: ........................................................................................................................... 57
Break Statement ................................................................................................................................. 58
Object oriented Programming in Java ........................................................................................................ 66
Class ........................................................................................................................................................ 66
Constructor ......................................................................................................................................... 67
this key word:.......................................................................................................................................... 71
this keyword with field(Instance Variable) ............................................................................................. 72
Example of Variable Hiding ................................................................................................................. 72
Inheritance: ............................................................................................................................................. 74
Abstract Class: ......................................................................................................................................... 78
Abstract method ................................................................................................................................. 79
Java Runtime Environment (JRE): Java Runtime Environment contains JVM, class
libraries, and other supporting files. It does not contain any development tools such as compiler,
debugger, etc. Actually JVM runs the program, and it uses the class libraries, and other supporting
files provided in JRE. If you want to run any java program, you need to have JRE installed in the
system.
Java Virtual Machine (JVM): The Java Virtual Machine provides a platform-independent
way of executable code. Programmers can concentrate on writing software, without having to be
concerned with how or where it will run. But, note that JVM itself not a platform independent. It
only helps Java to be executed on the platform-independent way. When JVM has to interpret the
byte codes to machine language, then it has to use some native or operating system specific
language to interact with the system. One has to be very clear on platform independent concept.
Even there are many JVMs written on Java, however they too have little bit of code specific to
the operating systems.
As we all aware when we compile a Java file, output is a ‘.class’ file and it consists of Java byte
codes which are understandable by JVM. Java Virtual Machine interprets the byte code into the
machine code depending upon the underlying operating system and hardware combination. It is
responsible for all the things like garbage collection, array bounds checking, etc. JVM is platform
dependent.
Just-In-Time (JIT) compiler: A just-in-time (JIT) compiler is a program that turns Java
bytecode (a program that contains instructions that must be interpreted) into instructions that can
be sent directly to the processor. After you've written a Java program, the source language
statements are compiled by the Java compiler into bytecode rather than into code that contains
instructions that match a particular hardware platform's processor (for example, an Intel Pentium
microprocessor or an IBM System/390 processor). The bytecode is platform-independent code
that can be sent to any platform and run on that platform.
JRE
Source Bytecode
JVM
Code Compiler JRE OS CPU
Prg.class JIT
Prg.java
A compiler is a program that reads a high-level program and translates it all at once, before running any
of the commands. Often you compile the program as a separate step, and then run the compiled code
later. In this case, the high-level program is called the source code, and the translated program is called
the object code or the executable.
Features of Java:
A program is a sequence of instructions that species how to perform a computation.
There is given many features of java. They are also known as java buzzwords. The Java Features given
below are simple and easy to understand.
1. Simple
2. Object-Oriented
3. Platform independent
4. Secured
5. Robust
6. Architecture neutral
7. Portable
8. Dynamic
9. Interpreted
10. High Performance
11. Multithreaded
12. Distributed
1) Simple
Java is a simple language because of its various features, Java Doesn’t Support Pointers , Operator
Overloading etc. It doesn’t require unreferenced object because java support automatic garbage
collection.
Java provides bug free system due to the strong memory management.
2) Object-Oriented
Object-Oriented Programming Language (OOPs) is the methodology which provide software
development and maintenance by using object state, behavior, and properties.
Object Oriented Programming Language must have the following characteristics.
Encapsulation
Polymorphism
Inheritance
Abstraction
As the languages like Objective C, C++ fulfills the above four characteristics yet they are not fully object
oriented languages because they are structured as well as object oriented languages.
In java everything is an Object. Java can be easily extended since it is based on the Object model.
3) Secure
Java is Secure Language because of its many features it enables to develop virus-free, tamper-free
systems. Authentication techniques are based on public-key encryption. Java does not support pointer
explicitly for the memory.
4) Robust
Java was created as a strongly typed language. Data type issues and problems are resolved at compile-
time, and implicit casts of a variable from one type to another are not allowed.
Memory management has been simplified java in two ways. First Java does not support direct pointer
manipulation or arithmetic. This make it possible for a java program to overwrite memory or corrupt
data.
Second , Java uses runtime garbage collection instead of instead of freeing of memory. In languages like
c++, it Is necessary to delete or free memory once the program has finished with it.
5) Platform-independent
Java Language is platform-independent due to its hardware and software environment. Java code can be
run on multiple platforms e.g. windows, Linux, sun Solaris, Mac/Os etc. Java code is compiled by the
compiler and converted into byte code. This byte code is a platform independent code because it can be
run on multiple platforms i.e. Write Once and Run Anywhere(WORA).
6) Architecture neutral
It is not easy to write an application that can be used on Windows , UNIX and a Macintosh. And its getting
more complicated with the move of windows to non-Intel CPU architectures.
Java takes a different approach. Because the Java compiler creates byte code instructions that are
subsequently interpreted by the java interpreter, architecture neutrality is achieved in the
implementation of the java interpreter for each new architecture.
7) Portable
Java code is portable. It was an important design goal of Java that it be portable so that as new
architectures (due to hardware, operating system, or both) are developed, the java environment could be
ported to them.
In java, all primitive types (integers, longs, floats, doubles, and so on) are of defined sizes, regardless of
the machine or operating system on which the program is run. This is in direct contrast to languages like
C and C++ that leave the sized of primitive types up to the compiler and developer.
Additionally, Java is portable because the compiler itself is written in Java.
8) Dynamic
Because it is interpreted , Java is an extremely dynamic language, At runtime, the java environment can
extends itself by linking in classes that may be located on remote servers on a network(for example, the
internet)
At runtime, the java interpreter performs name resolution while linking in the necessary classes. The Java
interpreter is also responsible for determining the placement of object in memory. These two features of
the Java interpreter solve the problem of changing the definition of a class used by other classes.
9) Interpreted
We all know that Java is an interpreted language as well. With an interpreted language such as Java,
programs run directly from the source code.
The interpreter program reads the source code and translates it on the fly into computations. Thus, Java
as an interpreted language depends on an interpreter program.
The versatility of being platform independent makes Java to outshine from other languages. The source
code to be written and distributed is platform independent.
Another advantage of Java as an interpreted language is its error debugging quality. Due to this any error
occurring in the program gets traced. This is how it is different to work with Java.
11) Multithreaded
Writing a computer program that only does a single thing at a time is an artificial constraint that we?ve
lived with in most programming languages. With java, we no longer have to live with this limitation.
Support for multiple, synchronized threads is built directly into the Java language and runtime
environment.
Synchronized threads are extremely useful in creating distributed, network-aware applications. Such as
application may be communicating with a remote server in one thread while interacting with a user in a
different thread.
12) Distributed
Java facilitates the building of distributed application by a collection of classes for use in networked
applications. By using java’s URL (Uniform Resource Locator) class, an application can easily access a
remote server. Classes also are provided for establishing socket-level connections.
Datatypes:
In Java, there are two types of datatypes.
Primitive datatypes:
o Boolean
boolean
o Numeric
Character
char
Integral
Integer
o byte
o short
o int
o long
Floating point
o Float
o double
Non-primitive datatype:
o String
o Array
byte: The smallest integer type is byte. It has a minimum value of -128 and a maximum value of 127
(inclusive). The byte data type can be useful for saving memory in large arrays, where the memory
savings actually matters. Byte variables are declared by use of the byte keyword.
For example, the following declares and initialize byte variables called b:
byte b =100;
short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -
32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a
short to save memory in large arrays, in situations where the memory savings actually matters. Following
example declares and initializes short variable:
short s =123;
int: The most commonly used integer type is int. It is a signed 32-bit type that has a range from –
2,147,483,648 to 2,147,483,647. In addition to other uses, variables of type int are commonly employed
to control loops and to index arrays. This data type will most likely be large enough for the numbers your
program will use, but if you need a wider range of values, use long instead.
int v = 123543;
int calc = -9876345;
long: long is a signed 64-bit type and is useful for those occasions where an int type is not large enough
to hold the desired value. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value
of 9,223,372,036,854,775,807 (inclusive). Use of this data type might be in banking application when
large amount is to be calculated and stored.
float: Floating-point numbers, also known as real numbers, are used when evaluating expressions that
require fractional precision. For example interest rate calculation or calculating square root. The float
data type is a single-precision 32-bit IEEE 754 floating point. As with the recommendations for byte and
short, use a float (instead of double) if you need to save memory in large arrays of floating point
numbers. The type float specifies a single-precision value that uses 32 bits of storage. Single precision is
faster on some processors and takes half as much space as double precision. The declaration and
initialization syntax for float variables given below, please note “f” after value initialization.
double: Double precision, as denoted by the double keyword, uses 64 bits to store a value. Double
precision is actually faster than single precision on some modern processors that have been optimized for
high-speed mathematical calculations. All transcendental math functions, such as sin( ), cos( ), and sqrt( ),
return double values. The declaration and initialization syntax for double variables given below, please
note “d” after value initialization.
boolean: The boolean data type has only two possible values: true and false. Use this data type for simple
flags that track true/false conditions. This is the type returned by all relational operators, as in the case of
a < b. boolean is also the type required by the conditional expressions that govern the control statements
such as if or while.
char: In Java, the data type used to store characters is char. The char data type is a single 16-bit Unicode
character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
There are no negative chars.
Output:
byte Value = 100
short Value = 123
int Value = 123543
int second Value = -9876345
long Value = 1234567891
float Value = 12.25
double Value = 12345.234
boolean Value = true
boolean Value = false
char Value = X
char Value = Y
String: A string is one or more characters considered as a single value. Everything entered in a program,
requested from the user, or displayed as a series of characters is primarily a string. To support strings,
Java is equipped with the String class. To declare a variable that would hold a string, use the String data
type. In Java, strings are objects and not primitive datatype. Strings can be declared two ways.
1. By using double quotes
2. By creating object of String class.
String s1 = “abc”;
String s2 = new String(“abc”);
Note: Except String, no other data type cannot initialize directly without using “new” operator.
T h i s i s A s a m p l e s t r i n g
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
In the above table, first row specifies character sequence and the second row specifies index of the
corresponding character.
Boolean contains(CharSequence s)
Returns true if and only if this string contains the specified sequence of char values.
byte[] getBytes()
Encodes this String into a sequence of bytes using the platform's default charset,
storing the result into a new byte array.
Int hashCode()
Returns a hash code for this string.
String intern()
Returns a canonical representation for the string object.
Boolean isEmpty()
Returns true if, and only if, length() is 0.
Int length()
Returns the length of this string.
Boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len)
Tests if two string regions are equal.
char[] toCharArray()
Converts this string to a new character array.
String toLowerCase()
Converts all of the characters in this String to lower case using the rules of the
default locale.
String toString()
This object (which is already a string!) is itself returned.
String toUpperCase()
Converts all of the characters in this String to upper case using the rules of the
default locale.
String trim()
Returns a copy of the string, with leading and trailing whitespace omitted.
Arrays:
An array is a collection of similar data types. Array is a container object that hold values of homogenous
type. It is also known as static data structure because size of an array must be specified at the time of its
declaration. An array can be either primitive or reference type. It gets memory in heap area. Index of an
array starts from zero to (array size-1).
The values stored in an array are called elements. The individual elements are accessed using an integer
index.
Accessing an element:
<array variable>[<integer expression>]
Arrays are linear collections of elements. They do not automatically resize. They have fixed lengths. This
makes them harder to use but faster. We can find utility/helper methods available in java.util.Arrays
class.
asList(T... a)
static
<T> List<T>
Returns a fixed-size list backed by the specified array.
static int Searches the specified array of bytes for the specified value using the binary search
algorithm.
static int Searches a range of the specified array of bytes for the specified value using the
binary search algorithm.
Searches the specified array of chars for the specified value using the binary search
algorithm.
static int Searches a range of the specified array of chars for the specified value using the
binary search algorithm.
static int Searches the specified array of doubles for the specified value using the binary
search algorithm.
static int Searches the specified array of floats for the specified value using the binary search
algorithm.
static int Searches a range of the specified array of floats for the specified value using the
binary search algorithm.
static int Searches the specified array of ints for the specified value using the binary search
algorithm.
static int Searches a range of the specified array of ints for the specified value using the binary
search algorithm.
static int Searches a range of the specified array of longs for the specified value using the
binary search algorithm.
Searches the specified array of longs for the specified value using the binary search
algorithm.
static int Searches the specified array for the specified object using the binary search
algorithm.
static int Searches a range of the specified array of shorts for the specified value using the
binary search algorithm.
static int Searches the specified array of shorts for the specified value using the binary search
algorithm.
static <T> int Searches the specified array for the specified object using the binary search
algorithm.
static byte[] Copies the specified array, truncating or padding with zeros (if necessary) so the
copy has the specified length.
Copies the specified array, truncating or padding with null characters (if necessary)
so the copy has the specified length.
static float[] Copies the specified array, truncating or padding with zeros (if necessary) so the
copy has the specified length.
static int[] Copies the specified array, truncating or padding with zeros (if necessary) so the
copy has the specified length.
static long[] Copies the specified array, truncating or padding with zeros (if necessary) so the
copy has the specified length.
static short[] Copies the specified array, truncating or padding with zeros (if necessary) so the
static <T> T[] Copies the specified array, truncating or padding with nulls (if necessary) so the copy
has the specified length.
deepHashCode(Object[] a)
static int
Returns a hash code based on the "deep contents" of the specified array.
deepToString(Object[] a)
static String
Returns a string representation of the "deep contents" of the specified array.
Returns true if the two specified arrays of booleans are equal to one another.
static void Assigns the specified boolean value to each element of the specified array of
booleans.
static void Assigns the specified boolean value to each element of the specified range of the
specified array of booleans.
static void Assigns the specified byte value to each element of the specified range of the
specified array of bytes.
static void Assigns the specified char value to each element of the specified range of the
specified array of chars.
static void Assigns the specified double value to each element of the specified range of the
specified array of doubles.
static void Assigns the specified float value to each element of the specified range of the
specified array of floats.
static void Assigns the specified int value to each element of the specified range of the specified
array of ints.
static void Assigns the specified long value to each element of the specified range of the
specified array of longs.
static void Assigns the specified Object reference to each element of the specified range of the
specified array of Objects.
static void Assigns the specified Object reference to each element of the specified array of
Objects.
static void Assigns the specified short value to each element of the specified range of the
specified array of shorts.
hashCode(boolean[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(byte[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(char[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(double[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(float[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(int[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(long[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(Object[] a)
static int
Returns a hash code based on the contents of the specified array.
hashCode(short[] a)
static int
Returns a hash code based on the contents of the specified array.
sort(byte[] a)
static void
Sorts the specified array into ascending numerical order.
sort(char[] a)
static void
Sorts the specified array into ascending numerical order.
sort(double[] a)
static void
Sorts the specified array into ascending numerical order.
sort(float[] a)
static void
Sorts the specified array into ascending numerical order.
sort(int[] a)
static void
Sorts the specified array into ascending numerical order.
sort(long[] a)
static void
Sorts the specified array into ascending numerical order.
sort(Object[] a)
static void Sorts the specified array of objects into ascending order, according to the natural
ordering of its elements.
static void Sorts the specified range of the specified array of objects into ascending order,
according to the natural ordering of its elements.
sort(short[] a)
static void
Sorts the specified array into ascending numerical order.
toString(boolean[] a)
static String
Returns a string representation of the contents of the specified array.
toString(char[] a)
static String
Returns a string representation of the contents of the specified array.
toString(double[] a)
static String
Returns a string representation of the contents of the specified array.
toString(float[] a)
static String
Returns a string representation of the contents of the specified array.
toString(int[] a)
static String
Returns a string representation of the contents of the specified array.
toString(long[] a)
static String
Returns a string representation of the contents of the specified array.
toString(Object[] a)
static String
Returns a string representation of the contents of the specified array.
toString(short[] a)
static String
Returns a string representation of the contents of the specified array.
Identifiers:
All Java components require names. Name used for classes, methods, interfaces and variables are called
Identifier. Identifier must follow some rules. Here are the rules:
All identifiers must start with either a letter (a to z or A to Z) or currency character ($) or an
underscore.
After the first character, an identifier can have any combination of characters.
A Java keyword cannot be used as an identifier.
Identifiers in Java are case sensitive; foo and Foo are two different identifiers.
Declaring a variable:
<access_modifies> <non_access_modifier> <datatype> <variable_name>;
Initializing a variable:
<access_modifies> <non_access_modifier> <datatype> <variable_name> = <initial_value>
Modifiers:
There are two types of modifiers in java: access modifiers and non-access modifiers.
public static
protected final
default abstract
private syncronized
native
transient
volatile
strictp
Access Modifiers:
The access modifiers in java specify accessibility (scope) of a data member, method, constructor or class.
Public
Private
Protected
Default
The below table illustrates what are the access modifiers applicable for classes, methods and variables.
Access Modifier Class Methods Variable
Public Yes Yes Yes
Private No Yes Yes
Protected No Yes Yes
Default Yes Yes Yes
Access Modifier within class within package outside package by subclass outside package
private Y N N N
default Y Y N N
protected Y Y Y N
public Y Y Y Y
1. static modifier:
Static Modifiers are used to create class variable and class methods which can be accessed without
instance of a class
When you try to access a non-static variable from a static context like main method, java compiler
throws a message like "a non-static variable cannot be referenced from a static context". This is because
non-static variables are related with instance of class (object) and they get created when instance of a
class is created by using new operator. So if you try to access a non-static variable without any instance
compiler will complain because those variables are not yet created and they don't have any existence
until an instance is created and associated with it.
2. final modifier: “final” is a keyword or reserved word in java and can be applied to member
variables, methods, class and local variables in Java. Once you make a reference final you are not
allowed to change that reference and compiler will verify this and raise compilation error if you try
to re-initialized final variables in java.
2.1. final variable: Any variable either member variable or local variable (declared inside method or
block) modified by final keyword is called final variable. Final variables are often declare with static
keyword in java and treated as constant.
2.2. final method: Final keyword in java can also be applied to methods. A java method with final
keyword is called final method and it can not be overridden in sub-class. You should make a method
final in java if you think it’s complete and its behavior should remain constant in sub-classes. Final
methods are faster than non-final methods because they are not required to be resolved during run-
time and they are bonded on compile time.
class PersonalLoan {
public final String getName() {
return "personal loan";
}
}
2.3. final class: final keyword helps to write immutable class. Immutable classes are the one which cannot
be modified once it gets created and String is primary example of immutable and final class.
Immutable classes offer several benefits one of them is that they are effectively read-only and can be
safely shared in between multiple threads without any synchronization overhead. You cannot make a
class immutable without making it final and hence final keyword is required to make a class
immutable in java.
3. abstract: The “abstract” keyword can be used on classes and methods. A class declared with the
“abstract” keyword cannot be instantiated, and that is the only thing the “abstract” keyword does.
4. synchronized: The "synchronized" keyword prevents concurrent access to a block of code or object
by multiple Threads. The synchronized keyword causes a thread to obtain a lock when entering the
method, so that only one thread can execute the method at the same time.
5. native: The native keyword is used to declare a method which is implemented in platform-
dependent code such as C or C++. When a method is marked as native, it cannot have a body and
must ends with a semicolon instead. The Java Native Interface (JNI)specification governs rules and
guidelines for implementing native methods, such as data type conversion between Java and the
native application.
6. transient: The keyword transient in Java used to indicate that the variable should not be serialized.
By default all the variables in the object is converted to persistent state. In some cases, you may want
to avoid persisting some variables because you don’t have the necessity to transfer across the
network. So, you can declare those variables as transient. If the variable is declared as transient, then
it will not be persisted. It is the main purpose of the transient keyword.
7. volatile: When multiple threads using the same variable, each thread will have its own copy of the
local cache for that variable. So, when it’s updating the value, it is actually updated in the local cache
not in the main variable memory. The other thread which is using the same variable doesn’t know
anything about the values changed by the other thread. To avoid this problem, if you declare a
variable as volatile, then it will not be stored in the local cache. Whenever threads are updating the
values, it is updated to the main memory. So, other threads can access the updated value.
8. strictfp: The strictfp means strict floating point, ensures that you get exactly the same results from
your floating point calculations on every platform and it forces the precision of floating point
calculations (float or double) in Java conform to IEEE’s 754 standard, explicitly. Without using strictfp
keyword, the floating point precision depends on target platform’s hardware, i.e. CPU’s floating point
processing capability. In other words, using strictfp ensures result of floating point computations is
always same on all platforms.
The strictfp keyword can be applied for classes, interfaces and methods.
}
}
Operators:
Operator in java is a symbol that is used to perform operations. Operators in java fall into 8 different
categories.
Assignment Operators
Arithmetic operators
Relational operators
Logical operators
Bitwise operators
Assignment Operators:
The assignment operator (=) is a way of copying a value on the right-hand side (rvalue), to a variable on
the left-hand side (lvalue). The rvalue can be any constant, variable, or any expression that produces a
value, while the lvalue must be a distinctly named variable that possesses the capacity to hold to a value.
There are following assignment operators supported by Java language:
When we assign primitives, it’s actually copy a value from one place to another. This is because primitives
hold actual values as opposed to objects that hold references. With the assignment of objects, one must
become properly acquainted with the phenomenon known as aliasing.
Aliasing can be observed in the behavior of object references that are copied and that point to the same
object. Consider the following example:
Program:
class Level {
int spaces;
}
l2 = l1;
System.out.println("2: l1.spaces: " + l1.spaces + ", l2.spaces: " +
l2.spaces);
l2.spaces = 0;
System.out.println("3: l1.spaces: " + l1.spaces + ", l2.spaces: " +
l2.spaces);
}
}
Output:
The CarPark class illustrates the logic of a car park spread over many levels. In this instance, the
class creates two Level instances (l1 and l2) in the main() and both objects are assigned different
field values that denote the number of empty spaces on each level. We can observe the aliasing
phenomenon at the point where l1 is assigned to l2 and how, subsequently assigning a different
value to l2 appears to change l1 as well, when you would intuitively expect that both objects were
completely independent of one and the other. Not quite so, I'm afraid. This is because at the point
where l1 is assigned to l2, both now contain the same reference that point to the same object and
changes to the one is bound to affect the other. This is fundamentally how Java works with
objects and demonstrates the aliasing effect.
To retain two independent objects in this particular instance, we would make the assignment call
to the object member explicit, like this: -
l2.spaces = l1.spaces;
This way we can avoid the idiosyncratic behavior of the aliasing phenomenon, which we must
add, is not limited to field assignments alone, but can also occur when you pass an object into a
method, where it can appear to change the value of an object or field that exists completely
outside of the method scope.
Arithmetic Operators:
Arithmetic operators are used in mathematical expressions in the same way that they are used in
algebra. The following table lists the arithmetic operators:
Operator Description Example
- Subtraction - Subtracts right hand operand from left hand operand A - B will give -10
* Multiplication - Multiplies values on either side of the operator A * B will give 200
/ Division - Divides left hand operand by right hand operand B / A will give 2
Modulus - Divides left hand operand by right hand operand and returns
% B % A will give 0
remainder
Relational Operators:
Relational operators evaluate the relationship between the values of two operands and produce a
boolean result i.e., true or false. They include less than (<), greater than (>), less than or equal to
(<=), greater than or equal to (>=), equivalence (==), and nonequivalence (!=). With the exception of the
equivalence and nonequivalence operators, all other relational operators work with all primitives except
boolean.
Checks if the value of two operands are equal or not, if yes then
== (A == B) is not true.
condition becomes true.
Checks if the value of two operands are equal or not, if values are not
!= (A != B) is true.
equal then condition becomes true.
Checks if the value of left operand is greater than the value of right
> (A > B) is not true.
operand, if yes then condition becomes true.
Checks if the value of left operand is less than the value of right
< (A < B) is true.
operand, if yes then condition becomes true.
Checks if the value of left operand is greater than or equal to the value
>= (A >= B) is not true.
of right operand, if yes then condition becomes true.
Checks if the value of left operand is less than or equal to the value of
<= (A <= B) is true.
right operand, if yes then condition becomes true.
The equivalence and nonequivalence operators, in addition to working with all primitives, also work with
objects; but here, one must be mindful to note that they actually compare object references and not the
actual content of objects themselves. For instance, if you were to try to compare two Double objects:
Program:
public class CompareDouble {
public static void main(String[] args) {
Double d1 = new Double(3.2);
Double d2 = new Double(3.2);
System.out.println(d2 != d1);
System.out.println(d2 == d1);
}
}
Output:
true
false
The output can be a bit confusing, returning a false result when both objects are tested for equivalence,
and a true result when tested for nonequivalence. This is of course not what you might expect given that
both objects are the same or to put it another way, both references point to the same object in memory.
The reason for what might seem an unusual result is because the == and != operators in fact compare
object references as opposed to the actual content of objects themselves.
To make the comparison of the actual content of objects, we may use the special equals() method that
exist for all objects like so:
Program:
public class CompareDouble {
public static void main(String[] args) {
Double d1 = new Double(3.2);
Double d2 = new Double(3.2);
System.out.println(d2.equals(d1));
}
}
Output:
true
false
Bitwise Operators:
These operators provide you with a way to manipulate individual bits in an integral primitive data type.
Integral data types are data types which store a finite subset of integers. Bitwise operators are said to
perform Boolean algebra on the corresponding bits in two arguments.
Java defines several bitwise operators which can be applied to the integer types, long, int, short, char, and
byte.
~ Binary Ones Complement Operator is unary and has (~A ) will give -60 which is 1100 0011
Logical Operators:
The Conditional or logical operators AND (&&) and OR (||) also produce a boolean result of true or false
based on the logical relationship of its arguments. They are known to exhibit a phenomenon known as
short-circuiting, which means that the expression is evaluated only to the extent that the truth or falsehood
of the it can be clearly determined. This is to say sometimes only a part of the expression need be
evaluated in order to determine its truth or falsehood. Below provides a demonstration on the use of
conditional operators:
Assume boolean variables A holds true and variable B holds false then:
Called Logical AND operator. If both the operands are non-zero then
&& (A && B) is false.
then condition becomes true.
Called Logical NOT Operator. Use to reverses the logical state of its
! operand. If a condition is true then Logical NOT operator will make !(A && B) is true.
false.
Conditional Operator ( ? : ):
Conditional operator is also known as the ternary operator. This operator consists of three operands and
is used to evaluate boolean expressions. The goal of the operator is to decide which value should be
assigned to the variable. The operator is written as :
variable x = (expression) ? value if true : value if false
Casting:
Casting is a way to convert from one type to another, for instance from a float to a double. With a
widening-conversion (i.e. going from a type that holds less information to one that holds much more),
you will find this to be a safe operation and as there is no risk of losing information, Java is able to
perform these sorts of casts automatically; however with a narrowing-conversion, the compiler will
always force you to use an explicit cast. To perform a cast, you simply put the desired type between
parenthesis and to the left of any value you wish to cast. Check out the following example:
Program:
public class Cast {
public static void main(String[] args) {
double d = 5.2;
int i = (int) d;// narrowing conversion cast required
long l = i;// widening conversion automatic cast
byte b = (byte) l;// narrowing conversion cast required
System.out.println(d);
System.out.println(i);
System.out.println(l);
System.out.println(b);
}
}
Output:
5.2
5
5
5
It is also good practice to be aware that when performing mathematical operations in Java, the larger or
largest data type determines the size of the result of that expression; for instance if you were to multiply
an int by say a double primitive data type, the result will almost certainly be double, likewise if you
were to perform an operation with of any of the smaller data types i.e. byte, char or short with an
int, the resulting value will be of type int. An explicit cast will be necessary to assign any resulting value
Order of operators:
Java has well-defined rules for specifying the order in which the operators in an expression are
evaluated when the expression has several operators. For example, multiplication and division
have a higher precedence than addition and subtraction. Precedence rules can be overridden by
explicit parentheses.
Precedence order:
When two operators share an operand the operator with the higher precedence goes first. For example, 1
+ 2 * 3 is treated as 1 + (2 * 3), whereas 1 * 2 + 3 is treated as (1 * 2) + 3 since multiplication has a higher
precedence than addition.
Associativity:
When an expression has two operators with the same precedence, the expression is evaluated according
to its associativity. For example x = y = z = 17 is treated as x = (y = (z = 17)), leaving all three
variables with the value 17, since the = operator has right-to-left associativity (and an assignment
statement evaluates to the value on the right hand side). On the other hand, 72 / 2 / 3 is treated as
(72 / 2) / 3 since the / operator has left-to-right associativity.
() Parentheses
15 1 [] Array subscript Left to Right
· Member selection
++ Unary post-increment
14 2 Right to left
-- Unary post-decrement
++ Unary pre-increment
13 3 Right to left
-- Unary pre-decrement
+ Unary plus
- Unary minus
! Unary logical negation
~ Unary bitwise complement
( type ) Unary type cast
* Multiplication
12 4 / Division Left to right
% Modulus
+ Addition
11 5 Left to right
- Subtraction
== Relational is equal to
8 8 Left to right
!= Relational is not equal to
+= Addition assignment
-= Subtraction assignment
*= Multiplication assignment
/= Division assignment
%= Modulus assignment
There is no explicit operator precedence table in the Java Language Specification and different
tables on the web and in textbooks disagree in some minor ways.
appears to the left of both D() and E(), we need the results of both D() and E() to evaluate C(). It is
considered poor style to write code that relies upon this behavior (and different programming languages
may use different rules).
Short circuiting:
When using the conditional and and or operators (&& and ||), Java does not evaluate the second
operand unless it is necessary to resolve the result. This allows statements like if (s != null
&& s.length() < 10) to work reliably. Programmers rarely use the non short-circuiting
versions (& and |) with boolean expressions.
was established in Microsoft Excel 2.0, it could not easily be changed without breaking backward
compatibility.
Output:
1 + 2 = 12
1 + 2 = 3
If either (or both) of the operands of the + operator is a string, the other is automatically cast to a string.
String concatenation and addition have the same precedence. Since they are left-associative, the
operators are evaluated left-to-right. The parentheses in the second statement ensures that the second +
operator performs addition instead of string concatenation.
Que: Add parentheses to the following expression to make the order of evaluation more clear.
year % 4 == 0 && year % 100 != 0 || year % 400 == 0
Ans:
((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)
Output:
3abc
abc12
Selection Statements:
The if statement:
The if statement executes a block of code only if the specified expression is true. If the value is false, then
the if block is skipped and execution continues with the rest of the program. You can either have a single
statement or a block of code within an if statement. Note that the conditional expression must be a
Boolean expression.
The simple if statement has the following syntax:
if (<conditional expression>) {
<statement(s)>
}
Example:
public class IfStatementDemo {
public static void main(String[] args) {
int a = 10, b = 20;
if (a > b)
System.out.println("a > b");
if (a < b)
System.out.println("b > a");
}
}
Output:
b>a
Below is an example that demonstrates conditional execution based on if else statement condition.
public class IfElseStatementDemo {
public static void main(String[] args) {
int a = 10, b = 20;
if (a > b) {
System.out.println("a > b");
} else {
System.out.println("b < a");
}
}
}
…
case label : <statement >
n n
default: <statement>
} // end switch
When executing a switch statement, the program falls through to the next case. Therefore, if you want to
exit in the middle of the switch statement code block, you must insert a break statement, which causes
the program to continue executing after the current code block.
Below is a java example that demonstrates conditional execution based on nested if else statement
condition to find the greatest of 3 numbers.
public class SwitchCaseStatementDemo {
Output:
c is the greatest
Iteration Statements:
The while Loop:
The while statement is a looping construct control statement that executes a block of code while a
condition is true. You can either have a single statement or a block of code within the while loop. The
loop will never be executed if the testing expression evaluates to false. The loop condition must be a
boolean expression.
The syntax of the while loop is:
while (<loop_condition>) {
<statements>
}
Increment: Code in the body that advances things so we are closer to making the test false. At the
end of the body, the code will loop around to the top of the body. Sometimes, some cleanup is
required at the end of the body to set things up for the next iteration. In the above example, the line
"count = count + 1;" accomplishes the increment. That can also be written as "count++;".
Below is an example that demonstrates the looping construct namely while loop used to print numbers
from 1 to 10.
public class WhileLoopDemo {
public static void main(String[] args) {
int count = 1;
System.out.println("Printing Numbers from 1 to 10");
while (count <= 10) {
System.out.println(count++);
}
}
}
Do-while Loop
The do-while loop is similar to the while loop, except that the test is performed at the end of the
loop instead of at the beginning. This ensures that the loop will be executed at least once. A do-
while loop begins with the keyword do, followed by the statements that make up the body of the
loop. Finally, the keyword while and the test expression completes the do-while loop. When the
loop condition becomes false, the loop is terminated and execution continues with the statement
immediately following the loop. You can either have a single statement or a block of code within
the do-while loop.
The syntax of the do-while loop is:
do {
<loop_body>
} while (condition)
Below is an example that demonstrates the looping construct namely do-while loop used to print
numbers from 1 to 10.
public class DoWhileLoopDemo {
System.out.println(count++);
} while (count <= 10);
}
}
Output
Printing Numbers from 1 to 10
1
2
3
4
5
6
7
8
9
10
Fibonacci sequence: The logic to generate next number in Fibonacci series is sum of previous
two numbers. The below table illustrate, how to generate Fibonacci series.
0 1 0+1 1+1 1+2 2+3 3+5 5+8 8+13 13+21
0 1 1 2 3 5 8 13 21 34
Output
Printing Limited set of Fibonacci Sequence
0.0
1.0
1.0
2.0
3.0
5.0
8.0
13.0
21.0
34.0
55.0
89.0
144.0
233.0
377.0
610.0
987.0
1597.0
2584.0
4181.0
6765.0
For Loops
The for loop is a looping construct which can execute a set of instructions a specified number of
times. It’s a counter controlled loop.
The syntax of the loop is as follows:
for (<initialization>; <loop condition>; <arithmetic_operation>) {
<loop body>
All the sections in the for-header are optional. Any one of them can be left empty, but the two
semicolons are mandatory. So, we can write for loop as below:
for ( ; ; ){
Output
Printing Numbers from 1 to 10
1
2
3
4
5
6
7
8
9
10
Transfer Statements
Continue Statement:
A continue statement stops the iteration of a loop (while, do or for) and causes execution to
resume at the top of the nearest enclosing loop. You use a continue statement when you do not
want to execute the remaining statements in the loop, but you do not want to exit the loop itself.
The syntax of the continue statement is
continue; // the unlabeled form
continue <label>; // the labeled form
You can also provide a loop with a label and then use the label in your continue statement. The
label name is optional, and is usually only used when you wish to return to the outermost loop in
a series of nested loops.
Below is a program to demonstrate the use of continue statement to print Odd Numbers between
1 to 10.
public class ContinueExample {
public static void main(String[] args) {
System.out.println("Odd Numbers");
for (int i = 1; i <= 10; ++i) {
if (i % 2 == 0)
continue;
// Rest of loop body skipped when i is even
System.out.println(i + "\t");
}
}
}
Output
Odd Numbers
1
3
5
7
9
Break Statement
The break statement transfers control out of the enclosing loop ( for, while, do or switch
statement). You use a break statement when you want to jump immediately to the statement
following the enclosing control structure. You can also provide a loop with a label, and then use
the label in your break statement. The label name is optional, and is usually only used when you
wish to terminate the outermost loop in a series of nested loops.
The Syntax for break statement is as shown below;
break; // the unlabeled form
break <label>; // the labeled form
Below is a program to demonstrate the use of break statement to print numbers Numbers 1 to 10.
public class BreakExample {
public static void main(String[] args) {
System.out.println("Numbers 1 - 10");
for (int i = 1;; ++i) {
if (i == 11)
break;
// Rest of loop body skipped when i is even
System.out.println(i + "\t");
}
}
}
Output
Numbers 1 – 10
1
2
3
4
5
6
7
8
9
10
/**
* Simple Java program which demonstrate use of break and continue statements in
* Java with lables, break and continue can be used alongside label and loop.
*
* @author Paramesh
*/
/**
* It performs how brak & continue statements works in java
*/
public static void performLabelDemo() {
int[] numbers = new int[] { 100, 18, 21, 30 };
break OUTER;
}
}
}
}
Output:
Odd number: 0, current number: 100 continue from OUTER label
Even number: 1, , current number: 100 break from INNER label
Even number: 1, , current number: 18 break from INNER label
Even number: 1, , current number: 21 break from INNER label
break keyword transfers control to next statement outside loop while continue keyword transfers
control to beginning of loop, ignoring rest of lines in loop.
break can also be used inside CASE statement of switch construct.
An optional label can be provided after break and continue which cause to apply break and continue
on specified loop.
Problem statement: Print all prime numbers from 1 – 20 by using for loop.
package com.sample;
if (flag) {
primes = primes.append(", ").append(x);
}
}
return primes.toString();
}
Output:
Prime Numbers from [1 - 20] : 1, 2, 3, 5, 7, 11, 13, 17, 19
Problem statement: Write the prime numbers b/w 1 – 20 by using continue, break and label statements.
package com.sample;
Output:
Prime Numbers from [1 - 20] : 1, 2, 3, 5, 7, 11, 13, 17, 19
Problem statement: Write a program to sort given integer array in descending order by using while and
for loops:
Array : {30, 50, 10, 80, 90, 20, 5, 6}
Solution:
Iteration/Index 0 1 2 3 4 5 6 7 Is Swapped
Actual array 30 50 10 80 90 20 5 6 (Y / N)
Iteration #1 50 30 80 90 20 10 6 5 Y
Iteration #2 50 80 90 30 20 10 6 5 Y
Iteration #3 80 90 50 30 20 10 6 5 Y
Iteration #4 90 80 50 30 20 10 6 5 Y
Iteration #5 90 80 50 30 20 10 6 5 N
Iteration #1:
1. In the very first iteration, compare first element (30) & second element (50). So 30 > 50, produces
false. Hence, swap the positions.
Result array is: {50, 30, 10, 80, 90, 20, 5, 6}
2. So far we swapped first and second elements. Now again compare 2nd element with 3rd element in
the above modified array. So 30 > 10, produces true. Hence, swapping not required.
Result array is: {50, 30, 10, 80, 90, 20, 5, 6}
3. Compare 3rd element & 4th element. So 10 > 80. So swap them. Result array will be as follows:
{50, 30, 80, 10, 90, 20, 5, 6}
4. Compare 4th element with 5th element. So, 10 > 90, produces false. Swap them and the result array
will be as follows;
{50, 30, 80, 90, 10, 20, 5, 6}
5. Compare 5th element & 6th element. So, 10 > 20, produces false. Swap them and result array will be
as follows:
{50, 30, 80, 90, 20, 10, 5, 6}
6. Compare 5th and 6th elements (5 > 6), produces false. Hence swap them and the result array will be as
follows:
{50, 30, 80, 90, 20, 10, 6, 6}
Now, we have completed one iteration and found that, the highlighted elements in the table are
saturated in their positions.
Follow the same procedure for each iteration until all the array elements saturated in their positions.
While condition will iterate loop till condition met false. Here, we can use flag “isSwapped”. Till its value
become false, we can proceed through required number of iterations and perform descending order on
sorting array.
Program:
package com.sample;
System.out.println(element);
}
Output:
Order of array :
90
80
50
30
20
10
6
5
Problem statement: Write a program which shows menu options to the user and prompt to input to
choose option from menu. The below are the menu options.
1. Generate sum of given numbers
2. Generate multiplication of given numbers
3. Generate Fibonacci series upto the given numbers.
4. Exit from menu
Solution:
1. To show the menu options irrespective of any condition, we can use do while statement.
2. Since options are from 1 – 4. This can be considered as expression producing a certain range of value.
Hence, we use switch statement to best suited for this scenario.
3. To accept many number of arguments for both sum and multiplication, we can use var args concept.
Program:
package com.sample;
import java.util.Scanner;
return seriers;
}
int choice = 0;
Scanner sc = new Scanner(System.in);
do {
switch (choice) {
case 1:
System.out.println("Input numbers separated with comma to
calculate sum :");
String s = sc.next();
int summation = summation(s.split(","));
System.out.println("summation : " + summation);
break;
case 2:
System.out.println("Input numbers separated with comma to
calculate multiplication :");
String mulString = sc.next();
int multiplication = multiplication(mulString.split(","));
System.out.println("multiplication : " + multiplication);
break;
case 3:
System.out.println("Please enter number to get generate
fibonacci series : ");
int upto = sc.nextInt();
String fibonacci = fibonacci(upto);
System.out.println("fibonacci : " + fibonacci);
break;
default:
System.out.println("No choice met, hence executing default
statement");
break;
}
Output:
Choose option from [1 - 4] : 1
Input numbers separated with comma to calculate sum : 1,2,3,4,5,6,7,8,9
summation : 45
Choose option from [1 - 4] : 2
Input numbers separated with comma to calculate multiplication : 20,30,40,50
multiplication : 1200000
Choose option from [1 - 4] : 3
Please enter number to get generate fibonacci series : 500
fibonacci : 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377
Choose option from [1 - 4] : 4
No choice met, hence executing default statement
Class
The basic building block of an object-oriented language such as Java
Is a template that describes the data and behavior associated with instances of that class.
Syntax:
<Access Modifier> class <Class_Name> extends <Super_Class_Name> implements <Interface_Name>{
<static initializer block>
<anonymous block>
<constructor declarations>
<field declarations (Static and Non-Static)>
<method declarations (Static and Non-Static)>
<Inner class declarations>
<nested interface declarations>
}
Constructor
Constructor is a block of code, which runs when you use new keyword in order to instantiate an
object. It looks like a method, however it is not a method. Methods have return type but constructors
don’t have any return type.
There are basically two rules defined for the constructor.
1. Constructor name must be same as its class name
2. Constructor must have no explicit return type
No-args Constructor: The constructor, which doesn’t any parameters is called “No-argument
constructor”. This constructor initializes default values to instance variables.
package com.sample;
boolean bool;
byte by;
char ch;
short sh;
int i;
long l;
float f;
double d;
String str;
ConstructorDemo() {
}
Output:
boolean : false
byte : 0
character :
short : 0
int : 0
long : 0
float : 0.0
double : 0.0
string : null
Default Constructor: When there is no constructor provided by programmer, then JVM provides a “No-
args constructor” to the class, the constructor provided by JVM in the absence of programmer provided
constructor is called default constructor. Default constructor and No-argument constructor both look
similar. But No-argument constructor can have many statements inside it, whereas compiler provided
constructor has one statement to call its super class constructor.
Parameterized Constructor: A constructor, which accept one or more arguments is called parameterized
constructor. If we define only parameterized constructors, then we cannot create an object with default
constructor. This is because compiler will not create default constructor. We need to create default
constructor explicitly if required.
While creation of object if it required to initialize instance variables with other than default values, we
can prefer parameterized constructor.
Suppose if it required to provide initial values as follows:
Int i = 10;
char ch = ‘M’;
We need to modify the constructor as follows:
package com.sample;
boolean bool;
byte by;
char ch;
short sh;
int i;
long l;
float f;
double d;
String str;
boolean : false
byte : 0
character : M
short : 0
int : 10
long : 0
float : 0.0
double : 0.0
string : null
Constructor Overloading: We can define more than one constructor in a single class.
Private Constructor:
If a method is private, it means that it cannot be accessed from any class other than itself. This is the
access control mechanism provided by Java. When it is used appropriately, it can produce security and
functionality. Constructors, like regular methods, can also be declared as private. It may very curious to
know why we need a private constructor since it is only accessible from its own class. When a class needs
to prevent the caller from creating objects. Private constructors are suitable. Objects can be constructed
only internally. In the case of a singleton, the policy is that only one object of that class is supposed to
exist. Creation of multiple objects of that class is forbidden.
package com.sample;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectStreamException;
import java.lang.reflect.Constructor;
import java.io.Serializable;
private SingletonObject() {
}
Constructor Rules
A constructor cannot have a return type.
Constructor must have the same name as that of the class.
Constructors cannot be marked static
Constructor cannot be marked abstract
Constructor cannot be overridden.
Constructor cannot be final.
Summary of Constructors:
1. Every class has a constructor whether it’s normal one or an abstract class.
2. As stated above, constructor is not methods and it doesn’t have any return type.
int variable = 5;
vh.method(20);
vh.method();
}
void method() {
int variable = 40;
System.out.println("Value of variable :" + variable);
}
}
Output:
Value of variable :10
Value of variable :40
As we can Instance Variable is hiding here and value getting displayed is the value of Local Variable (or
Method Parameter) and not Instance Variable. To solve this problem this keyword can be used with field
to point Instance Variable instead of Local Variable.
int variable = 5;
vh.method(20);
vh.method();
}
void method() {
int variable = 40;
System.out.println("Value of Instance variable :" + this.variable);
System.out.println("Value of variable :" + variable);
}
}
Output:
Value of Instance variable :5
Value of Local variable :10
Value of Instance variable :5
Value of Local variable :40
Inheritance:
Inheritance is one of the key features of Object Oriented Programming. Inheritance provided mechanism
that allowed a class to inherit property of another class. When a Class extends another class it inherits all
non-private members including fields and methods. Inheritance in Java can be best understood in terms
of Parent and Child relationship, also known as Super class(Parent) and Sub class(child) in Java language.
Java Inheritance defines an is-a relationship between a superclass and its subclasses. This means that an
object of a subclass can be used wherever an object of the superclass can be used.
Purpose of Inheritance
1. To promote code reuse.
2. To use Polymorphism.
Types of Inheritance
1. Single Inheritance
2. Multilevel Inheritance
3. Hierarchical Inheritance
To reduce the complexity and simplify the language, multiple inheritance is not supported in java.
Consider a scenario where A, B and C are three classes. The C class inherits A and B classes. If A and B
classes have same method and we call it from child class object, there will be ambiguity to call method of
A or B class.
super keyword:
In Java, super keyword is used to refer to immediate parent class of a class. In other
words super keyword is used by a subclass whenever it requires to refer to its immediate super class.
Example of Child class referring Parent class property using super keyword
class Parent {
String name;
Example of Child class refering Parent class methods using super keyword
class Parent {
String name;
Example of Child class calling Parent class constructor using super keyword
class Parent {
String name;
public Parent(String n) {
name = n;
}
Abstract Class:
The keyword “abstract” means incomplete. Abstract classes are used in java to create a class with some
default method implementation for subclasses. An abstract class can have abstract method without body
and it can have methods with implementation also. abstract keyword is used to create a abstract class.
Abstract classes can’t be instantiated and mostly used to provide base for sub-classes to extend and
implement the abstract methods and override or use the implemented methods in abstract class.
Moreover, an abstract class may contain methods without any implementation, called abstract methods.
The declaration of an abstract method starts with the abstract keyword and ends with a semicolon,
instead of the method’s body. If a class contains an abstract method, either declared or inherited, it must
be declared as an abstract class.
A class that extends an abstract class must implement all its abstract methods (if any). Otherwise, the
sub-class must be declared as abstract as well. Finally, any implementation of an abstract method can be
overridden by additional sub-classes.
Last things to mention are that abstract classes can also implement methods, despite providing just their
signature and that an abstract class may have static fields and static methods.
The purpose of an abstract class is to specify the default functionality of an object and let its sub-classes
to explicitly implement that functionality. Thus, it stands as an abstraction layer that must be extended
and implemented by the corresponding sub-classes.
Syntax:
<access_specifier> abstract class ClassName { }
Abstract method
Method that is declared without any body within an abstract class is known as abstract method. The
method body will be defined by its subclass. Abstract method can never be final and static. Any class that
extends an abstract class must implement all the abstract methods declared by the super class. If we
want a class to contain a particular method but you want the actual implementation of that method to be
determined by child classes, you can declare the method in the parent class as abstract.
abstract return_type function_name (); // No definition
Note:
abstract keyword is used to make a class abstract.
Abstract class can’t be instantiated.
We can use abstract keyword to create an abstract method, an abstract method doesn’t have body.
If a class has abstract methods, then the class also needs to be made abstract using abstract keyword,
else it will not compile.
Polymorphism:
Polymorphism is the capability of a method to do different things based on the object that it is acting
upon. In other words, polymorphism allows you define one interface and have multiple implementations.
In more simple words, polymorphism is the ability by which, we can create functions or reference
variables which behaves differently in different programmatic context.
1. Method Overloading:
In Java, it is possible to define two or more methods of same name in a class, provided that there
argument list or parameters are different. This concept is known as Method Overloading.
As the meaning is implicit, this is used to write the program in such a way, that flow of control is decided
in compile time itself. It is achieved using method overloading.
In method overloading, an object can have two or more methods with same name. But, with their
method parameters different. These parameters may be different on two bases:
1.1. Parameter type: Type of method parameters can be different. e.g. java.util.Math.max() function
comes with following versions:
public static double Math.max(double a, double b){}
public static float Math.max(float a, float b){}
public static int Math.max(int a, int b){}
public static long Math.max(long a, long b){}
The actual method to be called is decided on compile time based on parameters passed to function in
program.
Parameter count: Functions accepting different number of parameters.
Let's say a dog makes a woof sound, but if the dog is injured, the dog might make a whimper noise
instead. How can we use makeSound() to produce both sounds? Take a look at this code snippet:
public class Dog extends Animal {
public void makeSound() {
System.out.println("Woof");
}
We can see here that depending on the number of parameters we pass to makeSound(), the dog will
make a different sound.
2. Method Overriding:
Suppose if we take real time example; Car, Bus, Auto are comes under Vehicle category. Whenever we
can find Vehicle, can be replace with any one from its category.
By means of that, we can say:
Car is-a Vehicle,
Bus is-a Vehicle,
Auto is-a Vehicle.
In Java, parent and child class process IS-A relationship. It means that, we can assign child class object to
its parent class reference. Non-private method of a parent class can be overridden by all its child classes.
Hence, the overridden method behavior will change the based on the object we are going to assign at run
time to the parent class reference.
Ex:
Country.java
package com.sample.child;
India.java
package com.sample.child;
@Override
public String getCurrencyCode() {
return "INR";
}
}
Japan.java:
package com.sample.child;
@Override
public String getCurrencyCode() {
return "YEN";
}
}
MethodOverridingDemo.java:
package com.sample.child;
Output:
Currency Code for base class object : USD
Currency Code for India class object : INR
Currency Code for Japan class object : YEN
As we can have multiple subtype implementations for a super type, Java virtual machine
determines the proper type to be invoked at the runtime. Here, all the three times we just
invoked method as “country.getCurrencyCode())”, but produces three different outputs based on the
object acting on it.
Interface
Its business rule documentation or it defines the contract between different parties that needs to be
obeyed. It is a promise to provide certain behaviour and all classes which implement the interface
guarantee to also implement those behaviour. To define the expected behavior, the interface contains a
number of method signatures. Any class which uses the interface can rely on those methods being
implemented in the runtime class which implements the interface. This allows anyone using the interface
to know what functionality will be provided without having to worry about how that functionality will
actually be achieved.
An Interface contains:
Syntax:
public interface <InterfaceName> {
public static final <data_type> var_name1 = <constant>;
public static final <data_type> var_name2 = <constant>;
.
.
.
Ex:
package com.sample;
/**
*
* @author Paramesh
*
* This interface is useful for few arithmatic operations like sum,
* multiplication, abstract, devide, reminder
*
*/
public interface ArithmaticInterface {
/**
* Calculate the sum of all given inputs
*
* @param x
* first input
* @param y
* second input
* @return (x+y)
*/
public abstract int summation(int x, int y);
/**
* Multiply both given input and provide result back
*
* @param x
* @param y
* @return (x*y)
*/
public abstract int multiplication(int x, int y);
/**
* Substract second input from first one and provide the result back
*
* @param x
* @param y
* @return (x - y)
*/
public abstract long sbutract(long x, long y);
/**
* It devides fist input with second and provide the result back
*
* @param x
* @param y
* @return (x / y)
*/
public abstract float devide(float x, float y);
/**
* It devides first input with second one and provide their reminder
*
* @param x
* @param y
* @return (x % y)
*/
public abstract double reminder(double x, double y);
}
Note: It’s always recommended to write enough comments at both interface level and method level to
provide better understanding to client to use.
In the above interface, none of the methods have body. Each method has its own parameters and return
types. All implementer classes of this interface should follow the same signature (contract).
Interfaces are mainly used for:
1. Loose coupling
2. To achieve fully abstraction
Implementing an Interface:
If we want to create a class which will provide implementation for all the behaviours of the above
interface, we can use “implements” key word to convey to the compiler as going to provide definition for
the incomplete (abstract) methods.
package com.sample;
@Override
public int summation(int x, int y) {
return (x + y);
}
@Override
public int multiplication(int x, int y) {
return (x * y);
}
@Override
public int sbutract(int x, int y) {
return (x - y);
}
@Override
public int devide(int x, int y) {
return (x / y);
}
@Override
public int reminder(int x, int y) {
return (x % y);
}
If we fail to provide implementation for any method, class file cannot be compiled.
Marker Interfaces:
Marker interface is used as a tag to inform a message to the Java compiler so that it can add special
behaviour to the class implementing it. Java marker interface has no fields or methods in it.
Hence, an empty interface in java is called a marker interface. Marker interface is also called tag
interface. In java we have the following major marker interfaces as under:
Searilizable interface
Cloneable interface
The marker interface can be described as a design pattern which is used by many languages to
provide run-time type information about the objects. The marker interface provides a way to
associate metadata with the class where the language support is not available.
A normal interface specifies functionality which an implementing class must implement. But a
marker interface does not follow that pattern. On the other side, the implementing class defines
the behavior. There are some hybrid interfaces which act as a marker interface along with some
methods. But this type of design is confusing if not handled carefully.
From java 1.5, the need for marker interface is eliminated by the introduction of the java annotation
feature. So, it is wise to use java annotations than the marker interface. It has more feature and
advantages than the java marker interface.
All methods in an interface are implicitly abstract. On the other hand, an abstract class may contain
both abstract and non-abstract methods.
A class may implement a number of Interfaces, but can extend only one abstract class.
In order for a class to implement an interface, it must implement all its declared methods. However,
a class may not implement all declared methods of an abstract class. Though, in this case, the sub-
class must also be declared as abstract.
Abstract classes can implement interfaces without even providing the implementation of interface
methods.
Variables declared in a Java interface is by default public static final. An abstract class may contain
non-final variables.
Members of a Java interface are public by default. A member of an abstract class can either be
private, protected or public.
An interface is absolutely abstract and cannot be instantiated. An abstract class also cannot be
instantiated, but can be invoked if it contains a main method.
Abstraction:
In Object Oriented Programming Language, “Abstraction” is a way to segregate implementation. In
general, “Abstraction“ is a concept of exposing only the required essential characteristics and behavior
with respect to a context.
The process of creating a complex system by hiding all the implementation details from outside worlds
and expose only meaningful operations to interact with it is called as “Abstraction”.
Example: mobile or cell phone. The main purpose of both is to make call and here the voice of other
person. Both allow us to make call through key pad and never exposes how internally connects with
other mobile/cell and send/receive voice signals from other end.
In Java, abstraction can be achieved through abstract classes and interfaces.
Use case:
Build a payment system for a company that has two kinds of employees (say Contract & Permanent
employees). Permanent employees will receive payment through salary, whereas contract employees will
receive payment through commission. The manager of the company expecting that, system may be
changed later to accommodate different types of entities which will receive payments.
Solution:
1. The two types of employees will receive the payment on either commission basis or fixed pay basis. So,
however both are liable to receive the payment at the end of the month. Hence, we can consider both
kinds of employees as Payee.
2. To deposit money to employee’s account, bank expects
Employee name
Bank account number
Amount to be deposit
So, we can create a Payee interface as follows:
package com.emp.payroll;
String name();
Double grossPayment();
String bankAccount();
}
Note: All the methods of an interface, implicitly public and abstract. So no need to use public & abstract
modifiers again.
Hence, the above interface has ability to provide employee name, payment amount & account to be
deposited.
3. Since the organization can have many number of employees and they need to pick each and every
employee. Calculate the payment and request to bank to deposit the money to corresponding account.
Cycle through all employees and follow the same.
package com.emp.payroll;
import java.util.ArrayList;
import java.util.List;
/**
* Initiate Payee list
*/
public PaymentSystem() {
payees = new ArrayList<Payee>();
/**
* Add a new Payee, when new employee joined with organization
*
* @param payee {@link Payee}
*/
public void addPayee(Payee payee) {
if (!payees.contains(payee)) {
payees.add(payee);
}
}
/**
* Remove Payee, when he resigned from his responsibilities
*
* @param payee {@link Payee}
*/
public void removePayee(Payee payee) {
if (payees.contains(payee)) {
payees.remove(payee);
}
}
/**
* Cycle through all the {@link Payee}(s) and perform deposit money to
* their
* account
*/
public void processPayments() {
for (Payee payee : payees) {
Double grossPayment = payee.grossPayment();
System.out.println("=======================================");
System.out.println("Paying to employee " + payee.name());
System.out.println("\tAmount deposited :" + grossPayment);
System.out.println("\tTransferred to Account : " +
payee.bankAccount());
}
}
}
4. Since the organization has two kinds of employees called Contract & Permanent. So, we need to create
two kinds of classes to represent them. Since, Payment system needs to recognize these two types, we
can define PermanentEmployee and ContractEmployee classes by implementing Payee interface.
PermanentEmployee.java:
package com.emp.payroll;
ContractEmployee.java:
package com.emp.payroll;
From above two classes, we can observe that, only behaviour “grossPayment()” differs in each object. So,
to build similar kind of objects Abstract class is the best suitable rather than implementing common
features in each and every object.
Hence, introduce Employee abstract class as follows:
package com.emp.payroll;
ContractEmployee.java: Extend this with Employee class to reuse default implementation instead
implementing all the methods from Payee interface.
package com.emp.payroll;
PermanentEmployee.java: Extend this with Employee class to reuse default implementation instead
implementing all the methods from Payee interface.
package com.emp.payroll;
ProcesspaymentApplication.java:
package com.emp.payroll;
Output:
===================================================
Paying to employee Contract Employee 1
Amount deposited :90.0
Transferred to Account : 1111
===================================================
Paying to employee Contract Employee 2
Amount deposited :105.0
Transferred to Account : 2222
===================================================
Paying to employee Contract Employee 3
Amount deposited :500.0
Transferred to Account : 3333
===================================================
Paying to employee Contract Employee 4
Amount deposited :470.0
Transferred to Account : 4444
Marker Interfaces:
Exception Handling:
An exception is an event that occurs during the execution of a program that disrupts the normal flow of
instructions. In Java, all exceptions are objects.
When an error occurs within a method, the method creates an object and hands it off to the runtime
system. The object, called an exception object, contains information about the error, including its type
and the state of the program when the error occurred. Creating an exception object and handing it to the
runtime system is called throwing an exception.
After a method throws an exception, the runtime system attempts to find something to handle it. The set
of possible "somethings" to handle the exception is the ordered list of methods that had been called to
get to the method where the error occurred. The list of methods is known as the call stack (see the next
figure).
The runtime system searches the call stack for a method that contains a block of code that can handle the
exception. This block of code is called an exception handler. The search begins with the method in which
the error occurred and proceeds through the call stack in the reverse order in which the methods were
called. When an appropriate handler is found, the runtime system passes the exception to the handler.
An exception handler is considered appropriate if the type of the exception object thrown matches the
type that can be handled by the handler.
The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches
all the methods on the call stack without finding an appropriate exception handler, as shown in the next
figure, the runtime system (and, consequently, the program) terminates.
1. throw: We know that if any exception occurs, an exception object is getting created and then Java
runtime starts processing to handle them. Sometime we might want to generate exception explicitly
in our code, for example in a user authentication program we should throw exception to client if the
password is null. throw keyword is used to throw exception to the runtime to handle it.
2. throws: When we are throwing any exception in a method and not handling it, then we need to use
throws keyword in method signature to let caller program know the exceptions that might be thrown
by the method. The caller method might handle these exceptions or propagate it to its caller method
using throws keyword. We can provide multiple exceptions in the throws clause and it can be used
with main() method also.
3. try-catch: We use try-catch block for exception handling in our code. try is the start of the block and
catch is at the end of try block to handle the exceptions. We can have multiple catch blocks with a try
and try-catch block can be nested also. catch block requires a parameter that should be of type
Exception.
4. finally: finally block is optional and can be used only with try-catch block. Since exception halts the
process of execution, we might have some resources open that will not get closed, so we can use
finally block. finally block gets executed always, whether exception occurred or not.
Throwable is the parent class of Java Exceptions Hierarchy and it has two child objects – Error and
Exception. Exceptions are further divided into checked exceptions and runtime exception.
1. Errors: Errors are exceptional scenarios that are out of scope of application and it’s not possible to
anticipate and recover from them, for example hardware failure, JVM crash or out of memory error.
That’s why we have a separate hierarchy of errors and we should not try to handle these situations.
Ex: OutOfMemoryError
2. Checked Exceptions: Checked Exceptions are exceptional scenarios that we can anticipate in a
program and try to recover from it, for example FileNotFoundException. We should catch this
exception and provide useful message to user and log it properly for debugging purpose.
Exception is the parent class of all Checked Exceptions and if we are throwing a checked
exception, we must catch it in the same method or we have to propagate it to the caller using
throws keyword.
Ex:
ClassNotFoundException
InterruptedException
NoSuchMethodException
IOException
EOFException
FileNotFoundException
MalformedURLException
UnknownHostException
3. Runtime Exception: Runtime Exceptions are cause by bad programming, for example trying to
retrieve an element from the Array. We should check the length of array first before trying to
retrieve the element otherwise it might throw ArrayIndexOutOfBoundException at runtime.
RuntimeException is the parent class of all runtime exceptions. If we are throwing any runtime
exception in a method, it’s not required to specify them in the method signature throws clause.
Runtime exceptions can be avoided with better programming.
Ex:
ArithmeticException
ClassCastException
IllegalArgumentException
o NumberFormatException
IndexOutOfBoundsException
o ArrayIndexOutOfBoundsException
o StringIndexOutOfBoundsException
NegativeArraySizeException
NullPointerException
NoSuchElementException
1. public String getMessage() – This method returns the message String of Throwable and the
message can be provided while creating the exception through its constructor.
2. public String getLocalizedMessage() – This method is provided so that subclasses can override it to
provide locale specific message to the calling program. Throwable class implementation of this
method simply use getMessage() method to return the exception message.
3. public synchronized Throwable getCause() – This method returns the cause of the exception or
null id the cause is unknown.
4. public String toString() – This method returns the information about Throwable in String format,
the returned String contains the name of Throwable class and localized message.
5. public void printStackTrace() – This method prints the stack trace information to the standard error
stream, this method is overloaded and we can pass PrintStream or PrintWriter as argument to write
the stack trace information to the file or stream.
Output:
output:
Divided by zero
Explanation:
An exception will thrown by this program as we are trying to divide a number by zero
inside try block. The program control is transfered outside try block. Thus the line "This line will
not be executed" is never parsed by the compiler. The exception thrown is handle in catch block.
Once the exception is handled the program controls continue with the next line in the program.
Thus the line "After exception is handled" is printed.
2. Multiple catch blocks: A try block can be followed by multiple catch blocks. You can have any number
of catch blocks after a single try block.If an exception occurs in the guarded code the exception is
passed to the first catch block in the list. If the exception type of exception, matches with the first
catch block it gets caught, if not the exception is passed down to the next catch block. This continues
until the exception is caught or falls through all catches.
class Excep {
public static void main(String[] args) {
try {
int arr[] = { 1, 2 };
arr[2] = 3 / 0;
} catch (ArithmeticException ae) {
System.out.println("divide by zero");
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("array index out of bound exception");
}
}
}
Output:
divide by zero
3. Creating Custom Exception Classes: Java provides a lot of exception classes for us to use but
sometimes we may need to create our own custom exception classes to notify the caller about
specific type of exception with appropriate message and any custom fields we want to introduce for
tracking, such as error codes. For example, let’s say we write a method to process only text files, so
we can provide caller with appropriate error code when some other type of file is sent as input.
Here is an example of custom exception class and showing its usage.
MyException.java:
public class MyException extends Exception {
CustomExceptionExample.java:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
In Java 7, we can catch all these exceptions in a single catch block as:
catch(IOException | SQLException | Exception ex){
logger.error(ex);
throw new MyException(ex.getMessage());
}
If a catch block handles multiple exception, you can separate them using a pipe (|) and in this case
exception parameter (ex) is final, so you can’t change it. The byte code generated by this feature is
smaller and reduces code redundancy.
2. Automatic resource management: Resources such as Connections, Files, Input/OutStreams, etc.
should be closed manually by the developer by writing bog-standard code. Usually we use a try-finally
block to close the respective resources. See the current practice of creating a resource, using it and finally
closing it:
package com.sample;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
package com.sample;
import java.io.DataOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
While debugging we will have to look out at the stack trace carefully to identify the actual location of
exception. If we change our implementation logic to check for these exceptions early as below;
private static void processFile(String file) throws MyException {
if(file == null) throw new MyException("File name can't be null",
"NULL_FILE_NAME");
//further processing
}
Then the exception stack trace will be like below that clearly shows where the exception has
occurred with clear message.
com.journaldev.exceptions.MyException: File name can't be null
at
com.journaldev.exceptions.CustomExceptionExample.processFile(CustomExcepti
onExample.java:37)
at
com.journaldev.exceptions.CustomExceptionExample.main(CustomExceptionExamp
le.java:12)
3. Catch Late – Since java enforces to either handle the checked exception or to declare it in method
signature, sometimes developers tend to catch the exception and log the error. But this practice is
harmful because the caller program doesn’t get any notification for the exception. We should catch
exception only when we can handle it appropriately. For example, in above method I am throwing
exception back to the caller method to handle it. The same method could be used by other applications
that might want to process exception in a different manner. While implementing any feature, we
should always throw exceptions back to the caller and let them decide how to handle it.
4. Closing Resources – Since exceptions halt the processing of program, we should close all the
resources in finally block or use Java 7 try-with-resources enhancement to let java runtime close it for
you.
5. Logging Exceptions – We should always log exception messages and while throwing exception
provide clear message so that caller will know easily why the exception occurred. We should always
avoid empty catch block that just consumes the exception and doesn’t provide any meaningful details
of exception for debugging.
6. Single catch block for multiple exceptions – Most of the times we log exception details and
provide message to the user, in this case we should use java 7 feature for handling multiple exceptions
in a single catch block. This approach will reduce our code size and it will look cleaner too.
7. Using Custom Exceptions – It’s always better to define exception handling strategy at the design
time and rather than throwing and catching multiple exceptions, we can create a custom exception with
error code and caller program can handle these error codes. Its also a good idea to create a utility
method to process different error codes and use it.
8. Naming Conventions and Packaging – When you create your custom exception, make sure it ends
with Exception so that it will be clear from name itself that it’s an exception. Also make sure to package
them like it’s done in JDK, for example IOException is the base exception for all IO operations.
9. Use Exceptions Judiciously – Exceptions are costly and sometimes it’s not required to throw
exception at all and we can return a boolean variable to the caller program to indicate whether an
operation was successful or not. This is helpful where the operation is optional and you don’t want your
program to get stuck because it fails. For example, while updating the stock quotes in database from a
third party webservice, we may want to avoid throwing exception if the connection fails.
10. Document the Exceptions Thrown – Use javadoc @throws to clearly specify the exceptions
thrown by the method, it’s very helpful when you are providing an interface to other applications to use.
Enumerations
Enumerations (in general) are generally a set of related constants. Enumerations were added to Java
language in JDK5. An Enumeration can have constructors, methods and instance variables. It is created
using enum keyword. Each enumeration constant is public, static and final by default. Even though
enumeration defines a class type and have constructors, we cannot instantiate an enum using new.
Enumeration variables are used and declared in much a same way as we do a primitive variable.
Enumeration in java is supported by keyword enum. enums are a special type of class that always
extends java.lang.Enum. Since its already extending Enum class, cannot extend any other classes, since
java doesn’t support multiple inheritances.
This clearly means that enums are comparable and serializable implicitly. Also, all enum types in java
are singleton by default. So, you can compare enum types using ‘==’ operator also.
Identifiers SUNDAY, MONDAY, TEUSDAY, WEDNESSDAY, THURSDAY, FRIDAY & SATURDAY are called
enumeration constants. These are public, static final by default.
We should always use enums when a variable (especially a method parameter) can only take
one out of a small set of possible values.
Output:
Iterate an enum:
iterateEnum();
}
public static void iterateEnum() {
for(Day currentDay : Day.values()) {
System.out.println(currentDay);
}
}
}
Output:
MONDAY
TEUSDAY
WEDNESSDAY
THURSDAY
FRIDAY
SATURDAY
SUNDAY
Constructor in Enum:
Notes:
Constructors for an enum type should be declared as private. The compiler allows non private
declares for constructors, but this seems misleading to the reader, since new can never be used
with enum types.
Since these enumeration instances are all effectively singletons, they can be compared for
equality using identity (“==”).
Collection Framework
The Java language supports arrays to store several objects. An array is initialized with an predefined size
during instantiation. To support more flexible data structures the core Java library provides
the collection framework. A collection is a data structure which contains and processes a set of data. The
data stored in the collection is encapsulated and the access to the data is only possible via predefined
methods. For example the developer can add elements to an collection via a method. Collections use
internally arrays for their storage but hide the complexity of managing the dynamic size from the
developer.
Type information with generics: Java collections should get parameterized with a type declaration. This
enables the Java compiler to check if you try to use the collection with the correct type of
objects. Generics allow a type or method to operate on objects of various types while providing compile-
time type safety. Before generics, it needs to cast every object we read from a collection and if we
inserted an object of the wrong type into a collection you would create a runtime exception.
Interfaces: These are abstract data types that represent collections. Interfaces allow
collections to be manipulated independently of the details of their representation. In object-
oriented languages, interfaces generally form a hierarchy.
Implementations: These are the concrete implementations of the collection interfaces. In
essence, they are reusable data structures.
Algorithms: These are the methods that perform useful computations, such as searching and
sorting, on objects that implement collection interfaces. The algorithms are said to be
polymorphic: that is, the same method can be used on many different implementations of the
appropriate collection interface. In essence, algorithms are reusable functionality.
Reduces programming effort: By providing useful data structures and algorithms, the
Collections Framework frees you to concentrate on the important parts of your program rather
than on the low-level "plumbing" required to make it work. By facilitating interoperability
among unrelated APIs, the Java Collections Framework frees you from writing adapter
objects or conversion code to connect APIs.
Increases program speed and quality: This Collections Framework provides high-
performance, high-quality implementations of useful data structures and algorithms. The
various implementations of each interface are interchangeable, so programs can be easily
tuned by switching collection implementations. Because you're freed from the drudgery of
writing your own data structures, you'll have more time to devote to improving programs'
quality and performance.
Allows interoperability among unrelated APIs: The collection interfaces are the vernacular
by which APIs pass collections back and forth. If my network administration API furnishes a
collection of node names and if your GUI toolkit expects a collection of column headings, our
APIs will interoperate seamlessly, even though they were written independently.
Reduces effort to learn and to use new APIs: Many APIs naturally take collections on input
and furnish them as output. In the past, each such API had a small sub-API devoted to
manipulating its collections. There was little consistency among these ad hoc collections sub-
APIs, so you had to learn each one from scratch, and it was easy to make mistakes when using
them. With the advent of standard collection interfaces, the problem went away.
Reduces effort to design new APIs: This is the flip side of the previous advantage. Designers
and implementers don't have to reinvent the wheel each time they create an API that relies on
collections; instead, they can use standard collection interfaces.
Fosters software reuse: New data structures that conform to the standard collection
interfaces are by nature reusable. The same goes for new algorithms that operate on objects
that implement these interfaces.
Collection Class
name Ordered Sorted
Hashtable No No
HashMap No No
Map
TreeMap Sorted By natural order or custom order
LinkedHashMap By insertion order or last access order No
HashSet No No
Set TreeSet Sorted By natural order or custom order
LinkedHashSet By insertion order No
ArrayList Indexed No
Vector Indexed No
List
LinkedList Indexed No
Priority queue Sorted By to-do order
The following list describes the core collection interfaces:
Collection — the root of the collection hierarchy. A collection represents a group of objects
known as its elements. The Collection interface is the least common denominator that all
collections implement and is used to pass collections around and to manipulate them when
maximum generality is desired. Some types of collections allow duplicate elements, and others do
not. Some are ordered and others are unordered. The Java platform doesn't provide any direct
implementations of this interface but provides implementations of more specific subinterfaces, such
as Set and List. Also see The Collection Interface section.
Set — a collection that cannot contain duplicate elements. This interface models the mathematical
set abstraction and is used to represent sets, such as the cards comprising a poker hand, the courses
making up a student's schedule, or the processes running on a machine. See also The Set Interface
section.
List — an ordered collection (sometimes called a sequence). Lists can contain duplicate elements.
The user of a List generally has precise control over where in the list each element is inserted and
can access elements by their integer index (position). If you've used Vector, you're familiar with the
general flavor of List. Also see The List Interface section.
Queue — a collection used to hold multiple elements prior to processing. Besides basic Collection
operations, a Queue provides additional insertion, extraction, and inspection operations.
Queues typically, but do not necessarily, order elements in a FIFO (first-in, first-out) manner.
Among the exceptions are priority queues, which order elements according to a supplied
comparator or the elements' natural ordering. Whatever the ordering used, the head of the
queue is the element that would be removed by a call to remove or poll. In a FIFO queue, all
new elements are inserted at the tail of the queue. Other kinds of queues may use different
placement rules. Every Queue implementation must specify its ordering properties. Also see
The Queue Interface section.
Deque — a collection used to hold multiple elements prior to processing. Besides basic Collection
operations, a Deque provides additional insertion, extraction, and inspection operations.
Deques can be used both as FIFO (first-in, first-out) and LIFO (last-in, first-out). In a deque
all new elements can be inserted, retrieved and removed at both ends. Also see The Deque
Interface section.
Map — an object that maps keys to values. A Map cannot contain duplicate keys; each key can map to
at most one value. If you've used Hashtable, you're already familiar with the basics of Map. Also see
The Map Interface section.
The last two core collection interfaces are merely sorted versions of Set and Map:
SortedSet — a Set that maintains its elements in ascending order. Several additional operations
are provided to take advantage of the ordering. Sorted sets are used for naturally ordered sets, such
as word lists and membership rolls. Also see The SortedSet Interface section.
SortedMap — a Map that maintains its mappings in ascending key order. This is the Map analog of
SortedSet. Sorted maps are used for naturally ordered collections of key/value pairs, such as
dictionaries and telephone directories. Also see The SortedMap Interface section.
The Collection interface contains methods that perform basic operations, such as int size(),
boolean isEmpty(), boolean contains(Object element), boolean add(E element),
boolean remove(Object element), and Iterator<E> iterator().
add(E e)
Boolean
Ensures that this collection contains the specified element (optional operation).
Boolean Adds all of the elements in the specified collection to this collection (optional
operation).
clear()
Void
Removes all of the elements from this collection (optional operation).
contains(Object o)
Boolean
Returns true if this collection contains the specified element.
containsAll(Collection<?> c)
Boolean Returns true if this collection contains all of the elements in the specified
collection.
equals(Object o)
Boolean
Compares the specified object with this collection for equality.
hashCode()
Int
Returns the hash code value for this collection.
isEmpty()
Boolean
Returns true if this collection contains no elements.
iterator()
Iterator<E>
Returns an iterator over the elements in this collection.
remove(Object o)
Boolean Removes a single instance of the specified element from this collection, if it is
present (optional operation).
removeAll(Collection<?> c)
Boolean Removes all of this collection's elements that are also contained in the specified
collection (optional operation).
retainAll(Collection<?> c)
Boolean Retains only the elements in this collection that are contained in the specified
collection (optional operation).
size()
Int
Returns the number of elements in this collection.
toArray()
Object[]
Returns an array containing all of the elements in this collection.
toArray(T[] a)
<T> T[] Returns an array containing all of the elements in this collection; the runtime type
of the returned array is that of the specified array.
ArrayList:
In addition to the Arrays class, Java provides an ArrayList class which can be used to create
containers that store lists of objects. ArrayList can be considered as a growable array. It gives us
fast iteration and fast random access. ArrayList implements the new RandomAccess interface—a
marker interface (meaning it has no methods) that says, "This list supports fast (generally constant
time) random access".
Earlier versions of Java have one legacy collection class called Vector which is very much similar
to ArrayList. Vector implements a dynamic array. A Vector is basically the same as an ArrayList,
but Vector methods are synchronized for thread safety. You'll normally want to use ArrayList
instead of Vector because the synchronized methods add a performance hit you might not need. In
this tutorial we will discuss about ArrayList only considering all is applicable to Vector as well.
The java.util.ArrayList class is one of the most commonly used of all the classes in the
Collections Framework.An ArrayList is dynamically resizable, meaning that its size can change
during program execution. This means that:
You can add an item at any point in an ArrayList container and the array size expands
automatically to accommodate the new item.
You can remove an item at any point in an ArrayList container and the array size contracts
automatically.
To state the obvious: Arraylist is an ordered collection (by index), but not sorted.
To use the ArrayList class, you must use the following import statement:
import java.util.ArrayList;
Then, to declare an ArrayList, you can use the default constructor, as in the following example:
The default constructor creates an ArrayList with a capacity of 10 items. The capacity of an ArrayList is
the number of items it can hold without having to increase its size. Other constructors of ArrayList as
follows,
You can also specify a capacity/size of initial ArrayList as well as create ArrayList from other
collection types.
Methods of ArrayList:
Method Purpose
public void add(Object) Adds an item to an ArrayList. The default version adds an item at the next
public void add(int, available location; an overloaded version allows you to specify a position at
Object) which to add the item
public void remove(int) Removes an item from an ArrayList at a specified location
public void set(int,
Object) Alters an item at a specified ArrayList location
Object get(int) Retrieves an item from a specified location in an ArrayList
public int size() Returns the current ArrayList size
LinkedList
A LinkedList is ordered by index position, like ArrayList, except that the elements are doubly-
linked to one another. This linkage gives you new methods (beyond what you get from the List
interface) for adding and removing from the beginning or end, which makes it an easy choice for
implementing a stack or queue. Linked list has concept of nodes and data. Here Node is storing
values of next node while data stores the value it is holding. Below diagram shows how
LinkedList storing values. There are three elements in LinkedList A, B and C. We are removing
element B from middle of the LinkedList which will just change node value of element A’s node
to point to node C.
Keep in mind that a LinkedList may iterate more slowly than an ArrayList, but it's a good choice
when you need fast insertion and deletion.
The first constructor builds an empty linked list. The second constructor builds a linked list that is
initialized with the elements of the collection c.
Ex:
package com.sample;
import java.util.LinkedList;
myLinkedList.remove();
myLinkedList.removeLast();
myLinkedList.remove("C");
Set:
A Set is a Collection that cannot contain duplicate elements. There are three main
implementations of Set interface: HashSet, TreeSet, and LinkedHashSet. HashSet, which stores
its elements in a hash table, is the best-performing implementation; however it makes no
guarantees concerning the order of iteration. TreeSet, which stores its elements in a red-black tree,
orders its elements based on their values; it is substantially slower than HashSet. LinkedHashSet,
which is implemented as a hash table with a linked list running through it, orders its elements
based on the order in which they were inserted into the set (insertion-order).
HashSet:
This class implements the Set interface, backed by a hash table (actually a HashMap instance). It
makes no guarantees as to the iteration order of the set; in particular, it does not guarantee that the
order will remain constant over time. This class permits the null element. This class is not
synchronized.
Notes:
1. HashSet doesn’t maintain any order, the elements would be returned in any random order.
2. HashSet doesn’t allow duplicates. If you try to add a duplicate element in HashSet, the old value
would be overwritten.
3. HashSet allows null values however if you insert more than one nulls it would still return only one
null value.
5. The iterator returned by this class is fail-fast which means iterator would
throw ConcurrentModificationException if HashSet has been modified after creation of iterator, by
any means except iterator’s own remove method.
Methods:
4. boolean contains(Object o): It checks whether the specified Object o is present in the list or not.
If the object has been found it returns true else false.
Ex:
import java.util.HashSet;
Output:
As we can see there all the duplicate values are not present in the output including the duplicate null value.
TreeSet:
TreeSet is similar to HashSet except that it sorts the elements in the ascending order while HashSet
doesn’t maintain any order. HashSet allow null, but TreeSet won’t allow.
Ex:
import java.util.TreeSet;
// Displaying TreeSet
System.out.println(tset);
Output:
Map
A Map is an object that maps keys to values. A map cannot contain duplicate keys.
There are three main implementations of Map interfaces: HashMap, TreeMap, and LinkedHashMap. There
are 4 commonly used implementations of Map in Java SE - HashMap, TreeMap, Hashtable and
LinkedHashMap. If we use only one sentence to describe each implementation, it would be the following:
Hashtable: Hash table is a data structure to store key value pairs for all situations. So it is like a table
with each entry has a key and a value corresponding to it. So, it is an efficient way of mapping and
accessing data.
HashMap: it makes no guarantees concerning the order of iteration
TreeMap: It stores its elements in a red-black tree, orders its elements based on their values; it is
substantially slower than HashMap.
LinkedHashMap: It orders its elements based on the order in which they were inserted into the set
(insertion-order).
Hashtable:
A Hashtable is an array of list. Each list is known as a bucket. The position of bucket is identified by
calling the hashcode() method. A Hashtable contains values based on the key. It implements the Map
interface and extends Dictionary class.
It contains only unique elements.
It cannot store any null key or value.
It is synchronized.
Constructor Summary:
Hashtable()
Constructs a new, empty hashtable with a default initial capacity (11) and load factor (0.75).
Hashtable(int initialCapacity)
Constructs a new, empty hashtable with the specified initial capacity and default load factor (0.75).
Constructs a new, empty hashtable with the specified initial capacity and the specified load factor.
Constructs a new hashtable with the same mappings as the given Map.
Method Summary:
clear()
Void
Clears this hashtable so that it contains no keys.
clone()
Object
Creates a shallow copy of this hashtable.
contains(Object value)
Boolean
Tests if some key maps into the specified value in this hashtable.
containsKey(Object key)
Boolean
Tests if the specified object is a key in this hashtable.
containsValue(Object value)
Boolean
Returns true if this hashtable maps one or more keys to this value.
elements()
Enumeration<V>
Returns an enumeration of the values in this hashtable.
entrySet()
Set<Map.Entry<K,V>>
Returns a Set view of the mappings contained in this map.
equals(Object o)
Boolean Compares the specified Object with this Map for equality, as per the definition
in the Map interface.
get(Object key)
V Returns the value to which the specified key is mapped, or null if this map
contains no mapping for the key.
hashCode()
Int Returns the hash code value for this Map as per the definition in the Map
interface.
isEmpty()
Boolean
Tests if this hashtable maps no keys to values.
keys()
Enumeration<K>
Returns an enumeration of the keys in this hashtable.
keySet()
Set<K>
Returns a Set view of the keys contained in this map.
rehash()
protected void Increases the capacity of and internally reorganizes this hashtable, in order to
accommodate and access its entries more efficiently.
remove(Object key)
V
Removes the key (and its corresponding value) from this hashtable.
size()
Int
Returns the number of keys in this hashtable.
toString()
String
Returns a string representation of this Hashtable object in the form of a set
of entries, enclosed in braces and separated by the ASCII characters ", "
values()
Collection<V>
Returns a Collection view of the values contained in this map.
Assume that, “v” is a value to be stored and “k” is the key used for storage / retrieval, then “h” is a hash
function where “v” is stored at “h(k)” of table. To retrieve a value compute “h(k)” so that you can directly
get the position of “v”. So in a key-value pair table, you need not sequentially scan through the keys to
identify a value. “h(k)” is the hashing function and it is used to find the location to store the
corresponding value v. h(k) cannot compute to an indefinite space. Storage allocated for a Hashtable is
limited within a program. So, the hasing function h(k) should return a number within that allocated
spectrum (logical address space).
Hashtable performance: To get better performance Hashtable, need to use the initialCapacity and
loadFactor arguments.
initialCapacitiy is the number of buckets to be created at the time of Hashtable instantiation. The number
of buckets and probability of collision is inversely proportional. If you have more number of buckets than
needed then you have lesser possibility for a collision.
For example, if you are going to store 10 elements and if you are going to have initialCapacity as 100 then
you will have 100 buckets. You are going to calculate hashCoe() only 10 times with a spectrum of 100
buckets. The possibility of a collision is very less.
But if you are going to supply initialCapacity for the Hashtable as 10, then the possibility of collision is
very large. loadFactor decides when to automatically increase the size of the Hashtable. The default size of
initialCapacity is 11 and loadFactor is .75 That if the Hashtable is 3/4th full then the size of the Hashtable is
increased.
Example:
import java.util.Enumeration;
import java.util.Hashtable;
// You will see that the items will be arranged as per the hash function
System.out.println("Items in the Hashtable : " + ht );
System.out.println("-----------------------");
Output:
Hashtable in Java :
-----------------------
Adding items to the Hashtable
Items in the Hashtable : {4=HTML, 3=Javascript, 2=.NET, 1=Java}
-----------------------
4: HTML
3: Javascript
2: .NET
1: Java
HashMap:
The HashMap class does not guarantee that the order will remain constant over time.
This implementation provides constant-time performance for the basic operations (get and put),
assuming the hash function disperses the elements properly among the buckets.
The HashMap implementation is not synchronized. If multiple threads access this map concurrently,
and at least one of the threads modifies the map structurally, it must be synchronized externally.
Ex:
import java.util.Set;
import java.util.TreeSet;
import java.util.Iterator;
Output:
TreeMap:
A TreeMap is a Map implementation which provides total ordering on its elements. The elements are
ordered using their natural ordering, or by a Comparator typically provided at sorted map creation time.
A TreeMap is a Red-Black tree based NavigableMap implementation which insures log(n) time cost for
the basic operations (add, remove and contains).
A TreeMap is typically used when, in a map, we want to keep the elements sorted all times. The elements
are sorted by the keys in a map. The keys could also be custom objects defined with
comparable/comparator to decide the attribute responsible for sorting.
Important thing to note is that the ordering maintained by a TreeMap must be consistent with equals if this
sorted map is to correctly implement the Map interface.
import java.util.Map;
import java.util.TreeMap;
System.out.println(integerMap.toString());
}
}
Output:
@Override
public String toString() {
return firstName + " " + lastName + " " + salary;
}
@Override
public int compareTo(User o) {
return this.firstName.compareTo(o.firstName);
}
}
Now let’s see how to use TreeMap to get the inserted elements sorted on the basis of firstName.
System.out.println(userMap.toString());
diplayMap(userMap);
Output:
{Ani Bha 12=My Name1, CalYYY 15=My Name2, SSS TER 1=My Name4, XYZ WER 22=My
Name3}
Ani Bha 12
Cal YYY 15
SSS TER 1
XYZ WER 22
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.Comparator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
Output:
Java IO Operations
Java.io package provides classes for system input and output through data streams, serialization and the
file system.
Standard Streams
All the programming languages provide support for standard I/O where user's program can take input
from a keyboard and then produce output on the computer screen. Java provides the following three
standard streams.
Standard Input: This is used to feed the data to user's program and usually a keyboard is used as
standard input stream and represented as System.in.
Standard Output: This is used to output the data produced by the user's program and usually a
computer screen is used to standard output stream and represented as System.out.
Standard Error: This is used to output the error data produced by the user's program and usually a
computer screen is used to standard error stream and represented as System.err.
Example code to print output to console:
1. System.out.println("simple message");
2. System.err.println("error message");
Java encapsulates Stream under java.io package. Java defines two types of streams. They are,
1. Byte Stream: It provides a convenient means for handling input and output of byte.
2. Character Stream: It provides a convenient means for handling input and output of characters.
Character stream uses Unicode and therefore can be internationalized.
A stream can be defined as a sequence of data. There are two kinds of Streams.
InputStream: The InputStream is used to read data from a source and it is an abstract class. Source
may be a file, an array, peripheral device or socket.
OutputStream: the OutputStream is used for writing data to a destination and it is an abstract class.
An output stream accepts output bytes and sends them to some sink.
Method Description
public void write(int)throws IOException: is used to write a byte to the current output stream.
public void write(byte[])throws is used to write an array of byte to the current output
IOException: stream.
public void close()throws IOException: is used to close the current output stream.
Method Description
public abstract int read()throws reads the next byte of data from the input stream.It returns
IOException: -1 at the end of file.
public int available()throws returns an estimate of the number of bytes that can be read
IOException: from the current input stream.
public void close()throws
is used to close the current input stream.
IOException:
These classes define several key methods. Two most important are:
1. read() : reads byte of data.
2. write() : Writes byte of data.
Java byte streams are used to perform input and output of 8-bit bytes. Though there are many classes
related to byte streams but the most frequently used classes are , FileInputStream and
FileOutputStream.
2. ByteArrayOutputStream objects are used to create a buffer in memory. All the data that you send to
the stream is placed in this buffer.
4. ObjectOutputStream objects are used for serializing (saving) objects to various streams (See the
serialization topic).
5. PipedOutputStream objects are used to implement the write portion of the "piping" concept.
6. FilterOutputStream objects are used to process stream output so that it can be buffered and written
as blocks of useful data instead of as one byte at a time.
8. BufferedOutputStream is a FilterOutputStream class used to buffer data in a stream before writing it.
flush() is used to write the data to the stream.
9. DataOutputStream is a FilterOutputStream class used to write primitives (int, char, long, etc) to a
stream.
10. PrintStream is a FilterOutputStream class used for producing formatted output. (DataOutputStream
handles the storage of data, PrintStream handles the display of data.)
12. FileInputStream objects are used for reading data from a file.
13. ObjectInputStream objects are used for deserializing (reading) objects from various streams (See the
serialization topic).
14. PipedInputStream objects are used to implement the read portion of the "piping" concept (We will
defer the discussion of this stream to the multithreading topics).
15. SequenceInputStream are used to convert two or more InputStream objects into a single
InputStream object.
16. StringBufferInputStream objects are used to convert a String object into an InputSteam.
17. FilterInputStream objects are used to process stream input so that it can be read as blocks of useful
data instead of as one byte at a time.
18. All the FilterInputStream contructors require another InputStream object as an argument.
19. BufferedInputStream is a FilterInputStream class used to buffer data in a stream before reading it.
20. DataInputStream is a FilterInputStream class used to read primitives (int, char, long, etc) from a
stream.
21. LineNumberInputStream is a FilterInputStream class used to keep track of line numbers in the input
stream (getLineNumber(); setLineNumber(int)).
22. PushbackInputStream is a FilterInputStream class that has a one byte push-back buffer so you can
push back the last character read.
FileInputStream
This class is used for reading data from the files.
Following constructor takes a file object to create an input stream object to read the file. First we create
a file object using File() method as follows:
Method Description
public void close() throws IOException{} This method closes the file output stream. Releases any system
resources associated with the file. Throws an IOException.
protected void finalize()throws IOException {} This method cleans up the connection to the file. Ensures that
the close method of this file output stream is called when there
are no more references to this stream. Throws an IOException.
public int read(int r)throws IOException{} This method reads the specified byte of data from the
InputStream. Returns an int. Returns the next byte of data and -
1 will be returned if it's end of file
public int read(byte[] r) throws IOException{} This method reads r.length bytes from the input stream into an
array. Returns the total number of bytes read. If end of file -1
will be returned.
public int available() throws IOException{} Gives the number of bytes that can be read from this file input
stream. Returns an int.
FileOutputStream
FileOutputStream is used to create a file and write data into it. The stream would create a file, if it
doesn't already exist, before opening it for output.
Here are two constructors which can be used to create a FileOutputStream object.
Following constructor takes a file name as a string to create an input stream object to write the file:
Following constructor takes a file object to create an output stream object to write the file. First, we
create a file object using File() method as follows:
Method Description
Sample program:
package com.sample.file;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
try {
String[] arr = { "Ram", "Laxman", "Bharath", "Khathragna"};
OutputStream os = new
FileOutputStream("D:\\HAWB\\PARAMESH\\JPA\\FILES\\test.txt");
for (int index = 0; index < arr.length; index++) {
os.write(arr[index].getBytes()); // writes the bytes
}
os.close();
InputStream is = new
FileInputStream("D:\\HAWB\\PARAMESH\\JPA\\FILES\\test.txt");
int size = is.available();
So, why were the character-oriented classes added to the I/O library? Well, they were added to work
specifically with character data (characters, character arrays, strings). The character stream classes differ
from the byte streams classes in that they operate on buffered input and output and properly convert
each character from the encoding scheme of the native operating system to the Unicode character set
used by the Java platform. On the other hand, InputStream and OutputStream, and their subclasses
operate on bytes and arrays of bytes. The byte-oriented streams can read characters, but they only
correctly handle 7-bit ASCII characters (same as the first 128 Unicode characters).
It is important to note that the character stream classes were not added to completely replace the byte
stream classes. The InputStream and OutputStream classes remain in the I/O library and they still provide
valuable functionality (mainly for reading binary data like primitive types).
These two abstract classes have several concrete classes that handle unicode character.
We use the object of BufferedReader class to take inputs from the keyboard.
Reading Characters:
read() method is used with BufferedReader object to read characters. As this function returns integer
type value has we need to use typecasting to convert it into char type.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
To read string we have to use readLine() function with BufferedReader class's object.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
class FileStreamWriterDemo {
public static void main(String[] args) {
try {
File fl = new File("myfile.txt");
String str = "Write this string to my file";
FileWriter fw = new FileWriter(fl);
fw.write(str);
fw.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Serialization
The concept of transmitting objects from one place to another place is called Serialization.
The concept of persisting the state of an object (in a file, disk, DB) is called Serialization.
Serialization is a process in which current state of Object will be saved in stream of bytes. As byte stream
create is platform neutral hence once objects created in one system can be deserialized in other
platform.
Marshalling: The process of converting object to network understandable data is called “Marshalling.
Classes ObjectInputStream and ObjectOutputStream are high-level streams that contain the methods
for serializing and deserializing an object.
The ObjectOutputStream class contains many write methods for writing various data types, but one
method in particular stands out:
The above method serializes an Object and sends it to the output stream. Similarly, the
ObjectInputStream class contains the following method for deserializing an object:
This method retrieves the next Object out of the stream and deserializes it. The return value is Object, so
you will need to cast it to its appropriate data type.
Need of Serialization:
Serialization is usually used when the need arises to send your data over network or stored in files. By
data I mean objects and not text. Now the problem is your Network infrastructure and your Hard disk are
hardware components that understand bits and bytes but not Java objects. Serialization is the translation
of your Java object’s values/states to bytes to send it over network or save it.On other hand,
Deserialization is conversion of byte code to corresponding java objects.
Concept of serialVersionUID :
SerialVersionUID is used to ensure that same object(That was used during Serialization) is loaded during
Deserialization.serialVersionUID is used for version control of object.
Employee.java:
import java.io.Serializable;
/**
*
*/
private static final long serialVersionUID = 1L;
int employeeId;
String employeeName;
String department;
Steps to deserialize:
DeserializeDemo.java:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
Notes:
Threads
A Thread is a light weight process that executes some task simultaneously with other part of the
program. Threads are two types.
1. User threads
2. System Threads (Daemon Threads)
Every java program/application has at least one thread in it. Per example main() is a user thread, that will
be created as and when a java program starts execution. There will be many other threads running in
background like memory management, system management, signal processing etc. All these threads are
System threads or Daemon threads.
Multithreading refers to two or more threads executing concurrently in a single program. A computer
single core processor can execute only one thread at a time and time slicing is the OS feature to share
processor time between different processes and threads.
New: A thread begins its life cycle in the new state. It remains in this state until the program starts the
thread. It is also referred to as a born thread.
Runnable: After a newly born thread is started, the thread becomes runnable. A thread in this state is
considered to be executing its task.
Waiting: Sometimes, a thread transitions to the waiting state while the thread waits for another thread to
perform a task.A thread transitions back to the runnable state only when another thread signals the waiting
thread to continue executing.
Timed waiting: A runnable thread can enter the timed waiting state for a specified interval of time. A
thread in this state transitions back to the runnable state when that time interval expires or when the event it
is waiting for occurs.
Terminated (Dead): A runnable thread enters the terminated state when it completes its task or otherwise
terminates.
Thread Priority
Thread priority helps operating system to determine in scheduling the Threads. Every thread has its own
priority. Thread priorities are in the range between 1 – 10. Thread has three constants.
MAX_PRIORITY = 10
MIN_PRIORITY = 1
NORM_PRIORITY = 5
Operating system will schedule the threads based on their priority. Heigher priority has more important
and lower priority has less importance. NORM_PRIORITY is the default priority of a thread. However, if
there are two threads with the same priority, cannot guarantee the order in which threads execute and
very much platform dependent.
Thread creation
Thread can be created in two ways.
Syntax of run():
Step #2: We need to instantiate the Thread class object by using any one the following constructors.
Thread(Runnable threadObj);
Here, threadObj is an instance of a class that implements the Runnable interface and threadName is the
name given to the new thread.
Step #3: Once Thread object is created, we need to make a call to start() method to start the execution of
run() method.
void start( );
Methods Description
Starts the thread in a separate path of execution, then invokes the run()
public void start() method on this Thread object.
If this Thread object was instantiated using a separate Runnable target, the
public void run() run() method is invoked on that Runnable object.
public final void Changes the name of the Thread object. There is also a getName() method
for retrieving the name.
setName(String name)
public final void Sets the priority of this Thread object. The possible values are between 1
and 10.
setPriority(int priority)
public final void A parameter of true denotes this Thread as a daemon thread.
setDaemon(boolean on)
public final void The current thread invokes this method on a second thread, causing the
current thread to block until the second thread terminates or the specified
join(long millisec) number of milliseconds passes.
Returns true if the thread is alive, which is any time after the thread has
public final boolean isAlive() been started but before it runs to completion.
Methods Description
Causes the currently running thread to yield to any other threads of
public static void yield() the same priority that are waiting to be scheduled.
public static void sleep(long Causes the currently running thread to block for at least the
millisec) specified number of milliseconds.
public static boolean Returns true if the current thread holds the lock on the given
holdsLock(Object x) Object.
public static Thread Returns a reference to the currently running thread, which is the
currentThread() thread that invokes this method.
public static void Prints the stack trace for the currently running thread, which is
dumpStack() useful when debugging a multithreaded application.
Filename: thread_file.txt
RunnableThread.java:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
RunnableThread(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
System.out.println("Running thread name : " + threadName);
try (BufferedReader br = new BufferedReader(
new FileReader("D:\\ JPA\\FILES\\thread_file.txt"));) {
String str;
}
}
Output:
Step #1: We need to override run() method of Thread by placing with required business logic.
Step #2: Once created object for Thread class, it’s required to start() method.
Example:
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
ExtendingThread(String threadName) {
this.threadName = threadName;
}
@Override
public void run() {
System.out.println("Running thread name : " + threadName);
try (BufferedReader br = new BufferedReader(
new FileReader("D:\\JPA\\FILES\\thread_file.txt"));) {
String str;
while ((str = br.readLine()) != null) {
System.out.println(threadName + " - " + str);
}
} catch (IOException exp) {
exp.printStackTrace();
}
}
thread1.start();
thread2.start();
}
}
Output:
Synchronization:
There are many situations in which multiple threads must share access to common objects.
The keyword “synchronize” prevents multiple threads access the same object/resource simultaneously.
Thread communication:
Threads can be communicate with each other by using wait(), notify() & notifyAll(). These are the final
methods implemented in Object class. All three methods can be called only from within
a synchronized context.
ChatApplication.java:
package com.sample.threads;
System.out.println(ans);
flag = false;
notify();
}
}
CustomerThread.java:
ChatApplication ca;
String[] questions = { "Hi", "I have a problem in my
system", "Thank You..." };
@Override
public void run() {
for (String que : questions) {
ca.question("Customer : " + que);
}
}
}
CustomerCareThread.java:
ChatApplication ca;
@Override
public void run() {
for (String ans : answers) {
ca.answer("CustomerCare: " + ans);
}
}
}
ThreadCommunicationDemo.java:
Output:
Customer : Hi
CustomerCare: How may I help you?
Customer : I have a problem in my system
CustomerCare: Sure, please give us 24 hours to solve the problem
Customer : Thank You...
CustomerCare: Welcome
Reflection
Java Reflection makes it possible to inspect classes, interfaces, fields and methods at runtime, without
knowing the names of the classes, methods etc. at compile time. It is also possible to instantiate new
objects, invoke methods and get/set field values using reflection.
In Java, it is possible to inspect fields, classes, methods, annotations, interfaces, etc. at runtime. Its not
require to know how classes or methods are called, neither the parameters that are needed, all of that
can be retrieved at runtime using reflection. It is also possible to instantiate new classes, to create new
instances and to execute their methods, all of it using reflection.
Reflection API is the mechanism used to fetch information about a class. This mechanism is built into the
class named Class. The special class Class is the universal type for the meta information that describes
objects within the Java system. Class loaders in the Java system return objects of type Class.
Class: The Class contains all the reflection related methods that can be applied to classes and objects
like the ones that allow a programmer to retrieve the class name, to retrieve the public methods of a
class, etc.
forName(): Loads class of a given name, using the current class loader.
Syntax:
getName(): Returns the name of the class as a String object, which was useful for identifying object
references by their class name.
newInstance(): Invokes the no-args constructor on the class (if it exists) and return you an object
instance of that class of object.
Syntax:
public T newInstance()
throws InstantiationException,
IllegalAccessException
getConstructor(): Returns a Constructor object that reflects the specified public constructor of the
class represented by this Class object.
Syntax:
getConstructors(): Returns an array containing Constructor objects reflecting all the public
constructors of the class represented by this Class object.
Syntax:
Syntax:
getMethod(): Returns a Method object that reflects the specified public member method of the class
or interface represented by this Class object.
Syntax:
getMethods(): Returns an array containing Method objects reflecting all the public methods of the
class or interface represented by this Class object, including those declared by the class or interface
and those inherited from superclasses and superinterfaces.
Syntax:
getDeclaredMethods(): Returns an array containing Method objects reflecting all the declared
methods of the class or interface represented by this Class object, including public, protected, default
(package) access, and private methods, but excluding inherited methods.
Syntax:
getField(): Returns a Field object that reflects the specified public member field of the class or
interface represented by this Class object.
Syntax:
getFields(): Returns an array containing Field objects reflecting all the accessible public fields of the
class or interface represented by this Class object.
Syntax:
getDeclaredFields(): Returns an array of Field objects reflecting all the fields declared by the class or
interface represented by this Class object.
Syntax:
getSuperclass(): Returns the Class representing the superclass of the entity (class, interface, primitive
type or void) represented by this Class.
Syntax:
getInterfaces(): Determines the interfaces implemented by the class or interface represented by this
object.
Syntax:
Employee.java:
package com.sample.reflection;
int id;
String name;
String email;
@Override
public String toString() {
return new StringBuilder("Employee [id=").append(id)
.append(", name=").append(name)
.append(", email=").append(email)
.append("]").toString();
}
}
RefelectionDemo.java:
package com.sample.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
e.printStackTrace();
}
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException e) {
e.printStackTrace();
}
}
Output:
JDBC Architecture
Oracle: http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html
Mysql: http://www.mysql.com/downloads/connector/j/
1. Install the latest version of the Java SE JDK on your computer, if already not installed.
2. Set up the classpath for a JDBC driver. The JDBC driver is not needed for compiling the java
source but it is needed to execute the class. There are so many ways to set up this classpath
according to the OS, programming tools and your preferences.
3. Steps to setup te class path JDBC driver:
a. Right Click on Project name Properties Java Build Path Libraries
b. Click on “Add External JARs..” Browse and select JDBC driver jar Click “Open”
Java application calls the JDBC library. JDBC loads a driver which talks to the database In general, to
process any SQL statement with JDBC, you follow these steps:
1. Establish a connection.
2. Create a statement.
3. Execute the query.
4. Process the ResultSet object.
5. Close the connection
Establishing a Connection
In this step of the jdbc connection process, we load the driver class by calling Class.forName() with the
Driver class name as an argument. Once loaded, the Driver class creates an instance of itself.
The JDBC DriverManager class defines objects which can connect Java applications to a JDBC driver.
DriverManager is considered the backbone of JDBC architecture. DriverManager class manages the JDBC
drivers that are installed on the system. Its getConnection() method is used to establish a connection to a
database. It uses a username, password, and a jdbc url to establish a connection to the database and
returns a connection object. A jdbc Connection represents a session/connection with a specific database.
Within the context of a Connection, SQL, PL/SQL statements are executed and results are returned. An
application can have one or more connections with a single database, or it can have many connections
with different databases.
package com.sample.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
private DBConnection() {
A Statement is an interface that represents a SQL statement. You execute Statement objects, and they
generate ResultSet objects, which is a table of data representing a database result set. You need a
Connection object to create a Statement object.
There are three different kinds of statements.
Statement: Used to implement simple SQL statements with no parameters.
PreparedStatement: (Extends Statement.) Used for precompiling SQL statements that might contain
input parameters. See Using Prepared Statements for more information.
CallableStatement: (Extends PreparedStatement.) Used to execute stored procedures that may contain
both input and output parameters. See Stored Procedures for more information.
To execute a query, call an execute method from Statement such as the following:
execute: Returns true if the first object that the query returns is a ResultSet object. Use this method if
the query could return one or moreResultSet objects. Retrieve the ResultSet objects returned from the
query by repeatedly calling Statement.getResutSet.
executeQuery: Returns one ResultSet object.
executeUpdate: Returns an integer representing the number of rows affected by the SQL statement.
Use this method if you are using INSERT,DELETE, or UPDATE SQL statements.
Example of executeQuery:
Example of executeUpdate:
package com.sample.jdbc;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public ResultSet insertRecord(String name, String email, String country, String password) {
try {
Connection conn = DBConnection.getConnection();
final long id = DBConnection.getSequenceNumber();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("insert into USERS (id, name, email, country,
password) values " + "(" + id
+ ", '" + name + "', '" + email + "', '" + country + "', '" + password +
"')");
return rs;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
PreparedStatement ps = conn
.prepareStatement("insert into USERS (id, name, email, country,
password) values (?, ?, ?, ?, ?)");
ps.setLong(1, DBConnection.getSequenceNumber());
ps.setString(2, name);
ps.setString(3, email);
ps.setString(4, country);
ps.setString(5, password);
ResultSet rs = ps.executeQuery();
return rs;
} catch (SQLException e) {
e.printStackTrace();
}
return null;
}
Before executing the above program, its mandatory to create table and its sequence as follows:
MINVALUE 1
MAXVALUE 999999999999999999999999999