Core Java Notes
Complete Syllabus — Tokens to Collections
Every topic from your syllabus • Detailed explanations • Real code examples
Top Interview Q&A • Beginner Friendly Language
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Table of Contents
PART A — JAVA BASICS
1. Tokens
2. Keywords
3. Identifiers
4. Data Types
5. Primitive Types
6. Casting
PART B — OBJECT ORIENTED PROGRAMMING
7. Classes & Objects
8. New Keyword
9. Variables
10. Methods
11. Memory Structure (Stack & Heap)
12. Static and Non-Static Members
13. Variable Shadowing
14. this Keyword
15. Constructors
16. Inheritance
17. super Keyword | this and super
18. Non-Primitive Types
19. Type Casting — Upcasting & Downcasting
20. Polymorphism
21. Variable Hiding
22. Method Overloading & Overriding
23. Encapsulation
24. Abstraction
25. Abstract Class
26. Interface
27. Has-A Relationship
28. Packages
29. Access Modifiers
30. final Keyword
31. Singleton Class
32. Immutable Class
33. Object Class
34. Wrapper Class
PART C — JAVA FEATURES
Core Java Notes | Detailed Study Guide Page 2
Core Java Notes — Complete Syllabus Beginner to Interview Ready
35. Lambda Expressions
36. Stream API
37. Time & Date API
PART D — EXCEPTION HANDLING
38. try, catch, finally, throw, throws
PART E — FILE HANDLING
39. File Handling
PART F — MULTITHREADING
40. Multithreading
PART G — COLLECTIONS FRAMEWORK
41. Collection Framework
PART H — INTERVIEW Q&A;
42. Top Java Interview Questions & Answers
Core Java Notes | Detailed Study Guide Page 3
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part A — Java Basics
1. Tokens
A token is the smallest individual unit in a Java program that the compiler can understand. When the Java
compiler reads your source code, it first breaks it into tokens — just like how we break a sentence into
individual words. Every single thing you write in Java belongs to one of the following five token categories.
Token Type Description Example
Keywords Reserved words with a fixed meaning int, class, if, return
Identifiers Names given by the programmer myVariable, Car, calculateArea
Literals Fixed, constant values in code 42, 3.14, 'A', "Hello", true
Operators Symbols that perform operations +, -, *, /, ==, &&
Separators Symbols that separate code structures {}()[];,
public class TokenDemo { // 'public','class' = Keywords public static void main(String[]
args) { int number = 42; // 'int' Keyword | 'number' Identifier | '42' Literal int result
= number + 10; // '+' Operator | ';' Separator [Link](result); // '.'
Separator | method call } }
■ Real-world analogy: Think of a Java program like an English sentence. Tokens are the words. Just
as a sentence has nouns, verbs, and punctuation, a Java program has keywords, identifiers, operators,
literals, and separators.
2. Keywords
Keywords (also called reserved words) are words that Java has already assigned a special meaning. You
cannot use them as variable names, class names, or method names. Java has 53 reserved keywords
(including some reserved but unused ones). Here are the most important ones grouped by category:
Category Keywords
Data Type Keywords byte, short, int, long, float, double, char, boolean, void
Access Modifiers public, private, protected
Class & Object class, interface, extends, implements, abstract, new, this, super, instanceof
Control Flow if, else, switch, case, default, for, while, do, break, continue, return
Exception Handling try, catch, finally, throw, throws
Others static, final, synchronized, volatile, transient, import, package, enum, assert
Core Java Notes | Detailed Study Guide Page 4
Core Java Notes — Complete Syllabus Beginner to Interview Ready
■ Important: Keywords are always written in lowercase. Java is case-sensitive, so 'Int' is NOT a
keyword — only 'int' is. Also, true, false, and null are technically literals, not keywords, but they are
also reserved — you cannot use them as identifiers.
3. Identifiers
An identifier is a name that you (the programmer) give to something in your code — like a variable, a
class, a method, or an interface. Java has strict rules about what makes a valid identifier.
Rules for Identifiers:
• Can contain letters (a–z, A–Z), digits (0–9), underscore (_), and dollar sign ($)
• Cannot start with a digit — '2name' is invalid, 'name2' is valid
• Cannot be a keyword — 'int' as a variable name is illegal
• Cannot contain spaces or special characters like @, #, !, etc.
• Java identifiers are case-sensitive — 'Age', 'age', and 'AGE' are three different identifiers
• There is no limit on identifier length
// Valid identifiers int age; double _salary; String firstName; boolean isStudent; int
$count; int myVariable123; // Invalid identifiers int 2name; // ■ starts with digit int
my name; // ■ space not allowed int class; // ■ 'class' is a keyword int my@value; // ■
special character
Naming Conventions (Best Practices):
What Convention Example
Variables & Methods camelCase — start lowercase studentAge, calculateArea()
Classes & Interfaces PascalCase — start uppercase StudentDetails, Runnable
Constants (final) ALL_CAPS with underscore MAX_SIZE, PI_VALUE
Packages all lowercase [Link]
4. Data Types
A data type tells Java what kind of value a variable can hold and how much memory to allocate for it. Java
is a strongly typed language — every variable must have a declared type before it can be used. Java's
data types are divided into two broad categories:
• Primitive Data Types — 8 built-in types that store simple values directly in memory
• Non-Primitive (Reference) Types — Objects, Arrays, Strings — store a reference (memory address)
to data
5. Primitive Types
There are exactly 8 primitive data types in Java. They are not objects — they store their value directly in
the variable's memory location (stack memory).
Type Size Default Min Value Max Value Use For
Core Java Notes | Detailed Study Guide Page 5
Core Java Notes — Complete Syllabus Beginner to Interview Ready
byte 1 byte 0 -128 127 Saving memory in large arrays
short 2 bytes 0 -32,768 32,767 Medium whole numbers
int 4 bytes 0 -2.1 billion 2.1 billion Most whole numbers (default)
long 8 bytes 0L Very large Very large Huge numbers, timestamps
float 4 bytes 0.0f ~1.4E-45 ~3.4E+38 Decimal (less precise), add 'f'
double 8 bytes 0.0 ~5E-324 ~1.8E+308 Decimal (precise, default)
char 2 bytes '\u0000' 0 65535 Single Unicode character
boolean 1 bit false — — true/false conditions
// Declaring and initialising each primitive byte b = 100; short sh = 30000; int i =
1000000; long l = 9999999999L; // note the 'L' suffix float f = 3.14f; // note the 'f'
suffix double d = 3.14159265358; char c = 'A'; // single quotes for char boolean flag =
true; // Printing their values [Link]("byte: " + b);
[Link]("char: " + c); // prints: A [Link]("boolean: " + flag); //
prints: true
■ Memory tip: When in doubt, use int for whole numbers and double for decimals — they are the
default and most commonly used primitive types in Java.
6. Casting (Primitive Type Conversion)
Type casting means converting a value from one data type to another. This is necessary because you
sometimes need to use a value of one type where another is expected.
Widening Casting (Implicit / Automatic)
Widening means converting from a smaller type to a larger type. Java does this automatically — no
extra code needed. No data is lost because the larger type can hold everything the smaller type can.
Order of widening: byte → short → int → long → float → double
int myInt = 9; double myDouble = myInt; // automatic — int promoted to double
[Link](myDouble); // 9.0 (no data loss) long bigNum = 100L; float floatVal =
bigNum; // long → float, automatic [Link](floatVal); // 100.0
Narrowing Casting (Explicit / Manual)
Narrowing means converting from a larger type to a smaller type. You must tell Java explicitly using the
(type) syntax. Data may be lost — the extra bits are simply cut off. The decimal portion is dropped (NOT
rounded).
double price = 9.99; int intPrice = (int) price; // explicit cast required
[Link](intPrice); // 9 (NOT 10 — decimal dropped) long bigValue =
12345678901L; int small = (int) bigValue; // possible data loss — overflow!
[Link](small); // unpredictable result // Char and int interplay char letter
= 'A'; int ascii = letter; // widening: char → int [Link](ascii); // 65
(ASCII value of 'A') int num = 66; char ch = (char) num; // narrowing: int → char
[Link](ch); // B
Core Java Notes | Detailed Study Guide Page 6
Core Java Notes — Complete Syllabus Beginner to Interview Ready
■ Warning: Never narrow a large value into a small type without checking whether the value fits. For
example, casting 300 to byte gives -56, not 300, because byte can only hold -128 to 127.
Core Java Notes | Detailed Study Guide Page 7
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part B — Object Oriented Programming (OOP)
7. Classes and Objects
Java is an Object-Oriented language. Everything in Java revolves around classes and objects.
Understanding these two concepts is the foundation of all Java programming.
What is a Class?
A class is a blueprint or template that defines the properties (attributes) and behaviours (methods) that
objects of that type will have. A class itself does not occupy memory for the data — it just defines the
structure. Think of a class like an architectural drawing: you can build many houses from one drawing.
What is an Object?
An object is a real-world instance created from a class. When you create an object, Java allocates
memory for it and assigns initial values. Every object has: State (values of its attributes) and Behaviour
(what its methods do). A class can have unlimited objects.
// CLASS — the blueprint public class Student { // Attributes (fields / instance
variables) String name; int age; double marks; // Behaviour (methods) void study() {
[Link](name + " is studying."); } void displayInfo() {
[Link]("Name: " + name + ", Age: " + age + ", Marks: " + marks); } } // MAIN
CLASS — creating and using objects public class Main { public static void main(String[]
args) { // Creating Object 1 Student s1 = new Student(); [Link] = "Alice"; [Link] = 20;
[Link] = 92.5; [Link](); // Name: Alice, Age: 20, Marks: 92.5 [Link](); //
Alice is studying. // Creating Object 2 — same class, different data Student s2 = new
Student(); [Link] = "Bob"; [Link] = 22; [Link] = 78.0; [Link](); // Name: Bob,
Age: 22, Marks: 78.0 } }
■ Key point: s1 and s2 are two different objects made from the same Student class. They share the
same structure (name, age, marks) but hold completely independent data. Changing [Link] does
NOT affect [Link].
8. The 'new' Keyword
The new keyword is used to create (instantiate) an object from a class. When you write new
ClassName(), Java does three things automatically:
• Allocates memory in the heap for the new object
• Initialises all instance variables to their default values (0, null, false)
• Calls the constructor to set up the object
// Syntax: ClassName variableName = new ClassName(); Car myCar = new Car(); // ^^^ ^^^ //
Reference 'new' allocates heap memory + calls constructor // The variable 'myCar' is
stored in STACK memory // The actual Car object data lives in HEAP memory // 'myCar'
holds the memory address (reference) of the heap object // Multiple references to the
same object Car anotherRef = myCar; // both point to the SAME object [Link] =
200; [Link]([Link]); // 200 — same object!
Core Java Notes | Detailed Study Guide Page 8
Core Java Notes — Complete Syllabus Beginner to Interview Ready
9. Variables in Java
A variable is a named memory location that stores a value. In Java, variables are categorised into three
types based on where they are declared and how long they live.
Type Where Declared Lifetime Default Value Memory
Instance Variable Inside class, outside methods As long as object exists
Yes (0/null/false) Heap
Static Variable Inside class with 'static' As long as program Yes
runs Method Area
Local Variable Inside a method or block Until method/block ends
No (must initialise) Stack
public class VariableDemo { int instanceVar = 10; // Instance variable — each object gets
its own copy static int staticVar = 100; // Static variable — ONE shared copy for all
objects void showValues() { int localVar = 50; // Local variable — only exists inside
this method [Link](instanceVar); // 10 [Link](staticVar); // 100
[Link](localVar); // 50 } // localVar is destroyed here public static void
main(String[] args) { VariableDemo obj1 = new VariableDemo(); VariableDemo obj2 = new
VariableDemo(); [Link] = 20; [Link]([Link]); // 20
[Link]([Link]); // 10 — unaffected [Link] = 999;
[Link]([Link]); // 999 — shared! [Link]([Link]);
// 999 — shared! } }
10. Methods
A method is a named block of code that performs a specific task. Methods allow you to write code once
and reuse it multiple times. Every method has a signature: access_modifier return_type
methodName(parameters)
// Method with no parameters and no return value void greet() {
[Link]("Hello!"); } // Method with parameters and a return value int add(int
a, int b) { return a + b; // 'return' sends the result back to the caller } // Method
with multiple parameters String fullName(String first, String last) { return first + " "
+ last; } // Calling methods greet(); // Hello! int sum = add(5, 3); // sum = 8 String
name = fullName("John","Doe"); // "John Doe" // Method with varargs (variable number of
arguments) int sumAll(int... nums) { int total = 0; for (int n : nums) total += n; return
total; } sumAll(1, 2, 3, 4, 5); // 15
Pass by Value vs Pass by Reference
Java is strictly pass-by-value. For primitive types, a copy of the value is passed — the original is
unchanged. For objects, the reference (address) is copied — so the method CAN change the object's
internal state, but cannot change what the variable points to.
void changeInt(int x) { x = 999; } // modifies local copy int n = 10; changeInt(n);
[Link](n); // still 10 — primitive, passed by value copy void
changeName(Student s) { [Link] = "Changed"; } // modifies the object Student st = new
Student(); [Link] = "Original"; changeName(st); [Link]([Link]); //
"Changed" — object's state changed via reference
11. Memory Structure — Stack and Heap
Understanding how Java uses memory is very important for writing efficient programs and for debugging.
Java divides memory primarily into two areas: Stack and Heap.
Core Java Notes | Detailed Study Guide Page 9
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Feature Stack Memory Heap Memory
What is stored Local variables, method call frames, references
Objects, instance variables
Memory management Automatic (LIFO — Last In First Out) Managed by Garbage Collector
Access speed Very fast Slightly slower
Size Smaller Much larger
Thread safety Each thread has its own stack Shared among all threads
Lifetime Until method returns Until garbage collected
Error when full StackOverflowError OutOfMemoryError
public void calculate() { int x = 5; // 'x' goes on the STACK int y = 10; // 'y' goes on
the STACK Student s = new Student(); // reference 's' on STACK // actual Student object
on HEAP [Link] = "Alice"; // name stored in HEAP (inside object) } // When calculate()
ends: x, y, s are removed from stack // Student object stays in HEAP until no references
point to it // Garbage Collector eventually removes it from HEAP
■ Key insight: The variable (reference) lives on the Stack. The object it points to lives on the Heap.
Primitives (int, double, etc.) always live on the Stack. String literals are stored in a special 'String Pool'
inside the Heap.
12. Static and Non-Static Members
The static keyword is one of the most important in Java. When you mark something as static, it belongs to
the class itself, not to any particular object.
Static Members:
• Static variables: ONE copy shared across ALL objects of the class
• Static methods: Can be called without creating an object — [Link]()
• Static blocks: Run once when the class is first loaded into memory
• Static members CANNOT access non-static (instance) members directly
Non-Static (Instance) Members:
• Each object gets its OWN separate copy of instance variables
• Instance methods can access both static and non-static members
• Must create an object to access them
public class BankAccount { static int totalAccounts = 0; // shared — how many accounts
exist int balance; // per-object — each account has own balance String owner; static { //
static block — runs once on class load [Link]("BankAccount class loaded"); }
BankAccount(String owner, int balance) { [Link] = owner; [Link] = balance;
totalAccounts++; // update shared counter } static void showTotal() { // static method —
no object needed [Link]("Total accounts: " + totalAccounts); } void
showBalance() { // instance method — needs an object [Link](owner + "'s
balance: " + balance); } } // Usage BankAccount a1 = new BankAccount("Alice", 5000);
BankAccount a2 = new BankAccount("Bob", 3000); [Link](); // Total
accounts: 2 (called on class, not object) [Link](); // Alice's balance: 5000
Core Java Notes | Detailed Study Guide Page 10
Core Java Notes — Complete Syllabus Beginner to Interview Ready
[Link](); // Bob's balance: 3000
13. Variable Shadowing
Variable shadowing occurs when a local variable (inside a method or block) has the same name as an
instance variable. The local variable 'shadows' (hides) the instance variable within that scope. To access
the instance variable when shadowing occurs, you must use the this keyword.
public class Person { String name = "Instance Name"; // instance variable void
setName(String name) { // parameter 'name' shadows instance variable // Inside this
method, 'name' refers to the PARAMETER (local), not instance variable
[Link](name); // prints: Alice (the parameter) [Link]([Link]);
// prints: Instance Name (the instance variable) [Link] = name; // correct way to
assign parameter to instance var } public static void main(String[] args) { Person p =
new Person(); [Link]("Alice"); [Link]([Link]); // Alice — now updated
correctly } }
■ Best practice: Always use [Link] when a constructor or method parameter has the
same name as an instance variable. This avoids confusion and bugs.
14. The 'this' Keyword
The this keyword refers to the current object — the instance of the class on which the method or
constructor is being called. It has four main uses:
Use Case Description
[Link] Distinguish instance variable from local/parameter with same name
[Link]() Call another method of the same class from within a method
this(...) Call another constructor of the same class (constructor chaining)
return this Return the current object (used in method chaining / builder pattern)
public class Rectangle { double width, height; // Use 1: [Link] to resolve
shadowing Rectangle(double width, double height) { [Link] = width; // '[Link]' =
instance var, 'width' = parameter [Link] = height; } // Use 2: this() — constructor
chaining Rectangle() { this(1.0, 1.0); // calls the two-arg constructor above } // Use 3:
calling own method double area() { return [Link] * [Link]; // 'this.' optional
here, but explicit } // Use 4: return this (method chaining) Rectangle setWidth(double w)
{ [Link] = w; return this; // return current object } Rectangle setHeight(double h) {
[Link] = h; return this; } } // Method chaining thanks to 'return this' Rectangle r
= new Rectangle().setWidth(5).setHeight(3); [Link]([Link]()); // 15.0
15. Constructors
A constructor is a special method that is automatically called when an object is created using the new
keyword. Its job is to initialise the object's state (set initial values for its fields).
Rules for Constructors:
• Constructor name must be exactly the same as the class name
Core Java Notes | Detailed Study Guide Page 11
Core Java Notes — Complete Syllabus Beginner to Interview Ready
• Constructors have no return type — not even void
• A class can have multiple constructors (constructor overloading)
• If you don't write any constructor, Java provides a default no-arg constructor automatically
• If you write ANY constructor, Java no longer provides the default one
public class Employee { String name; int id; double salary; // 1. Default constructor (no
arguments) Employee() { name = "Unknown"; id = 0; salary = 0.0;
[Link]("Default constructor called"); } // 2. Parameterised constructor
Employee(String name, int id, double salary) { [Link] = name; [Link] = id;
[Link] = salary; } // 3. Copy constructor — creates a new object from an existing
one Employee(Employee other) { [Link] = [Link]; [Link] = [Link]; [Link] =
[Link]; } void display() { [Link]("ID: " + id + ", Name: " + name + ",
Salary: " + salary); } } // Usage Employee e1 = new Employee(); // calls default
constructor Employee e2 = new Employee("Alice", 101, 75000.0); // parameterised Employee
e3 = new Employee(e2); // copy constructor [Link](); // ID: 0, Name: Unknown, Salary:
0.0 [Link](); // ID: 101, Name: Alice, Salary: 75000.0 [Link](); // ID: 101,
Name: Alice, Salary: 75000.0 (independent copy)
16. Inheritance
Inheritance is the mechanism by which a child (sub) class acquires the properties and behaviours of a
parent (super) class. It promotes code reuse and establishes an IS-A relationship. In Java, inheritance
is achieved using the extends keyword. Java supports only single inheritance for classes (one parent
only), but multiple inheritance through interfaces.
Types of Inheritance in Java:
Type Description Support in Java
Single One child extends one parent YES
Multilevel A extends B, B extends C (chain) YES
Hierarchical Multiple children extend one parent YES
Multiple (class) One child extends two parents NO — use interfaces instead
Hybrid Combination of the above Partially — via interfaces
// Parent class public class Vehicle { String brand; int speed; Vehicle(String brand, int
speed) { [Link] = brand; [Link] = speed; } void start() {
[Link](brand + " started"); } void stop() { [Link](brand + "
stopped"); } } // Child class — inherits Vehicle public class Car extends Vehicle { int
doors; Car(String brand, int speed, int doors) { super(brand, speed); // calls parent
constructor [Link] = doors; } void honk() { [Link](brand + " goes beep
beep!"); } } // Grandchild — multilevel public class ElectricCar extends Car { int
batteryCapacity; ElectricCar(String brand, int speed, int doors, int battery) {
super(brand, speed, doors); [Link] = battery; } void charge() {
[Link](brand + " charging..."); } } // Usage ElectricCar ec = new
ElectricCar("Tesla", 250, 4, 100); [Link](); // inherited from Vehicle [Link](); //
inherited from Car [Link](); // own method
Core Java Notes | Detailed Study Guide Page 12
Core Java Notes — Complete Syllabus Beginner to Interview Ready
■ Key insight: A child class inherits all non-private members of the parent. Private members exist in
the parent but are not directly accessible by the child. Constructors are NOT inherited — but can be
called using super().
17. super Keyword | this and super
The super keyword refers to the parent class of the current class. It is used inside child classes to access
parent class members that have been hidden or overridden.
Feature this super
Refers to Current object Parent class
Access variables [Link] (resolve shadowing) [Link] (hidden parent var)
Call method [Link]() [Link]() (call overridden version)
Call constructor this(...) — same class constructor
super(...) — parent constructor
Where to use Instance methods and constructors
Child class methods and constructors
class Animal { String name = "Animal"; void sound() { [Link]("Some sound"); }
} class Dog extends Animal { String name = "Dog"; // hides parent's 'name' void show() {
[Link](name); // "Dog" — current class variable
[Link]([Link]); // "Animal" — parent class variable } @Override void
sound() { [Link](); // calls Animal's sound() first [Link]("Woof!"); //
then adds Dog's own sound } } class Puppy extends Dog { Puppy() { super(); // calls Dog's
constructor // MUST be the first statement if used } }
■ Rule: super() or this() must always be the FIRST statement in a constructor. You cannot use both in
the same constructor.
18. Non-Primitive Types
Non-primitive (also called reference) types are objects — they store a reference (memory address) to
data stored in the heap, not the value itself. They are created using classes and have methods you can
call on them.
• String — a sequence of characters (immutable object)
• Arrays — fixed-size collection of same-type elements
• Classes — user-defined types (Student, Car, BankAccount...)
• Interfaces — reference types defining a contract
• Enums — a set of named constants
• Wrapper classes — Integer, Double, Boolean etc. (covered later)
// Non-primitive examples String greeting = "Hello"; // refers to String object in
heap/pool int[] scores = {85, 90, 78}; // array object in heap Student s = new Student();
// custom class object // null — default value for any non-primitive String str = null;
// no object, str points to nothing // [Link](); // ■ NullPointerException — calling
method on null // Key difference from primitives: int a = 5; int b = a; b = 10;
[Link](a); // 5 — primitives are copied by value String x = "Hi"; String y =
Core Java Notes | Detailed Study Guide Page 13
Core Java Notes — Complete Syllabus Beginner to Interview Ready
x; // both x and y point to the SAME "Hi" object in the String Pool // (but String is
immutable, so this is safe)
19. Type Casting — Upcasting & Downcasting
When working with inheritance, you can cast object references between parent and child types. This is
called object type casting (not to be confused with primitive casting).
Upcasting (implicit — automatic)
Converting a child class reference to a parent class reference. Always safe. The object is still the child
— you just see it through the parent's lens. You can only access parent class members through an
upcasted reference.
Downcasting (explicit — manual)
Converting a parent class reference back to a child class reference. Must be done explicitly. Can fail at
runtime with ClassCastException if the object is not actually of the child type. Always check with
instanceof first.
class Animal { void eat() { [Link]("Animal eating"); } } class Dog extends
Animal { void bark() { [Link]("Woof!"); } } // UPCASTING — automatic Animal a
= new Dog(); // Dog object stored in Animal reference [Link](); // works — eat() is in
Animal // [Link](); // ■ error — Animal reference can't see bark() // DOWNCASTING —
manual, requires cast if (a instanceof Dog) { // always check first! Dog d = (Dog) a; //
explicit downcast [Link](); // works now — "Woof!" } // Dangerous downcast without check
Animal cat = new Animal(); // Dog d2 = (Dog) cat; // ■ ClassCastException at runtime —
cat is not a Dog
20. Polymorphism
Polymorphism means 'many forms'. In Java, it means a single entity (method or object) can behave
differently in different situations. There are two types:
Compile-time Polymorphism — Method Overloading
The compiler decides which method to call based on the method signature (name + parameters). Same
method name, different parameters in the SAME class.
public class MathUtils { // Same name, different parameter types/count int add(int a, int
b) { return a + b; } double add(double a, double b) { return a + b; } int add(int a, int
b, int c) { return a + b + c; } String add(String a, String b) { return a + b; } void
print(int x) { [Link]("int: " + x); } void print(double x) {
[Link]("double: " + x); } void print(String x) { [Link]("String:
" + x); } } // Compiler picks the right version at compile time (static binding)
Runtime Polymorphism — Method Overriding
The JVM decides which method to call at runtime based on the actual object type, not the reference type.
Child class redefines a parent class method.
class Shape { void draw() { [Link]("Drawing a shape"); } } class Circle
extends Shape { @Override void draw() { [Link]("Drawing a CIRCLE"); } } class
Rectangle extends Shape { @Override void draw() { [Link]("Drawing a
RECTANGLE"); } } // Runtime polymorphism in action Shape[] shapes = { new Circle(), new
Rectangle(), new Shape() }; for (Shape s : shapes) { [Link](); // JVM calls the ACTUAL
Core Java Notes | Detailed Study Guide Page 14
Core Java Notes — Complete Syllabus Beginner to Interview Ready
object's method at runtime } // Output: // Drawing a CIRCLE // Drawing a RECTANGLE //
Drawing a shape
21. Variable Hiding
Variable hiding is different from variable shadowing. It occurs in inheritance: when a child class declares
a variable with the same name as a variable in the parent class, the child variable hides the parent
variable. Unlike method overriding (which is dynamic/runtime), variable hiding is static — it depends on
the reference type, NOT the object type.
class Parent { String type = "Parent"; static int count = 10; // static variable } class
Child extends Parent { String type = "Child"; // hides Parent's 'type' static int count =
20; // hides Parent's 'count' } public class Main { public static void main(String[]
args) { Parent p = new Child(); // upcasting [Link]([Link]); // "Parent" ←
variable uses REFERENCE type (hiding) [Link]([Link]); // 10 ← static also
uses reference type Child c = new Child(); [Link]([Link]); // "Child"
[Link]([Link]); // 20 } } // Method overriding → runtime (object decides)
// Variable hiding → compile time (reference decides)
■ Interview tip: This distinction is very commonly asked in interviews. With methods, the runtime type
(object) decides. With variables, the compile-time type (reference) decides. This is why hiding variables
is generally considered bad practice.
Core Java Notes | Detailed Study Guide Page 15
Core Java Notes — Complete Syllabus Beginner to Interview Ready
22. Method Overloading and Method Overriding
A detailed comparison of these two key polymorphism techniques:
Feature Method Overloading Method Overriding
Also called Compile-time / Static polymorphism Runtime / Dynamic polymorphism
Where Same class Parent and child class
Method name Same Same
Parameters Must be different Must be exactly same
Return type Can be different Must be same (or covariant)
Access modifier Can be anything Cannot be more restrictive
Resolved at Compile time Runtime
@Override Not used Should always use
// Overloading — same class, different parameters class Printer { void print(int n) {
[Link]("int: " + n); } void print(double d) { [Link]("double: " +
d); } void print(String s) { [Link]("String: " + s); } } // Overriding —
child redefines parent's method class Animal { void speak() { [Link]("...");
} } class Cat extends Animal { @Override void speak() { [Link]("Meow"); } }
class Dog extends Animal { @Override void speak() { [Link]("Woof"); } } //
Runtime polymorphism Animal[] animals = { new Cat(), new Dog() }; for (Animal a :
animals) [Link](); // Meow, Woof
23. Encapsulation
Encapsulation is the process of wrapping data (fields) and the methods that operate on that data
together within a class, and hiding the internal details from the outside world. It is achieved by:
• Declaring all instance variables as private
• Providing public getter methods to read the values
• Providing public setter methods to change the values (with validation)
Benefits: Data security (control over what can be set), easier maintenance (implementation can change
without affecting code that uses the class), better testability.
public class Student { // Private — hidden from outside private String name; private int
age; private double marks; // Getter — read access public String getName() { return name;
} public int getAge() { return age; } public double getMarks() { return marks; } //
Setter — write access WITH validation public void setName(String name) { if (name != null
&& ![Link]()) [Link] = name; else [Link]("Invalid name"); } public
void setAge(int age) { if (age > 0 && age < 150) [Link] = age; else
[Link]("Invalid age"); } public void setMarks(double marks) { if (marks >= 0
&& marks <= 100) [Link] = marks; else [Link]("Marks must be 0-100"); } }
// Usage Student s = new Student(); [Link]("Alice"); [Link](-5); // "Invalid age" —
setter protects the data [Link](95.5); [Link]([Link]() + " scored " +
[Link]()); // [Link] = 200; // ■ Cannot access — private!
Core Java Notes | Detailed Study Guide Page 16
Core Java Notes — Complete Syllabus Beginner to Interview Ready
24. Abstraction
Abstraction means hiding complex implementation details and showing only the essential features to
the user. You define WHAT something does, not HOW it does it. Example: When you press a car's
accelerator, you don't need to know how fuel injection, combustion, or the gearbox works — that's
abstraction.
In Java, abstraction is achieved using abstract classes and interfaces.
Feature Abstract Class Interface
Keyword abstract class interface
Abstract methods Can have (can also have concrete)All abstract by default (pre-Java 8)
Concrete methods Yes Only default/static (Java 8+)
Variables Any type public static final (constants) only
Constructor Yes No
Multiple inheritance No — one extends only Yes — implements multiple
Use when Shared code + contract Pure contract / capability
25. Abstract Class
An abstract class is a class declared with the abstract keyword. It cannot be instantiated (you cannot
create objects of it directly). It may contain abstract methods (no body — must be implemented by
subclasses) and concrete methods (with full body). Use it when related classes share some common
behaviour but each must implement certain parts in their own way.
abstract class Shape { String color; Shape(String color) { [Link] = color; } abstract
double area(); // No body — MUST be implemented by child abstract double perimeter(); //
No body — MUST be implemented by child void describe() { // Concrete method — shared by
all shapes [Link]("This is a " + color + " shape with area: " + area()); } }
class Circle extends Shape { double radius; Circle(String color, double radius) {
super(color); [Link] = radius; } @Override double area() { return 3.14 * radius *
radius; } @Override double perimeter() { return 2 * 3.14 * radius; } } class Rectangle
extends Shape { double width, height; Rectangle(String color, double w, double h) {
super(color); [Link] = w; [Link] = h; } @Override double area() { return width *
height; } @Override double perimeter() { return 2 * (width + height); } } // Cannot do:
Shape s = new Shape(); ■ — abstract class! Circle c = new Circle("red", 5); [Link]();
// This is a red shape with area: 78.5 Rectangle r = new Rectangle("blue", 4, 6);
[Link](); // This is a blue shape with area: 24.0
26. Interface
An interface is a completely abstract reference type that defines a contract — a list of methods that
implementing classes MUST provide. It is like a legal agreement: if a class says 'implements Flyable', it
promises to implement all of Flyable's methods. Interfaces are used to achieve full abstraction and
multiple inheritance.
Core Java Notes | Detailed Study Guide Page 17
Core Java Notes — Complete Syllabus Beginner to Interview Ready
// Defining interfaces interface Flyable { void fly(); // abstract — must implement
default void land() { // Java 8+ default method — optional to override
[Link]("Landing..."); } static void rules() { // Java 8+ static — called on
interface itself [Link]("All flying objects follow aviation rules"); } }
interface Swimmable { void swim(); } // A class can implement MULTIPLE interfaces class
Duck implements Flyable, Swimmable { @Override public void fly() {
[Link]("Duck is flying"); } @Override public void swim() {
[Link]("Duck is swimming"); } // land() is not overridden — uses default } //
Interface extending interface interface Amphibious extends Flyable, Swimmable { } //
Usage Duck d = new Duck(); [Link](); // Duck is flying [Link](); // Duck is swimming
[Link](); // Landing... (default method) [Link](); // called on interface directly
// Polymorphism with interface Flyable f = new Duck(); // Upcasting [Link](); // Duck is
flying
■ Interface vs Abstract class decision: If the relationship is IS-A with shared code → use abstract
class. If the relationship is CAN-DO (capability) and unrelated classes need the same contract → use
interface.
27. Has-A Relationship (Composition & Aggregation)
We already know IS-A relationship (inheritance: 'Dog IS-A Animal'). The HAS-A relationship means one
class contains a reference to another class as one of its fields. It is achieved through composition or
aggregation.
Relationship Type Life dependency Example
IS-A Inheritance (extends) — Car IS-A Vehicle
HAS-A (Composition) Field of another class Object owns the part — if outer object
Car HAS-A
dies, inner
Engine
dies too
HAS-A (Aggregation) Field reference Weaker — inner object can exist independently
Department HAS-A Employee
// Composition — Engine cannot exist without Car (strong) class Engine { int horsepower;
Engine(int hp) { [Link] = hp; } void start() { [Link]("Engine
started"); } } class Car { String brand; Engine engine; // Car HAS-A Engine Car(String
brand, int hp) { [Link] = brand; [Link] = new Engine(hp); // Engine created
inside Car } void drive() { [Link](); // Car delegates to Engine
[Link](brand + " is moving at " + [Link] + "hp"); } } //
Aggregation — Employee exists independently of Department (weak) class Employee { String
name; Employee(String n) { name = n; } } class Department { String deptName; Employee
manager; // HAS-A but Employee exists independently Department(String name, Employee e) {
[Link] = name; [Link] = e; } } Employee emp = new Employee("Alice");
Department dept = new Department("Engineering", emp); // emp still exists even if dept
object is destroyed
28. Packages
A package is a namespace — a folder that groups related classes and interfaces. Packages prevent
naming conflicts (two classes can have the same name if they are in different packages) and provide
access protection.
Built-in Packages:
Core Java Notes | Detailed Study Guide Page 18
Core Java Notes — Complete Syllabus Beginner to Interview Ready
• [Link] — automatically imported; contains String, Math, Object, System, Integer...
• [Link] — ArrayList, HashMap, Scanner, Arrays, Collections...
• [Link] — File, FileReader, FileWriter, BufferedReader...
• [Link] — Socket, URL, HttpURLConnection...
• [Link] — Connection, Statement, ResultSet...
// Declaring a package (first line of the file) package [Link]; // Importing
a class from another package import [Link]; import [Link]; import
[Link].*; // import ALL classes from [Link] // Using fully qualified name (without
import) [Link]<String> list = new [Link]<>(); // Creating your
own package // File: com/myapp/models/[Link] package [Link]; public class
Student { public String name; } // File: com/myapp/main/[Link] package [Link];
import [Link]; public class Main { public static void main(String[]
args) { Student s = new Student(); } }
29. Access Modifiers
Access modifiers control the visibility and accessibility of classes, methods, and variables. Java has
four access levels:
Modifier Same Class Same Package Subclass (any pkg) Any Class (any pkg)
private YES NO NO NO
default (none) YES YES NO NO
protected YES YES YES NO
public YES YES YES YES
public class AccessDemo { public int publicVar = 1; // accessible everywhere protected
int protectedVar = 2; // accessible in subclasses int defaultVar = 3; // accessible in
same package private int privateVar = 4; // only in THIS class private void
privateMethod() { [Link]("private"); } public void publicMethod() {
[Link]("public"); privateMethod(); // OK — same class can call private
methods } } // In another class (different package): AccessDemo obj = new AccessDemo();
[Link] = 10; // ✓ // [Link] = 5; // ■ error — not accessible //
[Link] = 5; // ■ error — different package
■ Best practice — follow the Principle of Least Privilege: Always use the most restrictive access
level possible. Default: make everything private, expose only what is necessary via public methods.
30. The 'final' Keyword
The final keyword can be applied to variables, methods, and classes. In all cases, it means 'cannot be
changed or extended'.
Applied to Meaning
final variable Value cannot be changed after assignment (becomes a constant)
final method Method cannot be overridden in a child class
Core Java Notes | Detailed Study Guide Page 19
Core Java Notes — Complete Syllabus Beginner to Interview Ready
final class Class cannot be extended (inherited from) — e.g., String is final
// final variable final double PI = 3.14159; // PI = 3.0; // ■ cannot reassign // final
method — cannot be overridden class Vehicle { final void fuelType() {
[Link]("Uses petrol"); } } class Car extends Vehicle { // void fuelType() {
... } // ■ cannot override final method } // final class — cannot be subclassed final
class MathHelper { static int square(int n) { return n * n; } } // class BetterMath
extends MathHelper { } // ■ cannot extend final class // blank final — declared final but
initialised later (in constructor only) class Config { final String appName;
Config(String name) { [Link] = name; // OK — blank final assigned in constructor }
}
31. Singleton Class
A Singleton is a design pattern that ensures a class has only ONE instance throughout the entire life of
the application, and provides a global access point to it. Common use cases: Database connections,
Configuration managers, Logger.
How to implement Singleton:
• Make the constructor private — no one outside can call new
• Declare a static variable of the class type
• Provide a static public method (getInstance()) to get the single instance
public class DatabaseConnection { // Static variable holding the only instance private
static DatabaseConnection instance = null; private String url =
"jdbc:mysql://localhost/mydb"; private boolean connected = false; // Private constructor
— no one can call new directly private DatabaseConnection() {
[Link]("Connecting to database..."); connected = true; } // Public method to
get the one and only instance public static DatabaseConnection getInstance() { if
(instance == null) { instance = new DatabaseConnection(); // created only once } return
instance; } public void query(String sql) { [Link]("Executing: " + sql); } }
// Usage DatabaseConnection db1 = [Link](); DatabaseConnection
db2 = [Link](); [Link](db1 == db2); // true — same
object! [Link]("SELECT * FROM users"); // Thread-safe Singleton (double-checked
locking) public static synchronized DatabaseConnection getInstanceSafe() { if (instance
== null) { synchronized ([Link]) { if (instance == null) instance = new
DatabaseConnection(); } } return instance; }
32. Immutable Class
An immutable class is one whose state cannot be changed after creation. Once an object is created,
its values remain fixed forever. The most famous example is the String class in Java.
Rules to make a class immutable:
• Declare the class as final (cannot be subclassed)
• Declare all fields as private and final
• Provide only getters — no setters
• Initialise all fields through the constructor only
• If a field is a mutable object, return a deep copy from the getter
Core Java Notes | Detailed Study Guide Page 20
Core Java Notes — Complete Syllabus Beginner to Interview Ready
// Immutable class example public final class ImmutablePoint { private final double x;
private final double y; public ImmutablePoint(double x, double y) { this.x = x; this.y =
y; } public double getX() { return x; } public double getY() { return y; } // Instead of
modifying, return a NEW object public ImmutablePoint translate(double dx, double dy) {
return new ImmutablePoint(x + dx, y + dy); } @Override public String toString() { return
"(" + x + ", " + y + ")"; } } ImmutablePoint p1 = new ImmutablePoint(3.0, 4.0);
ImmutablePoint p2 = [Link](1.0, 2.0); // creates NEW point [Link](p1);
// (3.0, 4.0) — unchanged [Link](p2); // (4.0, 6.0) — new object
■ Benefits of immutable classes: Thread-safe (no synchronisation needed), can be safely shared
and cached, easier to reason about, good for use as HashMap keys.
33. The Object Class
The [Link] class is the root of the entire Java class hierarchy. Every class in Java implicitly
extends Object (if you don't extend anything, Java automatically extends Object). This means every Java
object has these methods available:
Method Signature Purpose
toString() String toString() Returns a string representation. Override this to print meaningful info.
equals() boolean equals(Object o) Checks logical equality. By default checks reference. Override for content.
hashCode() int hashCode() Returns an int hash. Must override with equals() — used in HashMap.
getClass() Class getClass() Returns runtime class of object. Useful for reflection.
clone() Object clone() Creates a copy. Must implement Cloneable interface.
finalize() void finalize() Called by GC before destroying object. Deprecated in Java 9+.
wait()/notify() void wait()/notify() Thread communication (used with synchronised blocks).
public class Person { String name; int age; Person(String name, int age) { [Link] =
name; [Link] = age; } // Override toString() — called automatically in print @Override
public String toString() { return "Person{name='" + name + "', age=" + age + "}"; } //
Override equals() — define logical equality @Override public boolean equals(Object obj) {
if (this == obj) return true; // same reference if (!(obj instanceof Person)) return
false; Person other = (Person) obj; return [Link]([Link]) && age == [Link]; }
// Override hashCode() — always override when equals() is overridden @Override public int
hashCode() { return [Link]() * 31 + age; } } Person p1 = new Person("Alice", 25);
Person p2 = new Person("Alice", 25); [Link](p1); // Person{name='Alice',
age=25} [Link]([Link](p2)); // true (same content) [Link](p1
== p2); // false (different references) [Link]([Link]().getName()); //
Person
34. Wrapper Classes
Wrapper classes are object versions of the 8 primitive types. Every primitive type has a corresponding
wrapper class in [Link]. They are needed because Collections (ArrayList, HashMap) can only store
objects, not primitives.
Core Java Notes | Detailed Study Guide Page 21
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Primitive Wrapper Class Useful Methods
byte Byte [Link](), Byte.MAX_VALUE
short Short [Link]()
int Integer [Link](), Integer.MAX_VALUE, [Link]()
long Long [Link](), Long.MAX_VALUE
float Float [Link](), [Link]()
double Double [Link](), [Link]()
char Character [Link](), [Link](), [Link]()
boolean Boolean [Link](), [Link]
Autoboxing and Unboxing
Autoboxing: Java automatically converts a primitive to its wrapper (int → Integer). Unboxing: Java
automatically converts wrapper back to primitive (Integer → int).
// Autoboxing — primitive → Wrapper (automatic) int primitiveInt = 42; Integer
wrapperInt = primitiveInt; // auto-boxed ArrayList<Integer> list = new ArrayList<>();
[Link](10); // 10 is auto-boxed to Integer(10) // Unboxing — Wrapper → primitive
(automatic) Integer wrappedVal = [Link](99); int plainVal = wrappedVal; //
auto-unboxed // Useful String conversions int num = [Link]("123"); // String →
int String s = [Link](456); // int → String String s2 = [Link](789); //
int → String // Other useful methods [Link](Integer.MAX_VALUE); //
2147483647 [Link](Integer.MIN_VALUE); // -2147483648
[Link]([Link](10)); // 1010
[Link]([Link](255)); // ff
[Link]([Link]('5')); // true
[Link]([Link]('a')); // A
Core Java Notes | Detailed Study Guide Page 22
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part C — Java Features (Java 8+)
35. Lambda Expressions
A lambda expression is a short, anonymous function — a method without a name, without a class, and
without an access modifier. Introduced in Java 8, lambdas make code shorter and more expressive,
especially when working with collections and threads. They can only be used where a functional
interface (interface with exactly ONE abstract method) is expected.
Lambda Syntax:
(parameters) → expression or (parameters) → { statements; }
// Before Java 8 — verbose anonymous class Runnable r1 = new Runnable() { @Override
public void run() { [Link]("Running thread"); } }; // Java 8+ — lambda
replaces anonymous class Runnable r2 = () -> [Link]("Running thread"); //
Lambda with parameters // Single parameter (brackets optional) [Link](name ->
[Link](name)); // Multiple parameters Comparator<Integer> comp = (a, b) -> a
- b; // Multiple statements — use curly braces Runnable r3 = () -> {
[Link]("Line 1"); [Link]("Line 2"); }; // Functional interfaces
from [Link] import [Link].*; Predicate<Integer> isEven = n -> n %
2 == 0; [Link]([Link](4)); // true Function<String, Integer> getLength =
str -> [Link](); [Link]([Link]("Hello")); // 5 Consumer<String>
printer = s -> [Link](s); [Link]("Hello Lambda"); Supplier<String>
greeter = () -> "Good Morning!"; [Link]([Link]()); // Sorting with
lambda List<String> names = [Link]("Charlie", "Alice", "Bob"); [Link]((a, b)
-> [Link](b)); [Link](names); // [Alice, Bob, Charlie] // Method
reference — even shorter [Link]([Link]::println); // :: is method reference
36. Stream API
The Stream API ([Link]) allows you to process collections of data in a functional, pipeline-style. A
stream is a sequence of elements that supports various operations. Streams are lazy (only computed
when needed) and do not modify the original collection.
Stream Pipeline = Source → Intermediate Operations → Terminal Operation
import [Link].*; import [Link].*; List<Integer> numbers = [Link](5,
3, 8, 1, 9, 2, 7, 4, 6, 10); // 1. filter() — keep elements matching condition
List<Integer> evens = [Link]() .filter(n -> n % 2 == 0)
.collect([Link]()); // [8, 2, 4, 6, 10] // 2. map() — transform each element
List<Integer> doubled = [Link]() .map(n -> n * 2) .collect([Link]());
// [10, 6, 16, 2, 18, 4, 14, 8, 12, 20] // 3. sorted() — sort elements List<Integer>
sorted = [Link]() .sorted() .collect([Link]()); // [1, 2, 3, 4, 5, 6,
7, 8, 9, 10] // 4. reduce() — combine all elements int sum = [Link]() .reduce(0,
(a, b) -> a + b); // 55 // or: .reduce(0, Integer::sum) // 5. count() — how many elements
long count = [Link]() .filter(n -> n > 5) .count(); // 5 // 6. Chaining multiple
operations List<String> result = [Link]() .filter(name -> [Link]() > 4) //
only names longer than 4 chars .map(String::toUpperCase) // convert to uppercase
.sorted() // sort alphabetically .collect([Link]()); // 7. forEach() —
terminal operation [Link]() .filter(n -> n % 2 != 0)
.forEach([Link]::println); // prints odd numbers // 8. anyMatch / allMatch /
Core Java Notes | Detailed Study Guide Page 23
Core Java Notes — Complete Syllabus Beginner to Interview Ready
noneMatch boolean hasNegative = [Link]().anyMatch(n -> n < 0); // false boolean
allPositive = [Link]().allMatch(n -> n > 0); // true // 9. min and max
Optional<Integer> max = [Link]().max(Integer::compareTo);
[Link]([Link]()); // 10
37. Time & Date API (Java 8+)
Java 8 introduced a brand new Date/Time API in [Link] package. The old Date and Calendar classes
were confusing, mutable, and not thread-safe. The new API is immutable, clear, and much easier to use.
import [Link].*; import [Link]; // LocalDate — date
without time LocalDate today = [Link](); // 2026-04-04 LocalDate birthday =
[Link](2000, 6, 15); [Link](today);
[Link]([Link]()); // SATURDAY
[Link]([Link]()); // 2026 [Link]([Link](10)); //
10 days later [Link]([Link](birthday));// false // LocalTime — time
without date LocalTime now = [Link](); // 14:30:45.123 LocalTime meeting =
[Link](9, 30); [Link]([Link]()); // current hour
[Link]([Link](2)); // 11:30 // LocalDateTime — date + time
LocalDateTime dt = [Link](); LocalDateTime dt2 = [Link](2026,
[Link], 4, 14, 30); // Period — difference in dates (years, months, days) Period age
= [Link](birthday, today); [Link]("Age: " + [Link]() + "
years"); // Duration — difference in time (hours, minutes, seconds) Duration duration =
[Link](meeting, [Link]()); [Link]("Hours since meeting: " +
[Link]()); // Formatting and Parsing DateTimeFormatter formatter =
[Link]("dd/MM/yyyy"); String formatted = [Link](formatter); //
"04/04/2026" LocalDate parsed = [Link]("15/06/2000", formatter);
Core Java Notes | Detailed Study Guide Page 24
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part D — Exception Handling
38. Exception Handling — try, catch, finally, throw, throws
An exception is an unexpected event that disrupts normal program execution (dividing by zero, accessing
null, file not found, etc.). Java provides a robust mechanism to handle exceptions gracefully so the
program does not crash abruptly.
Exception Hierarchy:
• Throwable — root of all exceptions and errors
• ■■■ Error — serious problems (StackOverflowError, OutOfMemoryError) — don't catch
• ■■■ Exception — recoverable problems
• ■■■ Checked Exceptions — must handle (IOException, SQLException)
• ■■■ Unchecked Exceptions (RuntimeException) — programming mistakes (NPE,
ArrayIndexOutOfBounds)
// ■■ try-catch-finally ■■ try { int[] arr = new int[5]; arr[10] = 100; // ■
ArrayIndexOutOfBoundsException } catch (ArrayIndexOutOfBoundsException e) {
[Link]("Array error: " + [Link]()); } catch (Exception e) { // catch
all other exceptions [Link]("General error: " + [Link]()); } finally {
[Link]("This ALWAYS runs (cleanup code goes here)"); } // ■■ Multiple
exception types in one catch (Java 7+) ■■ try { String s = null; [Link](); } catch
(NullPointerException | IllegalArgumentException e) { [Link]("Caught: " +
[Link]().getSimpleName()); } // ■■ throw — manually raise an exception ■■ void
validateAge(int age) { if (age < 0 || age > 150) throw new IllegalArgumentException("Age
must be 0-150, got: " + age); } // ■■ throws — declare that method might throw checked
exception ■■ void readFile(String path) throws IOException { FileReader fr = new
FileReader(path); // might throw IOException // process file... } // ■■ Custom Exception
■■ class InsufficientFundsException extends Exception { double amount;
InsufficientFundsException(double amount) { super("Insufficient funds! Needed: " +
amount); [Link] = amount; } } class BankAccount { double balance = 1000; void
withdraw(double amount) throws InsufficientFundsException { if (amount > balance) throw
new InsufficientFundsException(amount); balance -= amount; [Link]("Withdrawn:
" + amount); } } BankAccount acc = new BankAccount(); try { [Link](500); // OK
[Link](800); // throws InsufficientFundsException } catch
(InsufficientFundsException e) { [Link]([Link]()); } // ■■
try-with-resources (Java 7+) — auto closes resources ■■ try (FileReader fr = new
FileReader("[Link]"); BufferedReader br = new BufferedReader(fr)) { String line =
[Link](); [Link](line); } catch (IOException e) { [Link](); }
// fr and br are automatically closed here
Core Java Notes | Detailed Study Guide Page 25
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part E — File Handling
39. File Handling
Java provides the [Link] and [Link] packages to read from and write to files. File handling is a very
common real-world task — reading config files, saving user data, processing CSV files, etc.
Key Classes:
Class Package Purpose
File [Link] Represents a file/directory path. Create, delete, check existence.
FileWriter [Link] Write characters/text to a file
FileReader [Link] Read characters/text from a file
BufferedWriter [Link] Buffered writing — faster, use with FileWriter
BufferedReader [Link] Buffered reading — faster, use with FileReader. readLine()
PrintWriter [Link] Convenient writing with print/println methods
Scanner [Link] Read from file (also from console). nextLine(), nextInt()...
Files (NIO) [Link] Modern API. readAllLines(), write(), copy(), delete()...
import [Link].*; import [Link].*; import [Link]; // ■■ Writing to a file
■■ try (BufferedWriter writer = new BufferedWriter(new FileWriter("[Link]"))) {
[Link]("Line 1: Hello Java"); [Link](); [Link]("Line 2: File
Handling"); // file is auto-closed when try block exits } catch (IOException e) {
[Link]("Write error: " + [Link]()); } // Append to existing file (pass
true as second argument) try (FileWriter fw = new FileWriter("[Link]", true);
BufferedWriter bw = new BufferedWriter(fw)) { [Link]("Line 3: Appended"); [Link]();
} catch (IOException e) { [Link](); } // ■■ Reading from a file ■■ try
(BufferedReader reader = new BufferedReader(new FileReader("[Link]"))) { String line;
while ((line = [Link]()) != null) { [Link](line); } } catch
(FileNotFoundException e) { [Link]("File not found!"); } catch (IOException
e) { [Link]("Read error: " + [Link]()); } // ■■ Using
[Link] (modern, simpler) ■■ Path path = [Link]("[Link]"); // Read all
lines at once List<String> lines = [Link](path);
[Link]([Link]::println); // Write all lines at once List<String> content =
[Link]("First", "Second", "Third"); [Link](path, content); // ■■ File operations
■■ File file = new File("[Link]"); [Link]([Link]()); // true or
false [Link]([Link]()); // size in bytes
[Link]([Link]()); // "[Link]"
[Link]([Link]()); // full path [Link](); // delete the
file // Create directory File dir = new File("myFolder"); [Link](); // create single
directory [Link](); // create directory + all parents
Core Java Notes | Detailed Study Guide Page 26
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part F — Multithreading
40. Multithreading
A thread is the smallest unit of execution. Multithreading allows a Java program to perform multiple tasks
simultaneously, making better use of CPU resources. For example: one thread downloads a file while
another updates the UI.
Thread Lifecycle:
State Meaning
New Thread object created, start() not yet called
Runnable start() called, thread is ready and waiting for CPU time
Running Thread is actively executing code
Blocked/Waiting Thread is paused — waiting for lock, sleep, or another thread
Terminated run() method has completed execution
import [Link].*; // ■■ Method 1: Extend Thread class ■■ class MyThread
extends Thread { String taskName; MyThread(String name) { [Link] = name; }
@Override public void run() { for (int i = 1; i <= 5; i++) { [Link](taskName
+ " - step " + i); try { [Link](500); } catch (InterruptedException e) { } } } } //
■■ Method 2: Implement Runnable (preferred) ■■ class MyTask implements Runnable {
@Override public void run() { [Link]("Runnable task running in: " +
[Link]().getName()); } } // ■■ Method 3: Lambda (Java 8+) ■■ Thread t3 =
new Thread(() -> [Link]("Lambda thread!")); // Creating and starting threads
MyThread t1 = new MyThread("Download"); MyThread t2 = new MyThread("Upload"); [Link]();
// starts new thread, calls run() [Link](); // both run concurrently // join() — wait
for thread to finish [Link](); [Link]("Download complete!"); // ■■
Synchronisation — prevent race conditions ■■ class Counter { private int count = 0; //
synchronized — only one thread can execute this at a time public synchronized void
increment() { count++; } public synchronized int getCount() { return count; } //
synchronized block — finer control public void decrement() { synchronized(this) {
count--; } } } // ■■ Thread Pool (Executor Service) — better than raw threads ■■
ExecutorService pool = [Link](4); // 4 threads for (int i = 0; i <
10; i++) { int taskId = i; [Link](() -> { [Link]("Task " + taskId + " by
" + [Link]().getName()); }); } [Link](); // stop accepting new tasks
[Link](10, [Link]); // wait for all tasks // ■■ volatile
keyword ■■ // Ensures variable changes are visible to all threads (no caching) volatile
boolean running = true;
Core Java Notes | Detailed Study Guide Page 27
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part G — Collections Framework
41. Collections Framework
The Java Collections Framework is a set of classes and interfaces that provide ready-made, optimised
data structures. Unlike arrays (fixed size), collections can grow and shrink dynamically. All collection
classes are in the [Link] package.
Collections Hierarchy:
Interface Implementations Key Properties
List ArrayList, LinkedList, Vector, Stack Ordered, allows duplicates, index-based
Set HashSet, LinkedHashSet, TreeSet No duplicates
Queue LinkedList, PriorityQueue, ArrayDeque
FIFO (first in, first out)
Map HashMap, LinkedHashMap, TreeMap,
Key-value
Hashtable
pairs, keys unique
ArrayList — Most Commonly Used
import [Link].*; import [Link]; ArrayList<String> fruits = new
ArrayList<>(); [Link]("Apple"); [Link]("Banana"); [Link]("Cherry");
[Link](1, "Mango"); // insert at index 1 [Link](0, "Avocado"); // replace at
index 0 [Link]([Link](2)); // Cherry [Link]([Link]());
// 4 [Link]([Link]("Banana")); // true
[Link]([Link]("Cherry")); // 2 [Link]("Banana"); // remove by
value [Link](0); // remove by index for (String f : fruits) [Link](f);
[Link](fruits); // sort alphabetically [Link](fruits); // reverse
[Link](fruits); // random shuffle
LinkedList — Deque operations
LinkedList<Integer> ll = new LinkedList<>(); [Link](10); [Link](20); [Link](30);
[Link](5); // [5, 10, 20, 30] [Link](40); // [5, 10, 20, 30, 40]
[Link](); // removes 5 [Link](); // removes 40
[Link]([Link]()); // 10 — see head without removing
[Link]([Link]()); // 10 — remove and return head
HashMap — Key-Value Storage
HashMap<String, Integer> scores = new HashMap<>(); [Link]("Alice", 95);
[Link]("Bob", 82); [Link]("Carol", 88); [Link]("Alice", 99); // overwrites
Alice's previous score [Link]([Link]("Bob")); // 82
[Link]([Link]("Dave", 0)); // 0 — key missing
[Link]([Link]("Carol")); // true
[Link]([Link](99)); // true [Link]("Carol"); // Iterate
over all entries for ([Link]<String, Integer> entry : [Link]()) {
[Link]([Link]() + " → " + [Link]()); } // Iterate keys only
for (String name : [Link]()) [Link](name); // Iterate values only for
(int score : [Link]()) [Link](score);
HashSet — Unique Elements Only
Core Java Notes | Detailed Study Guide Page 28
Core Java Notes — Complete Syllabus Beginner to Interview Ready
HashSet<String> set = new HashSet<>(); [Link]("Java"); [Link]("Python");
[Link]("Java"); // duplicate ignored [Link]([Link]()); // 2
[Link]([Link]("Java")); // true // Set operations HashSet<Integer> a =
new HashSet<>([Link](1,2,3,4)); HashSet<Integer> b = new
HashSet<>([Link](3,4,5,6)); HashSet<Integer> union = new HashSet<>(a);
[Link](b); // 1,2,3,4,5,6 HashSet<Integer> intersect = new HashSet<>(a);
[Link](b); // 3,4 HashSet<Integer> diff = new HashSet<>(a);
[Link](b); // 1,2
TreeMap — Sorted Map
TreeMap<String, Integer> treeMap = new TreeMap<>(); // sorted by key
[Link]("Banana", 2); [Link]("Apple", 5); [Link]("Cherry", 1);
[Link](treeMap); // {Apple=5, Banana=2, Cherry=1} — sorted!
[Link]([Link]()); // Apple [Link]([Link]());
// Cherry
PriorityQueue — Min-Heap
PriorityQueue<Integer> pq = new PriorityQueue<>(); // min at top [Link](30); [Link](10);
[Link](50); [Link](20); [Link]([Link]()); // 10 — smallest (min-heap)
[Link]([Link]()); // 10 — removes smallest [Link]([Link]()); //
20 — next smallest
Collection Order Duplicates Null OK Thread-Safe Best For
ArrayList Insertion Yes Yes No Random access, iteration
LinkedList Insertion Yes Yes No Frequent add/remove ends
HashMap None Keys: No 1 null key No Fast key lookup
LinkedHashMap Insertion Keys: No 1 null key No Insertion-ordered map
TreeMap Sorted Keys: No No No Sorted key-value
HashSet None No Yes No Unique elements
TreeSet Sorted No No No Sorted unique elements
PriorityQueue Priority Yes No No Min/Max heap
Hashtable None Keys: No No Yes Legacy thread-safe map
Core Java Notes | Detailed Study Guide Page 29
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Part H — Top Java Interview Questions &
Answers
These are the most frequently asked Core Java interview questions for freshers and junior developers.
Read each answer carefully and try to explain it in your own words.
Q: 1. What is Java and what are its main features?
A: Java is a high-level, class-based, object-oriented programming language designed to have as few
implementation dependencies as possible. Its key features are: (1) Platform independence — 'Write
Once, Run Anywhere' via JVM bytecode. (2) Object-Oriented — everything is a class/object. (3)
Strongly typed — all variables must be declared. (4) Automatic memory management — Garbage
Collector. (5) Multithreading support. (6) Robust — exception handling, type checking. (7) Secure — no
pointers, bytecode verification.
Q: 2. Explain the difference between JDK, JRE, and JVM.
A: JVM (Java Virtual Machine) is the engine that executes Java bytecode. It is platform-specific. JRE
(Java Runtime Environment) = JVM + class libraries needed to run Java programs. It is enough to RUN
Java programs. JDK (Java Development Kit) = JRE + development tools (javac compiler, debugger,
javadoc, etc.). You need the JDK to WRITE and COMPILE Java programs. Developers install JDK; end
users only need JRE.
Q: 3. What is the difference between == and .equals()?
A: == compares memory addresses (references) — it checks if two variables point to the SAME object
in heap memory. .equals() compares the CONTENT (logical equality) of two objects. For primitive types,
== compares values directly. For Strings and objects, always use .equals() for content comparison.
Example: String a = new String('Hi'); String b = new String('Hi'); a == b is false (different objects), but
[Link](b) is true (same content). Exception: String literals 'Hi' == 'Hi' may be true due to the String
Pool.
Q: 4. What is the difference between Checked and Unchecked exceptions?
A: Checked exceptions are checked by the compiler at compile time. You must either handle them with
try-catch or declare them with 'throws' in the method signature. Examples: IOException, SQLException,
ClassNotFoundException. Unchecked exceptions (subclasses of RuntimeException) are not checked at
compile time. They represent programming bugs. Examples: NullPointerException,
ArrayIndexOutOfBoundsException, ClassCastException. Errors (like StackOverflowError) are also
unchecked — they represent serious JVM problems you generally should not catch.
Core Java Notes | Detailed Study Guide Page 30
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Q: 5. What is the difference between abstract class and interface?
A: Abstract class: can have abstract AND concrete methods, can have constructors, can have any
access modifiers, can have instance variables, a class can extend only ONE abstract class. Interface:
before Java 8 — only abstract methods; from Java 8 — can have default and static methods; all
variables are public static final (constants); no constructors; a class can implement MULTIPLE
interfaces. Use abstract class for IS-A relationship with shared code. Use interface for CAN-DO
capabilities (Flyable, Serializable) or for multiple inheritance.
Q: 6. What is method overloading vs method overriding?
A: Overloading: same method name in the SAME class, different parameters (type, number, or order).
Resolved at compile time (static polymorphism). Return type alone cannot differentiate overloaded
methods. Overriding: child class provides a NEW implementation for a method already defined in
parent. Same name, same parameters. Resolved at runtime (dynamic polymorphism). Use @Override
annotation. Access modifier cannot be more restrictive in override. static and final methods cannot be
overridden.
Q: 7. What is the 'static' keyword? Can a static method access instance variables?
A: The static keyword means a member belongs to the CLASS itself, not to any specific object. A static
variable is shared by ALL objects of the class. A static method can be called without creating an object
([Link]()). A static block runs once when the class is first loaded. NO — a static method
CANNOT directly access instance (non-static) variables or methods, because instance members need
an object to exist, and static methods can be called without an object. But a static method CAN access
static variables.
Q: 8. What is the difference between String, StringBuilder, and StringBuffer?
A: String is IMMUTABLE — every operation (concat, replace, etc.) creates a NEW String object in
memory. This can be slow and wasteful in loops. StringBuilder is MUTABLE — modifies the same
object without creating new ones. It is faster but NOT thread-safe (do not use in multiple threads).
StringBuffer is MUTABLE and thread-safe (all methods are synchronized) — but slower than
StringBuilder. Rule: Use String for fixed text. Use StringBuilder in single-threaded code with many
modifications. Use StringBuffer in multi-threaded code.
Core Java Notes | Detailed Study Guide Page 31
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Q: 9. Explain the 4 pillars of OOP with a real example.
A: Using a BankAccount example: (1) Encapsulation — balance is private; only accessible via deposit()
and withdraw() methods. The internals are hidden. (2) Inheritance — SavingsAccount extends
BankAccount, inheriting balance and basic operations, adding interest logic. (3) Polymorphism —
[Link]() behaves differently in SavingsAccount vs CurrentAccount (overriding).
(4) Abstraction — the user calls withdraw() without knowing whether the bank uses SQL, NoSQL, or a
ledger internally. The complexity is hidden behind a simple method.
Q: 10. What is the 'this' keyword and where is it used?
A: this refers to the current object — the instance on which the method or constructor is being invoked.
Uses: (1) [Link] — to distinguish instance variable from local variable/parameter with the same
name. (2) [Link]() — to call another method of the same class. (3) this() — constructor chaining —
to call another constructor of the same class (must be first line). (4) return this — to return current object
from a method, enabling method chaining (builder pattern).
Q: 11. What is the difference between ArrayList and LinkedList?
A: ArrayList uses a dynamic array internally. Access by index is O(1) — very fast. Insertion/deletion in
the middle is O(n) — slow (needs shifting). Best for random access and iteration. LinkedList uses a
doubly-linked list. Access by index is O(n) — slow (must traverse). Insertion/deletion at head/tail is O(1)
— very fast. Best for frequent additions/removals. Memory: LinkedList uses more memory (each node
stores data + two pointers). For most use cases, ArrayList is preferred because modern hardware
makes iteration fast.
Q: 12. What is the 'final' keyword and how is it used?
A: final applied to a variable — value cannot be changed after assignment (constant). Applied to a
method — method cannot be overridden in any subclass. Applied to a class — class cannot be
extended (e.g., String, Integer are final classes). Blank final variable — declared final but assigned only
once in the constructor. final parameter — parameter value cannot be changed inside the method. static
final — class-level constant (e.g., [Link], Integer.MAX_VALUE).
Q: 13. What is Singleton design pattern? How do you implement it?
A: Singleton ensures only ONE instance of a class exists throughout the program. Implementation
steps: (1) Make the constructor private — no one outside can call new. (2) Declare a private static
variable of the class type. (3) Provide a public static getInstance() method that creates the instance only
if it doesn't exist, then returns it. The lazy-initialised version creates the instance only when first needed.
For thread safety, use synchronized on getInstance() or use double-checked locking. Common uses:
Database connections, Logger, Configuration Manager.
Core Java Notes | Detailed Study Guide Page 32
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Q: 14. What is an Immutable class? How do you create one?
A: An immutable class is one whose state cannot be changed after creation. String is the most famous
example. To make a class immutable: (1) Declare the class as final (prevent subclassing). (2) Make all
fields private and final. (3) Initialize all fields in the constructor only. (4) Provide only getters — no
setters. (5) For mutable fields (like arrays or lists), return a defensive copy from the getter, not the
original. Benefits: Thread-safe without synchronisation, can be safely cached and shared, predictable
state.
Q: 15. What is the difference between HashMap and TreeMap?
A: HashMap stores key-value pairs with NO guaranteed order. It uses hashing internally. get() and put()
are O(1) average. Allows one null key and multiple null values. Not thread-safe. TreeMap stores
key-value pairs SORTED by key (natural order or custom Comparator). Uses a Red-Black tree
internally. get() and put() are O(log n). Does NOT allow null keys. Not thread-safe. Choose HashMap for
fast unordered lookup. Choose TreeMap when you need entries in sorted key order.
Q: 16. What is the difference between 'throw' and 'throws'?
A: 'throw' is used inside a method body to ACTUALLY THROW an exception object at a specific point:
throw new IllegalArgumentException('message'). You can throw only one exception at a time. 'throws' is
used in the METHOD SIGNATURE to DECLARE that the method might throw one or more checked
exceptions, warning callers to handle them: public void readFile() throws IOException, SQLException. It
does not throw anything by itself — it just advertises the possibility. A method can declare multiple
exceptions with throws, separated by commas.
Q: 17. What is Garbage Collection in Java?
A: Garbage Collection (GC) is Java's automatic memory management process. When an object on the
heap is no longer referenced by any variable (unreachable), the GC automatically reclaims its memory.
Programmers don't need to manually free memory (unlike C/C++). The GC runs in the background as a
low-priority thread. You can suggest it runs with [Link]() but there is no guarantee. Before collecting
an object, the GC calls finalize() on it (deprecated in Java 9+). Common GC algorithms:
Mark-and-Sweep, Generational GC, G1 GC. This prevents memory leaks in most cases but objects
must be de-referenced for GC to work.
Core Java Notes | Detailed Study Guide Page 33
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Q: 18. What is the difference between Comparable and Comparator?
A: Comparable ([Link]) is implemented BY the class itself. It has one method: compareTo(). It
defines the NATURAL ordering. Example: String, Integer implement Comparable. Comparator ([Link])
is a SEPARATE class/lambda defining custom ordering. It has one method: compare(). Use it when you
want multiple different sort orders, or when you can't modify the class. Example: sorting Employees by
salary in one place, by name in another. With Java 8, Comparator can be a lambda: (a, b) ->
[Link]() - [Link]().
Q: 19. What is autoboxing and unboxing?
A: Autoboxing is the automatic conversion of a primitive type to its corresponding Wrapper class object:
int to Integer, double to Double, etc. This happens automatically when you add a primitive to a collection
(which requires objects) or assign it to a wrapper type variable. Unboxing is the reverse — automatic
conversion from Wrapper object back to primitive. This happens when you assign a wrapper to a
primitive variable or use it in arithmetic. Caution: unboxing a null wrapper throws NullPointerException.
Also, excessive autoboxing in loops can hurt performance by creating many temporary objects.
Q: 20. What are lambda expressions and functional interfaces?
A: A lambda expression is a concise way to represent an anonymous function — a method without a
name, class, or access modifier. Syntax: (parameters) -> expression or (parameters) -> { statements }.
A functional interface is an interface with exactly ONE abstract method (SAM — Single Abstract
Method). The @FunctionalInterface annotation enforces this. Common functional interfaces from
[Link]: Predicate (test method — returns boolean), Function (apply method — transforms T to
R), Consumer (accept method — consumes T, returns void), Supplier (get method — produces T with
no input). Lambdas make code shorter, especially for event handlers, sorting, and stream operations.
Q: 21. What is the Stream API and how does it work?
A: The Stream API ([Link], Java 8+) allows processing sequences of elements in a
declarative, functional pipeline style. A stream pipeline has three parts: (1) Source — created from a
collection (.stream()), array ([Link]()), or range. (2) Intermediate operations — lazy, return
another stream: filter(), map(), sorted(), distinct(), limit(), skip(). (3) Terminal operation — triggers
processing and returns a result: collect(), count(), reduce(), forEach(), min(), max(), findFirst(). Streams
do NOT modify the original collection. They can be parallelized easily with .parallelStream(). Each
stream can be used only ONCE — a second terminal operation throws IllegalStateException.
Core Java Notes | Detailed Study Guide Page 34
Core Java Notes — Complete Syllabus Beginner to Interview Ready
Study Tips & Next Steps
■ Congratulations! You have now covered the complete Core Java syllabus — from Tokens all the
way through to the Collections Framework, along with top interview Q&A. Now the key is practice —
reading is not enough; you must write code every day.
Recommended Study Order:
• Week 1-2: Basics — Tokens, Keywords, Identifiers, Data Types, Casting
• Week 3-5: OOP — Classes, Objects, Constructors, Inheritance, Polymorphism
• Week 6-7: OOP Advanced — Abstraction, Interface, Encapsulation, final, static
• Week 8: Special Classes — Singleton, Immutable, Object class, Wrapper
• Week 9: Java 8 Features — Lambdas, Streams, Date-Time API
• Week 10: Exception Handling + File Handling
• Week 11: Multithreading — Thread, Runnable, synchronized, ExecutorService
• Week 12: Collections — ArrayList, LinkedList, HashMap, HashSet, TreeMap
• Ongoing: Practise all Interview Q&A until you can answer without reading
Practice Projects (Build these!):
• Student Grade Management System (OOP + Collections)
• Simple Bank Account App (Encapsulation + Exception Handling)
• File-based To-Do List (File Handling + Collections)
• Multi-threaded Download Simulator (Multithreading)
• Library Book Management System (all concepts together)
Online Resources:
• Oracle Java Documentation: [Link]/en/java
• Practice problems: LeetCode (Java filter), HackerRank Java domain
• IDE: IntelliJ IDEA Community Edition (free) or VS Code + Java Extension
■ Final advice: Do NOT just memorise answers. Understand the WHY behind each concept. If an
interviewer asks a follow-up question, you should be able to explain it from first principles. Write code,
make mistakes, debug, and learn. That is how real Java developers are made!
Core Java Notes | Detailed Study Guide Page 35