Advance Java – Module 1
1. Introduction to Java
1.1 Overview of Java and its Features
1.2 Java History and Evolution
1.3 JDK, JRE, and JVM (Differences & Roles)
1.4 Java Program Structure
1.5 Compilation & Execution Process
2. Java Basics
2.1 Java Syntax & Program Flow
2.2 Identifiers, Keywords, and Naming Conventions
2.3 Variables & Constants
2.4 Data Types (Primitive & Non-Primitive)
2.5 Type Casting & Type Conversion
2.6 Operators in Java (Arithmetic, Relational, Logical, Bitwise, Assignment, Unary, Ternary)
2.7 Expressions & Operator Precedence
2.8 Comments in Java (Single-line, Multi-line, Documentation)
3. Control Flow Statements
3.1 Decision-Making Statements (if, if-else, if-else-if, switch)
3.2 Looping Statements (for, while, do-while)
3.3 Enhanced for-loop
3.4 Jump Statements (break, continue, return)
3.5 Nested Loops and Labels
4. Arrays and Strings
4.1 Single-Dimensional Arrays
4.2 Multi-Dimensional Arrays
4.3 Array Operations (Copying, Sorting, Searching)
4.4 String Class and Methods
4.5 StringBuffer & StringBuilder
4.6 String Immutability & Interning
4.7 Common String Operations
Advance Java – Module 1
5. Methods in Java
5.1 Method Definition & Syntax
5.2 Parameter Passing (By Value vs. By Reference in Java)
5.3 Method Overloading
5.4 Recursion in Java
5.5 Varargs (Variable Arguments)
5.6 main() Method Deep Dive
6. Object-Oriented Programming (OOP)
6.1 Classes and Objects
6.2 Constructors & Constructor Overloading
6.3 this keyword
6.4 static keyword (Variables, Methods, Blocks)
6.5 Encapsulation & Access Modifiers
6.6 Inheritance (Single, Multilevel, Hierarchical)
6.7 super keyword
6.8 Method Overriding
6.9 Polymorphism (Compile-time & Runtime)
6.10 Abstraction (Abstract Class, Interface)
6.11 final keyword (Variables, Methods, Classes)
6.12 Nested & Inner Classes
7. Packages and Access Control
7.1 Creating and Using Packages
7.2 Access Modifiers Recap
7.3 Importing Classes & Static Imports
8. Exception Handling
8.1 Types of Exceptions (Checked, Unchecked, Errors)
8.2 try, catch, finally
8.3 Multiple Catch Blocks
8.4 Nested try-catch
Advance Java – Module 1
8.5 Throwing Exceptions (throw keyword)
8.6 Creating Custom Exceptions
8.7 throws keyword
8.8 Try-with-resources (Java 7+)
9. Java 8 Core Enhancements
9.1 Introduction to Java 8 Features
9.2 Lambda Expressions
9.3 Functional Interfaces (@FunctionalInterface)
9.4 Method References
9.5 Streams API (Creation, Intermediate & Terminal Operations)
9.6 forEach() Method
9.7 Default and Static Methods in Interfaces
9.8 Optional Class
9.9 New Date and Time API (java.time package)
10. Wrapper Classes and Autoboxing
10.1 Introduction to Wrapper Classes
10.2 Autoboxing & Unboxing
10.3 Utility Methods in Wrapper Classes
11. Java Memory Management
11.1 Stack & Heap Memory
11.2 Garbage Collection Overview
11.3 finalize() Method (Deprecated in Java 9)
12. Java I/O Basics
12.1 File Handling Introduction
12.2 Byte Streams vs. Character Streams
12.3 Reading & Writing Files
12.4 Buffered Streams
12.5 Serialization & Deserialization Basics
13. Multithreading Basics
Advance Java – Module 1
13.1 Thread Class & Runnable Interface
13.2 Thread Lifecycle
13.3 Thread Methods (start, sleep, join, interrupt)
13.4 Synchronization Basics
14. Miscellaneous Topics
14.1 Object Class Methods (toString, equals, hashCode, clone, getClass)
14.2 enum in Java
14.3 Annotations Basics
14.4 Command-Line Arguments
1. What Is Java?
Java is a high-level, object-oriented, class-based programming language designed to minimize
implementation dependencies. Originally developed by James Gosling and his team at Sun
Microsystems in the early 1990s (initially called "Oak," later renamed "Java"), it was publicly
released in 1996. Java’s hallmark is its “Write Once, Run Anywhere” (WORA) capability—thanks
to the JVM, the same bytecode runs identically across platforms
Key Features:
• Platform Independence: Source code compiles into bytecode (.class files), which the
JVM executes on any platform.
• Object-Oriented: Promotes modularity and code reusability using classes and objects.
• Robust & Secure: Provides exception handling, automatic memory management
(garbage collection), and runtime bytecode verification.
• Multithreading: Integrates thread support for concurrent programming.
• Dynamic Features: Supports dynamic class loading and interoperability across different
modules and versions.
2. JDK, JRE, and JVM
• JVM (Java Virtual Machine): The runtime environment that interprets or just-in-time
(JIT) compiles Java bytecode into machine-native code. It handles memory, executes
bytecode, and maintains security.
Advance Java – Module 1
• JRE (Java Runtime Environment): Includes the JVM and the standard Java class libraries.
It provides everything required to run Java applications but lacks development tools like
compilers.
• JDK (Java Development Kit): A full suite for developing Java applications. It includes the
JRE plus development tools like the Java compiler (javac), debugger, Javadoc generator,
etc.
Relationship: JDK includes JRE, which in turn contains the JVM.
3. Java Program Structure & Lifecycle
1. Source Code: Written in .java files, typically organized into packages.
2. Compilation: Use javac (part of JDK) to compile source code into .class bytecode files.
3. Execution: Run with java (JVM via JRE) which loads, verifies, and executes bytecode.
4. IDE Enhancements: Using an IDE simplifies coding, debugging, and project organization.
What is a Java IDE?
An IDE (Integrated Development Environment) is a software application that provides a
comprehensive set of tools for software development in one place. A Java IDE is specifically
designed to help developers write, compile, debug, and run Java programs efficiently.
Key Features of a Java IDE
Feature Description
Code Editor With syntax highlighting, code completion, and formatting
Compiler &
Built-in or configured to use JDK for compiling and running code
Runtime
Allows stepping through code, inspecting variables, and setting
Debugger
breakpoints
Project Explorer View and organize your project files and structure
Error Detection Real-time detection and hints for errors and warnings
Advance Java – Module 1
Feature Description
Build Tool Support Supports Maven, Gradle, Ant, etc.
Version Control Git integration for tracking changes and collaboration
Plugin Support Extend IDE functionality with plugins (e.g., for Spring, JavaFX, Android)
Summary Comparison
Step IntelliJ IDEA Eclipse IDE
JDK Installation Required first, verify with java -version Same
Download & Install IDE JetBrains site (Community Edition) eclipse.org (Java Developers pack)
Welcome → New Project → configure
New Project File → New Java Project
JDK
Create Class Right-click src → New → Java Class Same
Write & Run Code Write and press ▶ Write, then Run (menu or Ctrl+F11)
Plugins & Learning Tools IDE Features Trainer plugin Use Eclipse Marketplace for plugins
1. IntelliJ IDEA (Community Edition) – Step-by-Step Setup
Step 1: Install Java JDK
1. Download the latest JDK:
o Oracle JDK
o OpenJDK
Advance Java – Module 1
2. Install it.
3. Set environment variable JAVA_HOME (optional but helpful).
Step 2: Install IntelliJ IDEA
1. Go to https://www.jetbrains.com/idea/download
2. Choose Community Edition (Free).
3. Download and install.
Step 3: Create a New Java Project
1. Open IntelliJ → Click New Project
2. Select Java from the left.
3. Under Project SDK, click Add SDK and point to your installed JDK.
4. Click Next → Select Create project from template (optional) → Click Next
5. Name your project → Click Finish
Step 4: Create a Java Class
1. Right-click src folder → New → Java Class
2. Name it HelloWorld
3. Write the following code:
java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from IntelliJ!");
}
Advance Java – Module 1
Step 5: Run the Program
• Right-click the file → Click Run 'HelloWorld'
• Or click the green triangle beside main().
2. Eclipse IDE – Step-by-Step Setup
Step 1: Install Java JDK
1. Download from https://www.oracle.com/java/technologies/javase-downloads.html
2. Install it.
Step 2: Download Eclipse
1. Go to https://www.eclipse.org/downloads/
2. Download Eclipse IDE for Java Developers
3. Run the installer and choose Java Development Tools package.
4. Launch Eclipse.
Step 3: Create a New Java Project
1. File → New → Java Project
2. Enter project name (e.g., MyFirstProject)
3. Click Finish
Step 4: Create a Java Class
1. Right-click on src → New → Class
2. Enter HelloWorld as the class name
Advance Java – Module 1
3. Check the checkbox for public static void main(String[] args)
4. Click Finish
Step 5: Write and Run Code
Replace or add the following code if needed:
java
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from Eclipse!");
Run the program:
• Right-click file → Run As → Java Application
• Or click the green "Run" icon in the toolbar.
3. Visual Studio Code (VS Code) – Step-by-Step Setup
Step 1: Install Java JDK
1. Download and install JDK:
o Oracle
o OpenJDK
2. Confirm installation: run java -version in terminal/command prompt.
Step 2: Install VS Code
1. Download from https://code.visualstudio.com/
Advance Java – Module 1
2. Install and launch it.
Step 3: Install Java Extensions
1. Open Extensions panel (Ctrl+Shift+X)
2. Search for and install:
o "Extension Pack for Java" (by Microsoft)
▪ Includes: Language support, debugger, project manager, and test runner.
Step 4: Create Java Project
Option 1: Quick Start
1. Press Ctrl+Shift+P → Type: Java: Create Java Project
2. Choose No Build Tools
3. Choose location and name your project.
Option 2: Manual
1. Create a folder and a file HelloWorld.java
2. Open the folder in VS Code.
Step 5: Write Java Code
In HelloWorld.java:
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello from VS Code!");
Step 6: Run Java Program
• Click Run button (play icon at top-right)
Advance Java – Module 1
• Or right-click file → Run Java
2. Java Basics
Java Syntax & Program Flow
1. Definition
Java Syntax refers to the set of rules and conventions that define how Java code must be
written and structured so that the compiler can understand and execute it.
It covers keywords, data types, operators, statements, blocks, class/method definitions, and
naming rules.
Program Flow in Java refers to the sequence in which the instructions/statements are executed
— from starting a program to producing the final output.
2. Basic Structure of a Java Program
Every Java program follows a standard structure:
/*
Documentation Comment (Optional) – explains the program
*/
package packageName; // Optional
import java.util.*; // Optional imports
public class ClassName { // Class declaration
public static void main(String[] args) { // Main method
// Statements
}
Advance Java – Module 1
3. Components of Java Syntax
3.1 Comments
• Single-line: // comment
• Multi-line: /* comment */
• Documentation: /** comment */ (used with Javadoc)
3.2 Class Declaration
• Java code must be inside a class (except package/module declarations).
• Class names follow PascalCase naming convention.
3.3 main() Method
• Entry point of the program.
• Syntax:
public static void main(String[] args) { }
• public → accessible by JVM.
• static → no need to create an object to run.
• void → no return value.
• String[] args → stores command-line arguments.
3.4 Statements
• Instructions executed by JVM.
• End with a semicolon ;.
3.5 Blocks
• Group of statements enclosed in { }.
3.6 Identifiers & Keywords
• Identifiers: Names for variables, methods, classes, etc.
• Keywords: Reserved words like class, public, int.
Advance Java – Module 1
4. Java Program Flow
A Java program execution goes through these steps:
1. Write the Source Code → .java file.
2. Compile the Code → javac ProgramName.java
o Compiler checks syntax and generates .class file (bytecode).
3. Run the Program → java ProgramName
o JVM loads bytecode, interprets, and executes instructions.
Flow Diagram:
Source Code (.java)
↓ javac
Bytecode (.class)
↓ java
Execution by JVM
5. How Java Syntax Works
• Strict typing: Every variable must have a data type.
• Case-sensitive: Main and main are different.
• Class name = File name (if public class).
• One public class per file.
• Indentation & formatting → not mandatory for execution but improves readability.
• Blocks define scope → Variables declared inside a block can’t be accessed outside it.
6. Example Code
// This is a sample Java program
public class HelloWorld {
Advance Java – Module 1
public static void main(String[] args) {
// Printing message to the console
System.out.println("Hello, Java Syntax and Program Flow!");
7. Output
Hello, Java Syntax and Program Flow!
8. Step-by-Step Execution
1. Save file as HelloWorld.java.
2. Open terminal and compile:
javac HelloWorld.java
→ Generates HelloWorld.class.
3. Run the program:
java HelloWorld
→ JVM executes main() method and prints the output.
9. Key Points to Remember
• File name must match the public class name.
• main() method is the execution entry point.
• Java is compiled + interpreted (Bytecode + JVM).
• Use proper indentation for readability.
• Follow naming conventions for identifiers.
Advance Java – Module 1
Identifiers, Keywords, and Naming Conventions in Java
1. Definition
• Identifiers → Names given to elements like classes, variables, methods, objects,
packages, etc. They are user-defined names.
• Keywords → Predefined, reserved words in Java with special meaning for the compiler.
Cannot be used as identifiers.
• Naming Conventions → Standard rules & best practices for naming identifiers to make
code readable and maintainable.
2. Identifiers in Java
Rules for Identifiers
1. Can contain letters (A–Z, a–z), digits (0–9), underscore (_), and dollar sign ($).
2. Must start with a letter, _, or $ (cannot start with a digit).
3. Case-sensitive → myVar and myvar are different.
4. Cannot use Java keywords.
5. No special characters like @, #, %, &.
Valid Identifiers:
myVariable
_data
$amount
num1
MAX_VALUE
Invalid Identifiers:
1value // starts with a number
class // keyword
my-variable // contains hyphen
Advance Java – Module 1
3. Keywords in Java
Java has 50+ reserved words (in Java 8).
They are all lowercase.
List of Java Keywords
Category Keywords
Access Control public, private, protected
Class/Interface class, interface, enum
Method/Variable static, final, abstract, synchronized, volatile
Control
Object/Instance new, this, super, instanceof
Flow Control if, else, switch, case, default, while, do, for, break, continue, return
Exception Handling try, catch, finally, throw, throws
Primitive Types byte, short, int, long, float, double, char, boolean, void
Others package, import, extends, implements, goto (unused), const (unused),
native, strictfp, assert
4. Naming Conventions in Java
Java follows CamelCase style and industry naming guidelines.
Element Convention Example
Class PascalCase StudentDetails, BankAccount
Interface PascalCase Runnable, Comparable
Method camelCase calculateTotal(), getName()
Variable camelCase totalMarks, studentName
Constant UPPER_CASE MAX_SPEED, PI
Package lowercase java.util, com.mycompany
Advance Java – Module 1
5. How It Works
• The compiler strictly checks keywords and identifiers.
• If an identifier is the same as a keyword → Compile-time Error.
• Naming conventions don’t affect compilation, but following them improves readability
and maintainability.
6. Example Code
public class NamingExample {
// Constant
static final int MAX_SPEED = 120;
// Variable
int currentSpeed = 60;
// Method
public void increaseSpeed(int increment) {
currentSpeed += increment;
public static void main(String[] args) {
NamingExample car = new NamingExample();
car.increaseSpeed(20);
System.out.println("Current Speed: " + car.currentSpeed);
System.out.println("Max Speed: " + MAX_SPEED);
}
Advance Java – Module 1
7. Output
Current Speed: 80
Max Speed: 120
8. Key Points to Remember
• Identifiers are case-sensitive and must follow rules.
• Keywords are reserved; they can’t be used as variable names.
• Always follow naming conventions for clean, professional code.
Variables and Constants in Java
1. Definition
A variable in Java is a named memory location that stores data, whose value can change during
program execution.
A constant is a fixed value that does not change once assigned. In Java, constants are usually
declared using the final keyword.
2. Variable Types
Java variables are categorized into three main types:
1. Local Variables
o Declared inside methods, constructors, or blocks.
o Created when the method is called and destroyed after execution.
o Must be initialized before use.
2. Instance Variables
o Declared inside a class but outside any method.
o Each object gets its own copy.
Advance Java – Module 1
o Created when an object is created, destroyed when the object is destroyed.
3. Static Variables (Class Variables)
o Declared with the static keyword inside a class.
o Shared among all objects of the class.
o Created when the class is loaded, destroyed when the program ends.
3. Constant Declaration
• Declared using the final keyword.
• Once assigned, the value cannot be changed.
• By convention, constant names are written in UPPERCASE.
Example:
static final double PI = 3.14159;
4. Syntax
Variable Declaration
dataType variableName; // Declaration
dataType variableName = value; // Declaration + Initialization
Example:
int age;
int marks = 85;
Constant Declaration
final dataType CONSTANT_NAME = value;
Example:
final int MAX_STUDENTS = 100;
5. How It Works
Advance Java – Module 1
When a variable is declared, memory is allocated to store its value based on its data type.
Local variables are stored in the stack memory, while instance and static variables are stored in
the heap memory.
Constants are stored in a fixed memory location and cannot be reassigned once initialized.
6. Example Code
public class VariableExample {
// Instance variable
int rollNumber = 101;
// Static variable
static String collegeName = "ABC University";
// Constant
static final double PI = 3.14159;
public void displayDetails() {
// Local variable
String studentName = "John";
System.out.println("Name: " + studentName);
System.out.println("Roll Number: " + rollNumber);
System.out.println("College: " + collegeName);
System.out.println("PI Value: " + PI);
public static void main(String[] args) {
Advance Java – Module 1
VariableExample obj = new VariableExample();
obj.displayDetails();
7. Output
Name: John
Roll Number: 101
College: ABC University
PI Value: 3.14159
8. Key Points to Remember
• Variable names must follow identifier rules.
• Local variables must be initialized before use.
• static variables are shared across all instances.
• Constants are declared with final and cannot be modified.
Data Types in Java
1. Definition
A data type in Java defines the kind of data a variable can store, how much memory it will take,
and what operations can be performed on it.
Java is a strongly typed language, meaning every variable must have a declared data type
before it can be used.
2. Types of Data Types
Java data types are mainly divided into two categories:
2.1 Primitive Data Types
Advance Java – Module 1
These are the basic built-in data types in Java. They store simple values, not objects.
There are 8 primitive types:
Data Type Size (bytes) Default Value Range
byte 1 0 -128 to 127
short 2 0 -32,768 to 32,767
int 4 0 -2,147,483,648 to 2,147,483,647
long 8 0L -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807
float 4 0.0f ~6–7 decimal digits
double 8 0.0d ~15 decimal digits
char 2 '\u0000' 0 to 65,535 (Unicode)
boolean 1 bit false true or false
2.2 Non-Primitive (Reference) Data Types
These store references (addresses) to objects, not the actual values. Examples:
• Strings (String name = "Java";)
• Arrays (int[] arr = {1, 2, 3};)
• Classes (user-defined types)
• Interfaces
• Enums
3. Syntax
Primitive Type Example
int age = 25;
double salary = 50000.50;
boolean isActive = true;
Advance Java – Module 1
Non-Primitive Type Example
String name = "John";
int[] marks = {85, 90, 78};
4. How It Works
• Primitive types store the actual value in memory.
• Reference types store the memory address of the object.
• JVM allocates memory for variables depending on their data type.
• Default values are assigned to instance and static variables, but local variables must be
initialized before use.
5. Example Code
public class DataTypeExample {
// Primitive types
byte b = 10;
int num = 100;
double price = 99.99;
char grade = 'A';
boolean status = true;
// Non-primitive types
String name = "Alice";
int[] scores = {85, 90, 78};
public void display() {
System.out.println("Byte value: " + b);
Advance Java – Module 1
System.out.println("Integer value: " + num);
System.out.println("Double value: " + price);
System.out.println("Char value: " + grade);
System.out.println("Boolean value: " + status);
System.out.println("String value: " + name);
System.out.print("Array values: ");
for (int score : scores) {
System.out.print(score + " ");
public static void main(String[] args) {
DataTypeExample obj = new DataTypeExample();
obj.display();
6. Output
Byte value: 10
Integer value: 100
Double value: 99.99
Char value: A
Boolean value: true
String value: Alice
Array values: 85 90 78
Advance Java – Module 1
7. Key Points to Remember
• Java has 8 primitive types; all others are reference types.
• Primitive types store actual values; reference types store memory addresses.
• Local variables have no default values — must be initialized.
• Data type determines memory size and range.
1. Arithmetic Operators
Definition
Arithmetic operators are used to perform basic mathematical operations on numeric data
types (int, float, double, etc.).
Operators List
Operator Meaning
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus (remainder)
How it Works
• Takes two operands and performs the specified mathematical operation.
• Division between integers returns an integer result.
• % gives the remainder of a division.
Syntax
result = operand1 operator operand2;
Example
public class ArithmeticExample {
public static void main(String[] args) {
Advance Java – Module 1
int a = 10, b = 3;
System.out.println("Addition: " + (a + b));
System.out.println("Subtraction: " + (a - b));
System.out.println("Multiplication: " + (a * b));
System.out.println("Division: " + (a / b));
System.out.println("Modulus: " + (a % b));
Output
Addition: 13
Subtraction: 7
Multiplication: 30
Division: 3
Modulus: 1
2. Unary Operators
Definition
Unary operators work on a single operand to perform operations like increment, decrement,
negation, or logical NOT.
Types of Unary Operators in Java
Operator Meaning Example
+ Unary plus (positive value, usually redundant) +a
- Unary minus (negates value) -a
++ Increment (increases value by 1) ++a or a++
-- Decrement (decreases value by 1) --a or a--
Advance Java – Module 1
! Logical NOT (reverses boolean value) !false
How it Works
• Unary Plus (+) → Mostly unused because positive numbers are default.
• Unary Minus (-) → Converts positive to negative and vice versa.
• Increment (++) → Adds 1 to the operand.
o Pre-increment (++a) → Increases first, then uses the value.
o Post-increment (a++) → Uses the value first, then increases.
• Decrement (--) → Subtracts 1 from the operand.
o Pre-decrement (--a) → Decreases first, then uses the value.
o Post-decrement (a--) → Uses the value first, then decreases.
• Logical NOT (!) → Flips boolean values: true → false, false → true.
Syntax
++variable;
variable++;
--variable;
variable--;
-variable;
!booleanValue;
Example
public class UnaryExample {
public static void main(String[] args) {
int x = 5;
boolean flag = true;
Advance Java – Module 1
System.out.println("Original x: " + x);
// Pre-increment
System.out.println("++x: " + (++x)); // increments before printing
// Post-increment
System.out.println("x++: " + (x++)); // prints first, then increments
// Pre-decrement
System.out.println("--x: " + (--x)); // decrements before printing
// Post-decrement
System.out.println("x--: " + (x--)); // prints first, then decrements
// Unary minus
System.out.println("Unary minus of x: " + (-x));
// Logical NOT
System.out.println("Logical NOT of flag: " + (!flag));
Output
Original x: 5
++x: 6
Advance Java – Module 1
x++: 6
--x: 6
x--: 6
Unary minus of x: -5
Logical NOT of flag: false
3. Assignment Operators
Definition
Assignment operators are used to assign values to variables. The simplest is =, but Java also
provides compound assignment operators to perform an operation and assignment in one step.
Types of Assignment Operators
Operator Meaning Example Equivalent to
= Assigns right-hand value to left-hand variable x = 5; —
+= Adds right-hand value to left-hand variable x += 3; x = x + 3;
-= Subtracts right-hand value from left-hand variable x -= 3; x = x - 3;
*= Multiplies left-hand variable by right-hand value x *= 3; x = x * 3;
/= Divides left-hand variable by right-hand value x /= 3; x = x / 3;
%= Stores remainder in left-hand variable x %= 3; x = x % 3;
How it Works
The left-hand operand is updated with the result of applying the operator with the right-hand
operand. Compound operators reduce code repetition.
Syntax
variable = value;
variable operator= value;
Example
public class AssignmentExample {
Advance Java – Module 1
public static void main(String[] args) {
int a = 10;
System.out.println("Initial a: " + a);
a += 5;
System.out.println("After a += 5: " + a);
a -= 3;
System.out.println("After a -= 3: " + a);
a *= 2;
System.out.println("After a *= 2: " + a);
a /= 4;
System.out.println("After a /= 4: " + a);
a %= 3;
System.out.println("After a %= 3: " + a);
Output
Initial a: 10
After a += 5: 15
After a -= 3: 12
After a *= 2: 24
Advance Java – Module 1
After a /= 4: 6
After a %= 3: 0
4. Relational Operators
Definition
Relational operators are used to compare two values. They return a boolean result (true or
false) depending on the comparison outcome.
Types of Relational Operators
Operator Meaning Example Result
== Equal to 5 == 5 true
!= Not equal to 5 != 3 true
> Greater than 7>5 true
< Less than 3<5 true
>= Greater than or equal to 5 >= 5 true
<= Less than or equal to 4 <= 6 true
How it Works
• Compares left operand with right operand.
• Returns true if the comparison is correct, otherwise returns false.
• Commonly used in conditions like if, while, for.
Syntax
boolean result = (operand1 operator operand2);
Example
public class RelationalExample {
public static void main(String[] args) {
Advance Java – Module 1
int x = 10, y = 20;
System.out.println("x == y: " + (x == y));
System.out.println("x != y: " + (x != y));
System.out.println("x > y: " + (x > y));
System.out.println("x < y: " + (x < y));
System.out.println("x >= y: " + (x >= y));
System.out.println("x <= y: " + (x <= y));
Output
x == y: false
x != y: true
x > y: false
x < y: true
x >= y: false
x <= y: true
5. Logical Operators
Definition
Logical operators are used to combine multiple boolean expressions or values, producing a
boolean result (true or false).
Types of Logical Operators
Operator Meaning Example Result
&& Logical AND → true if both (x > 5 && y < true only if both conditions
operands are true 10) are true
Advance Java – Module 1
|| Logical OR → true if at least one (x > 5 || y < true if any condition is true
operand is true 10)
! Logical NOT → reverses boolean !(x > 5) true if x > 5 is false
value
How it Works
• AND (&&) → All conditions must be true for the result to be true.
• OR (||) → At least one condition must be true for the result to be true.
• NOT (!) → Inverts the truth value of a boolean expression.
Syntax
boolean result = condition1 && condition2;
boolean result = condition1 || condition2;
boolean result = !condition;
Example
public class LogicalExample {
public static void main(String[] args) {
int x = 8, y = 5;
System.out.println("(x > 5 && y < 10): " + (x > 5 && y < 10));
System.out.println("(x > 5 && y > 10): " + (x > 5 && y > 10));
System.out.println("(x > 5 || y > 10): " + (x > 5 || y > 10));
System.out.println("(x < 5 || y < 10): " + (x < 5 || y < 10));
System.out.println("!(x > 5): " + !(x > 5));
}
Advance Java – Module 1
Output
(x > 5 && y < 10): true
(x > 5 && y > 10): false
(x > 5 || y > 10): true
(x < 5 || y < 10): true
!(x > 5): false
6. Bitwise Operators
Definition
Bitwise operators perform operations directly on binary representations of integer types (byte,
short, int, long, and char). They work at the bit level, unlike logical operators which work with
boolean values.
Types of Bitwise Operators
Operator Meaning Example Result (Binary) Result (Decimal)
& Bitwise AND 5&3 0101 & 0011 = 0001 1
| Bitwise OR 5|3 0101 | 0011 = 0111 7
^ Bitwise XOR 5^3 0101 ^ 0011 = 0110 6
~ Bitwise Complement ~5 ~00000101 = 11111010 -6 (2’s
complement)
<< Left Shift 5 << 1 00000101 << 1 = 10
00001010
>> Right Shift (sign- 5 >> 1 00000101 >> 1 = 2
preserving) 00000010
>>> Unsigned Right Shift -5 >>> 1 Shifts right with zero fill Large positive value
How it Works
• & → Only 1 if both bits are 1.
• | → 1 if at least one bit is 1.
• ^ → 1 if bits are different.
Advance Java – Module 1
• ~ → Inverts every bit (1 → 0, 0 → 1).
• << → Shifts bits to the left, filling with zeros.
• >> → Shifts bits right, preserving the sign bit (keeps negative numbers negative).
• >>> → Shifts bits right, filling with zeros (ignores sign bit).
Syntax
result = operand1 & operand2;
result = operand1 | operand2;
result = operand1 ^ operand2;
result = ~operand;
result = operand << positions;
result = operand >> positions;
result = operand >>> positions;
Example
public class BitwiseExample {
public static void main(String[] args) {
int a = 5; // Binary: 0101
int b = 3; // Binary: 0011
System.out.println("a & b: " + (a & b));
System.out.println("a | b: " + (a | b));
System.out.println("a ^ b: " + (a ^ b));
System.out.println("~a: " + (~a));
System.out.println("a << 1: " + (a << 1));
System.out.println("a >> 1: " + (a >> 1));
System.out.println("-a >>> 1: " + (-a >>> 1));
}
Advance Java – Module 1
Output
a & b: 1
a | b: 7
a ^ b: 6
~a: -6
a << 1: 10
a >> 1: 2
-a >>> 1: 2147483645
7. Ternary Operator
Definition
The ternary operator (?:) is a conditional operator that evaluates a boolean expression and
returns one of two values depending on whether the expression is true or false.
How it Works
• If the condition is true, the first value is returned.
• If the condition is false, the second value is returned.
Syntax
variable = (condition) ? valueIfTrue : valueIfFalse;
Example
public class TernaryExample {
public static void main(String[] args) {
int a = 10, b = 20;
String result = (a > b) ? "a is greater" : "b is greater";
System.out.println(result);
Advance Java – Module 1
int max = (a > b) ? a : b;
System.out.println("Max value: " + max);
Output
b is greater
Max value: 20
Key Points
• The ternary operator is the only operator in Java that takes three operands.
• It’s a concise replacement for small if-else statements but should be avoided for complex
logic for readability.
8. Type Cast Operators
Definition
Type casting operators are used to convert a variable from one data type to another. In Java,
this can be done implicitly (widening) or explicitly (narrowing).
Types of Casting
Type Description Example
Widening Smaller type → Larger type (no data loss, done int → long, float →
(Implicit) automatically) double
Narrowing Larger type → Smaller type (possible data loss, double → int, long
(Explicit) must be done manually) → byte
How it Works
• Widening: Java automatically converts if no risk of losing data.
• Narrowing: You must use a cast operator (type) because data might be lost.
Syntax
// Widening
Advance Java – Module 1
largerTypeVar = smallerTypeVar;
// Narrowing
smallerTypeVar = (smallerType) largerTypeVar;
Example
public class TypeCastExample {
public static void main(String[] args) {
// Widening (Automatic)
int intVal = 100;
double doubleVal = intVal; // int → double
System.out.println("Widening: " + doubleVal);
// Narrowing (Manual)
double pi = 3.14159;
int intPi = (int) pi; // double → int
System.out.println("Narrowing: " + intPi);
// Narrowing with data loss
int largeNum = 260;
byte smallNum = (byte) largeNum; // int → byte (data loss)
System.out.println("Data loss example: " + smallNum);
Output
Widening: 100.0
Narrowing: 3
Advance Java – Module 1
Data loss example: 4
Key Points
• Widening is safe and automatic.
• Narrowing may lose precision or data and must be done explicitly.
• Casting between incompatible types (like String to int) requires parsing, not type casting.
9. Expressions in Java
Definition
An expression in Java is a combination of variables, constants, operators, and method calls that
produces a single value.
How it Works
• An expression is evaluated by the Java compiler to produce a result.
• The type of the result depends on the components and operators used.
• Every expression has:
o Operands (values or variables)
o Operators (symbols like +, *, &&, ? :)
o Result (evaluated value)
Types of Expressions
Type Example Result
Arithmetic Expression 5+3*2 11
Relational Expression a>b true / false
Logical Expression (a > b) && (c < d) true / false
Assignment Expression x = 10 10
Ternary Expression (a > b) ? a : b One of the two values
Method Call Expression Math.sqrt(16) 4.0
Syntax
Advance Java – Module 1
result = operand1 operator operand2;
boolean isTrue = (a > b) && (c < d);
Example
public class ExpressionExample {
public static void main(String[] args) {
int a = 5, b = 3, c = 10;
// Arithmetic Expression
int sum = a + b * c; // precedence: * before +
System.out.println("Arithmetic Expression: " + sum);
// Relational Expression
boolean isGreater = a > b;
System.out.println("Relational Expression: " + isGreater);
// Logical Expression
boolean logic = (a > b) && (c > a);
System.out.println("Logical Expression: " + logic);
// Ternary Expression
int max = (a > c) ? a : c;
System.out.println("Ternary Expression (Max): " + max);
// Assignment Expression
int x;
System.out.println("Assignment Expression: " + (x = 100));
Advance Java – Module 1
// Method Call Expression
double squareRoot = Math.sqrt(81);
System.out.println("Method Call Expression: " + squareRoot);
Output
Arithmetic Expression: 35
Relational Expression: true
Logical Expression: true
Ternary Expression (Max): 10
Assignment Expression: 100
Method Call Expression: 9.0
Key Points to Remember
• An expression always produces a value.
• Operator precedence and associativity matter in how expressions are evaluated.
• Use parentheses () to make expressions clearer and avoid precedence confusion.
Control Statements in Java
Control statements in Java are instructions that determine the flow of execution in a program.
They allow conditional execution, looping, and branching based on certain conditions.
Types of Control Statements
1. Decision-Making Statements (if, if-else, if-else-if, nested if, switch)
2. Looping Statements (for, while, do-while, for-each)
3. Branching Statements (break, continue, return)
Advance Java – Module 1
1. if Statement
Definition: Executes a block of code only if the given condition is true.
Syntax:
if (condition) {
// statements to execute if condition is true
How it works: The condition inside parentheses is evaluated. If it is true, the block executes;
otherwise, it is skipped.
Example:
public class IfExample {
public static void main(String[] args) {
int number = 10;
if (number > 5) {
System.out.println("Number is greater than 5");
Output:
Number is greater than 5
2. if-else Statement
Definition: Executes one block if the condition is true, otherwise executes another block.
Syntax:
if (condition) {
// executed if true
} else {
// executed if false
}
Advance Java – Module 1
How it works: If the condition is true, the first block executes; if false, the else block executes.
Example:
public class IfElseExample {
public static void main(String[] args) {
int number = 3;
if (number > 5) {
System.out.println("Number is greater than 5");
} else {
System.out.println("Number is 5 or less");
Output:
Number is 5 or less
3. if-else-if Ladder
Definition: Used to check multiple conditions sequentially.
Syntax:
if (condition1) {
// executed if condition1 is true
} else if (condition2) {
// executed if condition2 is true
} else {
// executed if none are true
}
Advance Java – Module 1
How it works: Conditions are evaluated from top to bottom. The first condition that evaluates
to true executes its block, and remaining conditions are skipped.
Example:
public class IfElseIfExample {
public static void main(String[] args) {
int marks = 85;
if (marks >= 90) {
System.out.println("Grade A+");
} else if (marks >= 75) {
System.out.println("Grade A");
} else {
System.out.println("Grade B");
Output:
Grade A
4. Nested if Statement
Definition: An if statement inside another if statement.
Syntax:
java
if (condition1) {
if (condition2) {
// executed if both are true
Advance Java – Module 1
How it works: The outer condition is evaluated first; if true, the inner condition is checked.
Example:
public class NestedIfExample {
public static void main(String[] args) {
int age = 20;
int weight = 65;
if (age >= 18) {
if (weight > 50) {
System.out.println("Eligible to donate blood");
Output:
Eligible to donate blood
5. Switch Statement in Java
Definition
The switch statement is a multi-way branch statement that allows a variable to be tested against
a list of values, each associated with a case. It is an alternative to the if-else-if ladder when
checking for equality against multiple constant values.
How it Works
1. The switch expression is evaluated once.
Advance Java – Module 1
2. The result is compared with each case value.
3. If a match is found, the corresponding block is executed.
4. The break statement is used to exit the switch after executing the matched case.
5. If no match is found, the default block is executed (optional).
Syntax
switch (expression) {
case value1:
// code block
break;
case value2:
// code block
break;
...
default:
// code block
Example
public class SwitchExample {
public static void main(String[] args) {
int day = 3;
String dayName;
switch (day) {
case 1:
dayName = "Monday";
break;
Advance Java – Module 1
case 2:
dayName = "Tuesday";
break;
case 3:
dayName = "Wednesday";
break;
case 4:
dayName = "Thursday";
break;
case 5:
dayName = "Friday";
break;
case 6:
dayName = "Saturday";
break;
case 7:
dayName = "Sunday";
break;
default:
dayName = "Invalid day";
System.out.println("Day: " + dayName);
Output
Advance Java – Module 1
Day: Wednesday
For Loop in Java
Definition
The for loop in Java is an entry-controlled looping statement that executes a block of code
repeatedly for a known number of iterations. It is often used when you know in advance how
many times you want to execute a statement or block of statements.
How it Works
1. Initialization: Runs only once at the start; used to initialize loop control variables.
2. Condition: Checked before each iteration; if true, the loop body executes; if false, the
loop terminates.
3. Update: Executed after each iteration; used to change the loop control variable.
Syntax
for (initialization; condition; update) {
// code to be executed
Example
public class ForLoopExample {
public static void main(String[] args) {
for (int i = 1; i <= 5; i++) {
System.out.println("Iteration: " + i);
Output
Iteration: 1
Iteration: 2
Advance Java – Module 1
Iteration: 3
Iteration: 4
Iteration: 5
While Loop in Java
Definition
The while loop in Java is an entry-controlled loop that repeatedly executes a block of code as
long as a given condition evaluates to true. It is generally used when the number of iterations is
not known beforehand and depends on a condition being met during execution.
How it Works
1. Condition Check: Before each iteration, the loop evaluates the condition.
2. Execution: If the condition is true, the loop body executes.
3. Re-evaluation: After executing the body, the condition is checked again.
4. Termination: When the condition becomes false, the loop ends.
Syntax
while (condition) {
// code to be executed
Example
public class WhileLoopExample {
public static void main(String[] args) {
int count = 1;
while (count <= 5) {
System.out.println("Count: " + count);
count++;
}
Advance Java – Module 1
Output
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Do-While Loop in Java
Definition
The do-while loop in Java is an exit-controlled loop that executes a block of code at least once,
and then repeatedly executes it as long as the given condition evaluates to true. Unlike the
while loop, the condition is checked after the loop body is executed.
How it Works
1. Execution First: The loop body executes once before any condition check.
2. Condition Check: After execution, the condition is evaluated.
3. Repeat or Terminate: If the condition is true, the loop body executes again. If false, the
loop ends.
Syntax
do {
// code to be executed
} while (condition);
Example
public class DoWhileExample {
public static void main(String[] args) {
int count = 1;
Advance Java – Module 1
do {
System.out.println("Count: " + count);
count++;
} while (count <= 5);
Output
Count: 1
Count: 2
Count: 3
Count: 4
Count: 5
Enhanced For Loop (For-Each) in Java
Definition
The enhanced for loop, also known as the for-each loop, is used to iterate over arrays or
collections without using an explicit counter. It automatically iterates through all elements in a
sequence, providing a simpler and more readable approach when you don’t need to know the
index.
How it Works
1. The loop picks each element from the collection or array one by one.
2. The variable in the loop temporarily stores the current element for use inside the loop
body.
3. The process repeats until all elements have been processed.
Syntax
for (datatype variable : array_or_collection) {
// code to be executed
Advance Java – Module 1
Example
public class EnhancedForLoopExample {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Cherry"};
for (String fruit : fruits) {
System.out.println("Fruit: " + fruit);
Output
Fruit: Apple
Fruit: Banana
Fruit: Cherry
Break Statement in Java
Definition
The break statement is used to terminate a loop or switch statement immediately, regardless of
whether the loop’s condition has been met or not. Control is transferred to the statement
immediately following the loop or switch.
How it Works
1. When the break statement is encountered inside a loop or switch, program control
jumps out of that structure.
2. It is often used when a certain condition is met and there’s no need to continue further
iterations.
Syntax
break;
Advance Java – Module 1
Continue Statement in Java
Definition
The continue statement is used in loops to skip the current iteration and move control to the
next iteration of the loop. Unlike break, it does not terminate the loop entirely—it just skips the
rest of the code in the current iteration.
How it Works
1. When continue is executed inside a loop, the remaining statements in that iteration are
ignored.
2. In for loops, the increment/decrement step is executed, and then the loop condition is
checked for the next iteration.
3. In while and do-while loops, control jumps to the condition check immediately.
Syntax
continue;
Return Statement in Java
Definition
The return statement is used in a method to exit from the method and optionally return a value
to the caller.
• In void methods, it is used without any value, simply to exit the method.
• In methods with a return type, it must return a value that matches the method's
declared return type.
How it Works
1. When the return statement is encountered, the method stops executing immediately.
2. If the method has a return type, the return statement must provide a value of that type.
3. After return executes, control is passed back to the method caller.
Syntax
return; // used in void methods
return value; // used in methods with a return type
Advance Java – Module 1
4.Arrays and Strings:
4.1 Single-dimensional array:
Definition
A single-dimensional array in Java is a collection of elements of the same data type stored in
contiguous memory locations and accessed using an index.
It allows you to store multiple values under one variable name, using indices to differentiate
them.
Key Points
• The index of an array starts at 0 and goes up to length - 1.
• Arrays are objects in Java (created in heap memory).
• Size of an array is fixed and must be specified at creation.
• Supports both declaration + initialization together or separately.
• Can hold primitive types or objects.
Syntax
// Declaration
dataType[] arrayName; // Recommended
dataType arrayName[]; // Allowed but not preferred
// Memory Allocation
arrayName = new dataType[size];
// Declaration + Initialization
dataType[] arrayName = new dataType[size];
// Inline Initialization
Advance Java – Module 1
dataType[] arrayName = {value1, value2, value3, ...};
How It Works
1. When you create an array using new, memory is allocated in the heap.
2. The reference variable (e.g., arr) points to the array’s memory location.
3. The length of the array is fixed and can be accessed using .length property.
4. Accessing an element outside the valid range throws ArrayIndexOutOfBoundsException.
Example 1 – Declaration, Creation, Initialization Separately
public class ArrayExample1 {
public static void main(String[] args) {
int[] numbers; // Declaration
numbers = new int[5]; // Memory allocation
// Initialization
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;
// Accessing elements
for (int i = 0; i < numbers.length; i++) {
System.out.println("Element at index " + i + ": " + numbers[i]);
}
Advance Java – Module 1
Output:
Element at index 0: 10
Element at index 1: 20
Element at index 2: 30
Element at index 3: 40
Element at index 4: 50
Example 2 – Inline Initialization
public class ArrayExample2 {
public static void main(String[] args) {
String[] fruits = {"Apple", "Banana", "Cherry"};
for (int i = 0; i < fruits.length; i++) {
System.out.println(fruits[i]);
Output:
Apple
Banana
Cherry
Example 3 – Using Enhanced For Loop
public class ArrayExample3 {
public static void main(String[] args) {
Advance Java – Module 1
double[] prices = {10.5, 20.75, 30.0};
for (double price : prices) {
System.out.println(price);
Output:
10.5
20.75
30.0
Default Values in Arrays
When an array is created without explicit initialization, Java assigns default values:
• Numeric types → 0
• char → '\u0000' (null character)
• boolean → false
• Object references → null
Example:
public class DefaultValuesExample {
public static void main(String[] args) {
int[] numbers = new int[3];
System.out.println(numbers[0]); // 0
System.out.println(numbers[1]); // 0
System.out.println(numbers[2]); // 0
}
Advance Java – Module 1
4.2 Multi-Dimensional Arrays
Definition
A multi-dimensional array is an array of arrays. The most common type is a 2D array (matrix-
like structure).
Types
• Rectangular arrays — each row has the same number of columns.
• Jagged arrays — rows have different column sizes.
How it Works
• In Java, a 2D array is actually an array where each element is a reference to another
array.
• Memory is allocated separately for each row.
Example Memory Layout:
int[][] arr = { {1, 2}, {3, 4, 5} };
// arr[0] → [1][2] (length 2)
// arr[1] → [3][4][5] (length 3)
Syntax
datatype[][] arrayName = new datatype[rows][cols];
datatype[][] arrayName = { {val1, val2}, {val3, val4} };
Example Code
public class MultiArrayExample {
public static void main(String[] args) {
// 2D array initialization
int[][] matrix = {
{1, 2, 3},
{4, 5, 6}
Advance Java – Module 1
};
// Accessing elements
System.out.println("Element at (0,1): " + matrix[0][1]);
// Iterating through 2D array
System.out.println("Matrix elements:");
for (int i = 0; i < matrix.length; i++) {
for (int j = 0; j < matrix[i].length; j++) {
System.out.print(matrix[i][j] + " ");
System.out.println();
Output
Element at (0,1): 2
Matrix elements:
123
456
4.3 Array Operations (Copying, Sorting, Searching)
1. Copying Arrays
Definition
Copying an array means creating a new array and transferring the elements from one array to
another.
Advance Java – Module 1
Ways to Copy
1. Manual copy using a loop — element-by-element copy.
2. System.arraycopy() — efficient native method.
3. Arrays.copyOf() — returns a new array with the specified length.
4. clone() — creates a shallow copy of the array.
Syntax & Example
import java.util.Arrays;
public class ArrayCopyExample {
public static void main(String[] args) {
int[] original = {1, 2, 3, 4, 5};
// 1. Manual copy
int[] manualCopy = new int[original.length];
for (int i = 0; i < original.length; i++) {
manualCopy[i] = original[i];
// 2. System.arraycopy()
int[] sysCopy = new int[original.length];
System.arraycopy(original, 0, sysCopy, 0, original.length);
// 3. Arrays.copyOf()
int[] arraysCopy = Arrays.copyOf(original, original.length);
// 4. clone()
Advance Java – Module 1
int[] clonedCopy = original.clone();
System.out.println("Original: " + Arrays.toString(original));
System.out.println("Manual Copy: " + Arrays.toString(manualCopy));
System.out.println("System Copy: " + Arrays.toString(sysCopy));
System.out.println("Arrays.copyOf: " + Arrays.toString(arraysCopy));
System.out.println("Cloned Copy: " + Arrays.toString(clonedCopy));
Output
Original: [1, 2, 3, 4, 5]
Manual Copy: [1, 2, 3, 4, 5]
System Copy: [1, 2, 3, 4, 5]
Arrays.copyOf: [1, 2, 3, 4, 5]
Cloned Copy: [1, 2, 3, 4, 5]
2. Sorting Arrays
Definition
Sorting rearranges elements in ascending or descending order.
Ways to Sort
• Arrays.sort() — ascending order by default.
• Arrays.sort(array, Collections.reverseOrder()) — descending order for objects.
• Manual sorting algorithms — Bubble sort, Selection sort, etc. (for learning).
Syntax & Example
java
Advance Java – Module 1
import java.util.Arrays;
import java.util.Collections;
public class ArraySortExample {
public static void main(String[] args) {
int[] numbers = {5, 2, 8, 1, 3};
// Ascending order
Arrays.sort(numbers);
System.out.println("Ascending: " + Arrays.toString(numbers));
// Descending order (for Integer objects)
Integer[] nums = {5, 2, 8, 1, 3};
Arrays.sort(nums, Collections.reverseOrder());
System.out.println("Descending: " + Arrays.toString(nums));
Output
Ascending: [1, 2, 3, 5, 8]
Descending: [8, 5, 3, 2, 1]
3. Searching in Arrays
Definition
Searching finds the index of an element in an array.
Types
• Linear Search — check each element (works for unsorted arrays).
Advance Java – Module 1
• Binary Search — divide-and-search (works only for sorted arrays).
Syntax & Example
import java.util.Arrays;
public class ArraySearchExample {
public static void main(String[] args) {
int[] numbers = {1, 2, 3, 5, 8};
// 1. Linear Search
int target = 5;
int index = -1;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == target) {
index = i;
break;
System.out.println("Linear Search - 5 found at index: " + index);
// 2. Binary Search (array must be sorted)
int binaryIndex = Arrays.binarySearch(numbers, 5);
System.out.println("Binary Search - 5 found at index: " + binaryIndex);
Output
Linear Search - 5 found at index: 3
Advance Java – Module 1
Binary Search - 5 found at index: 3
4.4 String Class and Methods
Definition
• In Java, a String is an object that represents a sequence of characters.
• The String class is part of the java.lang package and is immutable, meaning once a String
object is created, its value cannot be changed.
Types of String Creation
1. Using String literals
o Stored in the String Constant Pool (SCP) in the method area of memory.
o If a string with the same value exists, it will reuse the reference (no duplicate
object is created).
String s1 = "Hello";
String s2 = "Hello"; // points to the same object in SCP
2. Using new keyword
o Forces creation of a new String object in the heap, even if the value already exists
in SCP.
String s3 = new String("Hello"); // new object in heap + "Hello" in SCP
How Strings Work (Internally)
• Immutability:
o If you modify a string, a new object is created.
o The original string remains unchanged.
• Memory Model:
o SCP stores one copy of each literal string.
o Heap stores objects created via new.
Advance Java – Module 1
Example Memory Diagram:
String a = "Java";
String b = "Java"; // Points to same SCP object
String c = new String("Java"); // New heap object
Common Constructors
String(); // Empty string
String(String original); // Copy constructor
String(char[] chars); // From char array
String(char[] chars, int start, int length); // Partial array
String(byte[] byteArray); // From byte array
Common Methods of String Class
Here’s a table of frequently used methods:
Method Description Example
length() Returns string length "Hello".length() → 5
charAt(index) Returns char at position "Java".charAt(1) → 'a'
substring(start) From start index to end "Java".substring(2) → "va"
substring(start, end) From start to end-1 "Java".substring(1,3) → "av"
contains(str) Checks substring "Java".contains("va") → true
equals(str) Compares case-sensitive "Java".equals("java") → false
equalsIgnoreCase(str) Case-insensitive compare "Java".equalsIgnoreCase("java") →
true
toLowerCase() Lowercase string "JAVA".toLowerCase() → "java"
toUpperCase() Uppercase string "java".toUpperCase() → "JAVA"
Advance Java – Module 1
trim() Removes leading/trailing " hi ".trim() → "hi"
spaces
replace(old, new) Replaces chars "Java".replace('a', 'o') → "Jovo"
split(regex) Splits into array "a,b,c".split(",") → ["a","b","c"]
Example Code: Demonstrating Methods
public class StringMethodsExample {
public static void main(String[] args) {
String str = " Java Programming ";
// Basic info
System.out.println("Original: '" + str + "'");
System.out.println("Length: " + str.length());
// trim
String trimmed = str.trim();
System.out.println("Trimmed: '" + trimmed + "'");
// case change
System.out.println("Uppercase: " + trimmed.toUpperCase());
System.out.println("Lowercase: " + trimmed.toLowerCase());
// substring
System.out.println("Substring (5): " + trimmed.substring(5));
System.out.println("Substring (0,4): " + trimmed.substring(0, 4));
Advance Java – Module 1
// replace
System.out.println("Replace 'a' with '@': " + trimmed.replace('a', '@'));
// contains & equals
System.out.println("Contains 'Java': " + trimmed.contains("Java"));
System.out.println("Equals 'java programming' (ignore case): " +
trimmed.equalsIgnoreCase("java programming"));
// split
String csv = "apple,banana,grapes";
String[] fruits = csv.split(",");
System.out.print("Fruits: ");
for (String fruit : fruits) {
System.out.print(fruit + " ");
// charAt
System.out.println("\nChar at index 2: " + trimmed.charAt(2));
Output
Original: ' Java Programming '
Length: 21
Trimmed: 'Java Programming'
Uppercase: JAVA PROGRAMMING
Advance Java – Module 1
Lowercase: java programming
Substring (5): Programming
Substring (0,4): Java
Replace 'a' with '@': J@v@ Progr@mming
Contains 'Java': true
Equals 'java programming' (ignore case): true
Fruits: apple banana grapes
Char at index 2: v
Key Points to Remember
1. String is immutable → Every modification creates a new object.
2. Use StringBuilder or StringBuffer for mutable strings (we’ll cover in 4.5).
3. Always compare strings using equals() instead of == (which compares references).
4. String literals go to the String Constant Pool, objects created with new go to the heap.
4.5 StringBuffer & StringBuilder
Definition
• StringBuffer and StringBuilder are mutable sequence of characters.
• Unlike String, you can modify their contents without creating a new object.
• They are part of java.lang package.
Key Difference Between String, StringBuffer, StringBuilder
Feature String StringBuffer StringBuilder
Mutability Immutable Mutable Mutable
Thread-safe No Yes (synchronized) No
Advance Java – Module 1
Performance Slower for concat Slower (due to synchronization) Faster
Introduced in Java 1.0 Java 1.0 Java 5
How it Works
• StringBuffer: All methods are synchronized, meaning thread-safe but slower.
• StringBuilder: Methods are not synchronized, making it faster but not thread-safe.
• Both classes store characters in a char[] array internally and resize it automatically when
needed.
Constructors
java
StringBuffer(); // Default capacity 16
StringBuffer(String str); // Initialize with a string
StringBuffer(int capacity); // Initialize with given capacity
StringBuilder();
StringBuilder(String str);
StringBuilder(int capacity);
Common Methods (Both Classes)
Method Description Example
append(str) Adds text at the end sb.append("Java")
insert(offset, str) Inserts text at position sb.insert(1, "Hi")
replace(start, end, str) Replaces substring sb.replace(0, 4, "Hi")
delete(start, end) Deletes characters sb.delete(0, 3)
Advance Java – Module 1
reverse() Reverses the sequence sb.reverse()
capacity() Current storage capacity sb.capacity()
length() Current length of content sb.length()
charAt(index) Returns character at position sb.charAt(2)
Example: StringBuffer
public class StringBufferExample {
public static void main(String[] args) {
StringBuffer sb = new StringBuffer("Hello");
sb.append(" World");
System.out.println("After append: " + sb);
sb.insert(6, "Java ");
System.out.println("After insert: " + sb);
sb.replace(6, 10, "C++");
System.out.println("After replace: " + sb);
sb.delete(6, 10);
System.out.println("After delete: " + sb);
sb.reverse();
System.out.println("After reverse: " + sb);
System.out.println("Capacity: " + sb.capacity());
Advance Java – Module 1
System.out.println("Length: " + sb.length());
Output
After append: Hello World
After insert: Hello Java World
After replace: Hello C++ World
After delete: Hello World
After reverse: dlroW olleH
Capacity: 21
Length: 11
Example: StringBuilder
public class StringBuilderExample {
public static void main(String[] args) {
StringBuilder sb = new StringBuilder("Data");
sb.append(" Science");
System.out.println("After append: " + sb);
sb.insert(5, "Java ");
System.out.println("After insert: " + sb);
sb.replace(5, 9, "Python");
System.out.println("After replace: " + sb);
Advance Java – Module 1
sb.delete(5, 11);
System.out.println("After delete: " + sb);
sb.reverse();
System.out.println("After reverse: " + sb);
Output
After append: Data Science
After insert: Data Java Science
After replace: Data Python Science
After delete: Data Science
After reverse: ecneicS ataD
Performance Tip
• Use StringBuilder when thread safety is not required (single-threaded).
• Use StringBuffer when multiple threads will modify the same string object.
4.6 String Immutability & Interning
1. String Immutability
Definition
A String in Java is immutable, meaning once a String object is created, its value cannot be
changed.
Any modification (concatenation, replace, substring, etc.) creates a new String object instead of
changing the existing one.
Why String is Immutable?
Advance Java – Module 1
1. Security: Strings are used for sensitive data (e.g., database URLs, file paths, usernames,
passwords). If they were mutable, malicious code could change values without
detection.
2. Caching & Performance: Strings are stored in the String Constant Pool (SCP).
Immutability ensures one literal is reused without worrying about it being altered.
3. Thread Safety: Multiple threads can share a String without synchronization.
4. Hashcode Consistency: Strings are used as keys in hash-based collections (HashMap,
HashSet). If a String were mutable, its hashcode could change, breaking map lookups.
Example of Immutability
public class StringImmutability {
public static void main(String[] args) {
String s1 = "Java";
String s2 = s1.concat(" Programming");
System.out.println("s1: " + s1); // Original unchanged
System.out.println("s2: " + s2); // New object created
Output
s1: Java
s2: Java Programming
Here, s1.concat(...) didn’t change s1. A new String object was created for s2.
2. String Interning
Definition
Advance Java – Module 1
Interning means storing only one copy of each distinct String literal in the SCP (String Constant
Pool) so that all variables with the same value share the same reference.
How it Works
• When you create a String literal, JVM checks the SCP:
o If it exists → returns the existing reference.
o If it doesn’t exist → creates a new object in SCP.
• When you use new String("text"):
o Creates a new object in heap.
o Also places "text" in SCP (if not already there).
Using intern() Method
• The intern() method ensures a String is added to the SCP and returns the reference from
the SCP.
String s1 = new String("Hello");
String s2 = "Hello";
System.out.println(s1 == s2); // false (different memory)
System.out.println(s1.intern() == s2); // true (same SCP reference)
Example: Interning & Memory Behavior
public class StringInternExample {
public static void main(String[] args) {
String a = "Java"; // stored in SCP
String b = "Java"; // reuses SCP reference
String c = new String("Java"); // new object in heap
String d = c.intern(); // gets SCP reference
Advance Java – Module 1
System.out.println(a == b); // true
System.out.println(a == c); // false
System.out.println(a == d); // true
Output
true
false
true
Memory Diagram
SCP:
"Java" ← a, b, d reference here
Heap:
[Java] (c references this)
Key Takeaways
1. Immutable → safer, faster for constants, and thread-safe.
2. SCP → avoids duplicate String literals in memory.
3. Use intern() to explicitly add strings to SCP.
4. Use StringBuilder/StringBuffer for mutable strings.
4.7 Common String Operations
This section is basically a toolbox of daily String tasks you’ll perform in Java.
We’ll go through each operation with definition → usage → syntax → code → output.
Advance Java – Module 1
1. Concatenation
Definition: Joining two or more strings together.
Ways:
• Using + operator.
• Using concat() method.
• Using StringBuilder/StringBuffer for better performance in loops.
public class ConcatenationExample {
public static void main(String[] args) {
String s1 = "Java";
String s2 = "Programming";
String result1 = s1 + " " + s2;
String result2 = s1.concat(" ").concat(s2);
System.out.println("Using +: " + result1);
System.out.println("Using concat(): " + result2);
Output:
Using +: Java Programming
Using concat(): Java Programming
2. Comparison
Definition: Checking if two strings are equal or ordering them lexicographically.
• equals() → case-sensitive equality.
Advance Java – Module 1
• equalsIgnoreCase() → case-insensitive equality.
• compareTo() → returns 0 if equal, >0 if first > second, <0 if first < second.
public class ComparisonExample {
public static void main(String[] args) {
String a = "Java";
String b = "java";
System.out.println(a.equals(b)); // false
System.out.println(a.equalsIgnoreCase(b)); // true
System.out.println(a.compareTo("Java")); // 0
System.out.println(a.compareTo("Python")); // negative (Java < Python)
3. Substring Extraction
Definition: Extracting part of a string using substring(start) or substring(start, end).
public class SubstringExample {
public static void main(String[] args) {
String text = "Java Programming";
System.out.println(text.substring(5)); // Programming
System.out.println(text.substring(0, 4)); // Java
4. Splitting Strings
Advance Java – Module 1
Definition: Breaking a string into parts using a delimiter with split().
public class SplitExample {
public static void main(String[] args) {
String csv = "apple,banana,grapes";
String[] fruits = csv.split(",");
for (String fruit : fruits) {
System.out.println(fruit);
Output:
apple
banana
grapes
5. Joining Strings
Definition: Opposite of split — combining multiple strings into one with a delimiter.
import java.util.StringJoiner;
import java.util.Arrays;
public class JoinExample {
public static void main(String[] args) {
StringJoiner sj = new StringJoiner(", ");
sj.add("apple").add("banana").add("grapes");
System.out.println(sj); // apple, banana, grapes
Advance Java – Module 1
// Using String.join()
String joined = String.join(" - ", Arrays.asList("A", "B", "C"));
System.out.println(joined); // A - B - C
6. Trimming Spaces
Definition: Removing leading and trailing spaces using trim() or strip() (Java 11+).
public class TrimExample {
public static void main(String[] args) {
String name = " Java ";
System.out.println("Trimmed: '" + name.trim() + "'");
Output:
Trimmed: 'Java'
7. Changing Case
Definition: Converting all characters to uppercase or lowercase.
public class CaseExample {
public static void main(String[] args) {
String str = "Java";
System.out.println(str.toUpperCase()); // JAVA
System.out.println(str.toLowerCase()); // java
}
Advance Java – Module 1
8. Replacing Characters or Substrings
public class ReplaceExample {
public static void main(String[] args) {
String text = "I like Java";
System.out.println(text.replace("Java", "Python"));
System.out.println(text.replace('a', '@'));
Output:
I like Python
I like J@v@
9. Checking Prefixes & Suffixes
public class PrefixSuffixExample {
public static void main(String[] args) {
String filename = "report.pdf";
System.out.println(filename.startsWith("report")); // true
System.out.println(filename.endsWith(".pdf")); // true
10. Searching in Strings
Advance Java – Module 1
public class SearchExample {
public static void main(String[] args) {
String sentence = "Java is fun";
System.out.println(sentence.indexOf("is")); // 5
System.out.println(sentence.contains("fun")); // true
5. Methods in Java
A method in Java is a block of code that performs a specific task, can be reused, and is executed
when called.
They help in modularity (breaking down code into smaller parts) and code reusability.
5.1 Understanding Methods in Java
Definition
A method is a collection of statements grouped together to perform an operation.
A method can:
• Take input (parameters)
• Perform an operation
• Return a result (or not, if void)
5.1.1 Syntax of a Method
modifier returnType methodName(parameterList) {
// method body
// statements
return value; // if returnType is not void
Advance Java – Module 1
Explanation of parts:
1. modifier – Defines access level (public, private, protected, or default).
2. returnType – Data type of the value returned (int, String, void, etc.).
3. methodName – Unique name for identifying the method.
4. parameterList – Zero or more parameters inside parentheses.
5. method body – The code block {} where the operation happens.
5.1.2 Types of Methods
(a) Predefined (Built-in) Methods
Already available in Java libraries.
Examples:
Math.sqrt(16); // returns 4.0
System.out.println("Hello");
(b) User-defined Methods
Created by the programmer to perform a specific task.
Example:
public class Calculator {
public int add(int a, int b) { // user-defined method
return a + b;
public static void main(String[] args) {
Calculator calc = new Calculator();
int sum = calc.add(5, 3);
System.out.println("Sum: " + sum);
Advance Java – Module 1
5.1.3 Method Declaration vs Method Call
Declaration – Defining how the method works.
Call – Requesting the method to execute.
Example:
// Declaration
void greet() {
System.out.println("Hello, welcome!");
// Call
greet();
5.1.4 Returning a Value
Methods can return results using the return keyword.
Example:
public int square(int num) {
return num * num;
5.1.5 Method Parameters
• Pass by Value – Java passes a copy of the value to the method.
• Multiple Parameters – Separate with commas.
Example:
Advance Java – Module 1
void displayInfo(String name, int age) {
System.out.println(name + " is " + age + " years old.");
5.1.6 Static vs Non-static Methods
Static Methods:
• Belong to the class, not objects.
• Called using the class name.
class Test {
static void sayHello() {
System.out.println("Hello from static method");
public static void main(String[] args) {
Test.sayHello();
Non-static Methods:
• Belong to object instances.
• Require an object to call.
5.1.7 Method Overloading
Defining multiple methods with the same name but different parameter lists.
Example:
class MathOps {
int sum(int a, int b) { return a + b; }
Advance Java – Module 1
double sum(double a, double b) { return a + b; }
5.1.8 Example – Complete Program
public class MethodDemo {
// 1. User-defined method with parameters and return value
public int multiply(int x, int y) {
return x * y;
// 2. Void method
public void greet(String name) {
System.out.println("Hello, " + name + "!");
// 3. Static method
public static void displayInfo() {
System.out.println("Static method example");
public static void main(String[] args) {
MethodDemo obj = new MethodDemo();
// calling non-static methods
int result = obj.multiply(4, 5);
Advance Java – Module 1
System.out.println("Multiplication: " + result);
obj.greet("Chan");
// calling static method
MethodDemo.displayInfo();
Key Points to Remember
• Methods increase reusability and make code cleaner.
• Java always passes parameters by value.
• Static methods belong to the class; non-static methods belong to objects.
• Overloading allows flexibility in method calls.
5.2 Parameter Passing in Java (By Value vs. By Reference)
1. How Parameter Passing Works in Java
In Java, all arguments are passed by value, but the “value” can be:
• Primitive value → The actual value (e.g., 5, true, 'A')
• Object reference → The memory address (reference) to the object
However, Java never passes parameters by reference like C++ (where you can directly modify
the caller’s variable).
2. Passing Primitives (By Value)
When a primitive is passed to a method:
• A copy of the value is made.
Advance Java – Module 1
• Changes inside the method do not affect the original variable.
Example:
public class PassByValueDemo {
public static void main(String[] args) {
int num = 10;
changeValue(num);
System.out.println("After method call: " + num); // Output: 10
static void changeValue(int x) {
x = 20; // Only changes local copy
3. Passing Objects (Reference is Passed by Value)
When an object is passed:
• A copy of the reference is passed.
• Both the original and the method parameter point to the same object.
• Changes to the object’s fields will reflect outside the method.
• Reassigning the reference inside the method does not affect the original reference.
Example 1 – Modifying Object Fields (Affects Original):
class Person {
String name;
public class PassByReferenceDemo {
Advance Java – Module 1
public static void main(String[] args) {
Person p = new Person();
p.name = "Alice";
changeName(p);
System.out.println("After method call: " + p.name); // Output: Bob
static void changeName(Person person) {
person.name = "Bob"; // Changes original object
Example 2 – Reassigning Reference (Does NOT Affect Original):
public class ReassignReferenceDemo {
public static void main(String[] args) {
Person p = new Person();
p.name = "Alice";
reassignPerson(p);
System.out.println("After method call: " + p.name); // Output: Alice
static void reassignPerson(Person person) {
person = new Person(); // New object created
person.name = "Bob"; // Only affects new object
}
Advance Java – Module 1
4. Key Points to Remember
1. Java is always pass-by-value.
2. For primitives → copy of value is passed → no effect outside.
3. For objects → copy of reference is passed → changes to object’s fields affect the original.
4. Reassigning the reference inside the method does not affect the caller’s variable.
5.3 Method Overloading
Definition
Method Overloading in Java is the ability to define multiple methods in the same class with the
same method name but different parameter lists (different number of parameters or different
types of parameters).
It is a type of compile-time polymorphism (also known as static polymorphism).
Key Rules for Method Overloading
1. Same Method Name
All overloaded methods must have the same name.
2. Different Parameter List
At least one of the following must be different:
o Number of parameters
o Data types of parameters
o Order of parameters
3. Return Type Can Be Same or Different
But return type alone cannot differentiate methods — the parameter list must differ.
4. Access Modifier & Exceptions
These can differ but do not affect overloading.
5. Compile-Time Binding
The method to be called is determined at compile time based on the arguments passed.
Advance Java – Module 1
Example: Method Overloading
class MathUtils {
// Overloaded method with 2 int parameters
int add(int a, int b) {
return a + b;
// Overloaded method with 3 int parameters
int add(int a, int b, int c) {
return a + b + c;
// Overloaded method with 2 double parameters
double add(double a, double b) {
return a + b;
// Overloaded method with different parameter order
String add(String a, int b) {
return a + b;
public class Main {
public static void main(String[] args) {
Advance Java – Module 1
MathUtils obj = new MathUtils();
System.out.println(obj.add(10, 20)); // calls int, int
System.out.println(obj.add(10, 20, 30)); // calls int, int, int
System.out.println(obj.add(5.5, 6.5)); // calls double, double
System.out.println(obj.add("Hello", 5)); // calls String, int
Output
30
60
12.0
Hello5
Common Mistakes
Only changing return type will not work:
java
int sum(int a, int b) { return a + b; }
double sum(int a, int b) { return a + b; } // Compilation error
Overloading with same parameter type & count but different variable names is not valid.
Real-World Example
• println() method in Java is overloaded:
System.out.println(10); // int
Advance Java – Module 1
System.out.println(10.5); // double
System.out.println("Hello"); // String
System.out.println(true); // boolean
The JVM decides at compile time which version to call based on the argument type.
5.4 Recursion in Java
Definition
Recursion is a programming technique where a method calls itself to solve a smaller instance of
the same problem until a base condition is met.
It’s a way to solve problems by breaking them down into simpler sub-problems of the same
type.
How Recursion Works
• A recursive method calls itself with a modified parameter.
• There must be a base case (termination condition) to stop the recursive calls; otherwise,
it causes infinite recursion and a StackOverflowError.
• Each recursive call adds a new frame to the call stack until base case is reached, then the
calls return in reverse order.
Syntax of a Recursive Method
returnType methodName(parameters) {
if (base condition) {
// base case: stop recursion
return someValue;
} else {
// recursive call
return methodName(modifiedParameters);
Advance Java – Module 1
Example 1: Factorial Calculation
Factorial of n (written as n!) is:
• n! = n * (n-1) * (n-2) * ... * 1
• By definition, 0! = 1.
Recursive formula:
factorial(n) = n * factorial(n-1), where factorial(0) = 1
public class RecursionExample {
public static int factorial(int n) {
if (n == 0) { // base case
return 1;
} else {
return n * factorial(n - 1); // recursive call
public static void main(String[] args) {
int number = 5;
int fact = factorial(number);
System.out.println("Factorial of " + number + " is: " + fact);
Output:
Advance Java – Module 1
Factorial of 5 is: 120
Example 2: Fibonacci Series
Fibonacci sequence:
• Each number is the sum of the two preceding ones.
• fib(0) = 0, fib(1) = 1
Recursive formula:
fib(n) = fib(n-1) + fib(n-2)
public class FibonacciExample {
public static int fib(int n) {
if (n == 0) return 0; // base cases
if (n == 1) return 1;
return fib(n - 1) + fib(n - 2); // recursive call
public static void main(String[] args) {
int count = 7;
System.out.print("Fibonacci series up to " + count + ": ");
for (int i = 0; i < count; i++) {
System.out.print(fib(i) + " ");
Output:
Advance Java – Module 1
Fibonacci series up to 7: 0 1 1 2 3 5 8
Key Points
• Always define a base case to stop recursion.
• Recursive calls use stack memory — too deep recursion causes StackOverflowError.
• Recursion can be replaced by iteration but is more intuitive for problems like tree
traversal, factorial, Fibonacci, etc.
Visual: Recursive Calls for factorial(3)
factorial(3)
= 3 * factorial(2)
= 3 * (2 * factorial(1))
= 3 * (2 * (1 * factorial(0)))
= 3 * (2 * (1 * 1)) = 6
5.5 Varargs (Variable Arguments) in Java
Definition
Varargs allow a method to accept zero or more arguments of the same type as parameters.
Introduced in Java 5, it provides flexibility so you don’t have to overload methods for different
numbers of parameters.
How Varargs Work
• Syntax uses three dots ... after the data type.
• Inside the method, the varargs parameter is treated as an array.
• You can only have one varargs parameter per method and it must be the last
parameter.
Advance Java – Module 1
Syntax
returnType methodName(dataType... varName) {
// method body, varName is treated like an array
Example:
void printNumbers(int... numbers) {
for (int num : numbers) {
System.out.print(num + " ");
Examples
Example 1: Simple Varargs Method
public class VarargsExample {
static void printNumbers(int... numbers) {
System.out.print("Numbers: ");
for (int num : numbers) {
System.out.print(num + " ");
System.out.println();
public static void main(String[] args) {
printNumbers(1, 2, 3);
printNumbers(10, 20);
printNumbers(); // zero arguments allowed
Advance Java – Module 1
Output:
Numbers: 1 2 3
Numbers: 10 20
Numbers:
Example 2: Varargs with Other Parameters
public class VarargsWithOtherParams {
static void display(String name, int... scores) {
System.out.print(name + "'s scores: ");
for (int score : scores) {
System.out.print(score + " ");
System.out.println();
public static void main(String[] args) {
display("Alice", 90, 80, 85);
display("Bob");
Output:
Alice's scores: 90 80 85
Bob's scores:
Advance Java – Module 1
Important Notes
• You cannot have more than one varargs parameter in a method.
• The varargs parameter must be the last parameter in the parameter list.
• Varargs is internally treated as an array.
• Using varargs helps avoid multiple overloaded methods with varying parameter counts.
Example with Array and Varargs
Both these method calls are valid and equivalent:
printNumbers(new int[]{1, 2, 3});
printNumbers(1, 2, 3);
Comparison with Overloading
Without varargs, you might write multiple overloaded methods like:
void printNumbers(int a) { ... }
void printNumbers(int a, int b) { ... }
void printNumbers(int a, int b, int c) { ... }
With varargs, one method covers all.
5.6 main() Method Deep Dive
What is the main() Method?
• The main() method is the entry point of any Java application.
• When you run a Java program, the JVM looks for the main() method to start execution.
• It is where the program begins and ends.
Standard Syntax
public static void main(String[] args)
Advance Java – Module 1
Breaking Down the Syntax
Part Meaning
public Access modifier — must be public so JVM can access it from outside the class.
static JVM calls this method without creating an object of the class. Static means the
method belongs to the class itself.
void Return type — main() does not return any value.
main Method name — must be exactly main.
String[] Parameter — an array of strings which stores command-line arguments passed
args to the program.
Why These Keywords Are Mandatory?
• public — JVM needs to call it from outside the class.
• static — JVM calls main() without creating an instance of the class.
• void — JVM doesn’t expect any return value after execution.
• String[] args — Accepts arguments from the command line, which makes your program
flexible.
Command-Line Arguments
You can pass arguments to a Java program via the command line like this:
java MyProgram Hello World 123
Inside the program:
public class MyProgram {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(arg);
}
Advance Java – Module 1
Output:
Hello
World
123
Common Variations of main()
Technically, these are valid but not recommended or not used by JVM as entry point:
Variation Explanation
public static void main(String... args) Uses varargs instead of array (valid).
public static void main(String args[]) Array declaration syntax variation (valid).
static public void main(String[] args) Order of modifiers doesn’t matter (valid).
public void main(String[] args) Non-static — JVM cannot call this directly.
public static int main(String[] args) Return type not void — JVM won’t use it as entry.
private static void main(String[] args) Not public — JVM cannot access.
Example: Command-Line Arguments
public class CommandLineDemo {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println("No arguments passed");
} else {
System.out.println("Arguments passed:");
for (String arg : args) {
System.out.println(arg);
Advance Java – Module 1
Run with:
java CommandLineDemo Java 2025
Output:
Arguments passed:
Java
2025
Why Is main() Static?
• The JVM doesn’t instantiate your class to call main().
• It directly calls main() via the class name.
• Being static allows calling it without creating an object.
Can main() Be Overloaded?
Yes, you can overload main() by creating multiple methods with the same name but different
parameters.
public class MainOverload {
public static void main(String[] args) {
System.out.println("Main with String[]");
main(10); // calling overloaded method
public static void main(int num) {
Advance Java – Module 1
System.out.println("Overloaded main: " + num);
Output:
Main with String[]
Overloaded main: 10
But JVM always calls the main(String[] args) method as the program’s entry point.
Summary
Point Description
Purpose Entry point for Java programs
Signature public static void main(String[] args)
Static So JVM can call it without object instantiation
Command-line args String array to receive program arguments
Can be overloaded Yes, but JVM calls only the exact signature
6. Object-Oriented Programming (OOP)
6.1 Classes and Objects
Definition
• Class:
A class is a blueprint or template for creating objects. It defines properties (fields) and
behaviors (methods) that the objects created from the class will have.
Think of a class as a blueprint of a house — it defines the design but isn’t the actual
house.
• Object:
An object is an instance of a class. It represents an actual entity with state and behavior
defined by the class.
Continuing the analogy, the object is an actual house built using the blueprint.
Advance Java – Module 1
How Classes and Objects Work
• A class groups related variables (fields) and methods (functions) together.
• You can create multiple objects from a class.
• Each object has its own copy of fields and can call methods.
Syntax
java
// Class declaration
class ClassName {
// Fields (variables)
dataType field1;
dataType field2;
// Methods (functions)
returnType methodName(parameters) {
// method body
Creating Objects
java
ClassName obj = new ClassName();
• new keyword allocates memory and returns the reference to the object.
• obj is a reference variable that points to the object.
Advance Java – Module 1
Example
java
class Car {
// Fields (attributes)
String color;
String model;
int year;
// Method (behavior)
void displayInfo() {
System.out.println("Car Model: " + model);
System.out.println("Color: " + color);
System.out.println("Year: " + year);
public class TestCar {
public static void main(String[] args) {
// Create an object of Car
Car car1 = new Car();
// Set fields
car1.color = "Red";
car1.model = "Tesla Model S";
Advance Java – Module 1
car1.year = 2023;
// Call method
car1.displayInfo();
Output
Car Model: Tesla Model S
Color: Red
Year: 2023
Important Concepts
• Reference Variable: Points to the object stored in heap memory.
• Heap Memory: Where actual objects are stored.
• Multiple Objects: You can create many objects with different states.
Car car2 = new Car();
car2.color = "Blue";
car2.model = "BMW X5";
car2.year = 2022;
• car1 and car2 are two different objects with independent data.
Summary
Advance Java – Module 1
Term Description
Class Blueprint for objects; defines variables & methods.
Object Instance of a class; actual entity with state and behavior.
Fields Variables inside class to hold data.
Methods Functions inside class to define behaviors.
new Keyword to create an object and allocate memory.
6.2 Constructors & Constructor Overloading
What is a Constructor?
• A constructor is a special method in a class that is called automatically when an object
is created.
• Its purpose is to initialize the new object.
• A constructor has the same name as the class and no return type (not even void).
Key Characteristics
Property Description
Name Must be the same as the class name
Return Type None (not even void)
Invocation Automatically called with new
Purpose Initialize object’s fields
Can be overloaded Yes, multiple constructors with different parameters
Default Constructor
• If you do not define any constructor, the Java compiler provides a default constructor
(no-arg constructor) automatically.
Advance Java – Module 1
• The default constructor initializes instance variables with default values (0, null, false,
etc.).
Example:
class Person {
String name;
int age;
public class TestPerson {
public static void main(String[] args) {
Person p = new Person(); // default constructor is called
System.out.println(p.name); // null
System.out.println(p.age); // 0
Parameterized Constructor
• You can define your own constructor that takes parameters to initialize the object with
specific values.
Syntax:
class ClassName {
ClassName(parameters) {
// initialization code
Example:
class Person {
Advance Java – Module 1
String name;
int age;
// Parameterized constructor
Person(String name, int age) {
this.name = name;
this.age = age;
public class TestPerson {
public static void main(String[] args) {
Person p = new Person("Alice", 30); // parameterized constructor called
System.out.println(p.name); // Alice
System.out.println(p.age); // 30
Constructor Overloading
• You can have multiple constructors in the same class with different parameter lists.
• The compiler decides which constructor to call based on the arguments passed.
Example:
class Person {
String name;
int age;
Advance Java – Module 1
// No-arg constructor
Person() {
name = "Unknown";
age = 0;
// Parameterized constructor
Person(String name) {
this.name = name;
age = 0;
// Parameterized constructor with two parameters
Person(String name, int age) {
this.name = name;
this.age = age;
public class TestPerson {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person("Bob");
Person p3 = new Person("Charlie", 25);
System.out.println(p1.name + ", " + p1.age); // Unknown, 0
Advance Java – Module 1
System.out.println(p2.name + ", " + p2.age); // Bob, 0
System.out.println(p3.name + ", " + p3.age); // Charlie, 25
Important Points
• Constructors do not have return types.
• If you define any constructor, the default no-arg constructor is not provided
automatically.
• Use this keyword inside constructor to refer to the current object’s fields (explained in
6.3).
• Constructors can call other constructors using constructor chaining (this(...)) —
explained later.
Summary
Term Description
Constructor Special method to initialize new objects.
Default constructor No-arg constructor auto-provided if none defined.
Parameterized constructor Constructor with parameters to initialize fields.
Constructor Overloading Multiple constructors with different parameters.
6.3 this Keyword
Definition
• this is a reference variable in Java that refers to the current object — the instance on
which a method or constructor is being called.
Advance Java – Module 1
• It helps distinguish between instance variables and local variables when they have the
same name.
• It is also used to call other constructors in the same class (constructor chaining).
Uses of this Keyword
Use Case Explanation Example
Refer to current object’s Disambiguate between local and this.name = name; inside a
instance variable instance variables constructor
Call another constructor To reuse constructor code and this(10, 20); inside a
in the same class avoid duplication (this(...)) constructor
Pass current object as Pass current object reference to someMethod(this);
argument another method or constructor
Return current object To allow method chaining return this;
from method
1. Using this to Refer to Instance Variables
When a constructor or method has a parameter with the same name as an instance variable,
this clarifies which is which.
Example:
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name; // 'this.name' refers to instance variable, 'name' refers to parameter
this.age = age;
}
Advance Java – Module 1
void display() {
System.out.println("Name: " + this.name);
System.out.println("Age: " + this.age);
public class TestThis {
public static void main(String[] args) {
Person p = new Person("Alice", 25);
p.display();
Output:
Name: Alice
Age: 25
2. Using this() to Call Another Constructor (Constructor Chaining)
this() calls another constructor in the same class. It must be the first statement in the
constructor.
Example:
class Person {
String name;
int age;
Person() {
Advance Java – Module 1
this("Unknown", 0); // calls parameterized constructor
Person(String name, int age) {
this.name = name;
this.age = age;
void display() {
System.out.println(name + " - " + age);
public class TestThisConstructor {
public static void main(String[] args) {
Person p1 = new Person();
Person p2 = new Person("Bob", 30);
p1.display(); // Unknown - 0
p2.display(); // Bob - 30
3. Passing Current Object Using this
You can pass the current object to another method or constructor.
Advance Java – Module 1
class Printer {
void print(Person p) {
System.out.println(p.name + ", " + p.age);
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
void show() {
Printer printer = new Printer();
printer.print(this); // passing current object
public class TestThisPass {
public static void main(String[] args) {
Person p = new Person("Alice", 25);
p.show();
}
Advance Java – Module 1
Output:
Alice, 25
4. Returning Current Object (Method Chaining)
class Person {
String name;
int age;
Person setName(String name) {
this.name = name;
return this;
Person setAge(int age) {
this.age = age;
return this;
void display() {
System.out.println(name + ", " + age);
}
Advance Java – Module 1
public class TestThisChain {
public static void main(String[] args) {
Person p = new Person();
p.setName("Bob").setAge(30);
p.display();
Output:
Bob, 30
Important Notes
• this cannot be used in static contexts because static methods belong to the class, not to
any object.
• Use this mainly to resolve naming conflicts and for constructor chaining.
• this increases code clarity and helps avoid bugs.
6.4 static Keyword in Java
Definition
• The static keyword in Java means "belongs to the class rather than instances (objects)".
• When you declare a variable, method, or block as static, it belongs to the class itself and
not to any specific object.
• All instances of the class share the same static members.
Where can static be used?
Usage Description
Advance Java – Module 1
Static Variables Also called class variables; shared across all instances.
Static Methods Methods that can be called without creating an object.
Static Blocks Used to initialize static variables. Executes once when the class is
loaded.
Static Nested Nested classes declared static (more in topic 6.12).
Classes
1. Static Variables
• Declared using static keyword inside a class but outside methods.
• Only one copy exists, shared by all objects of the class.
• Used for constants or counters that are common to all instances.
Example:
class Counter {
static int count = 0; // static variable
Counter() {
count++; // Increment when new object is created
static void displayCount() {
System.out.println("Count: " + count);
public class TestStaticVar {
public static void main(String[] args) {
Advance Java – Module 1
Counter c1 = new Counter();
Counter c2 = new Counter();
Counter c3 = new Counter();
Counter.displayCount(); // Output: Count: 3
Output:
Count: 3
2. Static Methods
• Declared with static keyword.
• Can be called without creating an object.
• Cannot access instance variables or methods directly because they belong to objects.
• Can access static variables and other static methods directly.
• Can only use this keyword in instance methods, so this is not available in static
methods.
Example:
class MathUtils {
static int square(int x) {
return x * x;
public class TestStaticMethod {
Advance Java – Module 1
public static void main(String[] args) {
int result = MathUtils.square(5); // call without object
System.out.println("Square of 5 is: " + result);
Output:
Square of 5 is: 25
3. Static Blocks
• A static initialization block is used to initialize static variables.
• It runs once when the class is loaded (before any object is created).
• Useful for complex initialization.
Example:
class Demo {
static int data;
static {
data = 100;
System.out.println("Static block executed");
static void display() {
System.out.println("Data: " + data);
}
Advance Java – Module 1
public class TestStaticBlock {
public static void main(String[] args) {
Demo.display();
Output:
Static block executed
Data: 100
Summary Table
Static Member Description
Static Variable Single copy shared by all instances of the class
Static Method Can be called without an object; no access to instance members
Static Block Executes once when class is loaded; used for static init
Important Notes
• Static members belong to the class, not individual objects.
• Access static members using the class name, e.g., ClassName.staticMethod().
• Instance methods can access static variables and methods directly.
• Static methods cannot access instance variables or methods directly.
• main() method is static so JVM can call it without creating an object.
6.5 Encapsulation & Access Modifiers
Advance Java – Module 1
What is Encapsulation?
• Encapsulation is one of the fundamental concepts of Object-Oriented Programming
(OOP).
• It means wrapping data (variables) and code (methods) together as a single unit — a
class.
• It restricts direct access to some of an object’s components, which means internal
details are hidden from outside.
• This is done to protect the data from unauthorized access and modification.
• Encapsulation is also called data hiding.
How Encapsulation is Achieved in Java?
• By declaring class variables as private (restricting direct access).
• Providing public getter and setter methods to access and update the value of private
variables.
• This controls how the data is accessed or modified.
Access Modifiers in Java
Access modifiers control the visibility (scope) of classes, variables, methods, and constructors.
Modifier Class Package Subclass World Description
(Anywhere)
private Yes No No No Accessible only within the same class
(default)* Yes Yes No No Accessible within the same package
protected Yes Yes Yes No Accessible within same package &
subclasses
public Yes Yes Yes Yes Accessible from anywhere
Advance Java – Module 1
* Default access modifier means no modifier is specified.
Example: Encapsulation with Access Modifiers
class Person {
// Private variables — cannot be accessed directly outside the class
private String name;
private int age;
// Public getter method for name
public String getName() {
return name;
// Public setter method for name
public void setName(String name) {
this.name = name;
// Public getter method for age
public int getAge() {
return age;
// Public setter method for age with validation
public void setAge(int age) {
if (age > 0) {
Advance Java – Module 1
this.age = age;
} else {
System.out.println("Invalid age!");
public class TestEncapsulation {
public static void main(String[] args) {
Person p = new Person();
// Using setter methods to set values
p.setName("Alice");
p.setAge(25);
// Using getter methods to access values
System.out.println("Name: " + p.getName());
System.out.println("Age: " + p.getAge());
// Trying to set invalid age
p.setAge(-5); // Output: Invalid age!
Output:
Name: Alice
Advance Java – Module 1
Age: 25
Invalid age!
Why Encapsulation is Important?
• Data Protection: Private variables protect internal object data from being corrupted.
• Control: Control over how variables are set or retrieved (validation logic in setters).
• Maintainability: Internal implementation can change without affecting external code.
• Flexibility: Easy to change one part of the code without affecting others.
• Reusability: Encapsulated code can be reused more safely.
Summary Table
Concept Description
Encapsulation Binding data & methods; hiding internal state.
private Restricts access to within the same class only.
public Allows access from anywhere.
protected Access within package and subclasses.
default (no modifier) Access only within the package.
Getter/Setter Public methods to access private fields safely.
6.6 Inheritance in Java
What is Inheritance?
• Inheritance is an OOP concept where a new class (called child or subclass) inherits
properties and behaviors (fields and methods) from an existing class (called parent or
superclass).
• It promotes code reusability and establishes a "is-a" relationship.
For example, a Dog "is a" Animal, so Dog class can inherit from Animal class.
Advance Java – Module 1
Benefits of Inheritance
• Code reuse — avoid duplication.
• Method overriding (modify inherited behavior).
• Polymorphism support.
• Logical class hierarchy organization.
Syntax
class ParentClass {
// fields and methods
class ChildClass extends ParentClass {
// additional fields and methods
Types of Inheritance in Java
1. Single Inheritance
One class inherits from one superclass.
class Animal {
void eat() {
System.out.println("Eating...");
}
Advance Java – Module 1
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
2. Multilevel Inheritance
A class inherits from a subclass, forming a chain.
class Animal {
void eat() {
System.out.println("Eating...");
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
class Puppy extends Dog {
void weep() {
System.out.println("Weeping...");
3. Hierarchical Inheritance
Multiple subclasses inherit from a single superclass.
Advance Java – Module 1
class Animal {
void eat() {
System.out.println("Eating...");
class Dog extends Animal {
void bark() {
System.out.println("Barking...");
class Cat extends Animal {
void meow() {
System.out.println("Meowing...");
Example: Multilevel Inheritance
class Animal {
void eat() {
System.out.println("Eating...");
class Dog extends Animal {
Advance Java – Module 1
void bark() {
System.out.println("Barking...");
class Puppy extends Dog {
void weep() {
System.out.println("Weeping...");
public class TestInheritance {
public static void main(String[] args) {
Puppy p = new Puppy();
p.eat(); // inherited from Animal
p.bark(); // inherited from Dog
p.weep(); // own method
Output:
Eating...
Barking...
Weeping...
Important Points
Advance Java – Module 1
• Java does not support multiple inheritance (a class cannot extend more than one class)
to avoid ambiguity (diamond problem).
• Use interfaces for multiple inheritance of type.
• Constructors of the parent class are not inherited, but can be called using super()
keyword.
• Child class inherits all non-private members of parent class.
• The keyword extends is used to inherit from a class.
Summary
Inheritance Type Description
Single Inheritance One class inherits from one superclass
Multilevel Inheritance Class inherits from subclass, creating chain
Hierarchical Inheritance Multiple subclasses inherit from one superclass
6.7 super Keyword in Java
Definition
• The super keyword in Java is a reference variable used to refer to the immediate parent
class object.
• It is commonly used to:
o Access parent class methods that are overridden in the child class.
o Access parent class fields if hidden by child class fields.
o Invoke the parent class constructor from a child class constructor.
Uses of super Keyword
Use Case Explanation Syntax Example
Access parent class Call a method in the parent class super.methodName();
method overridden by child
Advance Java – Module 1
Access parent class Refer to parent class field hidden super.fieldName;
field by child field
Call parent class Invoke parent class constructor super(parameters); (must be first
constructor from child constructor statement)
1. Using super to Access Parent Class Methods
If a child class overrides a parent method, you can call the parent version using super.
class Animal {
void sound() {
System.out.println("Animal makes a sound");
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
void parentSound() {
super.sound(); // Calls Animal's sound()
public class TestSuper {
public static void main(String[] args) {
Dog d = new Dog();
Advance Java – Module 1
d.sound(); // Dog barks
d.parentSound(); // Animal makes a sound
2. Using super to Access Parent Class Fields
If child class has a field with the same name as the parent, super accesses the parent’s field.
class Parent {
int num = 100;
class Child extends Parent {
int num = 200;
void display() {
System.out.println("Child num: " + num); // 200
System.out.println("Parent num: " + super.num); // 100
public class TestSuperField {
public static void main(String[] args) {
Child c = new Child();
c.display();
}
Advance Java – Module 1
3. Using super to Call Parent Class Constructor
You can call the parent’s constructor from the child constructor using super(). It must be the
first statement.
class Parent {
Parent() {
System.out.println("Parent constructor");
class Child extends Parent {
Child() {
super(); // Calls Parent constructor
System.out.println("Child constructor");
public class TestSuperConstructor {
public static void main(String[] args) {
Child c = new Child();
Output:
kotlin
Advance Java – Module 1
Parent constructor
Child constructor
Important Points
• super() calls the immediate parent class constructor.
• If you don’t explicitly call super(), Java inserts a no-arg super() automatically if available.
• super can only be used in instance methods or constructors, not in static context.
• Using super helps to access overridden methods or hidden fields.
Summary
Usage Description
super.method() Call parent class method overridden by child
super.field Access parent class field hidden by child
super() Call parent class constructor
6.8 Method Overriding in Java
What is Method Overriding?
• Method Overriding occurs when a subclass (child class) provides a specific
implementation of a method that is already defined in its superclass (parent class).
• The method in the subclass must have the same name, return type, and parameters as
the method in the superclass.
• It allows a subclass to modify or extend the behavior of an inherited method.
• Overriding is a key feature that enables runtime polymorphism (dynamic method
dispatch).
Rules for Method Overriding
Advance Java – Module 1
Rule Description
Method name and parameter Must be exactly the same as in the parent class
list
Return type Must be the same or a subtype (covariant return)
Access modifier Cannot be more restrictive than the parent method
Exceptions Can only throw the same or fewer checked exceptions
Cannot override final or static final methods cannot be overridden; static methods are
methods hidden, not overridden
Syntax
class Parent {
void display() {
System.out.println("Parent display");
class Child extends Parent {
@Override
void display() {
System.out.println("Child display");
Example
class Animal {
void sound() {
Advance Java – Module 1
System.out.println("Animal makes a sound");
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
public class TestOverride {
public static void main(String[] args) {
Animal a = new Animal();
a.sound(); // Animal makes a sound
Dog d = new Dog();
d.sound(); // Dog barks
Animal a2 = new Dog();
a2.sound(); // Dog barks — runtime polymorphism
Output:
Animal makes a sound
Advance Java – Module 1
Dog barks
Dog barks
Key Points
• @Override annotation (optional but recommended) helps the compiler check that you
are correctly overriding a method.
• Overriding happens at runtime; the JVM determines which method to call based on the
object type.
• This enables polymorphism, allowing the same method call to behave differently
depending on the object.
• You cannot override methods declared final or static (static methods are hidden, not
overridden).
• Access modifiers of the overriding method cannot be more restrictive (e.g., cannot
change public to private).
6.9 Polymorphism in Java
What is Polymorphism?
• Polymorphism means "many forms".
• In Java, polymorphism allows an entity (method or object) to take multiple forms.
• It enables a single interface or method to represent different underlying forms (data
types or classes).
• Polymorphism improves code flexibility and reusability.
Types of Polymorphism in Java
Type Description When It Happens How
Implemented
Advance Java – Module 1
Compile-time Method overloading — At compile time Method
(Static) multiple methods with the (method signature Overloading
Polymorphism same name but different resolved)
parameters.
Runtime Method overriding — subclass At runtime Method
(Dynamic) provides specific (method to call Overriding +
Polymorphism implementation of a parent determined) Inheritance
method.
1. Compile-time Polymorphism (Method Overloading)
• Multiple methods with the same name but different parameter lists (type, number, or
order).
• The compiler decides which method to call based on method signature.
Example:
class Calculator {
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;
}
Advance Java – Module 1
public class TestOverloading {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(5, 10)); // 15
System.out.println(calc.add(3.5, 2.5)); // 6.0
System.out.println(calc.add(1, 2, 3)); // 6
2. Runtime Polymorphism (Method Overriding)
• When a subclass overrides a method of its superclass.
• The method to execute is determined at runtime based on the object's actual type (not
reference type).
• Supports dynamic method dispatch.
Example:
class Animal {
void sound() {
System.out.println("Animal makes a sound");
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
Advance Java – Module 1
class Cat extends Animal {
@Override
void sound() {
System.out.println("Cat meows");
public class TestPolymorphism {
public static void main(String[] args) {
Animal a;
a = new Dog();
a.sound(); // Dog barks
a = new Cat();
a.sound(); // Cat meows
a = new Animal();
a.sound(); // Animal makes a sound
Output:
Advance Java – Module 1
Dog barks
Cat meows
Animal makes a sound
How Runtime Polymorphism Works Internally?
• The JVM uses a virtual method table (vtable) for dynamic method dispatch.
• The actual method called depends on the runtime type of the object.
Key Points
Aspect Description
Compile-time polymorphism Method overloading; resolved by
compiler
Runtime polymorphism Method overriding; resolved at runtime
by JVM
Polymorphism enables Flexibility, code reuse, extensibility
Requires inheritance For runtime polymorphism
Allows treating subclass objects as superclass Promotes generalization
references
Summary Table
Polymorphism Description Example
Type
Compile-time Method overloading (same name, diff add(int, int) and add(double,
(Static) params) double)
Runtime (Dynamic) Method overriding in subclass Animal a = new Dog();
a.sound();
Advance Java – Module 1
6.10 Abstraction in Java
What is Abstraction?
• Abstraction is an OOP concept that focuses on hiding complex implementation details
and showing only the essential features of an object.
• It helps in reducing complexity and increasing efficiency.
• In Java, abstraction is achieved mainly through:
o Abstract Classes
o Interfaces
1. Abstract Class
• An abstract class is a class that cannot be instantiated directly.
• It can contain abstract methods (methods without a body) that must be implemented
by subclasses.
• It can also have concrete methods (methods with implementations).
• Used to provide a common base with some shared code and some methods to be
defined by subclasses.
Syntax
abstract class Animal {
abstract void sound(); // abstract method
void sleep() { // concrete method
System.out.println("Sleeping...");
class Dog extends Animal {
Advance Java – Module 1
void sound() {
System.out.println("Dog barks");
Example
abstract class Animal {
abstract void sound();
void sleep() {
System.out.println("Sleeping...");
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
public class TestAbstract {
public static void main(String[] args) {
// Animal a = new Animal(); // Error: Cannot instantiate abstract class
Dog d = new Dog();
d.sound(); // Dog barks
d.sleep(); // Sleeping...
Advance Java – Module 1
Output:
Dog barks
Sleeping...
2. Interface
• An interface is a reference type that can contain only abstract methods, default and
static methods (from Java 8), and constants.
• A class implements an interface and provides implementations for its abstract methods.
• Supports multiple inheritance of type (a class can implement multiple interfaces).
Syntax
java
interface Animal {
void sound(); // implicitly abstract
class Dog implements Animal {
public void sound() {
System.out.println("Dog barks");
}
Advance Java – Module 1
Example
java
interface Animal {
void sound();
class Dog implements Animal {
public void sound() {
System.out.println("Dog barks");
public class TestInterface {
public static void main(String[] args) {
Dog d = new Dog();
d.sound(); // Dog barks
Output:
Dog barks
Differences Between Abstract Class and Interface
Feature Abstract Class Interface
Advance Java – Module 1
Instantiation Cannot instantiate Cannot instantiate
Methods Can have abstract and Only abstract (before Java 8); default and
concrete methods static allowed after Java 8
Variables Can have instance variables Only constants (public static final)
Multiple Not supported Supported (a class can implement multiple
Inheritance interfaces)
Constructor Can have constructors Cannot have constructors
Use Case Shared code and common Define contract for classes
base
Summary
Concept Description
Abstraction Hiding internal details, showing essentials
Abstract Class Base class with abstract and concrete methods
Interface Pure abstraction with method declarations
Implement/Extend Class implements interface or extends abstract class
6.11 final Keyword in Java
What is the final Keyword?
• The final keyword in Java is used to declare constants, prevent method overriding, and
inheritance.
• It can be applied to:
o Variables (fields or local variables)
o Methods
o Classes
Advance Java – Module 1
1. final Variables
• A variable declared as final cannot be reassigned after it has been initialized.
• It effectively becomes a constant.
• If a final variable is not initialized at the point of declaration, it must be initialized in the
constructor (for instance variables).
Example:
class Constants {
final double PI = 3.14159; // constant
final int DAYS_IN_WEEK;
Constants() {
DAYS_IN_WEEK = 7; // final variable initialized in constructor
void display() {
System.out.println("PI = " + PI);
System.out.println("Days in a week = " + DAYS_IN_WEEK);
public class TestFinalVariable {
public static void main(String[] args) {
Constants c = new Constants();
c.display();
Advance Java – Module 1
// c.PI = 3.14; // Error: cannot assign a value to final variable PI
Output:
PI = 3.14159
Days in a week = 7
2. final Methods
• A method declared as final cannot be overridden by subclasses.
• It is used to prevent modification of method behavior in subclasses.
• Useful when you want to lock down certain methods.
Example:
class Parent {
final void show() {
System.out.println("Final method in Parent");
class Child extends Parent {
// void show() { // Error: Cannot override final method
// System.out.println("Trying to override");
// }
public class TestFinalMethod {
Advance Java – Module 1
public static void main(String[] args) {
Child c = new Child();
c.show(); // Output: Final method in Parent
3. final Classes
• A class declared as final cannot be subclassed.
• Used to prevent inheritance when you want to lock the class implementation.
• For example, String class is final in Java.
Example:
final class FinalClass {
void display() {
System.out.println("Final class method");
// class SubClass extends FinalClass { // Error: Cannot subclass final class
// }
public class TestFinalClass {
public static void main(String[] args) {
FinalClass obj = new FinalClass();
obj.display();
}
Advance Java – Module 1
Summary Table
Use of final Effect
final variable Value cannot be changed after initialization
final method Cannot be overridden by subclasses
final class Cannot be extended (no subclassing)
Important Notes
• final variables should be initialized once only.
• final method can still be overloaded, but not overridden.
• Marking a class final improves security and performance.
• final and static are often used together for constants, e.g., static final double PI =
3.14159;
6.12 Nested & Inner Classes in Java
What are Nested and Inner Classes?
• Nested Classes are classes defined within another class.
• They help logically group classes that are only used in one place, increase encapsulation,
and improve readability.
• There are two main types:
o Static Nested Classes
o Inner Classes (non-static nested classes)
Types of Nested Classes
Type Description
Advance Java – Module 1
Static Nested Nested class declared with static keyword. It can access only static members
Class of outer class.
Inner Class Non-static nested class that is associated with an instance of the outer class.
Can access all members, including private ones, of outer class.
Inner classes can be further divided into:
• Member Inner Class (non-static class inside another class)
• Local Inner Class (defined inside a method)
• Anonymous Inner Class (no name, used for quick implementation)
1. Static Nested Class
• Declared static inside an outer class.
• Does not have access to instance variables/methods of outer class directly.
• Can access only static members of outer class.
• Used when nested class functionality is related but does not need access to instance
data.
Syntax & Example:
class Outer {
static int data = 30;
static class StaticNested {
void display() {
System.out.println("Data from outer class: " + data);
public class TestStaticNested {
Advance Java – Module 1
public static void main(String[] args) {
Outer.StaticNested nested = new Outer.StaticNested();
nested.display();
Output:
Data from outer class: 30
2. Member Inner Class
• Defined inside a class without static modifier.
• Has access to all members (even private) of outer class.
• Associated with an instance of the outer class.
• To instantiate, first create an instance of the outer class.
Syntax & Example:
class Outer {
private int data = 10;
class Inner {
void display() {
System.out.println("Data from outer class: " + data);
public class TestInnerClass {
Advance Java – Module 1
public static void main(String[] args) {
Outer outer = new Outer();
Outer.Inner inner = outer.new Inner();
inner.display();
Output:
Data from outer class: 10
3. Local Inner Class
• Defined inside a method.
• Visible only within that method.
• Can access final or effectively final variables of the method.
Example:
class Outer {
void display() {
final int num = 100;
class LocalInner {
void print() {
System.out.println("Value of num: " + num);
LocalInner local = new LocalInner();
Advance Java – Module 1
local.print();
public class TestLocalInner {
public static void main(String[] args) {
Outer outer = new Outer();
outer.display();
Output:
Value of num: 100
4. Anonymous Inner Class
• Inner class without a name.
• Used to instantiate and override methods of a class or interface quickly.
• Commonly used in event handling, callbacks, etc.
Example:
abstract class Animal {
abstract void sound();
public class TestAnonymousInner {
public static void main(String[] args) {
Animal dog = new Animal() {
Advance Java – Module 1
void sound() {
System.out.println("Dog barks");
};
dog.sound();
Output:
Dog barks
Summary Table
Nested Class Description Access to Outer Class Instantiation
Type Members
Static Nested Static class inside outer Only static members Outer.StaticNested obj = new
Class class Outer.StaticNested();
Member Inner Non-static class inside All members, Outer.Inner obj = outer.new
Class outer class including private Inner();
Local Inner Class defined inside a Final/effectively final Inside method only
Class method method vars
Anonymous Class without name, Depends on parent Inline during instantiation
Inner Class instantiated on the spot class/interface
7. Packages and Access control:
7.1 Creating and Using Packages
Definition & purpose
Advance Java – Module 1
• A package is a namespace that groups related classes and interfaces.
• Packages help avoid name collisions, organize code, and control access (package-level
visibility).
• Common convention: reverse domain name (e.g. com.example.project).
How it maps to files / classpath
• If a class declares package com.example.util;, its .java file should live in
com/example/util/ relative to a source root.
• When compiling, either compile from the source root or use -d to specify an output
directory that preserves package directories.
• At runtime the JVM uses the classpath to locate package directories.
Syntax
package com.example.util; // must be top of file (except comments)
public class MyClass { ... }
You can use fully-qualified names instead of importing:
com.example.util.MyClass obj = new com.example.util.MyClass();
Rules / notes
• Top-level classes can be public or package-private (no modifier). They cannot be private
or protected.
• One public top-level class per .java file, and filename must match the public class name.
• import statements are optional (convenience) — you can always use fully-qualified
names.
• Wildcard import (import com.example.util.*;) imports types in that package only (not
subpackages).
Example — small project
Project layout:
project-root/
com/example/util/MathUtil.java
Advance Java – Module 1
com/example/util/Parent.java
com/example/app/Child.java
com/example/util/MathUtil.java
package com.example.util;
public class MathUtil {
public static final double PI = 3.141592653589793;
public static int add(int a, int b) { return a + b; }
// package-private (no modifier)
static int packageSecret() { return 42; }
// private
private static int privateSecret() { return -1; }
com/example/util/Parent.java
package com.example.util;
public class Parent {
public int publicField = 1;
protected int protectedField = 2;
int packageField = 3; // package-private
private int privateField = 4;
public int getPrivateField() { return privateField; }
}
Advance Java – Module 1
com/example/app/Child.java
package com.example.app;
import com.example.util.Parent;
import static com.example.util.MathUtil.PI; // static import example
import static com.example.util.MathUtil.add;
public class Child extends Parent {
public void showAccess() {
System.out.println("publicField = " + publicField); // OK
System.out.println("protectedField = " + protectedField); // OK (via inheritance)
// System.out.println("packageField = " + packageField); // COMPILE ERROR (package-
private)
// System.out.println("privateField = " + privateField); // COMPILE ERROR (private)
System.out.println("parentPrivateViaGetter = " + getPrivateField()); // OK
public static void main(String[] args) {
Child c = new Child();
c.showAccess();
System.out.println("PI via static import = " + PI);
System.out.println("add(2,3) via static import = " + add(2, 3));
// MathUtil.packageSecret(); // COMPILE ERROR if uncommented: packageSecret has
package access only
}
Advance Java – Module 1
Compile & run (from project-root)
javac com/example/util/*.java com/example/app/*.java
java com.example.app.Child
Expected output
publicField = 1
protectedField = 2
parentPrivateViaGetter = 4
PI via static import = 3.141592653589793
add(2,3) via static import = 5
Common pitfalls
• If you put package com.example.util; but don't place file in com/example/util/, javac will
complain if classpath/layout mismatch.
• Avoid mixing classes in the default package and named packages — classes in named
packages cannot import classes from the default package.
7.2 Access Modifiers
Four access levels for members/classes
1. public — accessible from anywhere (any package).
2. protected — accessible in same package and in subclasses (even if subclass is in a
different package). See the nuance below.
3. default (no modifier) — package-private: accessible only to classes in the same package.
4. private — accessible only inside the declaring class (but nested classes can access
private members of the outer class).
Top-level class modifiers
• A top-level class can be public or package-private (omit modifier). It cannot be private or
protected.
Advance Java – Module 1
Protected nuance (important)
• protected members are accessible to subclasses in other packages, but when accessed
from a subclass in a different package the access must be through the subclass (i.e.,
through this or through an expression whose type is the subclass). Accessing a protected
member through a superclass reference to an instance of the superclass from the
subclass in a different package is not allowed.
Example demonstrating the nuance:
// in package com.example.util
public class Parent {
protected int prot = 10;
// in package com.example.app
import com.example.util.Parent;
public class Child extends Parent {
void test() {
System.out.println(prot); // OK: accessed directly as subclass
Parent p = new Parent();
// System.out.println(p.prot); // COMPILE ERROR: cannot access protected via Parent ref
from different package
Access summary table (members accessed from another package)
• public → yes
• protected → yes if subclass (with the subclass-access nuance), otherwise no
• package-private (default) → no
• private → no
Advance Java – Module 1
Inner classes & private members
• Inner classes (non-static nested) and static nested classes inside the outer class can
access the outer class’s private members. Private is class-scoped (including nested
classes).
7.3 Importing Classes & Static Imports
import vs fully-qualified name
• import is compile-time convenience only. It lets you write List instead of java.util.List.
• You can always use java.util.List without an import.
Syntax
import com.example.util.MathUtil; // single-type import
import com.example.util.*; // on-demand import (types only)
Static import (since Java 5; available in Java 8)
• Lets you import static members (fields or methods) so you can reference them without
the class name.
import static java.lang.Math.PI;
import static java.lang.Math.*; // import all static members
• Use sparingly — static imports can hurt readability if overused.
Rules & gotchas
• import com.example.util.*; does not import subpackages (e.g.,
com.example.util.subpkg).
• import statements must appear after the package statement (if any) and before type
declarations.
• Static import only imports public and protected static members accessible from your
context.
Example (already shown above) — static import of PI and add:
import static com.example.util.MathUtil.PI;
import static com.example.util.MathUtil.add;
Advance Java – Module 1
System.out.println(PI);
System.out.println(add(2, 3));
When you don’t need import
• Types in java.lang (e.g., String, System) are implicitly imported.
• Nested classes can be referenced by Outer.Inner without import if Outer is accessible.
More examples & compiler error illustrations
Trying to access package-private from another package
If you uncomment the System.out.println("packageField = " + packageField); line in
Child.showAccess() you’ll get a compile error like:
error: packageField is not public in Parent; cannot be accessed from outside package
Trying to access private
If you try to access privateField directly you’ll see:
error: privateField has private access in Parent
Protected-access-through-superclass-reference error
If you do:
Parent p = new Parent();
System.out.println(p.protectedField);
from a subclass in a different package, javac will produce an error similar to:
error: protectedField has protected access in Parent
(While protectedField is accessible in the subclass when referenced directly as protectedField.)
1. A complete, pasteable Java 8 project folder (with build.sh / run.sh) so you can run and
test all package & access control examples.
2. Deep-dive expansions on:
o Package naming conventions
Advance Java – Module 1
o JARs & classpath basics
o Classloaders & package visibility
o Protected vs package-private nuances with more examples and exact compiler
output
Complete runnable Java 8 example project
Folder structure
java-packages-demo/
├── build.sh
├── run.sh
└── src/
└── com/
└── example/
├── util/
│ ├── MathUtil.java
│ └── Parent.java
└── app/
└── Child.java
src/com/example/util/MathUtil.java
package com.example.util;
public class MathUtil {
public static final double PI = 3.141592653589793;
Advance Java – Module 1
public static int add(int a, int b) {
return a + b;
// package-private
static int packageSecret() {
return 42;
// private
private static int privateSecret() {
return -1;
src/com/example/util/Parent.java
package com.example.util;
public class Parent {
public int publicField = 1;
protected int protectedField = 2;
int packageField = 3; // package-private
private int privateField = 4;
public int getPrivateField() {
return privateField;
}
Advance Java – Module 1
src/com/example/app/Child.java
package com.example.app;
import com.example.util.Parent;
import static com.example.util.MathUtil.PI;
import static com.example.util.MathUtil.add;
public class Child extends Parent {
public void showAccess() {
System.out.println("publicField = " + publicField); // OK
System.out.println("protectedField = " + protectedField); // OK (via inheritance)
// System.out.println("packageField = " + packageField); // ERROR: package-private,
different package
// System.out.println("privateField = " + privateField); // ERROR: private access
System.out.println("parentPrivateViaGetter = " + getPrivateField()); // OK
public static void main(String[] args) {
Child c = new Child();
c.showAccess();
System.out.println("PI via static import = " + PI);
System.out.println("add(2,3) via static import = " + add(2, 3));
Advance Java – Module 1
// MathUtil.packageSecret(); // ERROR: package-private access not allowed here
build.sh
#!/bin/bash
mkdir -p out
javac -d out $(find src -name "*.java")
run.sh
#!/bin/bash
java -cp out com.example.app.Child
How to run
chmod +x build.sh run.sh
./build.sh
./run.sh
Expected output
publicField = 1
protectedField = 2
parentPrivateViaGetter = 4
PI via static import = 3.141592653589793
add(2,3) via static import = 5
Deep-dive expansions
A. Package naming conventions
• Reverse domain name: ensures uniqueness.
Example: com.google.gson, org.apache.commons.lang3
• Lowercase letters: avoids clashes with class names.
Advance Java – Module 1
• Subpackages: reflect logical module separation:
com.mycompany.project.model
com.mycompany.project.service
com.mycompany.project.util
• Avoid underscores and special characters: stick to letters/numbers.
B. JARs & classpath basics
• JAR (Java Archive): a .zip file containing .class files, resources, and a META-
INF/MANIFEST.MF.
• Compile to a JAR:
jar cvf mylib.jar -C out .
• Run from JAR:
o With Main-Class in manifest:
java -jar mylib.jar
o Without manifest, add JAR to classpath:
java -cp mylib.jar com.example.app.Child
• Multiple classpath entries:
java -cp "lib/*:out" com.example.app.Child
C. Classloaders & package visibility
• Bootstrap loader: loads java.* core classes from rt.jar in Java 8.
• Extension loader: loads JDK extension libraries from lib/ext.
• System loader: loads classes from the application classpath.
• Custom classloaders: can load classes dynamically from URLs, encrypted files, etc.
• Package-level visibility: If two classes with the same package name are loaded by
different classloaders, they are considered to be in different packages for access control.
Advance Java – Module 1
D. Protected vs package-private nuances
Same package:
package pkg1;
public class A {
protected int prot = 1;
int pkg = 2;
class B {
void test() {
A a = new A();
System.out.println(a.prot); // OK
System.out.println(a.pkg); // OK
Different package, subclass:
package pkg2;
import pkg1.A;
public class C extends A {
void test() {
System.out.println(prot); // OK via inheritance
A a = new A();
// System.out.println(a.prot); // ERROR: can't access via superclass ref
Compiler error message in Java 8:
Advance Java – Module 1
error: prot has protected access in A
System.out.println(a.prot);
8. Exception Handling:
8.1 Types of Exceptions (Checked, Unchecked, Errors)
Definition
• In Java, an exception is an event that disrupts the normal flow of a program during
execution.
• Java categorizes throwable objects into three main categories:
Hierarchy
java.lang.Object
└── java.lang.Throwable
├── java.lang.Exception → recoverable issues
│ ├── Checked Exceptions → must be declared/handled
│ └── Unchecked Exceptions (RuntimeException) → programmer errors or logic issues
└── java.lang.Error → serious system-level issues
Checked Exceptions
• Definition: Exceptions that the compiler forces you to handle with try-catch or declare
with throws.
• Examples: IOException, SQLException, ClassNotFoundException
• Purpose: Represent conditions that a reasonable application might want to catch.
Example
import java.io.*;
public class CheckedExample {
Advance Java – Module 1
public static void main(String[] args) {
try {
FileReader fr = new FileReader("nonexistent.txt"); // may throw FileNotFoundException
} catch (FileNotFoundException e) {
System.out.println("Checked Exception caught: " + e);
Output
Checked Exception caught: java.io.FileNotFoundException: nonexistent.txt (No such file or
directory)
If you remove the try-catch and don’t declare throws FileNotFoundException, javac gives:
error: unreported exception FileNotFoundException; must be caught or declared to be thrown
Unchecked Exceptions
• Definition: Exceptions that are subclasses of RuntimeException.
• Compiler does not require explicit handling.
• Examples: NullPointerException, ArithmeticException, ArrayIndexOutOfBoundsException
• Purpose: Typically programming mistakes.
Example
public class UncheckedExample {
public static void main(String[] args) {
int a = 5 / 0; // ArithmeticException at runtime
Output
Advance Java – Module 1
Exception in thread "main" java.lang.ArithmeticException: / by zero
Errors
• Definition: Subclasses of java.lang.Error.
• Not meant to be caught — represent serious problems that usually cannot be recovered
from.
• Examples: OutOfMemoryError, StackOverflowError
Example
public class ErrorExample {
public static void main(String[] args) {
// StackOverflowError due to infinite recursion
recurse();
static void recurse() {
recurse();
Output
Exception in thread "main" java.lang.StackOverflowError
Summary Table
Type Examples Compile-time Typical Cause
Check?
Checked IOException, SQLException Yes External conditions
Exception (files, DB)
Unchecked NullPointerException, No Logic/programming
Exception ArithmeticException errors
Advance Java – Module 1
Error OutOfMemoryError, No JVM/system-level
StackOverflowError failures
8.2 try, catch, finally
Definition
In Java, exceptions are handled using:
• try → Block of code where exceptions might occur.
• catch → Block to handle specific exceptions.
• finally → Block that always executes after try (and catch), regardless of whether an
exception occurred.
Syntax
try {
// risky code
} catch (ExceptionType1 e1) {
// handle exception type 1
} catch (ExceptionType2 e2) {
// handle exception type 2
} finally {
// cleanup code (executes regardless)
Rules
1. try must be followed by at least one catch or finally (or both).
2. finally is optional, but when present, runs even if:
o An exception is thrown and caught.
o An exception is thrown and not caught.
Advance Java – Module 1
o A return statement is executed in try or catch.
3. Only case when finally does not run: JVM exits (System.exit(0)) or a fatal error occurs.
Example 1 — Normal Execution
public class TryCatchFinallyDemo {
public static void main(String[] args) {
try {
System.out.println("Inside try block");
int result = 10 / 2; // no exception
System.out.println("Result = " + result);
} catch (ArithmeticException e) {
System.out.println("Caught: " + e);
} finally {
System.out.println("Finally block always runs");
Output
Inside try block
Result = 5
Finally block always runs
Example 2 — Exception Occurs & is Caught
public class TryCatchFinallyDemo2 {
public static void main(String[] args) {
try {
Advance Java – Module 1
System.out.println("Before risky code");
int result = 10 / 0; // throws ArithmeticException
System.out.println("This line won't run");
} catch (ArithmeticException e) {
System.out.println("Caught exception: " + e);
} finally {
System.out.println("Finally block executed");
Output
Before risky code
Caught exception: java.lang.ArithmeticException: / by zero
Finally block executed
Example 3 — Exception Not Caught
public class TryCatchFinallyDemo3 {
public static void main(String[] args) {
try {
String str = null;
System.out.println(str.length()); // NullPointerException
} catch (ArithmeticException e) {
System.out.println("Caught ArithmeticException");
} finally {
System.out.println("Finally still runs");
}
Advance Java – Module 1
Output
Finally still runs
Exception in thread "main" java.lang.NullPointerException
at TryCatchFinallyDemo3.main(TryCatchFinallyDemo3.java:6)
(Notice: finally ran before the uncaught exception terminated the program.)
Example 4 — Finally with return
public class TryCatchFinallyReturn {
public static void main(String[] args) {
System.out.println(method());
static int method() {
try {
return 1;
} finally {
System.out.println("Finally runs before method returns");
Output
Finally runs before method returns
1
Advance Java – Module 1
Example 5 — Finally skipped with System.exit
public class FinallySkipDemo {
public static void main(String[] args) {
try {
System.out.println("Exiting JVM");
System.exit(0);
} finally {
System.out.println("This will NOT run");
Output
Exiting JVM
8.3 Multiple Catch Blocks
Definition
• Multiple catch blocks allow you to handle different exception types separately after a
single try block.
• The first catch block whose parameter matches the thrown exception type (or a
superclass of it) will handle the exception — then control moves past all other catches.
Syntax
try {
// risky code
} catch (ExceptionType1 e1) {
// handle exception type 1
} catch (ExceptionType2 e2) {
Advance Java – Module 1
// handle exception type 2
} catch (Exception e) {
// generic handler (must be last)
Rules
1. Catch blocks are checked in order — more specific exceptions must come before more
general exceptions, otherwise compilation fails.
2. Only one catch block executes for a given exception.
3. From Java 7+, you can combine multiple exception types in a single catch using the
multi-catch feature:
catch (IOException | SQLException ex) {
// common handling
Example 1 — Separate catch blocks
public class MultipleCatchDemo {
public static void main(String[] args) {
try {
String s = null;
System.out.println(s.length()); // NullPointerException
int x = 10 / 0; // ArithmeticException (won't reach here)
} catch (ArithmeticException e) {
System.out.println("Caught ArithmeticException: " + e);
} catch (NullPointerException e) {
System.out.println("Caught NullPointerException: " + e);
} catch (Exception e) {
System.out.println("Caught generic Exception: " + e);
Advance Java – Module 1
Output
Caught NullPointerException: java.lang.NullPointerException
(Only the NPE catch block runs; ArithmeticException line is never reached.)
Example 2 — Wrong order causes compile error
public class WrongOrderCatch {
public static void main(String[] args) {
try {
int x = 10 / 0;
} catch (Exception e) { // <-- Too general
System.out.println("Generic exception");
} catch (ArithmeticException e) { // <-- Unreachable
System.out.println("Arithmetic exception");
Compilation error
error: exception ArithmeticException has already been caught
Example 3 — Multi-catch (Java 7+)
import java.io.*;
public class MultiCatchDemo {
Advance Java – Module 1
public static void main(String[] args) {
try {
if (args.length == 0) {
throw new IOException("No file provided");
} else {
throw new NullPointerException("Simulated NPE");
} catch (IOException | NullPointerException e) {
System.out.println("Caught: " + e);
Output (when run without args)
Caught: java.io.IOException: No file provided
Example 4 — Variable in multi-catch is final
In a multi-catch, the exception variable is implicitly final — you cannot reassign it.
public class MultiCatchFinalVar {
public static void main(String[] args) {
try {
throw new IOException("Test");
} catch (IOException | RuntimeException e) {
// e = new IOException(); // Compile error: variable e is final
System.out.println(e.getMessage());
}
Advance Java – Module 1
8.4 Nested try-catch
Definition
• A nested try-catch means putting a try block inside another try (or inside catch/finally).
• This is used when you want to handle different risky operations separately while still
being in a larger protected block.
• Common in file operations, database work, or multi-step tasks where each step may fail
independently.
Syntax
try {
// outer risky code
try {
// inner risky code
} catch (SpecificException e) {
// handle inner exception
} catch (GeneralException e) {
// handle outer exception
Rules
1. Inner try must have its own catch or finally.
2. An exception thrown in the inner try can be caught by the inner catch if it matches.
3. If the inner catch does not handle it, the exception propagates to the outer try-catch.
4. Nested try-catch can also appear inside a catch or finally block.
Advance Java – Module 1
Example 1 — Inner try handles exception
public class NestedTryDemo1 {
public static void main(String[] args) {
try {
System.out.println("Outer try start");
try {
int result = 10 / 0; // ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Inner catch: " + e);
System.out.println("Outer try end");
} catch (Exception e) {
System.out.println("Outer catch: " + e);
Output
Outer try start
Inner catch: java.lang.ArithmeticException: / by zero
Outer try end
(Inner catch handled the exception, so outer catch never ran.)
Example 2 — Inner catch doesn’t handle, outer catch runs
public class NestedTryDemo2 {
public static void main(String[] args) {
try {
Advance Java – Module 1
System.out.println("Outer try start");
try {
String s = null;
System.out.println(s.length()); // NullPointerException
} catch (ArithmeticException e) {
System.out.println("Inner catch: " + e); // Won't catch NPE
System.out.println("Outer try end"); // Won’t run because NPE propagates
} catch (Exception e) {
System.out.println("Outer catch: " + e);
Output
Outer try start
Outer catch: java.lang.NullPointerException
Example 3 — Nested try inside catch
public class NestedTryInCatch {
public static void main(String[] args) {
try {
int[] arr = new int[3];
System.out.println(arr[5]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Outer catch: " + e);
try {
Advance Java – Module 1
int result = 10 / 0; // Another risky operation
} catch (ArithmeticException ex) {
System.out.println("Inner catch inside outer catch: " + ex);
Output
Outer catch: java.lang.ArrayIndexOutOfBoundsException: Index 5 out of bounds for length 3
Inner catch inside outer catch: java.lang.ArithmeticException: / by zero
Example 4 — Nested try inside finally
public class NestedTryInFinally {
public static void main(String[] args) {
try {
System.out.println("Main try");
} catch (Exception e) {
System.out.println("Catch block");
} finally {
try {
String s = null;
System.out.println(s.length());
} catch (NullPointerException e) {
System.out.println("Handled inside finally: " + e);
}
Advance Java – Module 1
Output
Main try
Handled inside finally: java.lang.NullPointerException
8.5 Throwing Exceptions (throw keyword)
Definition
• The throw keyword is used inside a method or block to explicitly throw an exception
object.
• You can throw either:
o A checked exception (must be declared with throws in the method signature or
caught).
o An unchecked exception (subclass of RuntimeException) — no declaration
required.
Syntax
throw new ExceptionType("message");
Rules
1. You can throw only one exception at a time with throw.
2. The object after throw must be an instance of Throwable (Exception or Error).
3. If throwing a checked exception, you must:
o Handle it in a try-catch, or
o Declare it in the method with throws.
4. Throwing an unchecked exception does not require declaration.
Example 1 — Throwing a checked exception
Advance Java – Module 1
import java.io.IOException;
public class ThrowCheckedExample {
public static void main(String[] args) {
try {
readFile();
} catch (IOException e) {
System.out.println("Caught exception: " + e.getMessage());
static void readFile() throws IOException {
throw new IOException("File not found");
Output
Caught exception: File not found
Example 2 — Throwing an unchecked exception
public class ThrowUncheckedExample {
public static void main(String[] args) {
checkAge(15);
static void checkAge(int age) {
if (age < 18) {
Advance Java – Module 1
throw new IllegalArgumentException("Age must be 18 or above");
System.out.println("Access granted");
Output
Exception in thread "main" java.lang.IllegalArgumentException: Age must be 18 or above
at ThrowUncheckedExample.checkAge(ThrowUncheckedExample.java:6)
at ThrowUncheckedExample.main(ThrowUncheckedExample.java:3)
Example 3 — Throw inside catch
You can re-throw an exception (possibly wrapped in another exception):
public class RethrowExample {
public static void main(String[] args) {
try {
int result = 10 / 0;
} catch (ArithmeticException e) {
throw new RuntimeException("Calculation failed", e);
Output
Exception in thread "main" java.lang.RuntimeException: Calculation failed
at RethrowExample.main(RethrowExample.java:6)
Caused by: java.lang.ArithmeticException: / by zero
at RethrowExample.main(RethrowExample.java:3)
Advance Java – Module 1
Example 4 — Throwing in initializer
You can throw exceptions from constructors or static initializers:
public class ThrowInConstructor {
public ThrowInConstructor() throws Exception {
throw new Exception("Constructor failed");
public static void main(String[] args) {
try {
new ThrowInConstructor();
} catch (Exception e) {
System.out.println(e.getMessage());
Output
Constructor failed
8.6 Creating Custom Exceptions
Definition
A custom exception is a user-defined class that extends Exception or RuntimeException to
represent an application-specific error scenario.
Why create custom exceptions?
• To provide more meaningful and domain-specific error messages.
Advance Java – Module 1
• To separate application errors from Java's built-in exceptions.
• To make debugging easier by creating exceptions that clearly describe the problem.
Types of custom exceptions
1. Checked Custom Exception
o Extend the Exception class (but not RuntimeException).
o Must be declared in the throws clause or caught in a try-catch.
2. Unchecked Custom Exception
o Extend the RuntimeException class.
o Do not require declaration or mandatory handling.
Syntax
Checked
class MyCheckedException extends Exception {
public MyCheckedException(String message) {
super(message);
Unchecked
class MyUncheckedException extends RuntimeException {
public MyUncheckedException(String message) {
super(message);
Example 1 — Checked Custom Exception
Advance Java – Module 1
// Custom checked exception
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
public class CustomCheckedExample {
public static void main(String[] args) {
try {
register(15);
} catch (InvalidAgeException e) {
System.out.println("Error: " + e.getMessage());
static void register(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("You must be 18 or older to register.");
System.out.println("Registration successful!");
Output
Error: You must be 18 or older to register.
Advance Java – Module 1
Example 2 — Unchecked Custom Exception
// Custom unchecked exception
class NegativeBalanceException extends RuntimeException {
public NegativeBalanceException(String message) {
super(message);
public class CustomUncheckedExample {
public static void main(String[] args) {
withdraw(200, 100);
static void withdraw(int balance, int amount) {
if (amount > balance) {
throw new NegativeBalanceException("Insufficient funds: attempted to withdraw " +
amount);
System.out.println("Withdrawal successful!");
Output
Exception in thread "main" NegativeBalanceException: Insufficient funds: attempted to
withdraw 100
at CustomUncheckedExample.withdraw(CustomUncheckedExample.java:10)
at CustomUncheckedExample.main(CustomUncheckedExample.java:5)
Advance Java – Module 1
Example 3 — Custom Exception with extra fields
You can add extra data to a custom exception.
class OrderNotFoundException extends Exception {
private int orderId;
public OrderNotFoundException(int orderId, String message) {
super(message);
this.orderId = orderId;
public int getOrderId() {
return orderId;
public class OrderService {
public static void main(String[] args) {
try {
findOrder(101);
} catch (OrderNotFoundException e) {
System.out.println("Error: " + e.getMessage() + " | Order ID: " + e.getOrderId());
static void findOrder(int id) throws OrderNotFoundException {
throw new OrderNotFoundException(id, "Order not found in database");
Advance Java – Module 1
Output
Error: Order not found in database | Order ID: 101
8.7 throws keyword:
Definition
The throws keyword in Java is used in a method or constructor signature to declare the
exceptions that the method may throw during execution.
It acts as a warning to the caller:
"This method might throw this exception, so you need to handle it."
Purpose
• To tell the compiler and the calling method about possible exceptions.
• To propagate exceptions up the call stack instead of handling them inside the method.
• It’s required for checked exceptions (but optional for unchecked exceptions).
Syntax
returnType methodName(parameters) throws ExceptionType1, ExceptionType2, ... {
// method body
How it works
1. Method declaration includes throws to list possible exceptions.
2. Caller of the method must either:
o Handle the exception using try-catch
o OR declare throws again in its own method signature.
Advance Java – Module 1
Example 1 — Checked Exception with throws
import java.io.*;
public class ThrowsExample {
public static void main(String[] args) {
try {
readFile("data.txt");
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
static void readFile(String fileName) throws IOException {
FileReader fr = new FileReader(fileName);
System.out.println("File opened successfully!");
fr.close();
Output (if file not found)
Error reading file: data.txt (No such file or directory)
Example 2 — Multiple Exceptions
public class MultipleThrowsExample {
public static void main(String[] args) {
try {
Advance Java – Module 1
process();
} catch (IOException | ClassNotFoundException e) {
System.out.println("Caught exception: " + e);
static void process() throws IOException, ClassNotFoundException {
if (Math.random() > 0.5) {
throw new IOException("I/O error occurred");
} else {
throw new ClassNotFoundException("Class not found");
Possible outputs
Caught exception: java.io.IOException: I/O error occurred
OR
Caught exception: java.lang.ClassNotFoundException: Class not found
Example 3 — With Custom Exception
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
Advance Java – Module 1
public class CustomThrowsExample {
public static void main(String[] args) {
try {
register(15);
} catch (InvalidAgeException e) {
System.out.println("Registration failed: " + e.getMessage());
static void register(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Must be 18+ to register");
System.out.println("Registration successful!");
Output
Registration failed: Must be 18+ to register
Important Notes
• throws vs throw
o throw: used inside a method to actually throw an exception object.
o throws: used in method signature to declare possible exceptions.
• Checked Exceptions
o Must be declared with throws or handled with try-catch.
• Unchecked Exceptions
Advance Java – Module 1
o Can be declared, but it’s optional.
8.8 Try-with-resources (Java 7+)
Definition
Try-with-resources is a Java feature (introduced in Java 7) that automatically closes resources
(like files, database connections, streams) when the try block finishes — whether normally or
due to an exception.
A resource here means any object that implements the AutoCloseable interface (like Closeable
in I/O streams).
Why it’s useful
• No need for explicit finally blocks to close resources.
• Automatically handles exceptions during resource closing.
• Makes code shorter, cleaner, and less error-prone.
Syntax
try (ResourceType resource = new ResourceType()) {
// use the resource
} catch (ExceptionType e) {
// handle exception
• You can declare multiple resources inside the parentheses, separated by semicolons.
• Each resource must implement AutoCloseable (or Closeable).
How it works
1. The resource is opened in the try parentheses.
Advance Java – Module 1
2. After the try block ends (successfully or due to an exception), the resource’s close()
method is automatically called.
3. This happens before the catch block runs.
Example 1 — File Reading
import java.io.*;
public class TryWithResourcesExample {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
} catch (IOException e) {
System.out.println("Error reading file: " + e.getMessage());
Output (if file contains)
Hello World
Java Try-with-resources
• Here, BufferedReader is closed automatically after the try block.
Example 2 — Multiple Resources
import java.io.*;
Advance Java – Module 1
public class MultipleResourcesExample {
public static void main(String[] args) {
try (
FileReader fr = new FileReader("input.txt");
BufferedReader br = new BufferedReader(fr)
){
System.out.println("First line: " + br.readLine());
} catch (IOException e) {
System.out.println("Error: " + e.getMessage());
Example 3 — Custom Resource
class MyResource implements AutoCloseable {
public void doSomething() {
System.out.println("Using resource");
@Override
public void close() {
System.out.println("Resource closed");
public class CustomResourceExample {
Advance Java – Module 1
public static void main(String[] args) {
try (MyResource res = new MyResource()) {
res.doSomething();
Output
Using resource
Resource closed
Exception Handling in Try-with-resources
• If both:
o The try block throws an exception, and
o The close() method throws an exception
→ The original exception from try is thrown, and the exception from close() is
suppressed.
• Suppressed exceptions can be retrieved using:
for (Throwable t : e.getSuppressed()) {
System.out.println(t);
Summary
1. Introduction to Java
• Java Overview – Java is a high-level, platform-independent, object-oriented
programming language known for "Write Once, Run Anywhere" (WORA) capability.
• History – Developed by Sun Microsystems (James Gosling, 1995), later acquired by
Oracle.
Advance Java – Module 1
• JDK, JRE, JVM –
o JDK (Java Development Kit): Contains tools to develop Java applications
(compiler, libraries, debugger).
o JRE (Java Runtime Environment): Contains JVM + libraries to run Java programs.
o JVM (Java Virtual Machine): Executes Java bytecode.
• Program Structure – Classes, methods, main() method, package declarations, imports.
• Compilation & Execution – javac compiles .java → .class bytecode → JVM executes.
2. Java Basics
• Syntax & Flow – Case-sensitive, class-based, follows top-down execution.
• Identifiers & Keywords – Identifiers (names for variables, methods, classes), keywords
(reserved words like class, public).
• Variables – Store data; constants declared with final.
• Data Types –
o Primitive: byte, short, int, long, float, double, char, boolean.
o Non-Primitive: Strings, arrays, classes, interfaces.
• Type Casting – Widening (implicit), narrowing (explicit).
• Operators – Arithmetic (+, -), relational (==, !=), logical (&&, ||), bitwise, assignment,
unary, ternary.
• Expressions & Precedence – Operator priority defines evaluation order.
• Comments – // single-line, /*...*/ multi-line, /**...*/ documentation.
3. Control Flow Statements
• Decision-making – if, if-else, switch.
• Loops – for, while, do-while, enhanced for-loop for arrays/collections.
• Jump Statements – break, continue, return.
• Nested Loops & Labels – Loops inside loops; labels allow breaking from specific loops.
Advance Java – Module 1
4. Arrays and Strings
• Arrays – Fixed-size, homogeneous data storage.
o Single-dimensional (int[] arr), multi-dimensional (int[][] matrix).
o Operations: cloning, sorting (Arrays.sort()), searching (Arrays.binarySearch()).
• Strings – Immutable sequences of characters; stored in the string pool.
• StringBuffer/StringBuilder – Mutable strings (Buffer → thread-safe, Builder → faster).
• Common Operations – concat, substring, toUpperCase, equals, trim, split.
5. Methods in Java
• Definition – Code block with a name, parameters, and return type.
• Parameter Passing – Always pass-by-value (objects pass reference value).
• Overloading – Multiple methods with same name but different parameters.
• Recursion – Method calls itself.
• Varargs – Accepts variable number of parameters (int... nums).
• main() Method – Entry point of Java application.
6. Object-Oriented Programming (OOP)
• Classes/Objects – Class defines blueprint; object is an instance.
• Constructors – Initialize objects; can be overloaded.
• this keyword – Refers to current object instance.
• static keyword – Belongs to class rather than object.
• Encapsulation – Private fields + public getters/setters.
• Inheritance – One class acquires properties of another.
• super keyword – Refers to parent class.
• Overriding – Redefining parent method in child.
Advance Java – Module 1
• Polymorphism – Compile-time (overloading), runtime (overriding).
• Abstraction – Hiding implementation (abstract classes, interfaces).
• final keyword – Prevent modification.
• Nested/Inner Classes – Classes inside classes.
7. Packages and Access Control
• Packages – Group related classes (package mypack;).
• Access Modifiers –
o public – Accessible everywhere.
o protected – Accessible in same package + subclasses.
o Default (no modifier) – Same package only.
o private – Same class only.
• Importing Classes – import packageName.ClassName; or import packageName.*;
• Static Imports – import static java.lang.Math.*;
8. Exception Handling
8.1 Types of Exceptions
• Checked Exceptions – Checked at compile-time (e.g., IOException).
• Unchecked Exceptions – Runtime exceptions (e.g., NullPointerException).
• Errors – Serious issues (e.g., OutOfMemoryError).
8.2 try-catch-finally
• try – Code that may throw exception.
• catch – Handles the exception.
• finally – Executes regardless of exception.
8.3 Multiple Catch Blocks
• Handle different exception types separately.
Advance Java – Module 1
8.4 Nested try-catch
• try-catch inside another try-catch.
8.5 throw keyword
• Manually throw an exception.
8.6 Custom Exceptions
• User-defined exceptions by extending Exception or RuntimeException.
8.7 throws keyword
• Declares exceptions a method may throw.
8.8 Try-with-resources (Java 7+)
• Automatically closes resources that implement AutoCloseable.