Java Complete Tutorial - Beginner to Advanced
This page is rebuilt from your Java learning page into a much more detailed Python-style Java course. Each left-side topic is now a focused lesson with explanation, syntax, code, output, production use, mistakes, practice, and study links. This expanded edition adds deeper JVM, memory, framework, validation, logging, performance, and project-readiness topics.
How to Use This Page
- Use the left sidebar to select one Java topic at a time.
- Use the search box to filter topics quickly.
- Read the concept, then type the code yourself instead of only copying it.
- Complete the practice task before moving to the next lesson.
Java Introduction
What is it?
Java is a high-level, object-oriented, strongly typed programming language used for enterprise systems, Android apps, backend APIs, desktop tools, and cloud applications.
Beginner + Developer Explanation
Java is popular because the same compiled bytecode can run on different operating systems through the JVM. For beginners, Java teaches clear structure: classes, methods, types, objects, and packages. For developers, Java provides a mature ecosystem with Spring Boot, Maven, Gradle, JUnit, JDBC, and powerful IDE support.
Important Concepts
- Java source files use .java extension
- Compiled files use .class bytecode
- JVM executes bytecode
- Java is case-sensitive
- Most programs start from main method
- Java is widely used in enterprise backend development
Syntax / Pattern
public class Main {
public static void main(String[] args) {
System.out.println("Hello Java");
}
}
Detailed Code Example
public class Main {
public static void main(String[] args) {
System.out.println("Welcome to Java Programming");
System.out.println("Learn basics, OOP, collections, backend, and production skills");
}
}
Output / Result
Welcome to Java Programming Learn basics, OOP, collections, backend, and production skills
Real-Time Production Scope
- Backend APIs with Spring Boot
- Banking and insurance systems
- Android app business logic
- Batch jobs and automation tools
Common Mistakes and Fixes
- Confusing Java with JavaScript
- Forgetting that Java code must be inside a class
- Using wrong file name for public class
- Skipping fundamentals and jumping directly to frameworks
Practice Task
Study Links
Install JDK and Setup
What is it?
The JDK, or Java Development Kit, contains the compiler, runtime tools, libraries, and utilities required to develop Java applications.
Beginner + Developer Explanation
Beginners need the JDK to compile and run Java. Developers also configure JAVA_HOME, PATH, IDE SDK, Maven/Gradle JDK, and CI/CD build images so every environment uses the correct version.
Important Concepts
- java command runs Java applications
- javac command compiles Java source files
- JAVA_HOME points to JDK location
- PATH lets terminal find java and javac
- IDE must use correct project JDK
- Build tools should match the project Java version
Syntax / Pattern
java -version javac -version javac Main.java java Main
Detailed Code Example
public class SetupCheck {
public static void main(String[] args) {
System.out.println("Java setup is working");
System.out.println(System.getProperty("java.version"));
}
}
Output / Result
Java setup is working Example: 21.0.2
Real-Time Production Scope
- New developer onboarding
- CI/CD server setup
- Docker image selection
- Standardizing Java version across teams
Common Mistakes and Fixes
- Installing only runtime instead of JDK
- Forgetting Add to PATH on Windows
- Using different Java versions locally and in production
- Not checking javac version
Practice Task
Study Links
JVM, JRE, and JDK
What is it?
JVM runs Java bytecode, JRE provides runtime libraries, and JDK provides tools to develop Java programs.
Beginner + Developer Explanation
A beginner can think of JDK as the full developer kit, JRE as the runtime environment, and JVM as the engine. Developers must understand these to debug deployment, version mismatch, and classpath problems.
Important Concepts
- JVM means Java Virtual Machine
- JRE means Java Runtime Environment
- JDK means Java Development Kit
- javac converts .java to .class
- JVM loads and executes .class files
- Garbage collector runs inside the JVM
Syntax / Pattern
.java source -> javac compiler -> .class bytecode -> JVM -> program output
Detailed Code Example
public class RuntimeInfo {
public static void main(String[] args) {
System.out.println("Java Version: " + System.getProperty("java.version"));
System.out.println("OS: " + System.getProperty("os.name"));
}
}
Output / Result
Java Version: depends on installed JDK OS: depends on your machine
Real-Time Production Scope
- Choosing runtime for cloud deployment
- Troubleshooting UnsupportedClassVersionError
- Explaining portability
- Tuning JVM memory
Common Mistakes and Fixes
- Thinking JVM is the compiler
- Deploying newer compiled code on older runtime
- Ignoring heap and GC settings in production
- Mixing JDK versions across tools
Practice Task
Study Links
Hello World and Program Structure
What is it?
Hello World is the smallest useful Java program and teaches class declaration, main method, statements, and output.
Beginner + Developer Explanation
Java applications usually start from public static void main(String[] args). Every statement ends with semicolon, and braces group code blocks.
Important Concepts
- public class name should match file name
- main method is the entry point
- System.out.println prints with newline
- Semicolon ends statements
- Curly braces define class and method body
- String[] args stores command-line arguments
Syntax / Pattern
public class ClassName {
public static void main(String[] args) {
// statements
}
}
Detailed Code Example
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
System.out.println("I am learning Java step by step.");
}
}
Output / Result
Hello, World! I am learning Java step by step.
Real-Time Production Scope
- Testing setup
- Starting command-line apps
- Understanding Spring Boot main method later
- Learning compile-run workflow
Common Mistakes and Fixes
- Wrong capitalization of main
- Missing semicolon
- File name not matching public class
- Writing statements outside class or method
Practice Task
Study Links
Comments and Javadoc
What is it?
Comments are human-readable notes ignored by the compiler. Javadoc comments can generate documentation for classes and methods.
Beginner + Developer Explanation
Beginners use comments to understand code. Developers use comments to explain business rules, edge cases, and public APIs. Good comments explain why, not just what.
Important Concepts
- // creates a single-line comment
- /* */ creates a block comment
- /** */ creates Javadoc
- Javadoc supports @param and @return
- Compiler ignores comments
- Outdated comments are harmful
Syntax / Pattern
// single line /* block comment */ /** Javadoc comment */
Detailed Code Example
/**
* Calculates final payable amount after discount.
* @param amount original amount
* @param discountPercent discount percentage
* @return final payable amount
*/
public class CommentDemo {
public static double finalAmount(double amount, double discountPercent) {
return amount - (amount * discountPercent / 100);
}
}
Output / Result
No output unless method is called
Real-Time Production Scope
- Documenting library APIs
- Explaining tax or discount rules
- Marking TODOs responsibly
- Helping future maintainers
Common Mistakes and Fixes
- Commenting obvious code
- Leaving commented-out dead code
- Writing comments that disagree with code
- Using comments instead of clear names
Practice Task
Study Links
Variables
What is it?
A variable is a named storage location that holds a value of a specific type.
Beginner + Developer Explanation
Java is statically typed, so every variable must declare or infer a type. Developers choose local variables, instance fields, static fields, and constants based on scope and lifetime.
Important Concepts
- Local variables live inside methods
- Instance variables belong to objects
- Static variables belong to class
- final variables cannot be reassigned
- Variable names are case-sensitive
- Use camelCase for variable names
Syntax / Pattern
type variableName = value; final type CONSTANT_NAME = value;
Detailed Code Example
public class VariableDemo {
public static void main(String[] args) {
String studentName = "Anu";
int age = 22;
double fee = 1499.00;
boolean paid = true;
final String COURSE = "Java Internship";
System.out.println(studentName + " joined " + COURSE);
System.out.println("Age: " + age + ", Fee: " + fee + ", Paid: " + paid);
}
}
Output / Result
Anu joined Java Internship Age: 22, Fee: 1499.0, Paid: true
Real-Time Production Scope
- Store request data
- Calculate totals
- Hold configuration values
- Represent business state
Common Mistakes and Fixes
- Using unclear names like a or x for business values
- Changing constant values accidentally
- Using static variables for request data
- Using wrong type for money
Practice Task
Study Links
Naming Conventions
What is it?
Naming conventions are standard rules for naming classes, methods, variables, packages, and constants.
Beginner + Developer Explanation
Clear names make code easier to read. Java developers follow PascalCase for classes, camelCase for methods and variables, lowercase packages, and UPPER_SNAKE_CASE for constants.
Important Concepts
- Class: StudentService
- Method: calculateTotal
- Variable: studentName
- Constant: MAX_RETRY_COUNT
- Package: com.company.project
- Boolean: isActive, hasPermission, canRetry
Syntax / Pattern
class StudentService {}
int studentAge = 22;
static final int MAX_ATTEMPTS = 3;
Detailed Code Example
public class NamingDemo {
private static final int MAX_LOGIN_ATTEMPTS = 3;
public static boolean isAdult(int age) {
return age >= 18;
}
public static void main(String[] args) {
int studentAge = 20;
System.out.println(isAdult(studentAge));
System.out.println(MAX_LOGIN_ATTEMPTS);
}
}
Output / Result
true 3
Real-Time Production Scope
- Readable enterprise code
- Framework class naming
- Clean APIs
- Better code reviews
Common Mistakes and Fixes
- Class names starting lowercase
- Constants written like normal variables
- Boolean variables with unclear names
- Abbreviations nobody understands
Practice Task
Study Links
Data Types
What is it?
Data types define what kind of value a variable can hold and what operations can be performed.
Beginner + Developer Explanation
Java has primitive types for simple values and reference types for objects. Primitives cannot be null; references can be null.
Important Concepts
- Primitive types: byte, short, int, long, float, double, char, boolean
- Reference types: String, arrays, classes, interfaces, records
- int is default whole number
- double is default decimal
- String is not primitive
- Wrapper classes allow primitives as objects
Syntax / Pattern
int count = 10; double price = 99.99; boolean active = true; String name = "Java";
Detailed Code Example
public class DataTypeDemo {
public static void main(String[] args) {
byte small = 100;
short medium = 20000;
int count = 500000;
long population = 1400000000L;
float temp = 36.6f;
double price = 1999.99;
char grade = 'A';
boolean active = true;
String course = "Java";
System.out.println(course + " " + grade + " " + active);
System.out.println(count + " " + population + " " + price);
}
}
Output / Result
Java A true 500000 1400000000 1999.99
Real-Time Production Scope
- DTO field design
- Database column mapping
- API request models
- Calculation and validation logic
Common Mistakes and Fixes
- Using double for exact money
- Forgetting L for long values
- Thinking String is primitive
- Using wrapper types without handling null
Practice Task
Study Links
Numbers and BigDecimal
What is it?
Java number handling includes integer types, floating-point types, and BigDecimal for precise decimal arithmetic.
Beginner + Developer Explanation
Use int or long for whole numbers, double for approximate decimals, and BigDecimal for money, tax, invoice, and banking calculations.
Important Concepts
- int has limited range
- long handles larger whole numbers
- float and double are approximate
- BigDecimal stores precise decimal values
- Create BigDecimal from String for accuracy
- RoundingMode is required for some divisions
Syntax / Pattern
BigDecimal amount = new BigDecimal("1499.99");
BigDecimal total = amount.multiply(BigDecimal.valueOf(2));
Detailed Code Example
import java.math.BigDecimal;
import java.math.RoundingMode;
public class NumberDemo {
public static void main(String[] args) {
BigDecimal price = new BigDecimal("199.99");
BigDecimal quantity = BigDecimal.valueOf(3);
BigDecimal subtotal = price.multiply(quantity);
BigDecimal gst = subtotal.multiply(new BigDecimal("0.18"));
BigDecimal total = subtotal.add(gst).setScale(2, RoundingMode.HALF_UP);
System.out.println("Subtotal: " + subtotal);
System.out.println("GST: " + gst.setScale(2, RoundingMode.HALF_UP));
System.out.println("Total: " + total);
}
}
Output / Result
Subtotal: 599.97 GST: 107.99 Total: 707.96
Real-Time Production Scope
- Payment systems
- Billing software
- Tax calculators
- Financial reports
Common Mistakes and Fixes
- Using double for money
- Creating BigDecimal from double
- Ignoring rounding mode
- Overflowing int with large values
Practice Task
Study Links
char and boolean
What is it?
char stores a single UTF-16 character; boolean stores true or false.
Beginner + Developer Explanation
char is useful for single symbols or grade codes. boolean is useful for decisions and flags such as isActive, paid, verified, and hasPermission.
Important Concepts
- char uses single quotes
- String uses double quotes
- char can use Unicode escape
- boolean accepts only true or false
- boolean is used in if conditions
- Boolean wrapper can be null
Syntax / Pattern
char grade = 'A'; char rupee = '\u20B9'; boolean isActive = true;
Detailed Code Example
public class CharBooleanDemo {
public static void main(String[] args) {
char grade = 'A';
char rupee = '\u20B9';
boolean emailVerified = true;
boolean paymentDone = false;
System.out.println("Grade: " + grade);
System.out.println("Symbol: " + rupee);
System.out.println("Allow access: " + (emailVerified && paymentDone));
}
}
Output / Result
Grade: A Symbol: ₹ Allow access: false
Real-Time Production Scope
- Grade codes
- Menu choices
- Validation flags
- Authorization checks
Common Mistakes and Fixes
- Using double quotes for char
- Expecting boolean to store 0 or 1
- Using unclear boolean names
- Unboxing null Boolean
Practice Task
Study Links
Type Casting and Parsing
What is it?
Type casting converts a value from one type to another. Parsing converts text into numeric or boolean values.
Beginner + Developer Explanation
Widening conversion is automatic; narrowing needs explicit cast and may lose data. String parsing can fail and should be handled.
Important Concepts
- Widening: int to double
- Narrowing: double to int
- Narrowing may lose decimals
- Integer.parseInt converts String to int
- Double.parseDouble converts String to double
- Invalid parsing throws NumberFormatException
Syntax / Pattern
double d = 10;
int i = (int) 10.9;
int age = Integer.parseInt("22");
Detailed Code Example
public class CastingDemo {
public static void main(String[] args) {
int count = 10;
double countDouble = count;
double price = 99.99;
int wholePrice = (int) price;
String input = "25";
int age = Integer.parseInt(input);
System.out.println(countDouble);
System.out.println(wholePrice);
System.out.println(age + 5);
}
}
Output / Result
10.0 99 30
Real-Time Production Scope
- Parsing request values
- Reading CSV data
- Converting form input
- Handling numeric calculations
Common Mistakes and Fixes
- Casting and losing data accidentally
- Parsing invalid strings without try/catch
- Downcasting objects unsafely
- Confusing String.valueOf with parseInt
Practice Task
Study Links
Operators
What is it?
Operators perform arithmetic, comparison, assignment, logical, bitwise, and conditional operations.
Beginner + Developer Explanation
Operators are used in calculations and decisions. Developers use them in validation rules, billing logic, eligibility checks, and business workflows.
Important Concepts
- Arithmetic: + - * / %
- Assignment: = += -= *= /=
- Comparison: == != > < >= <=
- Logical: && || !
- Increment/decrement: ++ --
- Ternary: condition ? a : b
Syntax / Pattern
int total = price * quantity; boolean allowed = age >= 18 && paid; String status = active ? "ON" : "OFF";
Detailed Code Example
public class OperatorDemo {
public static void main(String[] args) {
int price = 500;
int quantity = 3;
int discount = 100;
int total = price * quantity - discount;
boolean freeDelivery = total >= 1000 && quantity > 1;
String message = freeDelivery ? "Free delivery" : "Delivery charge applies";
System.out.println("Total: " + total);
System.out.println(message);
}
}
Output / Result
Total: 1400 Free delivery
Real-Time Production Scope
- Invoice calculation
- Eligibility rules
- Pagination math
- Permission checks
Common Mistakes and Fixes
- Integer division losing decimals
- Using & instead of && by mistake
- Overusing nested ternary
- Not using parentheses for readability
Practice Task
Study Links
String
What is it?
String stores text. In Java, String is immutable, meaning operations create new String objects instead of changing the original.
Beginner + Developer Explanation
Use equals() to compare String content, not ==. Java provides many methods for trimming, case conversion, searching, slicing, replacing, and formatting text.
Important Concepts
- String uses double quotes
- String is immutable
- equals compares content
- equalsIgnoreCase ignores case
- trim removes leading/trailing spaces
- substring extracts part
- contains checks text
Syntax / Pattern
String name = "Java";
name.equals("Java");
name.toUpperCase();
Detailed Code Example
public class StringDemo {
public static void main(String[] args) {
String email = " ANU@Example.COM ";
String clean = email.trim().toLowerCase();
System.out.println(clean);
System.out.println(clean.contains("@"));
System.out.println(clean.substring(0, clean.indexOf("@")));
System.out.println("java".equalsIgnoreCase("JAVA"));
}
}
Output / Result
anu@example.com true anu true
Real-Time Production Scope
- Email normalization
- Input validation
- Message building
- Log formatting
Common Mistakes and Fixes
- Using == for content comparison
- Calling methods on null
- Thinking replace changes original String
- Concatenating many strings in large loops
Practice Task
Study Links
StringBuilder and StringBuffer
What is it?
StringBuilder is a mutable class for efficient string construction. StringBuffer is similar but synchronized.
Beginner + Developer Explanation
Use StringBuilder when appending text repeatedly, especially inside loops. Use String for normal fixed text.
Important Concepts
- StringBuilder is mutable
- append adds text
- insert inserts text
- reverse reverses text
- toString converts to String
- StringBuffer is synchronized
Syntax / Pattern
StringBuilder sb = new StringBuilder();
sb.append("Hello");
String result = sb.toString();
Detailed Code Example
public class StringBuilderDemo {
public static void main(String[] args) {
StringBuilder report = new StringBuilder();
report.append("Student Report\n");
report.append("Name: Anu\n");
report.append("Marks: 92\n");
report.append("Status: PASS\n");
System.out.println(report);
}
}
Output / Result
Student Report Name: Anu Marks: 92 Status: PASS
Real-Time Production Scope
- Report generation
- CSV creation
- Large loop text building
- Dynamic messages
Common Mistakes and Fixes
- Using String concatenation in huge loops
- Sharing StringBuilder across threads
- Using StringBuffer without need
- Forgetting to convert with toString when required
Practice Task
Study Links
Scanner Input
What is it?
Scanner reads input from keyboard, files, or streams.
Beginner + Developer Explanation
Beginners use Scanner with System.in for console input. Developers must handle invalid input and the nextInt/nextLine newline issue.
Important Concepts
- Scanner is in java.util
- System.in is keyboard input
- nextLine reads full line
- nextInt reads integer
- nextDouble reads decimal
- InputMismatchException can happen
Syntax / Pattern
Scanner sc = new Scanner(System.in); String name = sc.nextLine(); int age = sc.nextInt();
Detailed Code Example
import java.util.Scanner;
public class ScannerDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.print("Enter name: ");
String name = sc.nextLine();
System.out.print("Enter age: ");
int age = sc.nextInt();
System.out.println(name + " is " + age + " years old");
sc.close();
}
}
Output / Result
Enter name: Anu Enter age: 22 Anu is 22 years old
Real-Time Production Scope
- CLI tools
- Practice programs
- Simple admin utilities
- File parsing demos
Common Mistakes and Fixes
- Mixing nextInt and nextLine incorrectly
- Not validating input
- Closing System.in too early in larger programs
- Assuming every input is correct
Practice Task
Study Links
Output Formatting
What is it?
Output formatting controls how values appear, especially numbers, columns, dates, and messages.
Beginner + Developer Explanation
Use printf for formatted console output and String.format when you need a formatted string value.
Important Concepts
- println adds newline
- print does not add newline
- printf formats output
- %s for String
- %d for integer
- %.2f for decimal with two digits
- %n for newline
Syntax / Pattern
System.out.printf("Name: %s, Marks: %.2f%n", name, marks);
Detailed Code Example
public class FormatDemo {
public static void main(String[] args) {
String product = "Laptop";
double price = 49999.756;
int qty = 2;
System.out.printf("%-10s %5d %10.2f%n", product, qty, price);
String bill = String.format("Total: %.2f", price * qty);
System.out.println(bill);
}
}
Output / Result
Laptop 2 49999.76 Total: 99999.51
Real-Time Production Scope
- Console reports
- Invoice printing
- Debug output
- Formatted logs
Common Mistakes and Fixes
- Wrong format specifier
- Forgetting newline in printf
- Using + for complex formatting
- Ignoring locale for currency
Practice Task
Study Links
Math, Random, and SecureRandom
What is it?
Java provides Math for common calculations, Random for simple random numbers, and SecureRandom for security-sensitive random values.
Beginner + Developer Explanation
Use Math for calculations, Random for games or simulations, and SecureRandom for OTPs, tokens, and cryptographic randomness.
Important Concepts
- Math methods are static
- Math.max/min compare values
- Math.sqrt calculates square root
- Random creates pseudo-random values
- SecureRandom is stronger for security
- BigDecimal handles precise decimal math
Syntax / Pattern
Math.max(10, 20); Random random = new Random(); int dice = random.nextInt(6) + 1;
Detailed Code Example
import java.security.SecureRandom;
import java.util.Random;
public class MathRandomDemo {
public static void main(String[] args) {
System.out.println(Math.max(10, 25));
System.out.println(Math.sqrt(64));
Random random = new Random();
System.out.println(random.nextInt(6) + 1);
SecureRandom secure = new SecureRandom();
int otp = 100000 + secure.nextInt(900000);
System.out.println("OTP: " + otp);
}
}
Output / Result
25 8.0 Example dice value: 4 OTP: random 6-digit number
Real-Time Production Scope
- Dice games
- Test data
- OTP generation
- Retry jitter
Common Mistakes and Fixes
- Using Random for passwords or tokens
- Expecting random values to be unique
- Using double for money
- Ignoring bounds in nextInt
Practice Task
Study Links
if Statement
What is it?
An if statement runs code only when a condition is true.
Beginner + Developer Explanation
Conditions must evaluate to boolean. This is the basic decision-making structure used in almost every Java program.
Important Concepts
- Condition must be boolean
- Block runs only when condition is true
- Use comparison and logical operators
- Braces improve safety
- Can call methods in condition
Syntax / Pattern
if (condition) {
// code
}
Detailed Code Example
public class IfDemo {
public static void main(String[] args) {
int age = 20;
if (age >= 18) {
System.out.println("Eligible for registration");
}
}
}
Output / Result
Eligible for registration
Real-Time Production Scope
- Validation checks
- Permission checks
- Payment status checks
- Inventory rules
Common Mistakes and Fixes
- Writing very long conditions
- Skipping braces
- Not handling false case when required
- Checking wrong boundary values
Practice Task
Study Links
if else
What is it?
if else chooses one of two paths.
Beginner + Developer Explanation
If the condition is true, the if block runs. Otherwise, the else block runs. Use it for binary decisions.
Important Concepts
- Two-way decision
- else has no condition
- Exactly one block runs
- Good for yes/no decisions
- Can assign a value in each branch
Syntax / Pattern
if (condition) {
// true path
} else {
// false path
}
Detailed Code Example
public class IfElseDemo {
public static void main(String[] args) {
int marks = 42;
if (marks >= 50) {
System.out.println("Pass");
} else {
System.out.println("Fail");
}
}
}
Output / Result
Fail
Real-Time Production Scope
- Login success/failure
- Stock available/unavailable
- Approval/rejection workflows
- Payment paid/pending status
Common Mistakes and Fixes
- Putting condition after else
- Duplicating same code in both branches
- Missing edge cases
- Using nested structure unnecessarily
Practice Task
Study Links
else if Ladder
What is it?
else if ladder checks multiple related conditions in order.
Beginner + Developer Explanation
Java evaluates from top to bottom and runs the first true block. Use it for categories like grade, discount slab, risk level, or status.
Important Concepts
- Order matters
- Only first matching branch runs
- else handles default
- Ranges should not overlap
- Switch may be better for fixed exact values
Syntax / Pattern
if (c1) { }
else if (c2) { }
else { }
Detailed Code Example
public class ElseIfDemo {
public static void main(String[] args) {
int marks = 82;
String grade;
if (marks >= 90) grade = "A+";
else if (marks >= 80) grade = "A";
else if (marks >= 70) grade = "B";
else if (marks >= 50) grade = "C";
else grade = "F";
System.out.println("Grade: " + grade);
}
}
Output / Result
Grade: A
Real-Time Production Scope
- Grade calculation
- Discount slabs
- Risk scoring
- Status mapping
Common Mistakes and Fixes
- Wrong condition order
- Missing final else
- Overlapping ranges
- Hardcoding changing business rules
Practice Task
Study Links
Nested if
What is it?
Nested if means an if statement inside another if statement.
Beginner + Developer Explanation
Use it when one condition should be checked only after another condition passes. Keep nesting limited for readability.
Important Concepts
- Inner condition depends on outer condition
- Useful for multi-step validation
- Deep nesting becomes hard to read
- Guard clauses can flatten logic
- Each level needs clear meaning
Syntax / Pattern
if (conditionA) {
if (conditionB) {
// both passed
}
}
Detailed Code Example
public class NestedIfDemo {
public static void main(String[] args) {
boolean accountActive = true;
boolean passwordCorrect = true;
boolean mfaVerified = false;
if (accountActive) {
if (passwordCorrect) {
if (mfaVerified) {
System.out.println("Login successful");
} else {
System.out.println("MFA required");
}
} else {
System.out.println("Wrong password");
}
} else {
System.out.println("Account inactive");
}
}
}
Output / Result
MFA required
Real-Time Production Scope
- Multi-step login
- Loan approval
- Course registration
- Order validation
Common Mistakes and Fixes
- Pyramid-shaped code
- Missing failure messages
- Repeating conditions
- Not extracting methods
Practice Task
Study Links
switch Statement
What is it?
switch selects behavior based on one value.
Beginner + Developer Explanation
Use switch when one variable has multiple fixed possible values, such as role, day, status, or menu choice.
Important Concepts
- case defines match
- default handles unknown value
- Old switch needs break
- Modern arrow switch is concise
- Works well with enum
- Avoid complex logic inside switch
Syntax / Pattern
switch (value) {
case A -> action;
default -> otherAction;
}
Detailed Code Example
public class SwitchDemo {
public static void main(String[] args) {
String role = "ADMIN";
String access = switch (role) {
case "ADMIN" -> "Full access";
case "MANAGER" -> "Team access";
case "USER" -> "Self access";
default -> "No access";
};
System.out.println(access);
}
}
Output / Result
Full access
Real-Time Production Scope
- Role mapping
- Menu systems
- Order status transitions
- HTTP code mapping
Common Mistakes and Fixes
- Forgetting break in old switch
- No default case
- Using strings where enum is safer
- Putting complex business processes in switch
Practice Task
Study Links
Ternary Operator
What is it?
The ternary operator is a compact if else expression that returns a value.
Beginner + Developer Explanation
Use it only for simple decisions. If the logic needs explanation, use normal if else.
Important Concepts
- Syntax uses ? and :
- Returns one of two values
- Good for simple assignments
- Bad for nested complex decisions
- Both branches should be compatible
Syntax / Pattern
String result = condition ? "YES" : "NO";
Detailed Code Example
public class TernaryDemo {
public static void main(String[] args) {
int stock = 0;
String status = stock > 0 ? "Available" : "Out of stock";
System.out.println(status);
}
}
Output / Result
Out of stock
Real-Time Production Scope
- Simple labels
- Status text
- Default values
- Small response messages
Common Mistakes and Fixes
- Nested ternary confusion
- Side effects in ternary
- Different incompatible return types
- Using ternary for large business logic
Practice Task
Study Links
for Loop
What is it?
A for loop repeats code when the count or range is known.
Beginner + Developer Explanation
It has initialization, condition, and update sections. It is useful for index-based operations and fixed repetitions.
Important Concepts
- Initialization runs once
- Condition checked before each iteration
- Update runs after body
- i++ increments
- Can count forward or backward
- Can be nested
Syntax / Pattern
for (int i = 1; i <= 5; i++) {
System.out.println(i);
}
Detailed Code Example
public class ForDemo {
public static void main(String[] args) {
int total = 0;
for (int i = 1; i <= 5; i++) {
total += i;
System.out.println("i=" + i + ", total=" + total);
}
}
}
Output / Result
i=1, total=1 i=2, total=3 i=3, total=6 i=4, total=10 i=5, total=15
Real-Time Production Scope
- Retry attempts
- Pagination loops
- Report row generation
- Array indexing
Common Mistakes and Fixes
- Off-by-one errors
- Wrong update expression
- Infinite loops
- Changing loop counter unexpectedly
Practice Task
Study Links
while Loop
What is it?
A while loop repeats while a condition is true.
Beginner + Developer Explanation
Use it when the number of repetitions is not known in advance. Make sure something changes so the loop can stop.
Important Concepts
- Condition checked before body
- May run zero times
- Good for unknown count
- Needs update inside loop
- break can stop it
Syntax / Pattern
while (condition) {
// repeated code
}
Detailed Code Example
public class WhileDemo {
public static void main(String[] args) {
int balance = 1000;
int day = 1;
while (balance > 0) {
balance -= 300;
System.out.println("Day " + day + ": balance=" + balance);
day++;
}
}
}
Output / Result
Day 1: balance=700 Day 2: balance=400 Day 3: balance=100 Day 4: balance=-200
Real-Time Production Scope
- Read until file ends
- Poll job status
- Run menu until exit
- Retry until success
Common Mistakes and Fixes
- Forgetting update
- Infinite loops
- No retry limit
- Using while when for is clearer
Practice Task
Study Links
do while Loop
What is it?
A do while loop runs at least once and then checks the condition.
Beginner + Developer Explanation
It is useful for menus and prompts where you want one execution before checking whether to repeat.
Important Concepts
- Runs body first
- Condition checked after body
- Ends with semicolon
- Useful for menus
- Can still be infinite
Syntax / Pattern
do {
// run first
} while (condition);
Detailed Code Example
public class DoWhileDemo {
public static void main(String[] args) {
int attempt = 1;
do {
System.out.println("Attempt " + attempt);
attempt++;
} while (attempt <= 3);
}
}
Output / Result
Attempt 1 Attempt 2 Attempt 3
Real-Time Production Scope
- Console menus
- Input prompts
- Retry confirmation
- Simple games
Common Mistakes and Fixes
- Missing semicolon after while
- Using it when zero runs are required
- Wrong condition
- No exit path
Practice Task
Study Links
Arrays
What is it?
An array stores multiple values of the same type in fixed-size indexed storage.
Beginner + Developer Explanation
Arrays are fast and simple. Index starts at 0. Use collections when you need flexible size.
Important Concepts
- Fixed length
- Same data type
- Index starts at zero
- length gives size
- Default values exist
- Invalid index throws ArrayIndexOutOfBoundsException
Syntax / Pattern
int[] marks = {90, 80, 70};
System.out.println(marks[0]);
Detailed Code Example
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] marks = {85, 90, 78, 92};
int total = 0;
for (int mark : marks) {
total += mark;
}
double avg = total / (double) marks.length;
System.out.println(Arrays.toString(marks));
System.out.println("Average: " + avg);
}
}
Output / Result
[85, 90, 78, 92] Average: 86.25
Real-Time Production Scope
- Algorithm practice
- Fixed-size buffers
- Primitive data processing
- Framework internals
Common Mistakes and Fixes
- Invalid index
- Confusing length and length()
- Trying to resize array directly
- Using arrays when List is better
Practice Task
Study Links
Methods
What is it?
A method is a reusable block of code that performs a task.
Beginner + Developer Explanation
Methods reduce repetition and make code testable. They receive parameters and can return values.
Important Concepts
- Method has name
- Return type can be void or a type
- Parameters receive input
- return sends output
- static methods can be called without object
- Use camelCase names
Syntax / Pattern
returnType methodName(parameterType parameterName) {
return value;
}
Detailed Code Example
public class MethodDemo {
static int add(int a, int b) {
return a + b;
}
static boolean isAdult(int age) {
return age >= 18;
}
public static void main(String[] args) {
System.out.println(add(10, 20));
System.out.println(isAdult(22));
}
}
Output / Result
30 true
Real-Time Production Scope
- Service business logic
- Reusable validations
- Utility functions
- Unit tests
Common Mistakes and Fixes
- Very long methods
- Unclear method names
- No validation
- Wrong return type
Practice Task
Study Links
Method Overloading
What is it?
Method overloading means multiple methods with the same name but different parameter lists.
Beginner + Developer Explanation
Java chooses the correct method at compile time based on argument types and count.
Important Concepts
- Same name
- Different parameter count or type
- Return type alone cannot overload
- Compile-time polymorphism
- Common with constructors
Syntax / Pattern
void print(String value) {}
void print(int value) {}
Detailed Code Example
public class OverloadDemo {
static int add(int a, int b) { return a + b; }
static double add(double a, double b) { return a + b; }
static int add(int a, int b, int c) { return a + b + c; }
public static void main(String[] args) {
System.out.println(add(2, 3));
System.out.println(add(2.5, 3.5));
System.out.println(add(1, 2, 3));
}
}
Output / Result
5 6.0 6
Real-Time Production Scope
- Utility APIs
- Multiple constructors
- Flexible calculations
- Convenience methods
Common Mistakes and Fixes
- Trying to overload only by return type
- Ambiguous overloads
- Too many similar methods
- Unexpected type promotion
Practice Task
Study Links
Classes and Objects
What is it?
A class is a blueprint; an object is an instance created from the blueprint.
Beginner + Developer Explanation
Classes group data and behavior. Objects hold actual values and can call methods.
Important Concepts
- Class defines structure
- Object is created with new
- Fields store state
- Methods define behavior
- Each object has separate instance values
- Object-oriented code models real-world entities
Syntax / Pattern
class Student { }
Student s = new Student();
Detailed Code Example
public class Student {
String name;
int marks;
void printResult() {
System.out.println(name + " scored " + marks);
}
public static void main(String[] args) {
Student s = new Student();
s.name = "Anu";
s.marks = 92;
s.printResult();
}
}
Output / Result
Anu scored 92
Real-Time Production Scope
- Domain models
- DTOs
- Entities
- Service objects
Common Mistakes and Fixes
- Putting all logic in main
- Public fields everywhere
- Confusing class and object
- Not initializing fields
Practice Task
Study Links
Constructors
What is it?
A constructor initializes a new object when it is created.
Beginner + Developer Explanation
Constructor name matches class name and has no return type. Constructors can be overloaded.
Important Concepts
- Runs during new object creation
- No return type
- Can accept parameters
- Default constructor exists only if no constructor is written
- this() calls another constructor
- Use constructor for required fields
Syntax / Pattern
public ClassName(parameters) {
// initialize
}
Detailed Code Example
public class Course {
private String title;
private int weeks;
public Course(String title) {
this(title, 12);
}
public Course(String title, int weeks) {
this.title = title;
this.weeks = weeks;
}
public void printInfo() {
System.out.println(title + " - " + weeks + " weeks");
}
public static void main(String[] args) {
new Course("Java").printInfo();
new Course("Spring Boot", 8).printInfo();
}
}
Output / Result
Java - 12 weeks Spring Boot - 8 weeks
Real-Time Production Scope
- Required object initialization
- Immutable object setup
- DTO construction
- Entity creation
Common Mistakes and Fixes
- Adding return type to constructor
- Forgetting default constructor disappears
- Heavy logic in constructor
- No validation of required fields
Practice Task
Study Links
this and static
What is it?
this refers to the current object. static belongs to the class rather than a specific object.
Beginner + Developer Explanation
Use this for instance fields and constructor clarity. Use static for constants, utility methods, and class-level data.
Important Concepts
- this.field distinguishes field from parameter
- this() calls another constructor
- static field is shared
- static method can be called by class name
- main is static
- static final is common for constants
Syntax / Pattern
this.name = name; static final int MAX = 3;
Detailed Code Example
public class ThisStaticDemo {
private static int objectCount = 0;
private static final String APP_NAME = "StudentApp";
private String name;
public ThisStaticDemo(String name) {
this.name = name;
objectCount++;
}
public void print() {
System.out.println(APP_NAME + ": " + this.name);
}
public static void main(String[] args) {
new ThisStaticDemo("Anu").print();
new ThisStaticDemo("Ravi").print();
System.out.println("Objects: " + objectCount);
}
}
Output / Result
StudentApp: Anu StudentApp: Ravi Objects: 2
Real-Time Production Scope
- Constants
- Object initialization
- Utility methods
- Shared counters
Common Mistakes and Fixes
- Using this in static method
- Making everything static
- Mutable static state in web apps
- Forgetting this when parameter shadows field
Practice Task
Study Links
Packages and Imports
What is it?
Packages organize classes into namespaces; imports allow using classes from other packages.
Beginner + Developer Explanation
Large Java projects use packages to separate controller, service, repository, model, dto, config, and exception layers.
Important Concepts
- package declaration comes first
- imports come after package
- java.lang is automatic
- Folder path should match package
- Use lowercase package names
- Avoid default package in real projects
Syntax / Pattern
package com.example.app; import java.util.List;
Detailed Code Example
package com.ngcxai.demo;
import java.time.LocalDate;
import java.util.List;
public class PackageDemo {
public static void main(String[] args) {
List<String> tasks = List.of("Learn packages", "Learn imports");
System.out.println(LocalDate.now());
System.out.println(tasks);
}
}
Output / Result
Current date [Learn packages, Learn imports]
Real-Time Production Scope
- Enterprise project organization
- Avoiding class name conflicts
- Layered architecture
- Reusable libraries
Common Mistakes and Fixes
- Wrong folder for package
- Using default package
- Too many wildcard imports
- Circular dependencies
Practice Task
Study Links
Access Modifiers and Encapsulation
What is it?
Access modifiers control visibility. Encapsulation hides internal state and exposes controlled behavior.
Beginner + Developer Explanation
Use private fields and public methods to protect data. This prevents invalid object state.
Important Concepts
- public: everywhere
- protected: package and subclass
- default: same package
- private: same class
- Encapsulation uses private fields
- Getters/setters or behavior methods control access
Syntax / Pattern
private double balance;
public double getBalance() { return balance; }
Detailed Code Example
public class BankAccount {
private double balance;
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Amount must be positive");
balance += amount;
}
public void withdraw(double amount) {
if (amount > balance) throw new IllegalArgumentException("Insufficient balance");
balance -= amount;
}
public double getBalance() {
return balance;
}
public static void main(String[] args) {
BankAccount acc = new BankAccount();
acc.deposit(5000);
acc.withdraw(1500);
System.out.println(acc.getBalance());
}
}
Output / Result
3500.0
Real-Time Production Scope
- Bank rules
- Order state protection
- User validation
- Safe domain models
Common Mistakes and Fixes
- Public mutable fields
- No validation in setters
- Returning internal mutable collections
- Making everything public
Practice Task
Study Links
Inheritance and super
What is it?
Inheritance lets a child class reuse and specialize a parent class. super refers to the parent.
Beginner + Developer Explanation
Use inheritance only for true is-a relationships. super() calls the parent constructor and super.method() calls parent behavior.
Important Concepts
- extends creates inheritance
- Java has single class inheritance
- Child inherits accessible methods
- super() must be first constructor statement
- Override customizes behavior
- Prefer composition when relationship is not is-a
Syntax / Pattern
class Dog extends Animal { }
super(name);
Detailed Code Example
class Person {
protected String name;
Person(String name) { this.name = name; }
void introduce() { System.out.println("I am " + name); }
}
class Employee extends Person {
private String department;
Employee(String name, String department) {
super(name);
this.department = department;
}
@Override
void introduce() {
super.introduce();
System.out.println("Department: " + department);
}
}
public class InheritanceDemo {
public static void main(String[] args) {
new Employee("Anu", "IT").introduce();
}
}
Output / Result
I am Anu Department: IT
Real-Time Production Scope
- Base entity classes
- Framework extension
- Template methods
- Shared behavior
Common Mistakes and Fixes
- Using inheritance only for code reuse
- Deep inheritance chains
- Forgetting parent constructor
- Making parent fields protected unnecessarily
Practice Task
Study Links
Overriding and Polymorphism
What is it?
Overriding changes parent behavior in a child class. Polymorphism lets one reference call different implementations at runtime.
Beginner + Developer Explanation
Use interfaces or parent classes to write flexible code where actual implementation can change.
Important Concepts
- Override needs same method signature
- @Override catches mistakes
- Parent reference can hold child object
- Runtime object decides method
- Polymorphism reduces if/else chains
Syntax / Pattern
Payment p = new UpiPayment(); p.pay(100);
Detailed Code Example
interface Notification {
void send(String message);
}
class EmailNotification implements Notification {
public void send(String message) { System.out.println("Email: " + message); }
}
class SmsNotification implements Notification {
public void send(String message) { System.out.println("SMS: " + message); }
}
public class PolyDemo {
public static void main(String[] args) {
Notification n = new EmailNotification();
n.send("Order shipped");
n = new SmsNotification();
n.send("OTP 1234");
}
}
Output / Result
Email: Order shipped SMS: OTP 1234
Real-Time Production Scope
- Payment strategies
- Notification channels
- Spring dependency injection
- Plugin-style systems
Common Mistakes and Fixes
- Forgetting @Override
- Changing parameter list accidentally
- Too many instanceof checks
- Not programming to interfaces
Practice Task
Study Links
Abstract Classes and Interfaces
What is it?
Abstract classes provide partial implementation. Interfaces define contracts that classes implement.
Beginner + Developer Explanation
Use abstract class when sharing state/code is important. Use interface when defining capability or contract.
Important Concepts
- abstract class cannot be instantiated
- Abstract methods must be implemented
- Interface supports multiple implementation
- Interface can have default/static methods
- Class can extend one class but implement many interfaces
Syntax / Pattern
abstract class Shape { abstract double area(); }
interface Printable { void print(); }
Detailed Code Example
abstract class Report {
void header() { System.out.println("=== Report ==="); }
abstract void body();
}
interface Exportable {
void export();
}
class SalesReport extends Report implements Exportable {
void body() { System.out.println("Sales data"); }
public void export() { System.out.println("Exporting PDF"); }
}
public class AbstractInterfaceDemo {
public static void main(String[] args) {
SalesReport report = new SalesReport();
report.header();
report.body();
report.export();
}
}
Output / Result
=== Report === Sales data Exporting PDF
Real-Time Production Scope
- Template methods
- Service contracts
- Payment gateways
- Reusable framework components
Common Mistakes and Fixes
- Using abstract class when interface is enough
- Fat interfaces with too many methods
- Trying to instantiate abstract class
- Forgetting public implementation of interface methods
Practice Task
Study Links
final, enum, and record
What is it?
final prevents reassignment or inheritance behavior; enum represents fixed constants; record creates compact immutable data carriers.
Beginner + Developer Explanation
These features make code safer and more expressive. Use enum for known states and record for DTO-like data.
Important Concepts
- final variable cannot be reassigned
- final class cannot be extended
- enum restricts allowed values
- record generates constructor/accessors/toString/equals/hashCode
- Records are shallowly immutable
Syntax / Pattern
final int MAX = 3;
enum Status { PENDING, PAID }
record Student(String name, int marks) {}
Detailed Code Example
enum OrderStatus { CREATED, PAID, SHIPPED, DELIVERED }
record Order(String id, OrderStatus status, double amount) {}
public class ModernTypesDemo {
public static void main(String[] args) {
final String appName = "OrderApp";
Order order = new Order("O100", OrderStatus.PAID, 1500.0);
System.out.println(appName);
System.out.println(order.id());
System.out.println(order.status());
System.out.println(order);
}
}
Output / Result
OrderApp O100 PAID Order[id=O100, status=PAID, amount=1500.0]
Real-Time Production Scope
- Fixed statuses
- Immutable API DTOs
- Constants
- Domain value objects
Common Mistakes and Fixes
- Using strings instead of enum
- Expecting record getters like getName()
- Thinking final object is deeply immutable
- Persisting enum ordinal in database
Practice Task
Study Links
equals, hashCode, and toString
What is it?
equals defines logical equality, hashCode supports hash-based collections, and toString controls readable object text.
Beginner + Developer Explanation
If two objects are equal, they must have the same hashCode. This is critical for HashSet and HashMap.
Important Concepts
- Override equals for logical equality
- Override hashCode with equals
- toString helps logs/debugging
- Records generate all three
- Bad hashCode breaks collections
Syntax / Pattern
public boolean equals(Object o) { ... }
public int hashCode() { ... }
public String toString() { ... }
Detailed Code Example
record UserId(String value) {}
public class EqualityDemo {
public static void main(String[] args) {
UserId a = new UserId("U1");
UserId b = new UserId("U1");
System.out.println(a.equals(b));
System.out.println(a.hashCode() == b.hashCode());
System.out.println(a);
}
}
Output / Result
true true UserId[value=U1]
Real-Time Production Scope
- Set uniqueness
- Map keys
- Value objects
- Readable logs
Common Mistakes and Fixes
- Overriding equals but not hashCode
- Using == for object equality
- No useful toString for logs
- Using mutable fields in hashCode
Practice Task
Study Links
Exception Handling
What is it?
Exception handling manages runtime problems without crashing the application unexpectedly.
Beginner + Developer Explanation
Use try/catch for recoverable errors, finally or try-with-resources for cleanup, and meaningful exception types for business errors.
Important Concepts
- try contains risky code
- catch handles matching exception
- finally runs cleanup
- Checked exceptions are compiler-checked
- Unchecked exceptions extend RuntimeException
- Stack trace shows error path
Syntax / Pattern
try {
riskyCode();
} catch (ExceptionType e) {
handle(e);
} finally {
cleanup();
}
Detailed Code Example
public class ExceptionDemo {
public static void main(String[] args) {
try {
int result = 10 / 0;
System.out.println(result);
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero");
} finally {
System.out.println("Done");
}
}
}
Output / Result
Cannot divide by zero Done
Real-Time Production Scope
- API error responses
- File/database failure handling
- Validation failures
- External service error handling
Common Mistakes and Fixes
- Catching Exception everywhere
- Ignoring exception silently
- Showing stack trace to users
- Using exceptions for normal flow
Practice Task
Study Links
throw, throws, and Custom Exceptions
What is it?
throw creates an exception; throws declares a method may pass an exception to its caller. Custom exceptions represent domain errors.
Beginner + Developer Explanation
Use custom exceptions for clear business failures such as InsufficientBalanceException or CourseFullException.
Important Concepts
- throw is used inside method body
- throws is used in method signature
- Custom checked exception extends Exception
- Custom unchecked exception extends RuntimeException
- Meaningful messages help debugging
Syntax / Pattern
throw new IllegalArgumentException("Invalid age");
void read() throws IOException { }
Detailed Code Example
class CourseFullException extends RuntimeException {
public CourseFullException(String message) { super(message); }
}
class CourseRegistration {
private int seats = 0;
void register(String student) {
if (seats <= 0) throw new CourseFullException("No seats available for " + student);
seats--;
}
}
public class CustomExceptionDemo {
public static void main(String[] args) {
try {
new CourseRegistration().register("Anu");
} catch (CourseFullException e) {
System.out.println(e.getMessage());
}
}
}
Output / Result
No seats available for Anu
Real-Time Production Scope
- Domain validation
- REST API error mapping
- Payment failures
- Business rule enforcement
Common Mistakes and Fixes
- Confusing throw and throws
- Generic exception names
- No meaningful message
- Losing original cause when wrapping
Practice Task
Study Links
try-with-resources
What is it?
try-with-resources automatically closes resources that implement AutoCloseable.
Beginner + Developer Explanation
Use it for files, streams, database connections, readers, writers, and sockets. It is safer than manual close.
Important Concepts
- Resource declared in try parentheses
- Closes automatically
- Works with AutoCloseable
- Can declare multiple resources
- Preferred for I/O and JDBC
Syntax / Pattern
try (Resource r = new Resource()) {
// use resource
}
Detailed Code Example
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
public class TryResourceDemo {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("demo.txt"))) {
writer.write("Hello try-with-resources");
} catch (IOException e) {
System.out.println("Write failed: " + e.getMessage());
}
}
}
Output / Result
Creates demo.txt with text
Real-Time Production Scope
- File processing
- JDBC connections
- Network streams
- Resource cleanup
Common Mistakes and Fixes
- Manual close in many places
- Ignoring IOException
- Opening too many resources
- Using non-AutoCloseable resources incorrectly
Practice Task
Study Links
Generics
What is it?
Generics make classes, methods, and collections type-safe.
Beginner + Developer Explanation
Use generics to avoid casting and prevent wrong types at compile time.
Important Concepts
- Use angle brackets
- T is common type parameter
- List<String> stores Strings
- Raw types remove safety
- Type erasure happens at runtime
Syntax / Pattern
List<String> names = new ArrayList<>();
class Box<T> { T value; }
Detailed Code Example
public class Box<T> {
private T value;
public void setValue(T value) { this.value = value; }
public T getValue() { return value; }
public static void main(String[] args) {
Box<String> box = new Box<>();
box.setValue("Java");
System.out.println(box.getValue().toUpperCase());
}
}
Output / Result
JAVA
Real-Time Production Scope
- Type-safe collections
- API response wrappers
- Repository patterns
- Reusable utilities
Common Mistakes and Fixes
- Using raw List
- Assuming generic type exists at runtime
- Trying new T()
- Overcomplicated generic designs
Practice Task
Study Links
List and ArrayList
What is it?
List stores ordered elements and ArrayList is a resizable-array implementation.
Beginner + Developer Explanation
Use List when order matters and duplicates are allowed. It is one of the most common Java collection types.
Important Concepts
- Ordered
- Allows duplicates
- Index-based access
- Resizable
- ArrayList is fast for get
- Use List as variable type
Syntax / Pattern
List<String> names = new ArrayList<>();
names.add("Anu");
Detailed Code Example
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
List<String> courses = new ArrayList<>();
courses.add("Java");
courses.add("Spring Boot");
courses.add("SQL");
courses.remove("SQL");
for (String course : courses) {
System.out.println(course);
}
System.out.println("Total: " + courses.size());
}
}
Output / Result
Java Spring Boot Total: 2
Real-Time Production Scope
- API responses
- Search results
- Batch records
- Form selections
Common Mistakes and Fixes
- Using raw ArrayList
- Removing during enhanced for
- Assuming thread safety
- Using LinkedList without reason
Practice Task
Study Links
Set and HashSet
What is it?
Set stores unique elements. HashSet is a common Set implementation based on hashing.
Beginner + Developer Explanation
Use Set when duplicates must be removed or membership checks should be fast.
Important Concepts
- No duplicates
- HashSet order not guaranteed
- contains is fast
- Uses equals and hashCode
- LinkedHashSet preserves insertion order
- TreeSet sorts
Syntax / Pattern
Set<String> emails = new HashSet<>();
emails.add("a@example.com");
Detailed Code Example
import java.util.HashSet;
import java.util.Set;
public class SetDemo {
public static void main(String[] args) {
Set<String> emails = new HashSet<>();
emails.add("a@example.com");
emails.add("b@example.com");
emails.add("a@example.com");
System.out.println(emails);
System.out.println("Unique: " + emails.size());
}
}
Output / Result
Order may vary Unique: 2
Real-Time Production Scope
- Duplicate removal
- Permission sets
- Unique IDs
- Fast lookup
Common Mistakes and Fixes
- Expecting sorted order
- Missing equals/hashCode for custom objects
- Changing key fields after adding
- Using List when uniqueness is required
Practice Task
Study Links
Map and HashMap
What is it?
Map stores key-value pairs. HashMap is the most common general-purpose implementation.
Beginner + Developer Explanation
Use Map when you want to quickly find a value using a key.
Important Concepts
- Keys are unique
- Values can repeat
- HashMap order not guaranteed
- put adds/updates
- get retrieves
- containsKey checks existence
Syntax / Pattern
Map<String, Integer> scores = new HashMap<>();
scores.put("Anu", 95);
Detailed Code Example
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<String, Integer> stock = new HashMap<>();
stock.put("Laptop", 5);
stock.put("Mouse", 25);
stock.put("Keyboard", 10);
stock.put("Mouse", stock.get("Mouse") - 1);
for (Map.Entry<String, Integer> entry : stock.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
}
Output / Result
Order may vary Mouse = 24 Laptop = 5 Keyboard = 10
Real-Time Production Scope
- Caches
- Inventory lookup
- Frequency counters
- Configuration maps
Common Mistakes and Fixes
- Expecting order
- get returns null when key missing
- Mutable key problems
- No equals/hashCode for custom keys
Practice Task
Study Links
Queue and Deque
What is it?
Queue processes elements usually first-in-first-out. Deque allows operations at both ends.
Beginner + Developer Explanation
Use Queue for task processing and Deque for stack/queue behavior.
Important Concepts
- offer adds safely
- poll removes or returns null
- peek views first
- ArrayDeque is fast
- PriorityQueue processes by priority
- Deque supports addFirst/addLast
Syntax / Pattern
Queue<String> q = new ArrayDeque<>();
q.offer("task");
q.poll();
Detailed Code Example
import java.util.ArrayDeque;
import java.util.Queue;
public class QueueDemo {
public static void main(String[] args) {
Queue<String> jobs = new ArrayDeque<>();
jobs.offer("Email customer");
jobs.offer("Generate invoice");
jobs.offer("Update report");
while (!jobs.isEmpty()) {
System.out.println("Processing: " + jobs.poll());
}
}
}
Output / Result
Processing: Email customer Processing: Generate invoice Processing: Update report
Real-Time Production Scope
- Task queues
- Breadth-first search
- Print queues
- Local retry queues
Common Mistakes and Fixes
- Using Stack instead of ArrayDeque
- Using remove on empty queue
- Assuming in-memory queue survives restart
- Using non-thread-safe queue across threads
Practice Task
Study Links
Comparable and Comparator
What is it?
Comparable defines natural ordering; Comparator defines custom ordering.
Beginner + Developer Explanation
Use Comparator when sorting by different fields like name, price, date, or marks.
Important Concepts
- Comparable uses compareTo
- Comparator uses compare
- Comparator.comparing is concise
- reversed changes order
- thenComparing adds secondary sort
Syntax / Pattern
list.sort(Comparator.comparing(Student::marks).reversed());
Detailed Code Example
import java.util.*;
record Student(String name, int marks) {}
public class ComparatorDemo {
public static void main(String[] args) {
List<Student> students = new ArrayList<>(List.of(
new Student("Anu", 92),
new Student("Ravi", 75),
new Student("Priya", 88)
));
students.sort(Comparator.comparing(Student::marks).reversed());
students.forEach(System.out::println);
}
}
Output / Result
Student[name=Anu, marks=92] Student[name=Priya, marks=88] Student[name=Ravi, marks=75]
Real-Time Production Scope
- Leaderboards
- Report sorting
- Search result ordering
- Priority ranking
Common Mistakes and Fixes
- Comparing with subtraction
- Ignoring nulls
- Confusing ascending/descending
- Implementing Comparable for multiple different orders
Practice Task
Study Links
Iterator and Collections Utility
What is it?
Iterator safely traverses collections; Collections utility class provides helper methods like sort, reverse, max, min, and frequency.
Beginner + Developer Explanation
Use Iterator when removing during traversal. Use Collections for common operations on lists and sets.
Important Concepts
- Iterator has hasNext and next
- Iterator.remove removes safely
- Collections.sort sorts
- Collections.reverse reverses
- Collections.max/min find extremes
- Collections.unmodifiableList protects returned data
Syntax / Pattern
Iterator<T> it = list.iterator(); Collections.sort(list);
Detailed Code Example
import java.util.*;
public class IteratorCollectionsDemo {
public static void main(String[] args) {
List<Integer> marks = new ArrayList<>(List.of(90, 35, 70, 20, 88));
Iterator<Integer> it = marks.iterator();
while (it.hasNext()) {
if (it.next() < 40) it.remove();
}
Collections.sort(marks);
System.out.println(marks);
System.out.println(Collections.max(marks));
}
}
Output / Result
[70, 88, 90] 90
Real-Time Production Scope
- Filtering records
- Sorting reports
- Defensive immutable returns
- Safe mutation
Common Mistakes and Fixes
- Removing directly inside enhanced for
- Calling next without hasNext
- Sorting immutable List.of list
- Confusing Collection and Collections
Practice Task
Study Links
Lambda Expressions
What is it?
A lambda expression is a compact way to implement a functional interface.
Beginner + Developer Explanation
Lambdas reduce boilerplate and are heavily used with streams, comparators, callbacks, and functional APIs.
Important Concepts
- Syntax uses ->
- Works with functional interfaces
- Can have one parameter or many
- Can use expression body or block body
- Can capture effectively final variables
Syntax / Pattern
name -> System.out.println(name) (a, b) -> a + b
Detailed Code Example
import java.util.List;
public class LambdaDemo {
public static void main(String[] args) {
List<String> names = List.of("Anu", "Ravi", "Priya");
names.forEach(name -> System.out.println("Hello " + name));
}
}
Output / Result
Hello Anu Hello Ravi Hello Priya
Real-Time Production Scope
- Stream filters
- Event callbacks
- Comparators
- Async handlers
Common Mistakes and Fixes
- Putting complex logic into lambda
- Mutating captured variables
- Ignoring readability
- Using lambda where method name is clearer
Practice Task
Study Links
Stream API
What is it?
Stream API processes collections through pipelines such as filter, map, sorted, and collect.
Beginner + Developer Explanation
Streams are useful for transforming and filtering data in a readable style.
Important Concepts
- Stream does not store data
- Intermediate operations are lazy
- Terminal operation triggers processing
- filter selects values
- map transforms values
- toList collects results
Syntax / Pattern
list.stream().filter(x -> condition).map(x -> transform).toList();
Detailed Code Example
import java.util.List;
record Student(String name, int marks) {}
public class StreamDemo {
public static void main(String[] args) {
List<Student> students = List.of(
new Student("Anu", 92),
new Student("Ravi", 45),
new Student("Priya", 88)
);
List<String> toppers = students.stream()
.filter(s -> s.marks() >= 80)
.map(Student::name)
.toList();
System.out.println(toppers);
}
}
Output / Result
[Anu, Priya]
Real-Time Production Scope
- DTO transformations
- Search filtering
- Report aggregation
- Dashboard metrics
Common Mistakes and Fixes
- Reusing a consumed stream
- Side effects inside map/filter
- Too-long pipelines
- Using parallelStream blindly
Practice Task
Study Links
Optional
What is it?
Optional represents a value that may be present or absent.
Beginner + Developer Explanation
Use Optional as a return type for methods that may not find a result.
Important Concepts
- Optional.empty means no value
- Optional.of needs non-null value
- Optional.ofNullable accepts null
- orElse gives default
- orElseThrow throws
- map transforms present value
Syntax / Pattern
Optional<String> value = Optional.ofNullable(input);
String result = value.orElse("Default");
Detailed Code Example
import java.util.Optional;
public class OptionalDemo {
static Optional<String> findEmail(int userId) {
if (userId == 1) return Optional.of("anu@example.com");
return Optional.empty();
}
public static void main(String[] args) {
String email = findEmail(2)
.map(String::toLowerCase)
.orElse("no-email@example.com");
System.out.println(email);
}
}
Output / Result
no-email@example.com
Real-Time Production Scope
- Repository findById
- Safe lookups
- Avoiding null return contracts
- Chained transformations
Common Mistakes and Fixes
- Calling get without checking
- Using Optional fields in JPA entities
- Optional parameters everywhere
- Confusing orElse and orElseGet
Practice Task
Study Links
Date and Time API
What is it?
java.time is Java's modern API for dates, times, durations, periods, instants, and time zones.
Beginner + Developer Explanation
Use LocalDate for dates, LocalTime for times, LocalDateTime for local date-time, ZonedDateTime for timezone-aware date-time, and Instant for machine timestamps.
Important Concepts
- LocalDate stores date only
- LocalTime stores time only
- LocalDateTime has no zone
- ZonedDateTime has zone
- Instant is UTC timestamp
- DateTimeFormatter formats/parses
Syntax / Pattern
LocalDate today = LocalDate.now(); LocalDate due = today.plusDays(7);
Detailed Code Example
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
public class DateTimeDemo {
public static void main(String[] args) {
LocalDate joining = LocalDate.of(2024, 5, 15);
LocalDate today = LocalDate.now();
Period experience = Period.between(joining, today);
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd-MM-yyyy");
System.out.println(joining.format(fmt));
System.out.println("Years: " + experience.getYears());
}
}
Output / Result
15-05-2024 Years: depends on current date
Real-Time Production Scope
- Subscription expiry
- Booking systems
- Audit timestamps
- Date-range reports
Common Mistakes and Fixes
- Using old Date/Calendar for new code
- Ignoring timezone
- Wrong formatter pattern
- Storing local time when UTC Instant is needed
Practice Task
Study Links
File Handling
What is it?
File handling means reading from and writing to files.
Beginner + Developer Explanation
Java supports classic IO and modern NIO. Always handle IOException and close resources safely.
Important Concepts
- FileReader/FileWriter for character files
- BufferedReader improves reading
- BufferedWriter improves writing
- IOException must be handled
- try-with-resources closes files
- Use UTF-8 for predictable encoding
Syntax / Pattern
try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) { }
Detailed Code Example
import java.io.*;
public class FileDemo {
public static void main(String[] args) {
try (BufferedWriter writer = new BufferedWriter(new FileWriter("notes.txt"))) {
writer.write("Java File Handling\n");
writer.write("Second line");
} catch (IOException e) {
System.out.println("Write error: " + e.getMessage());
}
try (BufferedReader reader = new BufferedReader(new FileReader("notes.txt"))) {
String line;
while ((line = reader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
System.out.println("Read error: " + e.getMessage());
}
}
}
Output / Result
Java File Handling Second line
Real-Time Production Scope
- Log processing
- CSV import/export
- Report generation
- Configuration reading
Common Mistakes and Fixes
- Not closing files
- Ignoring encoding
- Reading huge files fully into memory
- No missing-file handling
Practice Task
Study Links
NIO Files and Path
What is it?
NIO provides modern Path and Files APIs for file operations.
Beginner + Developer Explanation
Path represents locations. Files provides methods to read, write, copy, move, delete, and inspect files.
Important Concepts
- Path.of creates path
- Files.readString reads text
- Files.writeString writes text
- Files.readAllLines reads lines
- Files.exists checks existence
- Files.walk traverses directories
Syntax / Pattern
Path path = Path.of("data.txt");
Files.writeString(path, "Hello");
Detailed Code Example
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class NioDemo {
public static void main(String[] args) throws IOException {
Path path = Path.of("students.txt");
Files.write(path, List.of("Anu", "Ravi", "Priya"));
List<String> names = Files.readAllLines(path);
names.forEach(System.out::println);
System.out.println("Exists: " + Files.exists(path));
}
}
Output / Result
Anu Ravi Priya Exists: true
Real-Time Production Scope
- Batch file processing
- Upload storage
- Directory cleanup
- Config files
Common Mistakes and Fixes
- Using string concatenation for paths
- Reading huge files with readAllLines
- Not handling IOException
- Deleting without checks
Practice Task
Study Links
JSON and HTTP Client
What is it?
JSON is a data exchange format; Java HTTP Client calls REST APIs.
Beginner + Developer Explanation
Core Java has HTTP client, but JSON object mapping usually uses libraries like Jackson or Gson.
Important Concepts
- HttpClient sends requests
- HttpRequest builds request
- HttpResponse stores result
- JSON uses key-value text
- Jackson ObjectMapper maps objects to JSON
- Always handle status codes
Syntax / Pattern
HttpClient client = HttpClient.newHttpClient(); HttpRequest request = HttpRequest.newBuilder(uri).GET().build();
Detailed Code Example
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class HttpClientDemo {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://jsonplaceholder.typicode.com/posts/1"))
.GET()
.build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.statusCode());
System.out.println(response.body().substring(0, 30));
}
}
Output / Result
200 First 30 characters of JSON body
Real-Time Production Scope
- Calling REST APIs
- Webhook clients
- Microservice communication
- Data synchronization
Common Mistakes and Fixes
- No timeout
- Ignoring non-2xx status
- Logging tokens
- Parsing JSON manually in complex apps
Practice Task
Study Links
Thread and Runnable
What is it?
A thread is an independent execution path; Runnable defines work that a thread runs.
Beginner + Developer Explanation
Use manual threads to learn concurrency. In production, prefer ExecutorService, CompletableFuture, or virtual threads for better management.
Important Concepts
- Thread represents execution
- Runnable has run method
- start starts new thread
- run directly does not start new thread
- join waits for completion
- Output order can vary
Syntax / Pattern
Thread t = new Thread(() -> doWork()); t.start();
Detailed Code Example
public class ThreadDemo {
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
for (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + " - " + i);
}
};
Thread t1 = new Thread(task, "Worker-1");
Thread t2 = new Thread(task, "Worker-2");
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Done");
}
}
Output / Result
Order may vary Worker-1 - 1 Worker-2 - 1 Done
Real-Time Production Scope
- Background tasks
- Parallel processing
- Async notifications
- Learning concurrency
Common Mistakes and Fixes
- Calling run instead of start
- Updating shared state unsafely
- Creating too many threads
- Ignoring InterruptedException
Practice Task
Study Links
Synchronization
What is it?
Synchronization protects shared mutable data from race conditions.
Beginner + Developer Explanation
When multiple threads change the same value, synchronized ensures only one thread enters the critical section at a time.
Important Concepts
- Race condition causes wrong result
- synchronized method locks current object
- synchronized block locks selected object
- Atomic classes are alternatives
- Deadlock can happen with multiple locks
Syntax / Pattern
synchronized void increment() { count++; }
Detailed Code Example
class Counter {
private int count = 0;
public synchronized void increment() { count++; }
public int getCount() { return count; }
}
public class SyncDemo {
public static void main(String[] args) throws InterruptedException {
Counter counter = new Counter();
Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) counter.increment(); });
Thread t2 = new Thread(() -> { for (int i = 0; i < 1000; i++) counter.increment(); });
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(counter.getCount());
}
}
Output / Result
2000
Real-Time Production Scope
- Shared counters
- Inventory updates
- Critical sections
- In-memory state protection
Common Mistakes and Fixes
- Synchronizing too much
- Deadlocks
- Using different locks accidentally
- Sharing mutable state unnecessarily
Practice Task
Study Links
ExecutorService, Callable, Future
What is it?
ExecutorService manages worker threads. Callable returns a result. Future represents a result available later.
Beginner + Developer Explanation
Use executors instead of manually creating many threads. Use Callable/Future when you need results from async work.
Important Concepts
- Fixed thread pool controls concurrency
- submit returns Future
- Callable returns value
- Future.get waits
- shutdown is required
- Timeout prevents waiting forever
Syntax / Pattern
ExecutorService ex = Executors.newFixedThreadPool(2); Future<Integer> f = ex.submit(() -> 42);
Detailed Code Example
import java.util.concurrent.*;
public class ExecutorFutureDemo {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newFixedThreadPool(2);
Future<Integer> f1 = executor.submit(() -> 10 + 20);
Future<Integer> f2 = executor.submit(() -> 30 + 40);
System.out.println(f1.get() + f2.get());
executor.shutdown();
}
}
Output / Result
100
Real-Time Production Scope
- Batch processing
- Parallel calculations
- Background jobs
- Controlled async work
Common Mistakes and Fixes
- Forgetting shutdown
- Calling get too early
- No timeout
- Ignoring task exceptions
Practice Task
Study Links
CompletableFuture
What is it?
CompletableFuture creates asynchronous pipelines that can transform, combine, and handle results.
Beginner + Developer Explanation
It is useful when multiple tasks can run at the same time and their results need to be combined.
Important Concepts
- supplyAsync starts async supplier
- thenApply transforms result
- thenAccept consumes result
- thenCombine combines futures
- exceptionally handles errors
- join waits without checked exception
Syntax / Pattern
CompletableFuture.supplyAsync(() -> value).thenApply(v -> transform(v));
Detailed Code Example
import java.util.concurrent.CompletableFuture;
public class CompletableFutureDemo {
public static void main(String[] args) {
CompletableFuture<String> user = CompletableFuture.supplyAsync(() -> "Anu");
CompletableFuture<String> course = CompletableFuture.supplyAsync(() -> "Java");
String result = user.thenCombine(course, (u, c) -> u + " enrolled in " + c).join();
System.out.println(result);
}
}
Output / Result
Anu enrolled in Java
Real-Time Production Scope
- Parallel API calls
- Async workflows
- Notification pipelines
- Data aggregation
Common Mistakes and Fixes
- Ignoring exceptions
- Using common pool for heavy blocking tasks
- Joining too early
- Overcomplicating simple code
Practice Task
Study Links
Concurrent Collections and Virtual Threads
What is it?
Concurrent collections are thread-safe data structures; virtual threads are lightweight threads for high-concurrency blocking work.
Beginner + Developer Explanation
Use ConcurrentHashMap, BlockingQueue, AtomicInteger, and virtual threads when normal collections or platform threads are not suitable.
Important Concepts
- ConcurrentHashMap supports safe concurrent map access
- AtomicInteger supports atomic counters
- BlockingQueue supports producer-consumer
- Virtual threads are lightweight
- Do not pool virtual threads like platform threads
- Connection pools still limit throughput
Syntax / Pattern
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { }
Detailed Code Example
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ConcurrentDemo {
public static void main(String[] args) throws InterruptedException {
ConcurrentHashMap<String, AtomicInteger> counts = new ConcurrentHashMap<>();
Runnable task = () -> counts.computeIfAbsent("login", k -> new AtomicInteger()).incrementAndGet();
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start(); t2.start();
t1.join(); t2.join();
System.out.println(counts.get("login").get());
}
}
Output / Result
2
Real-Time Production Scope
- Thread-safe caches
- Counters and metrics
- Producer-consumer systems
- High-concurrency services
Common Mistakes and Fixes
- Using HashMap across threads
- Assuming all compound actions are atomic
- Pooling virtual threads unnecessarily
- Ignoring database pool limits
Practice Task
Study Links
JDBC
What is it?
JDBC is Java's standard API for connecting to relational databases.
Beginner + Developer Explanation
JDBC teaches connection, PreparedStatement, ResultSet, transactions, and SQL injection prevention. Even if you later use JPA, JDBC knowledge is important.
Important Concepts
- Connection represents DB session
- PreparedStatement prevents SQL injection
- ResultSet stores query results
- Transactions use commit and rollback
- Use try-with-resources
- Connection pooling is needed in production
Syntax / Pattern
Connection con = DriverManager.getConnection(url, user, pass);
PreparedStatement ps = con.prepareStatement("SELECT * FROM users WHERE id=?");
Detailed Code Example
import java.sql.*;
public class JdbcConceptDemo {
public static void main(String[] args) throws Exception {
// Example requires a JDBC driver and database URL
String sql = "SELECT id, name FROM students WHERE id = ?";
System.out.println("Prepared SQL: " + sql);
System.out.println("Use PreparedStatement to set id safely.");
}
}
Output / Result
Prepared SQL: SELECT id, name FROM students WHERE id = ? Use PreparedStatement to set id safely.
Real-Time Production Scope
- CRUD apps
- Batch imports
- Legacy systems
- Understanding ORM behavior
Common Mistakes and Fixes
- String concatenation in SQL
- Not closing connections
- No transactions
- Hardcoded credentials
Practice Task
Study Links
Spring Boot
What is it?
Spring Boot simplifies building production-ready Java applications, especially REST APIs and microservices.
Beginner + Developer Explanation
It auto-configures common setup and provides starters for web, data, validation, security, testing, and monitoring.
Important Concepts
- @SpringBootApplication starts app
- Starter dependencies simplify setup
- Embedded server runs app
- Dependency Injection manages objects
- application.properties configures app
- Actuator adds production endpoints
Syntax / Pattern
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
Detailed Code Example
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class StudentApplication {
public static void main(String[] args) {
SpringApplication.run(StudentApplication.class, args);
}
}
Output / Result
Starts Spring Boot application
Real-Time Production Scope
- REST APIs
- Microservices
- Internal enterprise systems
- Cloud-native services
Common Mistakes and Fixes
- Putting all logic in controller
- Not understanding dependency injection
- Too many starters
- Ignoring profiles/configuration
Practice Task
Study Links
Spring REST API
What is it?
A REST API exposes resources over HTTP using endpoints like GET, POST, PUT, PATCH, and DELETE.
Beginner + Developer Explanation
Spring uses annotations such as @RestController, @RequestMapping, @GetMapping, @PostMapping, @RequestBody, and @PathVariable.
Important Concepts
- @RestController returns JSON
- @GetMapping handles GET
- @PostMapping handles POST
- @RequestBody maps JSON
- @PathVariable reads URL part
- ResponseEntity controls status
Syntax / Pattern
@RestController
@RequestMapping("/api/students")
class StudentController { }
Detailed Code Example
import org.springframework.web.bind.annotation.*;
import java.util.*;
@RestController
@RequestMapping("/api/students")
class StudentController {
private final List<String> students = new ArrayList<>(List.of("Anu", "Ravi"));
@GetMapping
public List<String> all() { return students; }
@PostMapping
public String add(@RequestBody String name) {
students.add(name);
return "Added " + name;
}
}
Output / Result
GET /api/students -> ["Anu", "Ravi"]
Real-Time Production Scope
- Student management APIs
- Order services
- Mobile backends
- Admin dashboards
Common Mistakes and Fixes
- Using entities as DTOs everywhere
- No validation
- Wrong HTTP status codes
- No global exception handler
Practice Task
Study Links
JPA and Hibernate
What is it?
JPA maps Java objects to database tables. Hibernate is a common JPA implementation.
Beginner + Developer Explanation
ORM lets you work with entities and repositories instead of raw SQL for common CRUD operations.
Important Concepts
- @Entity maps class to table
- @Id defines primary key
- @GeneratedValue creates IDs
- Repository handles queries
- Transactions protect data changes
- Lazy loading needs care
Syntax / Pattern
@Entity
class Student {
@Id @GeneratedValue
private Long id;
}
Detailed Code Example
import jakarta.persistence.*;
@Entity
class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private int marks;
protected Student() {}
public Student(String name, int marks) {
this.name = name;
this.marks = marks;
}
}
Output / Result
Entity maps to a database table
Real-Time Production Scope
- CRUD APIs
- Enterprise data apps
- Domain persistence
- Repository pattern
Common Mistakes and Fixes
- N+1 query problem
- Using entities directly as API DTOs
- No transactions
- Ignoring database indexes
Practice Task
Study Links
Spring Security and JWT
What is it?
Spring Security handles authentication and authorization. JWT is a stateless token format often used for REST APIs.
Beginner + Developer Explanation
JWT is sent in Authorization header as Bearer token. The server validates signature, expiry, and claims.
Important Concepts
- Authentication verifies user identity
- Authorization checks permissions
- JWT has header, payload, signature
- Bearer token goes in Authorization header
- Passwords must be hashed
- Secrets must not be hardcoded
Syntax / Pattern
Authorization: Bearer <token>
Detailed Code Example
public class JwtFlowDemo {
public static void main(String[] args) {
String header = "Bearer abc.def.ghi";
if (header.startsWith("Bearer ")) {
String token = header.substring(7);
System.out.println("Extracted token: " + token);
}
}
}
Output / Result
Extracted token: abc.def.ghi
Real-Time Production Scope
- Login APIs
- Admin/user role security
- Microservice authentication
- Mobile app backend
Common Mistakes and Fixes
- Storing secrets in code
- No token expiry
- Trusting decoded payload without verifying signature
- Logging tokens
Practice Task
Study Links
Maven and Gradle
What is it?
Maven and Gradle are Java build tools that compile, test, package, and manage dependencies.
Beginner + Developer Explanation
Maven uses pom.xml. Gradle uses build.gradle or build.gradle.kts. Use the build tool required by your project.
Important Concepts
- Dependencies are external libraries
- Maven lifecycle includes compile/test/package
- Gradle tasks include test/build
- Wrapper standardizes tool version
- Build tools integrate with CI/CD
Syntax / Pattern
mvn clean package ./gradlew build
Detailed Code Example
<dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter</artifactId> <version>5.10.0</version> <scope>test</scope> </dependency>
Output / Result
Build creates target/*.jar or build/libs/*.jar
Real-Time Production Scope
- Dependency management
- CI/CD builds
- Packaging services
- Multi-module projects
Common Mistakes and Fixes
- Committing target/build folders
- Random dependency versions
- Not using Gradle wrapper
- Mixing build tools unnecessarily
Practice Task
Study Links
JUnit Testing
What is it?
JUnit is the standard framework for unit testing Java code.
Beginner + Developer Explanation
Tests verify that methods and classes behave correctly. Good tests are fast, isolated, repeatable, and clear.
Important Concepts
- @Test marks test method
- assertEquals checks equality
- assertTrue checks true condition
- assertThrows checks exceptions
- Tests run with Maven/Gradle
- JUnit 5 is called Jupiter
Syntax / Pattern
@Test
void testName() {
assertEquals(expected, actual);
}
Detailed Code Example
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class Calculator {
int add(int a, int b) { return a + b; }
}
public class CalculatorTest {
@Test
void addShouldReturnSum() {
Calculator calc = new Calculator();
assertEquals(5, calc.add(2, 3));
}
}
Output / Result
Test passed
Real-Time Production Scope
- Service method tests
- Regression protection
- CI validation
- Safe refactoring
Common Mistakes and Fixes
- Testing only happy path
- No assertions
- Tests depending on order
- Testing implementation instead of behavior
Practice Task
Study Links
Logging and Debugging
What is it?
Logging records application behavior; debugging helps inspect code execution.
Beginner + Developer Explanation
In production, use logging frameworks instead of System.out.println. Locally, use breakpoints, watches, and stack traces.
Important Concepts
- Log levels: TRACE, DEBUG, INFO, WARN, ERROR
- Do not log secrets
- Use parameterized logs
- Breakpoints pause code
- Stack traces show error path
- Correlation IDs help trace requests
Syntax / Pattern
logger.info("User {} logged in", userId);
Detailed Code Example
public class DebugDemo {
public static void main(String[] args) {
int price = 100;
int qty = 3;
int discount = 50;
int total = price * qty - discount;
System.out.println(total);
}
}
Output / Result
250
Real-Time Production Scope
- Production troubleshooting
- Audit logs
- Performance investigation
- Local bug fixing
Common Mistakes and Fixes
- Logging passwords/tokens
- Too many noisy logs
- Catching errors without logging
- Guessing bugs without debugging
Practice Task
Study Links
Docker for Java
What is it?
Docker packages Java applications with runtime dependencies into portable containers.
Beginner + Developer Explanation
Java services are commonly packaged as JAR files and run with java -jar inside containers.
Important Concepts
- Dockerfile defines image
- JAR is copied into image
- EXPOSE documents port
- ENTRYPOINT starts app
- Multi-stage builds reduce image size
- Use .dockerignore
Syntax / Pattern
FROM eclipse-temurin:21-jre COPY app.jar app.jar ENTRYPOINT ["java", "-jar", "app.jar"]
Detailed Code Example
FROM maven:3.9-eclipse-temurin-21 AS build WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn -q -DskipTests package FROM eclipse-temurin:21-jre WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
Output / Result
docker build -t java-app . docker run -p 8080:8080 java-app
Real-Time Production Scope
- Spring Boot deployments
- Cloud containers
- CI/CD artifacts
- Consistent runtime environments
Common Mistakes and Fixes
- Huge images
- Secrets inside image
- Running as root unnecessarily
- Ignoring JVM memory in containers
Practice Task
Study Links
Java Keywords, Tokens, and Identifiers
What is it?
Java source code is made from tokens: keywords, identifiers, literals, operators, separators, and comments. Understanding tokens helps beginners read compiler errors and write cleaner code.
Beginner Explanation
Think of Java code like a sentence. Keywords are reserved words such as class, public, static, if, for, return, try, and new. Identifiers are names you create, such as Student, totalMarks, and calculateGrade. Literals are fixed values like 10, 99.5, true, and "Java".
Important Concepts
- Keyword: reserved word with predefined meaning
- Identifier: class, method, variable, package, or constant name created by developer
- Literal: direct value written in code
- Separator: characters like ; , . ( ) { } [ ]
- Java is case-sensitive, so Student and student are different
- Avoid using names that look like keywords or Java class names
Syntax / Pattern
keyword identifier = literal;
class ClassName {
return value;
}
Detailed Code Example
public class TokenDemo {
public static void main(String[] args) {
int marks = 90;
String courseName = "Java";
boolean passed = marks >= 50;
if (passed) {
System.out.println(courseName + " passed with " + marks);
}
}
}
Output / Result
Java passed with 90
Real-Time Production Scope
- Code reviews use naming and keyword rules to keep enterprise projects readable
- Compiler errors often point to missing separators or invalid identifiers
- Clean identifiers improve API design, DTO names, method names, and database model classes
Common Mistakes and Fixes
- Using keyword as variable name: int class = 10 is invalid
- Using unclear names like x1, data2 in production
- Forgetting semicolon after statements
- Mixing case accidentally: total and Total are different variables
Practice Task
Study Links
Primitive vs Reference Types and Java Memory
What is it?
Java has primitive values stored as simple data and reference values that point to objects. This difference affects equality, memory, mutability, method calls, and performance.
Beginner Explanation
A primitive variable directly stores a value such as 10 or true. A reference variable stores a reference to an object created in memory. For example int age = 21 stores 21, but Student s = new Student() stores a reference to a Student object.
Developer Explanation
In production, memory knowledge matters in APIs, batch jobs, and services handling many requests. Object allocation, object lifetime, and reference sharing can affect speed and correctness.
Important Concepts
- Primitive types: byte, short, int, long, float, double, char, boolean
- Reference types: String, arrays, classes, interfaces, records, enums
- Stack stores local variables and method call frames
- Heap stores objects created with new
- == compares primitive values but compares object references for objects
- Use equals() for object content comparison
Syntax / Pattern
int a = 10;
Student s = new Student("Anu");
String x = new String("Java");
String y = new String("Java");
Detailed Code Example
class Student {
String name;
Student(String name) { this.name = name; }
}
public class MemoryDemo {
public static void main(String[] args) {
int a = 10;
int b = 10;
System.out.println(a == b);
Student s1 = new Student("Anu");
Student s2 = new Student("Anu");
Student s3 = s1;
System.out.println(s1 == s2);
System.out.println(s1 == s3);
System.out.println(s1.name.equals(s2.name));
}
}
Output / Result
true false true true
Real-Time Production Scope
- Bug fixing when == is wrongly used for Strings or entity objects
- Memory analysis for high-traffic APIs with many object allocations
- Understanding why changing one reference may affect the same shared object
- Performance tuning for DTO creation and collection processing
Common Mistakes and Fixes
- Comparing Strings with == instead of equals()
- Assuming object assignment creates a copy
- Creating too many temporary objects inside loops
- Not understanding null reference errors
Practice Task
Study Links
Wrapper Classes, Autoboxing, and Unboxing
What is it?
Wrapper classes convert primitive values into objects. Examples: Integer for int, Long for long, Double for double, Boolean for boolean, and Character for char.
Beginner Explanation
Collections such as ArrayList store objects, not primitives. That is why ArrayList<Integer> is used instead of ArrayList<int>. Java automatically boxes int into Integer and unboxes Integer back into int when needed.
Important Concepts
- Wrapper classes live in java.lang
- Autoboxing: primitive to wrapper automatically
- Unboxing: wrapper to primitive automatically
- Wrapper objects can be null; primitives cannot
- Wrapper classes provide parsing methods like Integer.parseInt()
- Use primitives for simple numeric fields unless null/object behavior is required
Syntax / Pattern
Integer x = 10; // autoboxing
int y = x; // unboxing
int n = Integer.parseInt("100");
Detailed Code Example
import java.util.*;
public class WrapperDemo {
public static void main(String[] args) {
List<Integer> marks = new ArrayList<>();
marks.add(90);
marks.add(Integer.valueOf(85));
int total = 0;
for (Integer mark : marks) {
total += mark;
}
String input = "100";
int parsed = Integer.parseInt(input);
System.out.println(total);
System.out.println(parsed + 50);
}
}
Output / Result
175 150
Real-Time Production Scope
- REST request bodies often map missing numeric fields to wrapper types like Integer
- Database nullable columns should usually map to wrapper types
- Collections and generics require wrapper types
- Parsing user input uses wrapper utility methods
Common Mistakes and Fixes
- Using Integer without null checks can cause NullPointerException during unboxing
- Using == with wrapper objects can be confusing
- Parsing invalid strings without try/catch
- Using wrapper types everywhere unnecessarily
Practice Task
Study Links
var Type Inference
What is it?
The var keyword lets Java infer the local variable type from the assigned value. It improves readability only when the right-side value makes the type obvious.
Beginner Explanation
var does not mean dynamic typing. Java still decides a fixed compile-time type. You can use var for local variables, but not for fields, method parameters, or return types.
Important Concepts
- Available for local variables from Java 10
- Type is inferred at compile time
- Must assign value immediately
- Cannot assign null alone
- Do not use var when it hides important business meaning
- Often useful with long generic types
Syntax / Pattern
var name = "Anu"; var count = 10; var list = new ArrayList<String>();
Detailed Code Example
import java.util.*;
public class VarDemo {
public static void main(String[] args) {
var name = "Anu";
var marks = new ArrayList<Integer>();
marks.add(90);
marks.add(95);
var total = 0;
for (var mark : marks) {
total += mark;
}
System.out.println(name + " total = " + total);
}
}
Output / Result
Anu total = 185
Real-Time Production Scope
- Useful in service methods where repository result type is obvious
- Reduces noise with streams and collectors
- Improves readability for complex generic declarations when carefully used
Common Mistakes and Fixes
- Using var everywhere and making code unclear
- Trying var field = 10 at class level
- Trying var x = null
- Changing mental model and thinking Java became dynamically typed
Practice Task
Study Links
Access Modifiers Deep Dive
What is it?
Access modifiers control visibility of classes, fields, constructors, and methods. They are important for encapsulation and API design.
Beginner Explanation
Java has public, protected, default/package-private, and private access. Beginner rule: keep fields private, expose behavior through public methods, and avoid exposing internal implementation details.
Important Concepts
- public: accessible from everywhere
- private: accessible only inside same class
- protected: same package plus subclasses
- default/package-private: accessible inside same package only
- Top-level class can be public or package-private
- Encapsulation protects business rules
Syntax / Pattern
private String name;
public String getName() { return name; }
protected void calculateInternal() {}
void packageOnlyMethod() {}
Detailed Code Example
class BankAccount {
private double balance;
public BankAccount(double openingBalance) {
if (openingBalance < 0) throw new IllegalArgumentException("Invalid balance");
this.balance = openingBalance;
}
public void deposit(double amount) {
if (amount <= 0) throw new IllegalArgumentException("Invalid amount");
balance += amount;
}
public double getBalance() {
return balance;
}
}
public class AccessDemo {
public static void main(String[] args) {
BankAccount account = new BankAccount(1000);
account.deposit(500);
System.out.println(account.getBalance());
}
}
Output / Result
1500.0
Real-Time Production Scope
- Domain models protect invariants such as account balance not going negative
- Service classes expose public business operations but hide helper methods
- Libraries expose stable public API and keep internals private/package-private
Common Mistakes and Fixes
- Making every field public
- Using protected when package-private is enough
- Skipping validation in setters
- Exposing mutable internal lists directly
Practice Task
Study Links
static and final Deep Dive
What is it?
static belongs to the class, not one object. final prevents reassignment, overriding, or inheritance depending on where it is used.
Beginner Explanation
Use static for constants and utility methods that do not depend on object state. Use final for values that should not change after assignment. Together, public static final is commonly used for constants.
Important Concepts
- static field: one copy shared by all objects
- static method: called using class name
- static block: runs when class loads
- final variable: cannot be reassigned
- final method: cannot be overridden
- final class: cannot be extended
Syntax / Pattern
public static final double GST_RATE = 0.18;
public static int count;
public final void cannotOverride() {}
Detailed Code Example
class InvoiceUtil {
public static final double GST_RATE = 0.18;
public static double addGst(double amount) {
return amount + (amount * GST_RATE);
}
}
class Employee {
static int count = 0;
final String employeeId;
Employee(String employeeId) {
this.employeeId = employeeId;
count++;
}
}
public class StaticFinalDemo {
public static void main(String[] args) {
new Employee("E101");
new Employee("E102");
System.out.println(Employee.count);
System.out.println(InvoiceUtil.addGst(1000));
}
}
Output / Result
2 1180.0
Real-Time Production Scope
- Constants for tax rate, date formats, error codes, and configuration keys
- Utility classes for validation or conversion
- Counting created objects in demos or instrumentation
- Immutable identifiers in domain objects
Common Mistakes and Fixes
- Using static for everything instead of proper object design
- Changing shared static mutable state in web apps
- Assuming final object means object fields cannot change
- Creating utility classes without private constructors
Practice Task
Study Links
Inner, Nested, Local, and Anonymous Classes
What is it?
Java supports classes inside classes. They are used when a helper type belongs strongly to another type or when creating quick one-time behavior.
Beginner Explanation
A nested class is declared inside another class. A static nested class does not require an outer object. An inner class is tied to an outer object. Anonymous classes are unnamed implementations often used for callbacks before lambdas became popular.
Important Concepts
- Static nested class
- Non-static inner class
- Local class inside method
- Anonymous class for one-time implementation
- Inner classes can access outer instance members
- Use carefully to avoid complex code
Syntax / Pattern
class Outer {
static class StaticNested {}
class Inner {}
}
Detailed Code Example
interface Notifier {
void send(String message);
}
class OrderService {
static class OrderResult {
String status;
OrderResult(String status) { this.status = status; }
}
OrderResult placeOrder() {
return new OrderResult("SUCCESS");
}
}
public class NestedDemo {
public static void main(String[] args) {
OrderService service = new OrderService();
OrderService.OrderResult result = service.placeOrder();
Notifier notifier = new Notifier() {
public void send(String message) {
System.out.println("Sending: " + message);
}
};
System.out.println(result.status);
notifier.send("Order placed");
}
}
Output / Result
SUCCESS Sending: Order placed
Real-Time Production Scope
- DTO-like helper classes scoped to a parent service
- Builder patterns using nested Builder class
- Event handlers and callbacks
- Test helper classes
Common Mistakes and Fixes
- Overusing inner classes and making code hard to read
- Using anonymous classes when lambda is simpler
- Unintentionally keeping reference to outer object
- Putting unrelated business classes inside one class
Practice Task
Study Links
Object Lifecycle and Garbage Collection
What is it?
Object lifecycle means creation, use, becoming unreachable, and garbage collection. Garbage collection automatically frees memory for unreachable objects.
Beginner Explanation
When you use new, Java creates an object on the heap. When no live reference can reach that object, it becomes eligible for garbage collection. You do not manually free memory like in C.
Important Concepts
- Object creation with new
- Reachable vs unreachable objects
- Garbage collector reclaims memory automatically
- System.gc() is only a request, not a guarantee
- Memory leaks can still happen if references are retained
- Close external resources manually or with try-with-resources
Syntax / Pattern
User u = new User(); u = null; // object may become eligible for GC
Detailed Code Example
import java.util.*;
public class LifecycleDemo {
static List<byte[]> cache = new ArrayList<>();
public static void main(String[] args) {
byte[] data = new byte[1024];
data = null;
cache.add(new byte[1024]);
System.out.println("One object released reference");
System.out.println("One object still referenced by cache");
}
}
Output / Result
One object released reference One object still referenced by cache
Real-Time Production Scope
- Long-running backend services must avoid unbounded caches
- File, socket, and database connections must be closed even though memory is GC-managed
- Production memory issues are investigated using heap dumps and profilers
Common Mistakes and Fixes
- Thinking GC closes files or database connections
- Using static lists/maps as unlimited caches
- Calling System.gc() as a solution
- Keeping references in listeners and scheduled tasks forever
Practice Task
Study Links
Immutability in Java
What is it?
An immutable object cannot change after creation. Immutability improves safety, thread-safety, caching, and predictable behavior.
Beginner Explanation
String is immutable. When you modify a String, Java creates a new String. You can create immutable classes by making fields private final, avoiding setters, validating in constructor, and returning defensive copies for mutable fields.
Important Concepts
- Use final class or record for strong immutability
- Use private final fields
- No setters
- Validate constructor input
- Defensive copy mutable objects
- Immutable objects are safer for concurrent applications
Syntax / Pattern
final class Money {
private final double amount;
}
Detailed Code Example
import java.util.*;
final class Course {
private final String title;
private final List<String> topics;
Course(String title, List<String> topics) {
this.title = title;
this.topics = List.copyOf(topics);
}
public String getTitle() { return title; }
public List<String> getTopics() { return topics; }
}
public class ImmutableDemo {
public static void main(String[] args) {
List<String> topics = new ArrayList<>();
topics.add("Java");
Course course = new Course("Backend", topics);
topics.add("Hacking change");
System.out.println(course.getTopics());
}
}
Output / Result
[Java]
Real-Time Production Scope
- DTOs and value objects such as Money, EmailAddress, DateRange
- Safe sharing between threads
- Configuration objects loaded at startup
- Domain objects where state should not change unexpectedly
Common Mistakes and Fixes
- Returning mutable internal list directly
- Using final but keeping mutable fields exposed
- Adding setters to immutable classes
- Not validating constructor data
Practice Task
Study Links
Annotations
What is it?
Annotations add metadata to code. Frameworks like Spring Boot, JPA, JUnit, and Bean Validation use annotations heavily.
Beginner Explanation
An annotation starts with @. It can mark classes, methods, fields, parameters, and more. Some annotations are used by compiler, some by frameworks at runtime.
Important Concepts
- @Override tells compiler a method overrides parent method
- @Deprecated marks old API
- @SuppressWarnings hides selected warnings
- @Entity, @Id for JPA
- @RestController, @Service for Spring
- Custom annotations can be created with @interface
Syntax / Pattern
@Override
public String toString() { return "text"; }
@interface Audit {}
Detailed Code Example
@interface Audited {
String value();
}
class PaymentService {
@Deprecated
public void oldPay() {
System.out.println("Old payment method");
}
@Audited("payment")
public void pay(double amount) {
System.out.println("Paid " + amount);
}
@Override
public String toString() {
return "PaymentService";
}
}
public class AnnotationDemo {
public static void main(String[] args) {
PaymentService service = new PaymentService();
service.pay(500);
System.out.println(service);
}
}
Output / Result
Paid 500.0 PaymentService
Real-Time Production Scope
- Spring dependency injection and REST controllers
- JPA entity mapping
- Validation annotations on DTO fields
- JUnit test discovery
- Lombok code generation in some projects
Common Mistakes and Fixes
- Adding annotation without understanding what framework does with it
- Forgetting @Override and silently creating wrong method
- Overusing custom annotations
- Depending on Lombok without team agreement
Practice Task
Study Links
Reflection API
What is it?
Reflection lets Java inspect classes, fields, constructors, methods, and annotations at runtime.
Beginner Explanation
Normally you call methods directly. With reflection, code can discover what a class contains and call methods dynamically. Frameworks use this for dependency injection, JSON mapping, testing, and annotation scanning.
Important Concepts
- Class<?> represents metadata of a class
- getDeclaredFields() reads fields
- getDeclaredMethods() reads methods
- setAccessible(true) can access private members
- Reflection can be slower and can break encapsulation
- Use carefully in application code
Syntax / Pattern
Class<?> clazz = User.class; Field[] fields = clazz.getDeclaredFields();
Detailed Code Example
import java.lang.reflect.*;
class User {
private String email = "a@test.com";
public void login() { System.out.println("login"); }
}
public class ReflectionDemo {
public static void main(String[] args) throws Exception {
Class<?> clazz = User.class;
System.out.println(clazz.getSimpleName());
for (Field field : clazz.getDeclaredFields()) {
System.out.println("Field: " + field.getName());
}
User user = new User();
Method method = clazz.getDeclaredMethod("login");
method.invoke(user);
}
}
Output / Result
User Field: email login
Real-Time Production Scope
- Spring scans classes and annotations
- Jackson maps JSON fields to Java objects
- JUnit finds test methods
- ORM frameworks map fields to columns
Common Mistakes and Fixes
- Using reflection instead of normal method calls unnecessarily
- Breaking private encapsulation
- Ignoring checked exceptions from reflection
- Reflection-heavy code can be harder to maintain
Practice Task
Study Links
Regular Expressions in Java
What is it?
Regular expressions define patterns for searching, validating, and extracting text.
Beginner Explanation
Java regex uses Pattern and Matcher classes. Beginners often use String.matches(), but production code often precompiles Pattern for repeated validation.
Important Concepts
- Pattern.compile() compiles regex
- Matcher checks input against pattern
- matches() checks full string
- find() searches inside string
- Groups extract sub-parts
- Escape backslash as double backslash in Java strings
Syntax / Pattern
Pattern pattern = Pattern.compile("^[A-Za-z]+$");
Matcher matcher = pattern.matcher(input);
boolean ok = matcher.matches();
Detailed Code Example
import java.util.regex.*;
public class RegexDemo {
public static void main(String[] args) {
Pattern emailPattern = Pattern.compile("^[\w.-]+@[\w.-]+\.[A-Za-z]{2,}$");
String[] emails = {"anu@test.com", "wrong-email", "user@site"};
for (String email : emails) {
Matcher matcher = emailPattern.matcher(email);
System.out.println(email + " -> " + matcher.matches());
}
}
}
Output / Result
anu@test.com -> true wrong-email -> false user@site -> false
Real-Time Production Scope
- Input validation for email, phone, username, pincode, PAN-like formats
- Log parsing
- Extracting IDs from text
- Search features in admin dashboards
Common Mistakes and Fixes
- Forgetting double backslash in Java regex strings
- Using overly complex regex for business rules
- Using matches() when find() is needed
- Not anchoring with ^ and $ for validation
Practice Task
Study Links
Locale, NumberFormat, and Date Formatting
What is it?
Locale-aware formatting adapts currency, numbers, dates, and text formatting based on country and language.
Beginner Explanation
Do not manually concatenate currency symbols or date formats for global applications. Java provides Locale, NumberFormat, DateTimeFormatter, and related classes for clean formatting.
Important Concepts
- Locale identifies language/country
- NumberFormat formats currency and numbers
- DateTimeFormatter formats dates and times
- Use BigDecimal for money calculations
- Store dates in standard formats and format only at display boundary
Syntax / Pattern
Locale india = new Locale("en", "IN");
NumberFormat currency = NumberFormat.getCurrencyInstance(india);
Detailed Code Example
import java.text.NumberFormat;
import java.time.*;
import java.time.format.*;
import java.util.*;
public class LocaleDemo {
public static void main(String[] args) {
Locale india = new Locale("en", "IN");
Locale us = Locale.US;
double amount = 123456.78;
System.out.println(NumberFormat.getCurrencyInstance(india).format(amount));
System.out.println(NumberFormat.getCurrencyInstance(us).format(amount));
LocalDate date = LocalDate.of(2026, 5, 28);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd MMM yyyy");
System.out.println(date.format(formatter));
}
}
Output / Result
Rs.123,456.78 $123,456.78 28 May 2026
Real-Time Production Scope
- Billing systems
- International dashboards
- Invoice generation
- User-facing date and currency display
Common Mistakes and Fixes
- Storing formatted dates instead of date objects
- Hardcoding currency symbols
- Using double for final money calculations
- Ignoring time zones in global apps
Practice Task
Study Links
Properties Files and Environment Variables
What is it?
Configuration should not be hardcoded. Java apps commonly read settings from properties files, environment variables, command-line arguments, or Spring Boot application.properties.
Beginner Explanation
A properties file stores key-value pairs. Environment variables are configured outside the app and are useful for secrets, database URLs, and deployment-specific settings.
Important Concepts
- Properties class reads .properties files
- System.getenv() reads environment variables
- System.getProperty() reads JVM system properties
- Do not commit secrets to Git
- Use different config for dev, test, and production
Syntax / Pattern
Properties props = new Properties();
props.load(new FileInputStream("app.properties"));
String url = System.getenv("DATABASE_URL");
Detailed Code Example
import java.io.*;
import java.util.*;
public class ConfigDemo {
public static void main(String[] args) throws Exception {
Properties props = new Properties();
props.setProperty("app.name", "Student API");
props.setProperty("app.port", "8080");
String envMode = System.getenv().getOrDefault("APP_MODE", "local");
System.out.println(props.getProperty("app.name"));
System.out.println(props.getProperty("app.port"));
System.out.println(envMode);
}
}
Output / Result
Student API 8080 local
Real-Time Production Scope
- Database connection config
- API keys and secrets
- Feature flags
- Port and profile settings
- Cloud deployment variables
Common Mistakes and Fixes
- Hardcoding passwords in source code
- Committing .env files to Git
- Using same config for test and production
- Not validating required config at startup
Practice Task
Study Links
Production Logging with SLF4J and Logback
What is it?
Logging records application events so developers can debug production issues without using System.out.println everywhere.
Beginner Explanation
In real Java projects, use a logging facade like SLF4J and an implementation like Logback. Logging supports levels such as TRACE, DEBUG, INFO, WARN, and ERROR.
Important Concepts
- INFO for normal business events
- WARN for recoverable problems
- ERROR for failed operations
- DEBUG for developer details
- Never log passwords, tokens, or sensitive data
- Use structured logs for cloud observability
Syntax / Pattern
private static final Logger log = LoggerFactory.getLogger(MyClass.class);
log.info("Order created: {}", orderId);
Detailed Code Example
import java.time.*;
class SimpleLogger {
static void info(String message) {
System.out.println("INFO " + LocalDateTime.now() + " - " + message);
}
static void error(String message, Exception e) {
System.out.println("ERROR " + LocalDateTime.now() + " - " + message);
System.out.println(e.getMessage());
}
}
public class LoggingDemo {
public static void main(String[] args) {
SimpleLogger.info("Application started");
try {
int value = Integer.parseInt("abc");
} catch (NumberFormatException e) {
SimpleLogger.error("Invalid number input", e);
}
}
}
Output / Result
INFO 2026-05-28T... - Application started ERROR 2026-05-28T... - Invalid number input For input string: "abc"
Real-Time Production Scope
- Debug API errors in production
- Trace payment/order lifecycle
- Monitor slow operations
- Send logs to CloudWatch, ELK, Splunk, Datadog, or OpenTelemetry pipelines
Common Mistakes and Fixes
- Using System.out.println in production code
- Logging sensitive data
- Catching exceptions but not logging context
- Too many DEBUG logs enabled in production
Practice Task
Study Links
Serialization and Deserialization
What is it?
Serialization converts an object into a storable or transferable format. Deserialization converts it back into an object.
Beginner Explanation
Java has built-in Serializable, but modern applications usually serialize to JSON using libraries like Jackson. Serialization is used in APIs, caches, queues, sessions, and files.
Important Concepts
- Serializable marker interface
- serialVersionUID identifies compatible class version
- transient fields are skipped
- JSON serialization maps objects to JSON
- Deserialization should validate untrusted input
- Avoid Java native serialization for untrusted data
Syntax / Pattern
class User implements Serializable {
private static final long serialVersionUID = 1L;
}
Detailed Code Example
import java.io.*;
class LoginSession implements Serializable {
private static final long serialVersionUID = 1L;
String username;
transient String token;
LoginSession(String username, String token) {
this.username = username;
this.token = token;
}
}
public class SerializationDemo {
public static void main(String[] args) throws Exception {
LoginSession session = new LoginSession("anu", "secret-token");
try (ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("session.bin"))) {
out.writeObject(session);
}
try (ObjectInputStream in = new ObjectInputStream(new FileInputStream("session.bin"))) {
LoginSession restored = (LoginSession) in.readObject();
System.out.println(restored.username);
System.out.println(restored.token);
}
}
}
Output / Result
anu null
Real-Time Production Scope
- REST JSON request/response
- Writing objects to files
- Messaging systems
- Session storage
- Cache values
Common Mistakes and Fixes
- Serializing passwords or tokens
- Forgetting serialVersionUID
- Trusting deserialized data from unknown sources
- Using Java native serialization where JSON is better
Practice Task
Study Links
Copying Objects: Shallow Copy and Deep Copy
What is it?
Copying objects can mean copying only the top-level object or copying nested objects too. This difference is important when objects contain lists, maps, or other objects.
Beginner Explanation
A shallow copy copies references to nested objects. A deep copy creates new nested objects also. If two objects share the same list, changing one can affect the other.
Important Concepts
- Assignment does not copy object
- Shallow copy shares nested references
- Deep copy creates independent nested data
- Copy constructors are clearer than clone()
- Use List.copyOf for immutable defensive copies
Syntax / Pattern
User a = new User("Anu");
User b = a; // same object
User c = new User(a); // copy constructor
Detailed Code Example
import java.util.*;
class StudentProfile {
String name;
List<String> skills;
StudentProfile(String name, List<String> skills) {
this.name = name;
this.skills = new ArrayList<>(skills);
}
StudentProfile(StudentProfile other) {
this.name = other.name;
this.skills = new ArrayList<>(other.skills);
}
}
public class CopyDemo {
public static void main(String[] args) {
StudentProfile p1 = new StudentProfile("Anu", List.of("Java"));
StudentProfile p2 = new StudentProfile(p1);
p2.skills.add("Spring");
System.out.println(p1.skills);
System.out.println(p2.skills);
}
}
Output / Result
[Java] [Java, Spring]
Real-Time Production Scope
- DTO transformations
- Defensive copies in immutable classes
- Avoiding accidental mutation of cached data
- Safely returning lists from domain objects
Common Mistakes and Fixes
- Using = and expecting a copy
- Returning internal mutable collections
- Using clone() without understanding it
- Copying only top-level object when nested objects also need copying
Practice Task
Study Links
Generics Wildcards and Bounds
What is it?
Generics make Java code type-safe. Wildcards and bounds allow methods to accept flexible generic types while preserving safety.
Beginner Explanation
List<Integer> is not a subtype of List<Number>. Wildcards solve this. Use ? extends T when reading values of T from a collection. Use ? super T when writing T values into a collection.
Important Concepts
- T is a type parameter
- ? is unknown type
- ? extends Number means Number or subclass
- ? super Integer means Integer or parent type
- PECS rule: Producer Extends, Consumer Super
- Generics are erased at runtime
Syntax / Pattern
void printNumbers(List<? extends Number> nums) {}
void addIntegers(List<? super Integer> nums) {}
Detailed Code Example
import java.util.*;
public class WildcardDemo {
static double sum(List<? extends Number> numbers) {
double total = 0;
for (Number n : numbers) total += n.doubleValue();
return total;
}
static void addDefaultMarks(List<? super Integer> marks) {
marks.add(50);
marks.add(60);
}
public static void main(String[] args) {
List<Integer> intMarks = List.of(80, 90, 70);
System.out.println(sum(intMarks));
List<Number> numbers = new ArrayList<>();
addDefaultMarks(numbers);
System.out.println(numbers);
}
}
Output / Result
240.0 [50, 60]
Real-Time Production Scope
- Reusable utility methods for numbers, DTOs, repositories, and events
- Framework and library design
- Collections APIs
- Type-safe service layer helpers
Common Mistakes and Fixes
- Using raw List without generic type
- Confusing extends and super
- Trying to add items to ? extends collection
- Overcomplicating simple application code with unnecessary generics
Practice Task
Study Links
Collections Internals: ArrayList, LinkedList, HashMap, TreeMap
What is it?
Collections have different internal data structures. Choosing the right one affects performance and correctness.
Beginner Explanation
ArrayList uses a resizable array. LinkedList uses nodes. HashMap uses hashing for key lookup. TreeMap keeps keys sorted using a tree. You should choose based on access pattern.
Important Concepts
- ArrayList: fast index access, slower middle insert/remove
- LinkedList: node-based, usually not faster for most app cases
- HashMap: fast key lookup, no guaranteed order
- LinkedHashMap: preserves insertion order
- TreeMap: sorted keys
- HashSet uses HashMap internally for uniqueness
Syntax / Pattern
List<String> list = new ArrayList<>(); Map<String, Integer> map = new HashMap<>(); Map<String, Integer> sorted = new TreeMap<>();
Detailed Code Example
import java.util.*;
public class CollectionChoiceDemo {
public static void main(String[] args) {
Map<String, Integer> hashMap = new HashMap<>();
hashMap.put("banana", 20);
hashMap.put("apple", 10);
hashMap.put("orange", 30);
System.out.println("HashMap: " + hashMap);
Map<String, Integer> treeMap = new TreeMap<>(hashMap);
System.out.println("TreeMap: " + treeMap);
Map<String, Integer> linked = new LinkedHashMap<>();
linked.put("first", 1);
linked.put("second", 2);
System.out.println("LinkedHashMap: " + linked);
}
}
Output / Result
HashMap: order not guaranteed
TreeMap: {apple=10, banana=20, orange=30}
LinkedHashMap: {first=1, second=2}
Real-Time Production Scope
- Product catalogs use maps for ID lookup
- Caches use LinkedHashMap patterns
- Sorted reports use TreeMap or sorted streams
- Large lists need correct collection choice for performance
Common Mistakes and Fixes
- Using HashMap when sorted order is required
- Assuming HashMap order is stable
- Using LinkedList expecting better performance without testing
- Using list search when map lookup is better
Practice Task
Study Links
Advanced Stream Collectors
What is it?
Collectors convert streams into lists, sets, maps, grouped data, joined strings, statistics, and custom results.
Beginner Explanation
Basic streams use filter and map. Real production code often needs groupingBy, partitioningBy, counting, joining, summarizingInt, and toMap.
Important Concepts
- Collectors.toList()
- Collectors.toSet()
- Collectors.toMap()
- Collectors.groupingBy()
- Collectors.partitioningBy()
- Collectors.joining()
- Collectors.summarizingInt()
Syntax / Pattern
list.stream()
.collect(Collectors.groupingBy(Item::category));
Detailed Code Example
import java.util.*;
import java.util.stream.*;
record Order(String customer, String status, int amount) {}
public class CollectorDemo {
public static void main(String[] args) {
List<Order> orders = List.of(
new Order("Anu", "PAID", 1000),
new Order("Ravi", "PENDING", 500),
new Order("Anu", "PAID", 700)
);
Map<String, List<Order>> byCustomer = orders.stream()
.collect(Collectors.groupingBy(Order::customer));
Map<Boolean, List<Order>> paidOrNot = orders.stream()
.collect(Collectors.partitioningBy(o -> o.status().equals("PAID")));
IntSummaryStatistics stats = orders.stream()
.collect(Collectors.summarizingInt(Order::amount));
System.out.println(byCustomer.keySet());
System.out.println(paidOrNot.get(true).size());
System.out.println(stats.getSum());
}
}
Output / Result
[Anu, Ravi] 2 2200
Real-Time Production Scope
- Report generation
- Dashboard aggregation
- Order grouping by customer or status
- Data transformation before API response
Common Mistakes and Fixes
- Using streams for code that is harder to read than loops
- Forgetting duplicate key handling in toMap
- Doing database-scale operations in memory
- Using parallel streams without measuring
Practice Task
Study Links
Parallel Streams and When Not to Use Them
What is it?
Parallel streams split stream work across multiple threads. They can improve CPU-heavy work but can also make code slower or unsafe when misused.
Beginner Explanation
Parallel does not automatically mean faster. It has overhead. It is best for large independent CPU-bound operations, not database calls, API calls, or tasks with shared mutable state.
Important Concepts
- parallelStream() uses common ForkJoinPool
- Best for independent CPU-bound operations
- Avoid shared mutable variables
- Order may be affected in some operations
- Measure performance before using
- Do not use for blocking I/O by default
Syntax / Pattern
list.parallelStream()
.map(this::heavyCalculation)
.toList();
Detailed Code Example
import java.util.*;
public class ParallelStreamDemo {
static long square(long n) { return n * n; }
public static void main(String[] args) {
List<Long> nums = new ArrayList<>();
for (long i = 1; i <= 10; i++) nums.add(i);
long sum = nums.parallelStream()
.mapToLong(ParallelStreamDemo::square)
.sum();
System.out.println(sum);
}
}
Output / Result
385
Real-Time Production Scope
- CPU-heavy data processing
- Image or file transformation batches
- Large calculations with independent items
- Quick prototypes when measured against sequential stream
Common Mistakes and Fixes
- Using parallel streams with shared ArrayList.add()
- Parallelizing small lists
- Calling remote APIs inside parallel stream without control
- Assuming output order always matches source order
Practice Task
Study Links
Locks, ReentrantLock, and Atomic Classes
What is it?
Locks and atomic classes coordinate access to shared data across threads.
Beginner Explanation
synchronized is simple, but ReentrantLock gives more control such as tryLock and explicit unlock. AtomicInteger provides lock-free counters for simple numeric updates.
Important Concepts
- synchronized protects critical sections
- ReentrantLock must be unlocked in finally
- AtomicInteger supports atomic increment
- Volatile gives visibility but not compound atomicity
- Avoid shared mutable state where possible
- Use higher-level concurrency utilities first
Syntax / Pattern
Lock lock = new ReentrantLock();
lock.lock();
try { /* critical section */ } finally { lock.unlock(); }
Detailed Code Example
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;
class SafeCounter {
private final AtomicInteger atomicCount = new AtomicInteger();
private final Lock lock = new ReentrantLock();
private int lockedCount = 0;
void incrementBoth() {
atomicCount.incrementAndGet();
lock.lock();
try {
lockedCount++;
} finally {
lock.unlock();
}
}
int atomicValue() { return atomicCount.get(); }
int lockedValue() { return lockedCount; }
}
public class LockDemo {
public static void main(String[] args) {
SafeCounter c = new SafeCounter();
c.incrementBoth();
System.out.println(c.atomicValue());
System.out.println(c.lockedValue());
}
}
Output / Result
1 1
Real-Time Production Scope
- Inventory counters
- Rate limiters
- Thread-safe metrics counters
- Protecting shared in-memory state
Common Mistakes and Fixes
- Forgetting lock.unlock() in finally
- Using volatile for count++ expecting atomicity
- Locking too much code
- Creating deadlocks by acquiring locks in different order
Practice Task
Study Links
Java Memory Model and volatile
What is it?
The Java Memory Model defines how changes made by one thread become visible to another thread.
Beginner Explanation
Without proper synchronization, one thread may not immediately see updates made by another. volatile ensures visibility for a variable, but it does not make compound operations like count++ atomic.
Important Concepts
- Visibility: one thread sees another thread update
- Atomicity: operation completes as one indivisible action
- volatile provides visibility
- synchronized provides visibility and mutual exclusion
- Atomic classes provide atomic operations
- Happens-before relationships define safe visibility
Syntax / Pattern
private volatile boolean running = true;
while (running) { }
Detailed Code Example
class Worker implements Runnable {
private volatile boolean running = true;
public void stop() {
running = false;
}
public void run() {
while (running) {
// do work
}
System.out.println("Worker stopped");
}
}
public class VolatileDemo {
public static void main(String[] args) throws Exception {
Worker worker = new Worker();
Thread thread = new Thread(worker);
thread.start();
Thread.sleep(100);
worker.stop();
}
}
Output / Result
Worker stopped
Real-Time Production Scope
- Graceful shutdown flags
- Thread communication
- Avoiding stale reads in simple flags
- Understanding bugs in concurrent services
Common Mistakes and Fixes
- Using volatile for increment counters
- Ignoring synchronization with multiple fields
- Assuming thread bugs are deterministic
- Busy-waiting instead of using better concurrency tools
Practice Task
Study Links
Common Java Design Patterns
What is it?
Design patterns are reusable solutions to common software design problems. They help structure enterprise Java code cleanly.
Beginner Explanation
Patterns are not code you blindly copy. They are ideas. Common Java patterns include Singleton, Factory, Builder, Strategy, Repository, DTO, and Dependency Injection.
Important Concepts
- Singleton: one shared instance
- Factory: central object creation
- Builder: readable object creation for many fields
- Strategy: interchangeable behavior
- Repository: data access abstraction
- DTO: API request/response shape
Syntax / Pattern
interface DiscountStrategy {
double apply(double amount);
}
Detailed Code Example
interface DiscountStrategy {
double apply(double amount);
}
class NoDiscount implements DiscountStrategy {
public double apply(double amount) { return amount; }
}
class FestivalDiscount implements DiscountStrategy {
public double apply(double amount) { return amount * 0.90; }
}
class BillingService {
private final DiscountStrategy strategy;
BillingService(DiscountStrategy strategy) {
this.strategy = strategy;
}
double finalAmount(double amount) {
return strategy.apply(amount);
}
}
public class PatternDemo {
public static void main(String[] args) {
BillingService service = new BillingService(new FestivalDiscount());
System.out.println(service.finalAmount(1000));
}
}
Output / Result
900.0
Real-Time Production Scope
- Payment strategy selection
- Notification channel factory
- Builder for complex DTOs
- Repository pattern in service layer
- Dependency injection in Spring
Common Mistakes and Fixes
- Overusing patterns for simple code
- Singleton with mutable state in web apps
- DTOs that expose internal entity design
- Factory class becoming too large
Practice Task
Study Links
Bean Validation and Input Validation
What is it?
Validation ensures input data is correct before business logic or database operations run.
Beginner Explanation
In Spring Boot, Bean Validation annotations such as @NotBlank, @Email, @Min, and @Max are commonly used on DTOs. Plain Java can still validate manually using if conditions.
Important Concepts
- Validate at API boundary
- Use DTOs for request validation
- Return clear error messages
- Do not trust frontend validation alone
- Sanitize where needed
- Validation prevents invalid database state
Syntax / Pattern
if (name == null || name.isBlank()) {
throw new IllegalArgumentException("Name is required");
}
Detailed Code Example
class RegisterRequest {
String name;
String email;
int age;
}
class RegisterValidator {
static void validate(RegisterRequest request) {
if (request.name == null || request.name.isBlank()) {
throw new IllegalArgumentException("Name is required");
}
if (request.email == null || !request.email.contains("@")) {
throw new IllegalArgumentException("Valid email is required");
}
if (request.age < 18) {
throw new IllegalArgumentException("Age must be 18+");
}
}
}
public class ValidationDemo {
public static void main(String[] args) {
RegisterRequest r = new RegisterRequest();
r.name = "Anu";
r.email = "anu@test.com";
r.age = 21;
RegisterValidator.validate(r);
System.out.println("Valid request");
}
}
Output / Result
Valid request
Real-Time Production Scope
- Signup APIs
- Admin forms
- Payment forms
- Student registration systems
- Microservice request validation
Common Mistakes and Fixes
- Validating only in frontend
- Returning vague error messages
- Mixing validation everywhere instead of boundary/service rules
- Not validating nested objects
Practice Task
Study Links
Spring Boot Layered Architecture
What is it?
Layered architecture separates controller, service, repository, entity, DTO, and exception handling responsibilities.
Beginner Explanation
A controller should handle HTTP request/response. A service should contain business logic. A repository should access data. DTOs should define API input/output. This separation makes code testable and maintainable.
Important Concepts
- Controller: API endpoints
- Service: business rules
- Repository: database operations
- Entity: database model
- DTO: API contract
- Exception handler: consistent errors
Syntax / Pattern
controller -> service -> repository -> database DTO <-> service <-> entity
Detailed Code Example
// Controller
@RestController
class StudentController {
private final StudentService service;
StudentController(StudentService service) { this.service = service; }
@PostMapping("/students")
StudentResponse create(@RequestBody StudentRequest request) {
return service.create(request);
}
}
// Service
@Service
class StudentService {
StudentResponse create(StudentRequest request) {
// validate, map, save, return response
return new StudentResponse(1L, request.name());
}
}
record StudentRequest(String name, int marks) {}
record StudentResponse(Long id, String name) {}
Output / Result
POST /students -> service validates -> repository saves -> response returned
Real-Time Production Scope
- Enterprise REST APIs
- Student/admin dashboards
- Banking apps
- Healthcare systems
- Microservices
Common Mistakes and Fixes
- Putting business logic inside controller
- Returning entity directly for every API
- No global exception handler
- Service class doing SQL manually when repository should handle it
Practice Task
Study Links
Spring Transactions
What is it?
A transaction groups database operations so they either all succeed or all fail together.
Beginner Explanation
In Spring, @Transactional is used around service methods that perform multiple database changes. If an unchecked exception occurs, Spring rolls back the transaction by default.
Important Concepts
- Atomicity: all or nothing
- Consistency: valid database state
- Isolation: concurrent transactions are controlled
- Durability: committed data persists
- @Transactional usually belongs in service layer
- Rollback behavior must be understood
Syntax / Pattern
@Transactional
public void placeOrder(OrderRequest request) {
// save order, reduce stock, create payment record
}
Detailed Code Example
@Service
class OrderService {
private final OrderRepository orderRepository;
private final PaymentRepository paymentRepository;
OrderService(OrderRepository orderRepository, PaymentRepository paymentRepository) {
this.orderRepository = orderRepository;
this.paymentRepository = paymentRepository;
}
@Transactional
public void placeOrder(Order order, Payment payment) {
orderRepository.save(order);
paymentRepository.save(payment);
// if payment save fails, order save should rollback
}
}
Output / Result
Either both order and payment save, or both rollback on failure.
Real-Time Production Scope
- Order and payment creation
- Bank transfer debit and credit
- Student registration and payment record
- Inventory update with invoice creation
Common Mistakes and Fixes
- Putting @Transactional on private method and expecting it to work
- Catching exceptions and hiding rollback signal
- Long transactions around slow API calls
- Not understanding checked vs unchecked rollback behavior
Practice Task
Study Links
API Versioning and Error Response Design
What is it?
API versioning and consistent error responses help clients use your APIs safely as the application evolves.
Beginner Explanation
A beginner API may return random strings for errors. A production API should return predictable JSON with timestamp, status, error code, message, path, and validation details.
Important Concepts
- URI versioning: /api/v1/students
- Header versioning is another option
- Use stable error response format
- Use correct HTTP status codes
- Do not expose stack traces to users
- Log internal details but return safe messages
Syntax / Pattern
{
"timestamp": "2026-05-28T10:00:00",
"status": 400,
"code": "VALIDATION_ERROR",
"message": "Marks must be 0-100"
}
Detailed Code Example
record ApiError(int status, String code, String message, String path) {}
class ErrorFactory {
static ApiError validation(String message, String path) {
return new ApiError(400, "VALIDATION_ERROR", message, path);
}
static ApiError notFound(String message, String path) {
return new ApiError(404, "NOT_FOUND", message, path);
}
}
public class ApiErrorDemo {
public static void main(String[] args) {
ApiError error = ErrorFactory.validation("Email is invalid", "/api/v1/users");
System.out.println(error);
}
}
Output / Result
ApiError[status=400, code=VALIDATION_ERROR, message=Email is invalid, path=/api/v1/users]
Real-Time Production Scope
- Frontend can display errors consistently
- Mobile apps can handle error codes
- Backward compatibility for public APIs
- Microservices communicate clearly
Common Mistakes and Fixes
- Changing API response shape without versioning
- Returning HTTP 200 for errors
- Returning raw exception stack trace
- Using one generic message for all validation errors
Practice Task
Study Links
Performance Profiling and JVM Tuning Basics
What is it?
Performance tuning means measuring bottlenecks before changing code or JVM settings.
Beginner Explanation
Java apps can be profiled for CPU, memory, garbage collection, slow database queries, thread blocking, and startup time. Tools include JDK Mission Control, Java Flight Recorder, VisualVM, logs, and application metrics.
Important Concepts
- Measure before optimizing
- CPU profiling finds slow methods
- Heap dumps find memory retention
- Thread dumps find deadlocks/blocking
- GC logs show memory pressure
- JVM flags should be changed carefully
Syntax / Pattern
java -Xms512m -Xmx1024m -jar app.jar jcmd <pid> Thread.print jcmd <pid> GC.heap_dump heap.hprof
Detailed Code Example
public class PerfDemo {
public static void main(String[] args) {
long start = System.nanoTime();
long sum = 0;
for (int i = 1; i <= 1_000_000; i++) {
sum += i;
}
long end = System.nanoTime();
System.out.println("Sum = " + sum);
System.out.println("Time ns = " + (end - start));
}
}
Output / Result
Sum = 500000500000 Time ns = <machine dependent>
Real-Time Production Scope
- Investigating slow APIs
- Reducing memory usage in batch jobs
- Finding database bottlenecks
- Debugging high CPU in production
- Optimizing startup for containers
Common Mistakes and Fixes
- Optimizing without measuring
- Increasing heap forever instead of fixing memory leak
- Using micro-benchmarks incorrectly
- Ignoring database/network time
Practice Task
Study Links
Java Interview and Project Practice Roadmap
What is it?
A roadmap helps learners move from syntax knowledge to real project confidence and interview readiness.
Beginner Explanation
Do not learn Java only by reading. Build small programs, then console apps, then REST APIs, then database-backed applications with tests and deployment.
Important Concepts
- Phase 1: syntax and control flow
- Phase 2: OOP and collections
- Phase 3: exceptions, files, JDBC
- Phase 4: Spring Boot REST API
- Phase 5: security, testing, Docker
- Phase 6: performance and deployment
Syntax / Pattern
learn -> code -> debug -> refactor -> test -> deploy -> explain
Detailed Code Example
import java.util.*;
public class RoadmapPractice {
public static void main(String[] args) {
List<String> projects = List.of(
"Console Calculator",
"Student Management CLI",
"Bank Account OOP App",
"REST API with Spring Boot",
"JWT Secured Student Portal"
);
for (int i = 0; i < projects.size(); i++) {
System.out.println((i + 1) + ". " + projects.get(i));
}
}
}
Output / Result
1. Console Calculator 2. Student Management CLI 3. Bank Account OOP App 4. REST API with Spring Boot 5. JWT Secured Student Portal
Real-Time Production Scope
- Interview preparation
- Internship practice
- Portfolio building
- Backend developer learning path
- Production-ready application thinking
Common Mistakes and Fixes
- Only watching tutorials without coding
- Skipping debugging practice
- Not writing tests
- Not learning Git and build tools
- Building only one huge project instead of many small ones
Practice Task
Study Links
Final Project: Student Management API
What is it?
This final project combines Java basics, OOP, collections, exceptions, testing, and Spring Boot-style layered design.
Beginner + Developer Explanation
Build a Student Management API using controller, service, repository, DTO, exception, and test layers. This teaches production structure.
Important Concepts
- Controller handles HTTP
- Service handles business rules
- Repository handles data
- DTO defines API contract
- Exception layer maps errors
- Tests verify behavior
- Docker packages app
Syntax / Pattern
student-api/ controller/ service/ repository/ model/ dto/ exception/ tests/
Detailed Code Example
import java.util.*;
record Student(long id, String name, int marks) {}
class StudentService {
private final Map<Long, Student> students = new HashMap<>();
private long sequence = 1;
public Student create(String name, int marks) {
if (name == null || name.isBlank()) throw new IllegalArgumentException("Name required");
if (marks < 0 || marks > 100) throw new IllegalArgumentException("Marks must be 0-100");
Student student = new Student(sequence++, name, marks);
students.put(student.id(), student);
return student;
}
public List<Student> findAll() {
return new ArrayList<>(students.values());
}
}
Output / Result
create("Anu", 92) -> Student[id=1, name=Anu, marks=92]
Real-Time Production Scope
- Internship portal backend
- Student dashboard
- Admin CRUD system
- Learning center API
Common Mistakes and Fixes
- No service layer
- No validation
- No exception strategy
- No tests
- Returning database entity directly everywhere