Section 1: Core Java Basics
Java Features
Java is a high-level, object-oriented programming language that is platform-independent due to the JVM (Java
Virtual Machine). Key features include: Platform Independence, OOP, Robust, Secure, Automatic Garbage
Collection, and a Rich API.
JVM, JDK, JRE
- JVM (Java Virtual Machine): Executes Java bytecode, enables platform independence. - JRE (Java Runtime
Environment): JVM + Libraries to run Java programs. - JDK (Java Development Kit): JRE + development tools
(compiler, debugger, etc.).
Hello World Example
The simplest Java program demonstrating compilation and execution:
public class HelloWorld {
public static void main(String[] args) {
[Link]("Hello, World!");
}
}
Data Types & Variables
Java supports two categories of data types: 1. Primitive (int, byte, short, long, float, double, char, boolean) 2.
Non-Primitive (String, Arrays, Classes, Objects).
// Example: Primitive vs Non-Primitive
int age = 30;
double salary = 55000.5;
char grade = 'A';
boolean isActive = true;
String name = "Abhay";
int[] marks = {85, 90, 95};
Type Casting
Type casting is converting one data type into another. - Implicit Casting (Widening): smaller type to larger type
automatically. - Explicit Casting (Narrowing): larger type to smaller type explicitly.
// Implicit casting (int → double)
int num = 100;
double d = num;
// Explicit casting (double → int)
double price = 99.99;
int p = (int) price;
Operators
Java provides arithmetic (+, -, *, /, %), relational (==, !=, >, <), logical (&&, ||, !), assignment (=, +=, -=), and bitwise
operators.
int a = 10, b = 5;
[Link](a + b); // 15
[Link](a > b); // true
[Link](a & b); // 0 (bitwise AND)
Control Structures
Control structures allow decision making and looping:
int number = 7;
if (number % 2 == 0) {
[Link]("Even number");
} else {
[Link]("Odd number");
}
for (int i = 1; i <= 5; i++) {
[Link]("Count: " + i);
}
Section 2: Object-Oriented Programming (OOP)
Classes and Objects
A class is a blueprint, an object is an instance of a class.
class Car {
String brand;
int speed;
void drive() {
[Link](brand + " is driving at " + speed + " km/h");
}
}
public class TestCar {
public static void main(String[] args) {
Car car1 = new Car();
[Link] = "Honda";
[Link] = 120;
[Link]();
}
}
Constructors
Constructors are used to initialize objects. They have the same name as the class.
class Student {
String name;
int age;
Student(String n, int a) {
name = n;
age = a;
}
}
public class TestStudent {
public static void main(String[] args) {
Student s1 = new Student("Abhay", 25);
[Link]([Link] + " - " + [Link]);
}
}
this and super
this refers to the current object; super refers to the parent class object.
class Animal {
String type = "Animal";
}
class Dog extends Animal {
String type = "Dog";
void printTypes() {
[Link]([Link]); // Dog
[Link]([Link]); // Animal
}
}
Inheritance
Inheritance allows one class to acquire the properties and behaviors of another.
class Parent {
void display() {
[Link]("Parent class");
}
}
class Child extends Parent {
void show() {
[Link]("Child class");
}
}
public class TestInheritance {
public static void main(String[] args) {
Child c = new Child();
[Link](); // from Parent
[Link](); // from Child
}
}
Polymorphism
Polymorphism allows methods to take many forms: overloading and overriding.
// Compile-time polymorphism (Overloading)
class Calculator {
int add(int a, int b) { return a + b; }
double add(double a, double b) { return a + b; }
}
// Runtime polymorphism (Overriding)
class Animal {
void sound() { [Link]("Some sound"); }
}
class Dog extends Animal {
@Override
void sound() { [Link]("Bark"); }
}
Encapsulation
Encapsulation = wrapping data and methods inside a class with restricted access.
class BankAccount {
private double balance;
public BankAccount(double initialBalance) {
[Link] = initialBalance;
}
public double getBalance() { return balance; }
public void deposit(double amount) {
if(amount > 0) balance += amount;
}
}
Abstraction
Abstraction hides implementation details and exposes only essential features.
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() { [Link]("Drawing Circle"); }
}
Access Modifiers
- private: within class only - default: within package - protected: within package + subclasses - public: accessible
everywhere
Section 3: Advanced OOP Concepts
Abstract Classes
Abstract classes can have both abstract and concrete methods. They cannot be instantiated.
abstract class Vehicle {
abstract void start();
void fuel() { [Link]("Fuels with petrol/diesel"); }
}
class Car extends Vehicle {
void start() { [Link]("Car starts with key"); }
}
Interfaces
Interfaces define contracts. A class implementing an interface must provide method implementations.
interface Animal {
void sound();
}
class Dog implements Animal {
public void sound() {
[Link]("Bark");
}
}
Functional Interfaces
Functional interfaces have exactly one abstract method. Used with Lambda expressions.
@FunctionalInterface
interface Greeting {
void sayHello(String name);
}
public class Test {
public static void main(String[] args) {
Greeting g = (name) -> [Link]("Hello, " + name);
[Link]("Abhay");
}
}
Nested and Inner Classes
Java supports member inner, static nested, local inner, and anonymous inner classes.
// Static Nested Class
class Outer {
static class Nested {
void show() { [Link]("Inside static nested class"); }
}
}
// Anonymous Inner Class
abstract class Person {
abstract void display();
}
class Test {
public static void main(String[] args) {
Person p = new Person() {
void display() { [Link]("Anonymous inner class"); }
};
[Link]();
}
}
Static Keyword
Static members belong to the class rather than an object.
class Counter {
static int count = 0;
Counter() { count++; }
static void showCount() { [Link]("Count = " + count); }
}
Final Keyword
final: variable = constant, method = cannot override, class = cannot inherit.
final class Parent {}
// class Child extends Parent {} // Error
class Demo {
final int x = 10;
final void display() { [Link]("Final method"); }
}
Object Class Methods
Every class inherits from Object. Common methods: toString(), equals(), hashCode().
class Student {
String name;
Student(String name) { [Link] = name; }
@Override
public String toString() {
return "Student: " + name;
}
@Override
public boolean equals(Object o) {
if(o instanceof Student) {
Student s = (Student) o;
return [Link]([Link]);
}
return false;
}
}
Section 4: Java Memory Management
Stack vs Heap
- Stack Memory: Stores local variables and method calls. - Heap Memory: Stores objects and instance variables.
class Demo {
public static void main(String[] args) {
int x = 10; // Stored in stack
String s = new String("Hello"); // Object in heap, reference in stack
}
}
Garbage Collection
Garbage Collection (GC) automatically reclaims memory occupied by unreachable objects. It helps prevent
memory leaks but does not guarantee immediate cleanup.
class TestGC {
public static void main(String[] args) {
TestGC obj = new TestGC();
obj = null; // Eligible for garbage collection
[Link](); // Request GC (not guaranteed)
}
@Override
protected void finalize() {
[Link]("Object is garbage collected");
}
}
Memory Leaks
Memory leaks occur when objects are no longer needed but cannot be garbage collected due to active
references. Common causes: static references, unclosed resources (files, DB connections).
class MemoryLeakDemo {
private static List<Double> list = new ArrayList<>();
public static void main(String[] args) {
while(true) {
[Link]([Link]()); // Keeps growing, memory leak
}
}
}
Try-with-Resources
Introduced in Java 7, ensures automatic closing of resources.
import [Link].*;
class FileReadDemo {
public static void main(String[] args) {
try (BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
[Link]([Link]());
} catch(IOException e) {
[Link]();
}
}
}
ClassLoaders
ClassLoaders are responsible for loading classes into memory. Types: - Bootstrap ClassLoader (loads core Java
classes from [Link]) - Extension ClassLoader (loads JDK extensions) - System/Application ClassLoader (loads
classes from classpath)
class TestClassLoader {
public static void main(String[] args) {
ClassLoader cl = [Link]();
[Link](cl); // Application ClassLoader
[Link]([Link]()); // Extension ClassLoader
[Link]([Link]().getParent()); // Bootstrap (null)
}
}
Section 5: Exception Handling
Checked vs Unchecked Exceptions
- Checked Exceptions: Checked at compile-time (e.g., IOException, SQLException). - Unchecked Exceptions:
Runtime exceptions (e.g., NullPointerException, ArithmeticException).
// Checked Exception Example
import [Link].*;
class FileRead {
public static void main(String[] args) throws IOException {
FileReader fr = new FileReader("[Link]"); // Checked Exception
}
}
// Unchecked Exception Example
class Divide {
public static void main(String[] args) {
int x = 10 / 0; // ArithmeticException at runtime
}
}
Try, Catch, Finally
The try block contains risky code, catch handles exceptions, finally executes always.
class Example {
public static void main(String[] args) {
try {
int arr[] = {1,2,3};
[Link](arr[5]); // ArrayIndexOutOfBoundsException
} catch(ArrayIndexOutOfBoundsException e) {
[Link]("Exception caught: " + e);
} finally {
[Link]("Finally block executed.");
}
}
}
throw and throws
- throw: Used to explicitly throw an exception. - throws: Declares exceptions a method can throw.
class Example {
static void checkAge(int age) throws Exception {
if(age < 18) {
throw new Exception("Not eligible to vote");
} else {
[Link]("Eligible to vote");
}
}
public static void main(String[] args) {
try {
checkAge(15);
} catch(Exception e) {
[Link]([Link]());
}
}
}
Custom Exceptions
We can create user-defined exceptions by extending Exception or RuntimeException.
class InvalidAmountException extends Exception {
InvalidAmountException(String msg) {
super(msg);
}
}
class Bank {
void withdraw(int amount) throws InvalidAmountException {
if(amount <= 0) throw new InvalidAmountException("Amount must be positive");
[Link]("Withdrawn: " + amount);
}
}
Best Practices
1. Catch specific exceptions instead of generic Exception. 2. Log exceptions properly. 3. Use try-with-resources
for closing resources. 4. Avoid suppressing exceptions silently.
// Example: Try-with-resources
import [Link].*;
class Demo {
public static void main(String[] args) {
try(BufferedReader br = new BufferedReader(new FileReader("[Link]"))) {
[Link]([Link]());
} catch(IOException e) {
[Link]();
}
}
}
Section 6: Collections Framework
Collection Hierarchy
The Java Collections Framework provides classes and interfaces to store and manipulate groups of objects. Main
interfaces: Collection (List, Set, Queue) and Map.
import [Link].*;
class Demo {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
[Link]("Apple");
[Link]("Banana");
[Link](list);
Map<Integer, String> map = new HashMap<>();
[Link](1, "One");
[Link](2, "Two");
[Link](map);
}
}
List Implementations
ArrayList (dynamic array, fast access) vs LinkedList (doubly linked list, fast insert/delete).
List<String> arrayList = new ArrayList<>();
[Link]("A");
[Link]("B");
List<String> linkedList = new LinkedList<>();
[Link]("X");
[Link]("Y");
Set Implementations
HashSet (no duplicates, no order), LinkedHashSet (insertion order), TreeSet (sorted order).
Set<String> set = new HashSet<>();
[Link]("Banana");
[Link]("Apple");
[Link]("Banana"); // ignored duplicate
[Link](set);
Map Implementations
HashMap (unordered), LinkedHashMap (insertion order), TreeMap (sorted by keys).
Map<Integer, String> map = new HashMap<>();
[Link](3, "Three");
[Link](1, "One");
[Link](2, "Two");
[Link](map); // Order not guaranteed
Concurrent Collections
Thread-safe alternatives: ConcurrentHashMap, CopyOnWriteArrayList, BlockingQueue.
import [Link].*;
class DemoConcurrent {
public static void main(String[] args) {
ConcurrentHashMap<Integer, String> cmap = new ConcurrentHashMap<>();
[Link](1, "One");
[Link](2, "Two");
[Link](cmap);
}
}
Iterator & Fail-fast vs Fail-safe
- Iterator: traverse collections. - ListIterator: bi-directional iterator. - Fail-fast: throws
ConcurrentModificationException (e.g., ArrayList). - Fail-safe: works on a copy (e.g., ConcurrentHashMap).
import [Link].*;
class TestIterator {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
[Link]("A"); [Link]("B");
Iterator<String> it = [Link]();
while([Link]()) {
[Link]([Link]());
}
}
}
Section 7: Multithreading & Concurrency
Thread Lifecycle
States: New → Runnable → Running → Waiting/Timed Waiting → Terminated.
class MyThread extends Thread {
public void run() {
[Link]("Thread is running...");
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
[Link](); // moves to Runnable state
}
}
Creating Threads
Two ways: extending Thread class or implementing Runnable interface.
// Extending Thread
class Task1 extends Thread {
public void run() {
[Link]("Task1 running...");
}
}
// Implementing Runnable
class Task2 implements Runnable {
public void run() {
[Link]("Task2 running...");
}
}
Synchronization
Used to prevent race conditions on shared resources.
class Counter {
int count;
synchronized void increment() {
count++;
}
}
Volatile & Atomic Variables
volatile ensures visibility, Atomic variables provide lock-free thread safety.
class Shared {
volatile int flag = 0;
}
import [Link];
class AtomicDemo {
AtomicInteger count = new AtomicInteger(0);
void increment() { [Link](); }
}
Executor Framework
Manages threads efficiently using pools (FixedThreadPool, CachedThreadPool, ScheduledThreadPool).
import [Link].*;
class ExecutorDemo {
public static void main(String[] args) {
ExecutorService executor = [Link](2);
[Link](() -> [Link]("Task 1"));
[Link](() -> [Link]("Task 2"));
[Link]();
}
}
Deadlock, Livelock, Starvation
- Deadlock: threads wait on each other forever. - Livelock: threads keep changing states, no progress. -
Starvation: thread never gets CPU due to others.
Concurrent Utilities
Utilities: CountDownLatch, CyclicBarrier, Semaphore for advanced control.
import [Link].*;
class LatchDemo {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for(int i=0; i<3; i++) {
new Thread(() -> {
[Link]("Thread working...");
[Link]();
}).start();
}
[Link](); // waits for all threads
[Link]("All threads finished");
}
}
Section 8: Java 8+ Features
Lambda Expressions
Lambdas provide a concise way to represent anonymous functions.
@FunctionalInterface
interface Greeting {
void say(String name);
}
class Demo {
public static void main(String[] args) {
Greeting g = (name) -> [Link]("Hello " + name);
[Link]("Abhay");
}
}
Streams API
Streams allow functional-style processing of collections (filter, map, reduce).
import [Link].*;
import [Link].*;
class StreamDemo {
public static void main(String[] args) {
List<Integer> nums = [Link](1,2,3,4,5);
int sum = [Link]()
.filter(n -> n % 2 == 0)
.mapToInt(n -> n * 2)
.sum();
[Link]("Sum = " + sum);
}
}
Functional Interfaces
Common functional interfaces: Predicate, Consumer, Function, Supplier.
import [Link].*;
class FuncDemo {
public static void main(String[] args) {
Predicate<Integer> isEven = n -> n % 2 == 0;
Consumer<String> printer = s -> [Link](s);
Function<Integer, Integer> square = x -> x * x;
Supplier<Double> random = () -> [Link]();
[Link]([Link](4));
[Link]("Hello");
[Link]([Link](5));
[Link]([Link]());
}
}
Optional Class
Optional helps avoid NullPointerException by wrapping nullable values.
import [Link].*;
class OptionalDemo {
public static void main(String[] args) {
Optional<String> name = [Link](null);
[Link]([Link]("Default Name"));
}
}
Method References
Method references are shorthand for lambdas calling existing methods.
import [Link].*;
class MethodRefDemo {
public static void main(String[] args) {
List<String> list = [Link]("A","B","C");
[Link]([Link]::println); // method reference
}
}
Default & Static Methods in Interfaces
Interfaces can have default and static methods since Java 8.
interface Vehicle {
default void start() { [Link]("Vehicle is starting..."); }
static void stop() { [Link]("Vehicle stopped."); }
}
class Car implements Vehicle {}
class Test {
public static void main(String[] args) {
Car c = new Car();
[Link]();
[Link]();
}
}
Section 9: File I/O & Serialization
File Handling Basics
The [Link] package provides classes for file handling such as File, FileReader, FileWriter, BufferedReader, etc.
import [Link].*;
class FileDemo {
public static void main(String[] args) throws IOException {
File file = new File("[Link]");
if (![Link]()) {
[Link]();
}
[Link]("File created: " + [Link]());
}
}
Byte vs Character Streams
Byte Streams handle binary data, Character Streams handle text data with Unicode support.
// Byte Stream Example
FileInputStream fin = new FileInputStream("[Link]");
int i;
while((i = [Link]()) != -1) {
[Link]((char)i);
}
[Link]();
// Character Stream Example
FileReader fr = new FileReader("[Link]");
int j;
while((j = [Link]()) != -1) {
[Link]((char)j);
}
[Link]();
Buffered Streams
Buffered streams improve performance by reducing I/O operations.
BufferedReader br = new BufferedReader(new FileReader("[Link]"));
String line;
while((line = [Link]()) != null) {
[Link](line);
}
[Link]();
Serialization
Serialization converts an object into a byte stream, deserialization converts it back.
import [Link].*;
class Student implements Serializable {
String name;
int age;
Student(String n, int a) { name = n; age = a; }
}
class Test {
public static void main(String[] args) throws Exception {
Student s1 = new Student("Abhay", 25);
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("[Link]"));
[Link](s1);
[Link]();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream("[Link]"));
Student s2 = (Student) [Link]();
[Link]();
[Link]([Link] + " - " + [Link]);
}
}
Java NIO
NIO provides high-speed, non-blocking I/O with Path, Files, Channels, Buffers.
import [Link].*;
import [Link];
class NioDemo {
public static void main(String[] args) throws IOException {
Path path = [Link]("[Link]");
[Link](path, "Hello NIO".getBytes());
String content = [Link](path);
[Link](content);
}
}
Section 10: JDBC (Java Database Connectivity)
JDBC Architecture
JDBC allows Java applications to connect and interact with databases. Main Components: DriverManager,
Connection, Statement, PreparedStatement, CallableStatement, ResultSet.
Steps to Connect to a Database
1. Load driver 2. Establish connection 3. Create statement 4. Execute query 5. Process results 6. Close
connection
import [Link].*;
class JdbcDemo {
public static void main(String[] args) {
try {
[Link]("[Link]");
Connection con = [Link](
"jdbc:mysql://localhost:3306/testdb","root","password");
Statement stmt = [Link]();
ResultSet rs = [Link]("SELECT * FROM users");
while([Link]()) {
[Link]([Link](1) + " " + [Link](2));
}
[Link]();
} catch(Exception e) {
[Link]();
}
}
}
Statement vs PreparedStatement vs CallableStatement
- Statement: Executes static SQL queries. Not safe against SQL injection. - PreparedStatement: Precompiled
SQL with parameters, prevents SQL injection. - CallableStatement: Executes stored procedures.
// Using PreparedStatement
PreparedStatement ps = [Link]("INSERT INTO users VALUES(?,?)");
[Link](1, 101);
[Link](2, "Abhay");
[Link]();
Transaction Management
Transactions group multiple operations as one unit. Methods: setAutoCommit(false), commit(), rollback().
try {
[Link](false);
Statement stmt = [Link]();
[Link]("INSERT INTO accounts VALUES(1,1000)");
[Link]("INSERT INTO accounts VALUES(2,2000)");
[Link]();
} catch(Exception e) {
[Link]();
}
Batch Processing
Batch processing improves performance by executing multiple SQL statements together.
Statement stmt = [Link]();
[Link]("INSERT INTO users VALUES(102,'John')");
[Link]("INSERT INTO users VALUES(103,'Mary')");
int[] result = [Link]();