📘 Core Java Notes — Ekdum Basic Se
Java ke 34 topics — Basics se leke Java 8+ tak — har ek ek chhoti kahani + animation ke saath, jaise koi bachha pehli baar Java seekh raha ho. Category chuno, card par click karke kholo.
Java ek programming language hai jisse hum computer ko instructions dete hain. Ye 1995 mein bani thi aur aaj bhi apps, websites, games — sabme use hoti hai.
Sabse khaas baat: "Write Once, Run Anywhere". Matlab ek baar Java code likho, wo Windows, Mac, Linux — har jagah chal sakta hai, bina dobara likhe!
Kaise? Tumhara .java file pehle "compile" hoti hai aur .class file (bytecode) banti hai. Fir JVM (Java Virtual Machine) us bytecode ko har computer par samajh kar chala deti hai — jaise ek universal translator!
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Code10x!");
}
}Java mein har variable ka ek type hota hai — jaise int (whole number), double (decimal number), char (single letter), boolean (true/false), aur String (text).
Java "statically typed" language hai — matlab dabbe ka type shuru mein hi batana padta hai, aur us dabbe mein sirf wahi type ki cheez fit hogi.
int age = 10;
double price = 99.5;
char grade = 'A';
boolean isFun = true;
String name = "Duke";Arithmetic operators (+ - * / %) numbers par maths karte hain. % operator "remainder" deta hai — jaise 10 % 3 = 1.
Relational operators (== != > < >= <=) do values compare karke true/false batate hain. Logical operators (&& || !) multiple conditions jodte hain.
int a = 10, b = 3;
System.out.println(a % b); // 1
System.out.println(a > b && b > 0); // trueif block tabhi chalta hai jab condition true ho. Agar false ho, to else block chalta hai.
Tum kai conditions bhi laga sakte ho else if se — jaise ek ke baad ek gate check karna.
int marks = 85;
if (marks >= 90) {
System.out.println("A grade");
} else if (marks >= 60) {
System.out.println("B grade");
} else {
System.out.println("Keep trying!");
}for loop tab use karte hain jab pata ho kitni baar repeat karna hai. while loop tab jab condition ke true rehne tak repeat karna ho.
do-while loop kam se kam ek baar zaroor chalta hai, chahe condition false hi kyun na ho.
for (int i = 1; i <= 5; i++) {
System.out.println("Lap " + i);
}Array ek fixed-size collection hai jisme same type ki multiple values ek saath store hoti hain.
Har value ka apna "index" hota hai, jo 0 se start hota hai — pehla element index 0 par hota hai, na ki 1!
int[] scores = {90, 85, 77, 60};
System.out.println(scores[0]); // 90Class define karti hai ki object ke paas kya properties (fields) aur kya behavior (methods) honge.
Object class ka ek "instance" hota hai — real cheez jisko tum use kar sakte ho, apni values ke saath.
class Car {
String color;
void drive() { System.out.println(color + " car driving!"); }
}
Car myCar = new Car();
myCar.color = "Red";
myCar.drive();Constructor ek special method hai jiska naam class ke naam jaisa hota hai, aur wo tab call hota hai jab "new" keyword se object banaya jaata hai.
Isse hum object ko turant valid starting state de sakte hain — bina alag se har field set kiye.
class Student {
String name;
Student(String n) { name = n; }
}
Student s1 = new Student("Aarav");this current object ko refer karta hai — jab parameter aur field ka naam same ho, tab confusion door karta hai.
static member class ka hota hai, kisi ek object ka nahi — sab objects usko share karte hain, jaise ek common counter.
class Counter {
static int total = 0;
Counter() { total++; }
}extends keyword se ek class dusri class ke fields aur methods use kar sakti hai, bina dobara likhe.
Ye code reuse badhata hai — common cheezein parent mein likho, specific cheezein child mein.
class Animal {
void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Woof!"); }
}Overloading: same method naam, alag parameters — jaise add(int,int) aur add(double,double). Ye compile-time par decide hota hai.
Overriding: child class parent ke method ko apne tareeke se dobara likhti hai — jaise Dog apna sound() khud define karta hai. Ye run-time par decide hota hai.
class Animal { void sound() { System.out.println("..."); } }
class Cat extends Animal { void sound() { System.out.println("Meow"); } }Fields ko private banao, taaki koi bahar se seedha change na kar sake.
public getter/setter methods do jisse controlled tareeke se value padhi/badli ja sake — jaise ATM se paisa nikalna, seedha locker khol kar nahi.
class Account {
private double balance;
public double getBalance() { return balance; }
public void deposit(double amt) { if (amt > 0) balance += amt; }
}Abstraction complex implementation ko chhupa kar sirf zaroori cheezein dikhata hai.
abstract class ya interface se hum "kya karna hai" batate hain, "kaise karna hai" wo implementing class decide karti hai.
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
double r;
double area() { return 3.14 * r * r; }
}Interface mein (Java 8 se pehle) sirf method signatures hote the, koi body nahi — implementing class ko sab likhna padta tha.
Abstract class mein kuch methods complete ho sakte hain aur kuch abstract (incomplete) — aur ek class sirf ek abstract class extend kar sakti hai, par kayi interfaces implement kar sakti hai.
interface Flyable { void fly(); }
abstract class Bird {
void breathe() { System.out.println("breathing"); }
abstract void fly();
}try block mein wo code likhte hain jo error de sakta hai. Agar error aaye, catch block use "pakad" leta hai aur program crash nahi hota.
finally block hamesha chalta hai — chahe error aaye ya na aaye — jaise cleanup karna, files band karna.
try {
int x = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
} finally {
System.out.println("Done trying.");
}ArrayList ordered list hai, duplicates allowed, index se access hota hai.
HashSet sirf unique values rakhta hai, order guarantee nahi karta. HashMap key-value pairs store karta hai — key se turant value dhoond sakte ho, jaise naam se locker.
List<String> names = new ArrayList<>();
Set<Integer> ids = new HashSet<>();
Map<String, Integer> ages = new HashMap<>();
ages.put("Aarav", 10);Thread program ka ek independent flow hai. Normally Java ek thread (main) mein chalta hai.
Thread class extend karke ya Runnable implement karke naye threads bana sakte ho, jo parallel kaam karte hain.
class MyThread extends Thread {
public void run() { System.out.println("Running..."); }
}
new MyThread().start();String immutable hai — jab tum s = s + "x" karte ho, ek naya String object banta hai, purana wahi rehta hai.
Agar bahut saare changes karne hain (jaise loop mein), to StringBuilder use karo — wo same object ko modify karta hai, fast hota hai.
String s = "Hi";
s = s + " Java"; // new object created
StringBuilder sb = new StringBuilder("Hi");
sb.append(" Java"); // same object modifiedWidening (implicit) casting mein chhota type bade type mein khud-ba-khud convert ho jaata hai — jaise int se double, kuch loss nahi hota.
Narrowing (explicit) casting mein bada type chhote mein manually convert karna padta hai — jaise double se int, kuch data (decimal part) kho sakta hai.
Wrapper classes (Integer, Double, Character, Boolean) primitive types ko object ki tarah use karne dete hain. Autoboxing primitive ko wrapper mein badal deta hai automatically, unboxing ulta karta hai.
double d = 100.99;
int i = (int) d; // narrowing, i = 100
int x = 5;
Integer boxed = x; // autoboxing
int y = boxed; // unboxingMethod parameters leta hai, kaam karta hai, aur (chahe to) ek value return karta hai — isse code repeat nahi karna padta.
Java "pass by value" follow karta hai — method ko values ki copy milti hai, original variable change nahi hota (objects ke case mein reference ki copy milti hai).
Recursion mein ek method khud ko call karta hai — jaise factorial(5) = 5 * factorial(4)... jab tak base case (factorial(1)=1) na aaye.
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}switch multiple if-else ki jagah use hota hai jab ek variable ki alag-alag fixed values check karni ho — har case ke baad break lagana zaroori hai, warna agla case bhi chal jaata hai (fall-through).
break loop ko turant rok deta hai. continue current iteration skip karke agli iteration par chala jaata hai.
switch (day) {
case 1: System.out.println("Mon"); break;
case 2: System.out.println("Tue"); break;
default: System.out.println("Other");
}2D array ek "array of arrays" hai — pehla index row batata hai, dusra column.
Isse grid-jaisa data store hota hai — jaise tic-tac-toe board, ya matrix.
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(grid[1][2]); // 6 (row 1, col 2)Har class implicitly Object class extend karti hai, isliye har object ko toString(), equals(), hashCode() free mein milte hain.
Default toString() ajeeb sa text deta hai (jaise ClassName@hashcode) — isliye hum usse override karte hain readable output ke liye.
equals() aur hashCode() ko saath mein override karna chahiye — HashMap/HashSet ko sahi se kaam karne ke liye ye zaroori hai.
class Point {
int x, y;
public String toString() { return "(" + x + "," + y + ")"; }
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
Point p = (Point) o;
return x == p.x && y == p.y;
}
}Static nested class outer class ke bina bhi independently use ho sakti hai — sirf Outer.Nested se access.
Inner (non-static) class outer object se juda hota hai — usse outer ke instance members bhi directly dikhte hain.
Anonymous class ek naam-less class hai jo turant, one-time use ke liye define ki jaati hai — jaise ek button click listener.
class Outer {
static class Nested { void show() { System.out.println("Nested"); } }
class Inner { void show() { System.out.println("Inner"); } }
}enum ek special type hai jisme sirf fixed constants define hote hain — jaise Day.MONDAY, Day.TUESDAY.
Ye normal String/int se better hai kyunki compiler galat value use hone hi nahi deta — sirf wahi options allowed hain jo tumne define kiye.
enum Level { LOW, MEDIUM, HIGH }
Level l = Level.MEDIUM;
if (l == Level.MEDIUM) System.out.println("Medium level!");Generics <T> se hum classes/methods ko "kisi bhi type ke liye kaam karne wala" bana sakte hain, bina alag-alag versions likhe.
Compile-time par type-safety milti hai — galat type dalne ki koshish par compiler turant error de deta hai, run-time crash se bacha leta hai.
class Box<T> {
T item;
void set(T item) { this.item = item; }
T get() { return item; }
}
Box<String> b = new Box<>();
b.set("Hello");public: kahin se bhi access ho sakta hai. private: sirf usi class ke andar. protected: same package + subclasses mein. default (kuch na likho): sirf same package mein.
Package related classes ka ek folder/group hai — jaise java.util mein List, Map jaise collection classes hote hain. Apna package banane ke liye "package com.code10x;" likhte hain.
package com.code10x;
public class Robot {
private int battery;
protected void charge() { battery = 100; }
}Comparable (compareTo method) class ke andar define hota hai — "natural ordering" batata hai. Comparator (compare method) bahar se custom ordering deta hai, jitni chaho utni banao.
Queue FIFO (First-In-First-Out) order follow karta hai — jaise ticket line. Deque dono taraf se add/remove kar sakta hai.
TreeMap/TreeSet apne aap keys ko sorted order mein rakhte hain (HashMap/HashSet ke ulat, jaha order guaranteed nahi hota).
List<String> names = new ArrayList<>(List.of("Zoya","Aman","Ravi"));
names.sort(Comparator.naturalOrder());
// [Aman, Ravi, Zoya]
Queue<Integer> q = new LinkedList<>();
q.add(1); q.add(2);
System.out.println(q.poll()); // 1Lambda expression (param) -> { code } se ek functional interface (jisme sirf ek abstract method ho) ko chhote tareeke se implement karte hain.
Stream API collections par filter, map, sort jaise operations chain karke likhne deta hai — bina manual loops likhe, code chhota aur readable ban jaata hai.
List<Integer> nums = List.of(1, 2, 3, 4, 5, 6);
List<Integer> evenSquares = nums.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.toList();
// [4, 16, 36]java.io package files ke saath kaam karne ke tools deta hai — FileReader/FileWriter characters ke liye, BufferedReader fast line-by-line reading ke liye.
try-with-resources resource ko apne aap close kar deta hai jab block khatam ho — file/connection khuli reh jaane ki galti se bachata hai.
try (BufferedReader br = new BufferedReader(new FileReader("notes.txt"))) {
String line = br.readLine();
System.out.println(line);
} catch (IOException e) {
System.out.println("File error: " + e.getMessage());
}Ek catch block mein "|" se multiple exception types pakad sakte ho: catch (IOException | SQLException e).
Custom exceptions ka apna hierarchy bana sakte ho — jaise ek base AppException, aur usse extend karke specific PaymentFailedException — bade projects mein errors ko organize karta hai.
try {
riskyOperation();
} catch (IOException | SQLException e) {
System.out.println("Handled: " + e.getMessage());
}
class AppException extends Exception {}
class PaymentFailedException extends AppException {}Thread ke 5 states hote hain: New, Runnable, Running, Waiting/Blocked, Terminated.
wait()/notify() threads ko ek doosre ke signal ka intezaar karne dete hain. ExecutorService thread pool manage karta hai — naye threads manually banane ke bajaye, ready threads reuse hote hain.
Deadlock tab hota hai jab do threads ek-doosre ke paas jo resource hai uska intezaar karte reh jaate hain, aur koi aage nahi badhta — jaise do log ek hi darwaze par ek-doosre ko pehle jaane de rahe hon, hamesha ke liye.
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(() -> System.out.println("Task running!"));
pool.shutdown();Stack memory method calls aur local variables store karti hai — fast, aur method khatam hote hi automatically clean ho jaati hai.
Heap memory objects store karti hai (jo "new" se banaye jaate hain) — ye lambe samay tak rehti hai, jab tak koi reference use na kare.
Garbage Collector (GC) automatically un objects ko dhoondh kar hata deta hai jinki koi reference nahi bachi — Java mein manually memory free karne ki zaroorat nahi padti.
void createObjects() {
Student s = new Student(); // heap par banta hai
} // method khatam -> s ab unreachable -> GC eligibleStatic block { } class load hote hi ek baar chalta hai — static variables initialize karne ke liye best. Instance block har object banते waqt chalta hai (constructor se pehle).
clone() Object class ka method hai jo ek existing object ki copy bana deta hai (Cloneable interface implement karna padta hai).
Serializable interface implement karke object ko bytes mein convert kar sakte ho (jaise file mein save karna ya network par bhejna), aur baad mein deserialize karke wapas object bana sakte ho.
class Config implements Cloneable, Serializable {
static { System.out.println("Loaded once!"); }
int value = 10;
}