Core Java
Core Java
Variable declaration
[access/ non-access modifier] data-type variable-name [=value];
Method definition
[access/ non-access modifier] return-type method-name([arguments]){
Statement(s)
}
Types of variable
Local variable- declared inside the method is called local variable
Instance variable-declared inside the class but outside the method, is called instance variable
Static/ Class variable-declared with keyword static inside the class but outside the method
Static variable Can not be local to method
Example,
class Sample{
int x; //x is instance variable
static int y; //y is class variable
void foo(int a, int b){ //a,b,c local variables
int c;
….
}
}
Operators in Java
Based on no. of operands
Unary
Binary
Ternary
Based on operation:
Arithmetic
Logical
Assignment
Relational
Bitwise etc.
Precedence Operator Associativity
10 () [] . L->R
9 ++ -- + - ! ~ (type) R->L
8 */% +- L->R
7 << >> >>> L->R
6 < <= > >= instanceof L->R
5 == != L->R
4 & ^ | L->R
3 && || L->R
2 ?: R->L
1 = += -= *= /= %= R->L
0 , L->R
***Larger number means higher precedence
Comments in Java
//Single line comments
/*
Multi line comments
*/
/**
*Documentation comments
*/
Comments are non executable statements and used for describing sometning
Statements in program
Sequential statements-execute in sequence, I/O, declaration, expression etc
Selection statements- decision making statements, if, if-else, nested if-else, switch etc
Iteration statements- looping statements. Eg. for, while, do-while etc
break statement-terminates the loop conditionally
continue statement-skips over this iteration of loop & start new iteration
labelled continue and break
Branching statements
if(condition){ if(a>b){
Statement(s) System.out.println(a);
} }
if(condition){ if(a>b){
Statements1 System.out.println(a);
}else{ }else{
Statements2 System.out.println(b);
} }
Branching statements
if(a>b){
if(condition1){
System.out.println(a);
Statements1
}else if(b>a){
}else if(condition2){
System.out.println(b);
Statements2
} else{
}else if(condition3){
System.out.println(“Equal nos.”);
Statements3
}
}.....
else{
Default statements
}
Branching statements
switch(color){
switch(expression){
case variable1/constant1: case “R”:
Statement(s) System.out.println(“RED”);
break; break;
while(i<=10){
while(condition){
System.out.println(i);
statements
i++;
}
}
do{ do{
statements System.out.println(i); i++;
}while(condition); }while(i<=10);
break & continue
break is used to terminate the loop while(i<=10){
if(i==5)
continue is used to skip current iteration break;
of loop & start new iteration System.out.println(i);
Java allows labelled break & continue also i++;
break label; }
//Numbers 1-4 will be displayed in output
continue label;
break stops the loop when condition while(i<=10){
becomes true if(i==5)
continue skips on-going iteration and continue;
starts new System.out.println(i);
i++;
}
//Numbers 1-4 and 6-10 will be displayed
Array
Collection of elements having same type and same int[]array={10,20,30,40,50};
name for(int i=0;i<array.length;i++){
First element is stored at 0 index and last at one less System.out.println(array[i]);
than the size of an array
}
Array declaration & instantiation-
//Loop will display all array elements
datatype [] arrayname;
arrayname=new datatype[size];
int[][]arr={{10,20,30},{40,50,60},{70,80,90}};
datatype[]arrayname=new datatype[size];
for(int i=0;i<3;i++){
Compile time initialization of 1D array-
for(int j=0;j<3;j++){
int[]arr={100,200,300,400,500};
System.out.print(arr*i+*j++” “);
2D array-
}
int[][]arr=new int[2][4]; //arr is array of 2 rows & 4 cols
System.out.println();
Compile time initialization of 1D array-
}
int[][]arr={{10,20},{30,40},{50,60},{70,80}};
//Loop will display array elements in tabular form
Static members
static variable-
Shared among all objects of class & accessible by classname
static method-
Used to manipulate static data & accessible by classname
static block-
Used to initialize static members & executes before main()
Multiple static blocks are executed in the sequence they appear in program.
static import- imports the static members from a class
import static <pkg_list>.<class_name>.<member_name>;
OR
import static <pkg_list>.<class_name>.*;
Example, import static java.lang.Math.*; //This will import all static members of Math
static & non-static access
class A{
Inside class void m1(){
Static Non-static new B().m3();
B.m4();
Static Direct Through object }
static void m2(){
Non-static Direct Direct new B().m3();
B.m4();
}
Within two classes }
class B{
Static Non-static void m3(){
Static Through classname Through object }
static void m4(){
Non-static Through classname Through object }
}
Method overloading- compile time polymorphism
Overloaded methods have same name class Message{
but different parameters void sayHello(){
Differences can be either in types, count System.out.println(“Hello”);
or sequence of parameters }
void sayHello(String name){
Method overloading achieves static
System.out.println(“Hello ”+name);
binding or early binding AKA compile
}
time polymorphism or
String sayHello(char[]name){
String str=new String(name);
System.out.println(“Hello “+str);
}
}
Creating object of class
class Sample{
Object declaration & instantiation
//other class members
classname referencename;
void foo(){
referencename=new constructor([arguments]);
//statements
}
OR
}
classname referencename=new
constructor([arguments]);
Constructor method initializes the object //Creating object of Sample
Gets invoked at the time of object creation
Name must be same as its class name and no Sample s1;
explicit return type s1=new Sample();
Can be parameterized or parameterless s1.foo();
Constructor overloading- example
class Point{ Defining multiple constructors in class
int x,y; is called constructor overloading
Point(){
} Overloaded constructor have
Point(int x, int y){ different argument list
this.x=x;
this.y=y; Depending on parameters passed
} while creating object, appropriate
Point(Point pt){ constructor get invoked
x=pt.x;
y=pt.y
}
...
}
this and super keywords
this refers current class instance class Point{
variable int x,y;
this() can be used to invoke current Point(){
class constructor this(0,0);
}
this() calls current class constructor in
constructor chaining Point(int x, int y){
this.x=x;
super is a reference to immediate this.y=y;
parent class object
}
super() calls immediate parent class Point(Point pt){
constructor this(pt.x, pt.y);
}
...
}
final Keyword
final class A{
final field can not change its value, it //class members
is a constant }
final method can not be overridden
class B extends A{ //Error
final class can not be inherited
}
class A{ class A{
final float PI=3.14f; final void foo(),…-
A(){ }
class B extends A{
PI++; //Error
@Override
} void foo(),…- //Error
} }
Inheritance in Java
Creating new classes using properties of existing //Here, A is super or parent or base class
classes using extends keyword //B is sub or child or derived class
Inheritance leads to reusability and extensibility
Represents the IS-A relationship. In inheritance,
Java allows single, hierarchical & multilevel private members are not inherited
inheritences directly and multiple inheritance
directly through interfaces base class object can access its own members
whereas derived class object can access its own
class A{ and base class members
.... derived class object is instantiated by invoking
} base class constructor first
class B extends A{
....
}
Inheritance in Java- example
//Single inheritance //Multilevel inheritance //Hierarchical inheritance
class A{ class A{ class A{
//class members //class members //class members
} } }
class B extends A{ class B extends A{ class B extends A{
//class members //class members //class members
} } }
class C extends B{ class C extends A{
//class members //class mebers
} }
Association, Aggregation, Composition & Dependency
Association is a simple form of relation class B{ .... }
between two classes which establishes through
their objects class A{
Association can be one-to-one, many-to-one,
one-to-many or many-to-many B b; //Aggregation
Dependency is a weaker form of relationship }
and in code terms indicates that a class uses
another by parameter or return type
Aggregation & Composition represent HAS-A class A{
AKA PART-OF relationship
Aggregation implies a relationship where the class B{ //Composition
child can exist independently of the parent ...
Composition implies a relationship where the
child cannot exist independently of the parent }
Inheritance is IS-A relationship }
Method overriding
Subclass has the same method as declared in class A{
the super class
void foo(){
Parent class method is overridden method & //some code
child class method is overriding method
}
Dynamic polymorphism can be achieved
using this concept }
Overriding method must not be less
accessible class B extends A{
Overriding method can throw only those @Override
exceptions or their subclasses which have void foo(){
been already thrown by overridden method
//some code
Overriding method should have covariant
return type with respect to overridden }
method }
Covariant return type
The covariant return type specifies that the B’s method get() can return reference of
return type may vary in the same direction as
the subclass either A or B or any subclass A, but not
super class of A
Overriding method becomes variant w.r.t.
return type B’s method get() can have access modifier
protected or higher, but not lesser than
class A{ protected
protected A get(){return this;}
}
class B extends A{
@Override
public B get(){return this;}
}
Runtime polymorphism in Java
Runtime polymorphism or Dynamic class A{
Method Dispatch is a process in which a void foo(){….}
call to an overridden method is resolved at void doo(){…}
runtime rather than compile-time }
class B extends A{
In this process, an overridden method is @Override
called through the reference variable of a void foo(){…}
superclass void koo(){…}
The determination of the method to be }
called is based on the object being referred A a=new B();
to by the reference variable a.foo(); //B’s foo() invokes
a.doo();
a.koo(); //Error
B b=(B)a; //a down-casted to b
b.foo(); //B’s foo() invokes
b.koo();
Object casting
When reference variable of Parent class refers to the object of Child class, it is known as
upcasting.
class A{}
class B extends A{}
A a=new B(); //upcasting
Let us consider another example:
class Sample{
Object getObject(Object obj){return obj;}
}
Sample sample=new Sample();
Integer i=new Integer(100);
Integer j=(Integer)sample.getObject(i);
//Here, i is being upcasted to Object & return value is being downcasted to Integer.
Static binding
Connecting a method call to the method body is known as binding
Two types of binding- static or early binding and dynamic or late binding
In static binding object is determined at compile time by the compiler
If there is any private, final or static method in a class then there is static binding
class Dog{
private void eat(){
System.out.println("dog is eating...");
}
public static void main(String args[]){
Dog dog=new Dog();
dog.eat();
}
}
Dynamic binding
When type of the object is determined at run-time, it is known as dynamic binding.
class Animal{
void eat(){
System.out.println("animal is eating...");
}
}
class Dog extends Animal{
@Override
void eat(){
System.out.println("dog is eating...");
}
public static void main(String args[]){
Animal a=new Dog();
a.eat();
}
}
In the above example object type cannot be determined by the compiler, because the instance of Dog is also an instance of Animal, so
compiler doesn't know its type, only its base type.
instanceof operator
It is a boolean operator used to test whether the object is an instance of the specified type
Applying instanceof operator with any variable that has null value, returns false.
class Employee{...}
class Manager extends Employee{...}
Employee emp1=new Employee(); //emp1 instanceof Employee will return true
Employee emp2=new Manager(); //emp2 instanceof Manager will return true
Manager emp3=new Manager(); //emp3 instanceof Manager will return true
public final void wait(long timeout)throws causes the current thread to wait for the specified milliseconds, until another thread notifies
InterruptedException (invokes notify() or notifyAll() method).
public final void wait(long timeout,int causes the current thread to wait for the specified milliseconds and nanoseconds, until
nanos)throws InterruptedException another thread notifies (invokes notify() or notifyAll() method).
public final void wait()throws causes the current thread to wait, until another thread notifies (invokes notify() or
InterruptedException notifyAll() method).
protected void finalize()throws Throwable is invoked by the garbage collector before object is being garbage collected.
Object cloning class Student implements Cloneable{
Cloning is way to create exact copy of an object int rollno;
Types of cloning- deep cloning and shallow cloning String name;
For deep cloning, clone() method of Object class is Student(int rollno,String name){
used this.rollno=rollno; this.name=name; }
The Java.lang.Cloneable marker interface must be public Object clone()throws
implemented by the class whose object clone we CloneNotSupportedException{ return super.clone();}
want to create
public static void main(String args[]){
If we don't implement Cloneable interface, clone() try{
method generates CloneNotSupportedException
Student s1=new Student(101,"amit");
protected Object clone() throws
CloneNotSupportedException Student s2=(Student)s1.clone();
System.out.println(s1.rollno+" "+s1.name);
clone() method saves the extra processing task for
creating the exact copy of an object System.out.println(s2.rollno+" "+s2.name);
If we perform it by using the new keyword, it will }catch(CloneNotSupportedException c){}
take a lot of processing to be performed that is }
why we use object cloning
}
Wrapper classes
Wrapper classes are object counter part of
primitives Primitive Type Wrapper class
Wrapper class in Java provides the mechanism boolean Boolean
to convert primitive into object and object into
primitive char Character
Since J2SE 5.0, auto-boxing and auto-unboxing
feature converts primitive into object and byte Byte
object into primitive automatically
short Short
All the wrapper classes are final
Except Boolean and Character others are int Integer
subclasses of an abstract class Number
long Long
All of the wrapper classes except Character
provide two constructors- one that takes a float Float
primitive of the type being constructed, and
one that takes a String representation of the double Double
type being constructed
Wrapper classes- features
//Wapper class methods
//boxing and unboxing Boolean wboo = new Boolean("false");
int a=20; Boolean yboo=new Boolean(false);
Byte wbyte = new Byte("2");
Integer Byte ybyte=new Byte(2);
i=Integer.valueOf(a);//boxing Short wshort = new Short("4");
Integer j=a;//autoboxing Short yshort = new Short(4);
Integer wint = new Integer("16");
Integer yint = new Integer(16);
Integer a=new Integer(3); Long wlong = new Long("123");
Long ylong = new Long(123);
int i=a.intValue();//unboxing Float wfloat = new Float("12.34f");
int j=a;//autounboxing Float yfloat = new Float(12.34f);
Double wdouble = new Double("12.56d");
Double wdouble = new Double(12.56d);
Character c1 = new Character('c');
Wrapper classes
Wrapper class static method valueOf() returns object same as an argument
Method takes a String representation of the appropriate type of primitive as their first
argument, the second method (optional) takes an additional argument indicates base
Integer i2 = Integer.valueOf("101011", 2);
The valueOf(…) method in the Character class accepts only char as an argument, other
wrapper class accept primitive type or String argument
The valueOf(…) method in the integer number wrapper classes (Byte, Short, Integer, and
Long) also accepts two arguments together: a String and a radix, where radix is the base
To perform a quick operation on value such as converting the type, using an appropriate
static method of the appropriate wrapper class
String s = "123";
int i = Integer.parseInt(s);
Methods to convert String to primitive types
Boolean--> static boolean parseBoolean(…)--> String
Character--> Not Available
Byte static byte parseByte(…)--> String, or String and radix
Short--> static short parseShort(…)--> String, or String and radix
Integer--> static int parseInt(…)--> String, or String and radix
Long--> static long parseLong(…)--> String, or String and radix
Float--> static float parseFloat(…)--> String
Double--> static double parseDouble(…)--> double or String
parseXxx() and valueOf()
Both parseXxx() and valueOf() take a String as an argument, throw a
NumberFormatException if the String argument is not properly formed, and
can convert String objects from different bases (radix), when the underlying
primitive type is any of the four integer types
parseXxx() returns the named primitive
valueOf() returns a newly created wrapped object of the type that invoked the
method
double d = Double.parseDouble("3.14"); // will convert a String to a primitive
System.out.println("d = " + d); // will display d = 3.14
Double d = Double.valueOf("3.14"); // will create a Double object
System.out.println(d instanceof Double ); //will display true
More features
//strictfp keyword
//Call by value and Call by reference Java strictfp keyword ensures that floating-point
There is only call by value in Java, not call operations get the same result on every
by reference platform
The precision may differ from platform to
If we call a method passing a value, it is platform
known as call by value strictfp keyword gets same result on every
The changes being done in the called platform
method, is not affected in the calling This keyword can be applied on methods,
method classes and interfaces
Even when we pass object, that uses call strictfp class A{}
by value concept strictfp interface M{}
To demonstrate call by reference, we can class A{
use array of objects strictfp void m(){}
}
Command line arguments
The arguments passed from the terminal public class Demo{
window before runtime can be received in public static void main(String[]args){
the Java program and it can be used as an
int i=0;
input
for(;i<args.length;i++){
These are accepted in String array
argument of main() function System.out.println(args[i]);
Command line array has no fixed size }
}
}
//javac Demo.java
//java hello 1234 !@#$
Java String
String is a sequence of characters or array of characters
Java String class provides a lot of methods to perform operations on string such as
compare(), concat(), equals(), split(), length(), replace(), compareTo(), substring() etc.
There are two ways to create String object-using string literal and using new keyword,
example
char[]ch={'h','e','l','l','o'};
String s=new String(ch);
String s="hello";
String implements Serializable, Comparable and CharSequence interfaces
String class creates immutable string
String objects are stored in a special memory area known as string constant pool
Each time string literal is created, the JVM checks the string constant pool first
If the string already exists in the pool, a reference to the pooled instance is returned
If string doesn't exist in the pool, a new string instance is created and placed in the pool
Creating String with new keyword
String message=new String("Hello");
Above statement creates two objects and one reference variable
Here JVM will create a new string object in normal(non pool) heap memory and the literal
"Hello" will be placed in the string constant pool
The variable message will refer to the object in heap(non pool)
Because String objects are immutable, every time we perform operation on String, the result
has to be stored in same String object
String message="Hello";
message.concat("World"); //Will not make message="Hello World";
message=message.concat("World"); // Will make message to change its contents
String compare by equals() method
There are three ways to compare string in Java-
equals() method
= = operator
compareTo() method
equals(Object another) compares this string to the specified object
equalsIgnoreCase(String another) compares this String to another string, ignoring case
The compareTo() method compares values lexicographically and returns an integer value
that describes if first string is less than, equal to or greater than second string
String s1=“abcd"; String s2=“abcd"; String s3=“abcd";
System.out.println(s1.compareTo(s2));//0
System.out.println(s1.compareTo(s3));//1(because s1>s3)
System.out.println(s3.compareTo(s1));//-1(because s3 < s1)
String concatenation
There are two ways to concat string in Java- using + operator, concat() method
String str="Hello"; str=str+"World";
The Java compiler transforms above code to this:
String str=(new StringBuilder()).append("Hello").append("World").toString();
In Java, String concatenation is implemented through the StringBuilder or StringBuffer class and its
append method
String concatenation operator produces a new string by appending the second operand onto the end of
the first operand
The string concatenation operator can concatenate not only string but primitive values also
concat() method concatenates the specified string to the end of current string
concat() method if called on null String reference variable, will throw NullPointerException; while this is
not the case with + operator
concat() takes only one argument while + can take any number of arguments
concat() only takes String type as argument. If any other type of argument is passed to concat() it will
give compile time error
At least one argument of + must be of string type otherwise + will behave like mathematical addition
operator instead of string concatenation operator
More on String
//Garbage collection for String //StringBuffer and StringBuilder classes
String literals are never eligible for StringBuffer class is used to create
Garbage Collection, because it is literal mutable string
and not object The StringBuffer class in Java is same as
String literals always have a reference to String class except it is mutable
them from the String Literal Pool StringBuffer class is thread-safe
That means that they always have a StringBuilder class is used to create
reference to them and are, therefore, not mutable string.
eligible for garbage collection
StringBuilder class is non-synchronized.
But there may be some String Object
which don’t have any reference then they StringBuilder is faster than StringBuffer
will be eligible for garbage collection StringBuilder added in jdk5; StringBuffer is
older than StringBuilder
String, StringBuffer & StringBuilder at a glance
String StringBuffer StringBuilder
boolean test whether the regular expression matches static Pattern compiles the given regex and return the
matches() the pattern. compile(String regex) instance of pattern.
HashMap contains values based on the key TreeMap implements the Map interface by using a
tree
Contains only unique elements
Provides an efficient means of storing key/value
May have one null key and multiple null values pairs in sorted order
It maintains no order TreeMap contains values based on the key
LinkedHashMap class is Hash table and Linked list It implements the NavigableMap interface and
implementation of the Map interface, with extends AbstractMap class
predictable iteration order
It contains only unique elements
Inherits HashMap class and implements the Map
interface It cannot have null key but can have multiple null
values
LinkedHashMap contains values based on the key
It is same as HashMap instead maintains
It contains only unique elements ascending order
It may have one null key and multiple null values
Hashtable , Properties class & Iterator interface
Hashtable class implements a hashtable which maps keys to values
Inherits Dictionary class and implements the Map interface
Hashtable contains values based on the key
It contains only unique elements
It must not have any null key or value
It is synchronized
Properties object contains key and value pair both as a string
It is subclass of Hashtable
Iterator is used for iterating over the collection classes
Methods, hasNext(), next(), remove()
ListIterator that allows us to traverse the list in both directions
Methods, next(), hasNext(), previous(), hasPrevious(), remove()
More collections
//EnumSet & EnumMap classes //SortedSet & SortedMap classes
EnumSet class is the specialized Set SortedSet interface extends Set and declares
implementation for use with enum the behavior of a set sorted in an ascending
types order
EnumMap class is the specialized Map Implemeted by TreeSet
implementation for enum keys SortedMap interface extends Map and declares
It inherits Enum and AbstractMap the behavior of a map sorted in an ascending
classes order
Implemeted by TreeMap
More collections
//NavigableSet & NavigableMap //Comparable & Comparator interfaces
interfaces Comparable inteface is used to order the
NavigableSet is a sub interface of the objects of user-defined class
SortedSet interface Found in java.lang package & contains only one
method compareTo(Object).
Provides navigation methods and
descending iterator Comparator interface is used to order the
objects of user-defined class
NavigableMap is sub interface of Found in java.util package and contains
SortedMap interface
methods compare(Object obj1,Object obj2)
Provides navigation methods and and equals(Object element)
descending views similar to
NavigableSet
Multithreading
Process of executing multiple threads
simultaneously
Thread is basically a lightweight sub-
process, a smallest unit of processing
Multiprocessing and multithreading, both
are used to achieve multitasking
Supports multiple things to be carried out
at once
Programs can be splited into small pieces;
threads and can be executed parallely
Improved system performance
Simultaneous access to multiple
applications
Thread lifecycle
Thread begins its life cycle in the new state
Remains in this state until the start() method is called on it
After invocation of start() method on new thread, the thread becomes runnable
Thread is in running state if the thread scheduler has selected it
Thread is in waiting state if it waits for another thread to perform a task
Thread enters the terminated state when it complete its task is killed
Two ways to create, implementing java.lang.Runnable and extending java.lang.Thread
To call the run() method, start() method is used
On calling start(), a new stack is provided to the thread and run() method is called to
introduce the new thread into the program
Thread methods
void run() is used to perform action for a thread
void start() starts the execution of the thread, JVM calls the run() method on the
thread
public void sleep(long miliseconds) causes the currently executing thread to sleep for
the specified number of milliseconds
void join() waits for a thread to die
void join(long miliseconds) waits for a thread to die for the specified miliseconds
int getPriority() returns the priority of the thread
int setPriority(int priority) changes the priority of the thread
String getName() returns the name of the thread
void setName(String name) changes the name of the thread
Thread currentThread() returns the reference of currently executing thread
int getId() returns the id of the thread
Thread methods
boolean isAlive() tests if the thread is alive
void yield() causes the currently executing thread object to temporarily pause
and allow other threads to execute
void suspend() is used to suspend the thread
void resume() is used to resume the suspended thread
void stop() is used to stop the thread
boolean isDaemon() tests if the thread is a daemon thread
void setDaemon(boolean b) marks the thread as daemon or user thread
void interrupt() interrupts the thread
boolean isInterrupted() tests if the thread has been interrupted
static boolean interrupted() tests if the current thread has been interrupted
Thread scheduling
Execution of multiple threads on a single CPU in some order is called scheduling
If a high-priority thread wakes up, and a low-priority thread is running then the
high-priority thread gets to run immediately
Allows on-demand processing
Under preemptive scheduling, the highest priority task executes until it enters
the waiting or dead states or a higher priority task comes into existence
Under time slicing, a task executes for a predefined slice of time and then
reenters the pool of ready tasks
The scheduler then determines which task should execute next, based on
priority and other factors
More on Thread
//Thread priority //Deamon thread
Three constants defined in Thread Daemon thread in java is a service
class: provider thread that provides services
to the user thread
public static int MIN_PRIORITY
public static int NORM_PRIORITY Its life depend on the mercy of user
threads , when all the user threads
public static int MAX_PRIORITY dies, JVM terminates this thread
Default priority of a thread is 5 automatically
(NORM_PRIORITY). The value of Examples, gc, finalizer etc
MIN_PRIORITY is 1 and the value of
MAX_PRIORITY is 10 Methods, void setDaemon(boolean) &
boolean isDaemon()
Thread synchronization & inter-thread communication
Synchronization in java is the capability to control the access of multiple threads to any shared
resource
Java Synchronization is better option where one thread to access the shared resource
Two types of thread synchronization, mutual exclusion and inter-thread communication.
Mutual Exclusion
Synchronized method
Synchronized block
static synchronization
Inter-thread communication in java
wait(), notify(), notifyAll() provide means of communication between threads that synchronize
on the same object
yield() is used to give the other threads of the same priority a chance to execute i.e. causes
current running thread to move to runnable state
sleep() is used to pause a thread for a specified period of time i.e. moves the current running
thread to Sleep state for a specified amount of time, before moving it to runnable state
Inner classes
Type Description
Member class A class created within class and outside method.