📘 Core Java नोट्स — बिल्कुल शुरू से
Java के 34 topics — Basics से लेकर Java 8+ तक — हर एक एक छोटी कहानी + animation के साथ, जैसे कोई बच्चा पहली बार Java सीख रहा हो। Card खोलो quick overview के लिए, या "Full Deep Dive" दबाओ पूरी detail के साथ — subtopics, extra code examples, सब कुछ।
Java एक programming language है जिससे हम computer को instructions देते हैं। ये 1995 में बनी थी और आज भी apps, websites, games — सबमें use होती है।
सबसे ख़ास बात: "Write Once, Run Anywhere"। मतलब एक बार Java code लिखो, वो Windows, Mac, Linux — हर जगह चल सकता है, बिना दोबारा लिखे!
कैसे? तुम्हारा .java file पहले "compile" होती है और .class file (bytecode) बनती है। फिर JVM (Java Virtual Machine) उस bytecode को हर computer पर समझ कर चला देती है — जैसे एक universal translator!
public class Hello {
public static void main(String[] args) {
System.out.println("Hello, Code10x!");
}
}📖 Full Deep Dive (4 subtopics) →Java में हर variable का एक type होता है — जैसे int (whole number), double (decimal number), char (single letter), boolean (true/false), और String (text)।
Java "statically typed" language है — मतलब डिब्बे का type शुरू में ही बताना पड़ता है, और उस डिब्बे में सिर्फ़ वही type की चीज़ fit होगी।
int age = 10;
double price = 99.5;
char grade = 'A';
boolean isFun = true;
String name = "Duke";📖 Full Deep Dive (3 subtopics) →Arithmetic operators (+ - * / %) numbers पर maths करते हैं। % operator "remainder" देता है — जैसे 10 % 3 = 1।
Relational operators (== != > < >= <=) दो values compare करके true/false बताते हैं। Logical operators (&& || !) multiple conditions जोड़ते हैं।
int a = 10, b = 3;
System.out.println(a % b); // 1
System.out.println(a > b && b > 0); // true📖 Full Deep Dive (5 subtopics) →if block तभी चलता है जब condition true हो। अगर false हो, तो else block चलता है।
तुम कई conditions भी लगा सकते हो else if से — जैसे एक के बाद एक gate check करना।
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!");
}📖 Full Deep Dive (3 subtopics) →for loop तब use करते हैं जब पता हो कितनी बार repeat करना है। while loop तब जब condition के true रहने तक repeat करना हो।
do-while loop कम से कम एक बार ज़रूर चलता है, चाहे condition false ही क्यों ना हो।
for (int i = 1; i <= 5; i++) {
System.out.println("Lap " + i);
}📖 Full Deep Dive (5 subtopics) →Array एक fixed-size collection है जिसमें same type की multiple values एक साथ store होती हैं।
हर value का अपना "index" होता है, जो 0 से start होता है — पहला element index 0 पर होता है, ना कि 1!
int[] scores = {90, 85, 77, 60};
System.out.println(scores[0]); // 90📖 Full Deep Dive (4 subtopics) →Class define करती है कि object के पास क्या properties (fields) और क्या behavior (methods) होंगे।
Object class का एक "instance" होता है — real चीज़ जिसको तुम use कर सकते हो, अपनी values के साथ।
class Car {
String color;
void drive() { System.out.println(color + " car driving!"); }
}
Car myCar = new Car();
myCar.color = "Red";
myCar.drive();📖 Full Deep Dive (3 subtopics) →Constructor एक special method है जिसका नाम class के नाम जैसा होता है, और वो तब call होता है जब "new" keyword से object बनाया जाता है।
इससे हम object को तुरंत valid starting state दे सकते हैं — बिना अलग से हर field set किए।
class Student {
String name;
Student(String n) { name = n; }
}
Student s1 = new Student("Aarav");📖 Full Deep Dive (4 subtopics) →this current object को refer करता है — जब parameter और field का नाम same हो, तब confusion दूर करता है।
static member class का होता है, किसी एक object का नहीं — सब objects उसको share करते हैं, जैसे एक common counter।
class Counter {
static int total = 0;
Counter() { total++; }
}📖 Full Deep Dive (4 subtopics) →extends keyword से एक class दूसरी class के fields और methods use कर सकती है, बिना दोबारा लिखे।
ये code reuse बढ़ाता है — common चीज़ें parent में लिखो, specific चीज़ें child में।
class Animal {
void eat() { System.out.println("Eating..."); }
}
class Dog extends Animal {
void bark() { System.out.println("Woof!"); }
}📖 Full Deep Dive (4 subtopics) →Overloading: same method नाम, अलग parameters — जैसे add(int,int) और add(double,double)। ये compile-time पर decide होता है।
Overriding: child class parent के method को अपने तरीक़े से दोबारा लिखती है — जैसे Dog अपना sound() ख़ुद define करता है। ये run-time पर decide होता है।
class Animal { void sound() { System.out.println("..."); } }
class Cat extends Animal { void sound() { System.out.println("Meow"); } }📖 Full Deep Dive (4 subtopics) →Fields को private बनाओ, ताकि कोई बाहर से सीधा change ना कर सके।
public getter/setter methods दो जिससे controlled तरीक़े से value पढ़ी/बदली जा सके — जैसे ATM से पैसा निकालना, सीधा locker खोल कर नहीं।
class Account {
private double balance;
public double getBalance() { return balance; }
public void deposit(double amt) { if (amt > 0) balance += amt; }
}📖 Full Deep Dive (4 subtopics) →Abstraction complex implementation को छुपाकर सिर्फ़ ज़रूरी चीज़ें दिखाता है।
abstract class या interface से हम "क्या करना है" बताते हैं, "कैसे करना है" वो implementing class decide करती है।
abstract class Shape {
abstract double area();
}
class Circle extends Shape {
double r;
double area() { return 3.14 * r * r; }
}📖 Full Deep Dive (3 subtopics) →Interface में (Java 8 से पहले) सिर्फ़ method signatures होते थे, कोई body नहीं — implementing class को सब लिखना पड़ता था।
Abstract class में कुछ methods complete हो सकते हैं और कुछ abstract (incomplete) — और एक class सिर्फ़ एक abstract class extend कर सकती है, पर कई interfaces implement कर सकती है।
interface Flyable { void fly(); }
abstract class Bird {
void breathe() { System.out.println("breathing"); }
abstract void fly();
}📖 Full Deep Dive (5 subtopics) →try block में वो code लिखते हैं जो error दे सकता है। अगर error आए, catch block उसे "पकड़" लेता है और program crash नहीं होता।
finally block हमेशा चलता है — चाहे error आए या ना आए — जैसे cleanup करना, files बंद करना।
try {
int x = 10 / 0;
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero!");
} finally {
System.out.println("Done trying.");
}📖 Full Deep Dive (4 subtopics) →ArrayList ordered list है, duplicates allowed, index से access होता है।
HashSet सिर्फ़ unique values रखता है, order guarantee नहीं करता। HashMap key-value pairs store करता है — key से तुरंत value ढूँढ सकते हो, जैसे नाम से locker।
List<String> names = new ArrayList<>();
Set<Integer> ids = new HashSet<>();
Map<String, Integer> ages = new HashMap<>();
ages.put("Aarav", 10);📖 Full Deep Dive (5 subtopics) →Thread program का एक independent flow है। Normally Java एक thread (main) में चलता है।
Thread class extend करके या Runnable implement करके नए threads बना सकते हो, जो parallel काम करते हैं।
class MyThread extends Thread {
public void run() { System.out.println("Running..."); }
}
new MyThread().start();📖 Full Deep Dive (4 subtopics) →String immutable है — जब तुम s = s + "x" करते हो, एक नया String object बनता है, पुराना वही रहता है।
अगर बहुत सारे changes करने हैं (जैसे loop में), तो StringBuilder use करो — वो same object को modify करता है, fast होता है।
String s = "Hi";
s = s + " Java"; // new object created
StringBuilder sb = new StringBuilder("Hi");
sb.append(" Java"); // same object modified📖 Full Deep Dive (5 subtopics) →Widening (implicit) casting में छोटा type बड़े type में ख़ुद-ब-ख़ुद convert हो जाता है — जैसे int से double, कुछ loss नहीं होता।
Narrowing (explicit) casting में बड़ा type छोटे में manually convert करना पड़ता है — जैसे double से int, कुछ data (decimal part) खो सकता है।
Wrapper classes (Integer, Double, Character, Boolean) primitive types को object की तरह use करने देते हैं। Autoboxing primitive को wrapper में बदल देता है automatically, unboxing उल्टा करता है।
double d = 100.99;
int i = (int) d; // narrowing, i = 100
int x = 5;
Integer boxed = x; // autoboxing
int y = boxed; // unboxing📖 Full Deep Dive (3 subtopics) →Method parameters लेता है, काम करता है, और (चाहे तो) एक value return करता है — इससे code repeat नहीं करना पड़ता।
Java "pass by value" follow करता है — method को values की copy मिलती है, original variable change नहीं होता (objects के case में reference की copy मिलती है)।
Recursion में एक method ख़ुद को call करता है — जैसे factorial(5) = 5 * factorial(4)... जब तक base case (factorial(1)=1) ना आए।
int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}📖 Full Deep Dive (4 subtopics) →switch multiple if-else की जगह use होता है जब एक variable की अलग-अलग fixed values check करनी हो — हर case के बाद break लगाना ज़रूरी है, वरना अगला case भी चल जाता है (fall-through)।
break loop को तुरंत रोक देता है। continue current iteration skip करके अगली iteration पर चला जाता है।
switch (day) {
case 1: System.out.println("Mon"); break;
case 2: System.out.println("Tue"); break;
default: System.out.println("Other");
}📖 Full Deep Dive (3 subtopics) →2D array एक "array of arrays" है — पहला index row बताता है, दूसरा column।
इससे grid-जैसा data store होता है — जैसे tic-tac-toe board, या matrix।
int[][] grid = {
{1, 2, 3},
{4, 5, 6}
};
System.out.println(grid[1][2]); // 6 (row 1, col 2)📖 Full Deep Dive (4 subtopics) →हर class implicitly Object class extend करती है, इसलिए हर object को toString(), equals(), hashCode() free में मिलते हैं।
Default toString() अजीब सा text देता है (जैसे ClassName@hashcode) — इसलिए हम उसे override करते हैं readable output के लिए।
equals() और hashCode() को साथ में override करना चाहिए — HashMap/HashSet को सही से काम करने के लिए ये ज़रूरी है।
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;
}
}📖 Full Deep Dive (4 subtopics) →Static nested class outer class के बिना भी independently use हो सकती है — सिर्फ़ Outer.Nested से access।
Inner (non-static) class outer object से जुड़ा होता है — उससे outer के instance members भी directly दिखते हैं।
Anonymous class एक नाम-less class है जो तुरंत, one-time use के लिए define की जाती है — जैसे एक button click listener।
class Outer {
static class Nested { void show() { System.out.println("Nested"); } }
class Inner { void show() { System.out.println("Inner"); } }
}📖 Full Deep Dive (4 subtopics) →enum एक special type है जिसमें सिर्फ़ fixed constants define होते हैं — जैसे Day.MONDAY, Day.TUESDAY।
ये normal String/int से better है क्योंकि compiler ग़लत value use होने ही नहीं देता — सिर्फ़ वही options allowed हैं जो तुमने define किए।
enum Level { LOW, MEDIUM, HIGH }
Level l = Level.MEDIUM;
if (l == Level.MEDIUM) System.out.println("Medium level!");📖 Full Deep Dive (4 subtopics) →Generics <T> से हम classes/methods को "किसी भी type के लिए काम करने वाला" बना सकते हैं, बिना अलग-अलग versions लिखे।
Compile-time पर type-safety मिलती है — ग़लत type डालने की कोशिश पर compiler तुरंत error दे देता है, run-time crash से बचा लेता है।
class Box<T> {
T item;
void set(T item) { this.item = item; }
T get() { return item; }
}
Box<String> b = new Box<>();
b.set("Hello");📖 Full Deep Dive (4 subtopics) →public: कहीं से भी access हो सकता है। private: सिर्फ़ उसी class के अंदर। protected: same package + subclasses में। default (कुछ ना लिखो): सिर्फ़ same package में।
Package related classes का एक folder/group है — जैसे java.util में List, Map जैसे collection classes होते हैं। अपना package बनाने के लिए "package com.code10x;" लिखते हैं।
package com.code10x;
public class Robot {
private int battery;
protected void charge() { battery = 100; }
}📖 Full Deep Dive (4 subtopics) →Comparable (compareTo method) class के अंदर define होता है — "natural ordering" बताता है। Comparator (compare method) बाहर से custom ordering देता है, जितनी चाहो उतनी बनाओ।
Queue FIFO (First-In-First-Out) order follow करता है — जैसे ticket line। Deque दोनों तरफ़ से add/remove कर सकता है।
TreeMap/TreeSet अपने आप keys को sorted order में रखते हैं (HashMap/HashSet के उलट, जहाँ order guaranteed नहीं होता)।
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()); // 1📖 Full Deep Dive (5 subtopics) →Lambda expression (param) -> { code } से एक functional interface (जिसमें सिर्फ़ एक abstract method हो) को छोटे तरीक़े से implement करते हैं।
Stream API collections पर filter, map, sort जैसे operations chain करके लिखने देता है — बिना manual loops लिखे, code छोटा और readable बन जाता है।
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]📖 Full Deep Dive (14 subtopics) →java.io package files के साथ काम करने के tools देता है — FileReader/FileWriter characters के लिए, BufferedReader fast line-by-line reading के लिए।
try-with-resources resource को अपने आप close कर देता है जब block ख़त्म हो — file/connection खुली रह जाने की ग़लती से बचाता है।
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());
}📖 Full Deep Dive (4 subtopics) →एक catch block में "|" से multiple exception types पकड़ सकते हो: catch (IOException | SQLException e)।
Custom exceptions का अपना hierarchy बना सकते हो — जैसे एक base AppException, और उससे extend करके specific PaymentFailedException — बड़े projects में errors को organize करता है।
try {
riskyOperation();
} catch (IOException | SQLException e) {
System.out.println("Handled: " + e.getMessage());
}
class AppException extends Exception {}
class PaymentFailedException extends AppException {}📖 Full Deep Dive (4 subtopics) →Thread के 5 states होते हैं: New, Runnable, Running, Waiting/Blocked, Terminated।
wait()/notify() threads को एक दूसरे के signal का इंतज़ार करने देते हैं। ExecutorService thread pool manage करता है — नए threads manually बनाने के बजाय, ready threads reuse होते हैं।
Deadlock तब होता है जब दो threads एक-दूसरे के पास जो resource है उसका इंतज़ार करते रह जाते हैं, और कोई आगे नहीं बढ़ता — जैसे दो लोग एक ही दरवाज़े पर एक-दूसरे को पहले जाने दे रहे हों, हमेशा के लिए।
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(() -> System.out.println("Task running!"));
pool.shutdown();📖 Full Deep Dive (6 subtopics) →Stack memory method calls और local variables store करती है — fast, और method ख़त्म होते ही automatically clean हो जाती है।
Heap memory objects store करती है (जो "new" से बनाए जाते हैं) — ये लंबे समय तक रहती है, जब तक कोई reference use ना करे।
Garbage Collector (GC) automatically उन objects को ढूँढ कर हटा देता है जिनकी कोई reference नहीं बची — Java में manually memory free करने की ज़रूरत नहीं पड़ती।
void createObjects() {
Student s = new Student(); // heap par banta hai
} // method khatam -> s ab unreachable -> GC eligible📖 Full Deep Dive (5 subtopics) →Static block { } class load होते ही एक बार चलता है — static variables initialize करने के लिए best। Instance block हर object बनते वक़्त चलता है (constructor से पहले)।
clone() Object class का method है जो एक existing object की copy बना देता है (Cloneable interface implement करना पड़ता है)।
Serializable interface implement करके object को bytes में convert कर सकते हो (जैसे file में save करना या network पर भेजना), और बाद में deserialize करके वापस object बना सकते हो।
class Config implements Cloneable, Serializable {
static { System.out.println("Loaded once!"); }
int value = 10;
}📖 Full Deep Dive (4 subtopics) →