Java
Java
Thread:
"A thread is the smallest unit of a process that can be executed independently by a
scheduler. In a program, threads help perform multiple tasks at the same time,
improving performance and responsiveness — especially in tasks like web servers,
downloading files, or handling user inputs."
"Threads share the same memory space within a process but execute independently.
This makes communication between threads easier and faster than processes, which
have separate memory. Most programming languages support multithreading — for
example, Java uses the `Thread` class or implements the `Runnable` interface to
create threads."
"For example, in a web browser, one thread might handle UI rendering while another
fetches data from the internet. That way, the app doesn’t freeze when waiting for
data."
2. Multi Threading:
"Each thread in multithreading shares the same memory space but runs independently.
This is useful when we want to perform tasks like reading user input, loading data
from the internet, and processing animations simultaneously without blocking the
main thread."
Example in Java:
"In Java, we can create multiple threads using the `Thread` class or implementing
the `Runnable` interface. For example, in a web server, multithreading allows it to
handle multiple client requests at the same time."
💡 Real-life analogy:
"Think of multithreading like a restaurant kitchen — while one chef cooks, another
prepares ingredients, and someone else washes dishes — all working in parallel to
serve customers faster."
3. Garbage Collection:
💡 Real-world analogy:
"Think of it like cleaning up a desk. Once you're done using a file and you no
longer need it, the cleaner (garbage collector) removes it so your desk (memory)
stays organized and clutter-free."
```java
interface Animal {
void eat();
}
interface Bird {
void fly();
}
"Here, the `Bat` class implements two interfaces, `Animal` and `Bird`, achieving
multiple inheritance. This way, Java avoids the complications of multiple class
inheritance while still allowing a class to inherit from multiple sources."
"JVM stands for Java Virtual Machine. It’s a part of the Java platform that
executes Java bytecode and makes Java programs platform-independent. It provides an
environment to run Java programs by converting bytecode into machine-specific
code."
🔧 Components of JVM:
3. Execution Engine
- Executes the bytecode line by line.
- Contains:
- Interpreter: Reads and executes bytecode instructions one by one.
- JIT Compiler (Just-In-Time): Converts bytecode into native machine code for
better performance.
- Garbage Collector: Automatically manages memory by clearing unused objects.
"JRE stands for Java Runtime Environment. It provides everything needed to run Java
applications — including the JVM, core libraries, and other supporting files.
However, it does not include development tools like the compiler (`javac`)."
JRE gives the minimum setup required to run any Java application. It includes the
JVM and standard libraries. The key advantage is that it allows
platform-independent execution, automatic memory management, and runs Java apps
without needing full development tools.”
🔍 Example:
```java
String str = "Hello";
str += " World"; // A new object is created
```
🔹 Immutable
🔹 Thread-safe (indirectly, because it cannot be changed)
🔹 Stored in the String Constant Pool (if declared using double quotes)
"`StringBuilder` is a mutable class, which means we can change the content without
creating new objects. It’s faster than `String` when performing many modifications,
like appending or deleting characters."
🔍 Example:
```java
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // Modifies the same object
🔹 Mutable
🔹 Not thread-safe
🔹 Faster than `StringBuffer` (no synchronization overhead)
✅ Now, `StringBuffer`:
🔍 Example:
```java
StringBuffer sbf = new StringBuffer("Hello");
sbf.append(" World"); // Thread-safe version
```
🔹 Mutable
🔹 Thread-safe (due to synchronization)
🔹 Slightly slower than `StringBuilder`
"Internally, `HashMap` stores data in the form of key-value pairs. It uses a data
structure called an array of buckets, where each bucket is essentially a linked
list or a balanced tree (in newer versions). When we add a key-value pair, the
key's hash code is used to determine the index of the array where the entry will be
placed."
🔧 Step-by-step working:
1. Hashing
- The key’s `hashCode()` is computed.
- This hash code is processed using a hashing function to find the index in the
internal array (bucket).
```java
int hash = key.hashCode();
int index = hash % array.length; // simplified
```
2. Index Mapping
- The element is placed at that index in the array.
- If two keys map to the same index, it's a collision.
3. Collision Handling
- If collision occurs:
- Initially handled by a LinkedList (chaining).
- From Java 8 onwards, if the number of items in a bucket exceeds 8, the list is
converted into a Red-Black Tree for better performance (O(log n)).
4. Retrieval
- To get a value:
- Compute hash → find index → scan bucket → compare keys using `.equals()` to
ensure the exact key.
🔁 Example:
```java
Map<String, String> map = new HashMap<>();
map.put("A", "Apple");
map.put("B", "Ball");
```
"So, `HashMap` uses an array + linked list/tree, uses hashCode to locate buckets,
handles collisions by chaining, and ensures fast lookup with `equals()`."
8. OOPs in java:
- In a car, you don’t need to know how the engine works to drive it.
- You only interact with the steering, accelerator, brakes, etc.
In Java:
```java
class Car {
private int speed; // hidden from outside
In Java:
```java
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}
- When you start() a car or a bike, the behavior is different, but the action is
called the same.
```java
class Vehicle {
void start() {
System.out.println("Vehicle starts");
}
}
- You drive the car using the steering wheel, accelerator, and brakes.
- You don’t know or care about the internal gearbox mechanism.
In Java:
```java
abstract class Vehicle {
abstract void drive();
}
> "Just like in real life, OOP in Java allows us to model complex systems (like
vehicles, employees, accounts, etc.) into objects with clear roles and
responsibilities, while keeping the code modular, secure, and reusable."
📌 Real-Life Example:
👉 ATM Machine – You can withdraw money in different ways:
They all have the same action: withdraw(), but input methods differ.
Java Example:
```java
class ATM {
void withdraw(int amount) {
System.out.println("Withdraw " + amount + " using card");
}
📘 Definition:
> Method Overriding occurs in two classes (inheritance) where the child class
redefines a method from the parent class with the same name, return type, and
parameters.
📌 Real-Life Example:
👉 Vehicle → Car / Bike / Truck
Java Example:
```java
class Vehicle {
void start() {
System.out.println("Vehicle starts");
}
}
👇 Run:
```java
Vehicle v = new Car();
v.start(); // Output: Car starts with key
```
---
---
> “Overloading is like using the same remote button for different TVs — it depends
on the signal you send. Overriding is like customizing how each TV reacts to the
power button — they all have it, but their behavior differs.”
📌 Real-Life Analogy:
Remote Control Interface – All devices (TV, AC, Fan) implement a Remote interface,
but each one defines its own behavior for `turnOn()`, `turnOff()`.
Java Example:
```java
interface Remote {
void turnOn();
void turnOff();
}
📘 Definition:
> An abstract class is a class that cannot be instantiated, and can have both
abstract methods (no body) and concrete methods (with body).
📌 Real-Life Analogy:
Bank Account – The concept of a `BankAccount` is abstract. You can’t create it
directly. But specific types like `SavingsAccount`, `CurrentAccount` extend it and
define exact behavior.
Java Example:
```java
abstract class BankAccount {
int balance = 1000;
void checkBalance() {
System.out.println("Balance: " + balance);
}
}
- Use Interface when you want to define a contract that multiple classes can
implement, and you need multiple inheritance.
- Use Abstract Class when you want to share common base functionality (like method
body, variables) along with some abstract behavior.
> “Interfaces are like contracts – they tell what to do but not how. Abstract
classes are like blueprints – they give partial implementation and let subclasses
complete the rest. I use interfaces for full abstraction and multiple inheritance,
and abstract classes when I need shared logic with flexibility.”
== compares memory addresses for objects, while .equals() compares actual content.
For example, two strings with the same value will return true with .equals() but
might return false with == if they’re not pointing to the same memory. So for
content comparison, I always use .equals().
Student(String name) {
this.name = name; // refers to the instance variable
}
}
```
Without `this`, it would refer to the constructor parameter, not the instance
variable.
📘 Definition:
> `super` refers to the parent (superclass) object.
🧠 Real-life Analogy
> “`this` refers to the current object — I mostly use it when constructor
parameters shadow instance variables. On the other hand, `super` is used when I
want to call a method or constructor from the parent class — especially useful in
inheritance.”
🔁 Python vs Java
🔁 C vs Java
| Feature | C | Java
|
|----------------------|------------------------------------|----------------------
-------------------|
| Type | Compiled, Procedural Language | Compiled to bytecode,
Object-Oriented |
| Memory Management| Manual (malloc, free) | Automatic (Garbage
Collection via JVM) |
| Platform | Platform-dependent (compiled to .exe) | Platform-independent
(JVM) |
| Syntax | Concise but low-level | More structured,
higher-level |
| Pointers | Yes (direct memory access) | No direct pointer usage
(safer) |
| Speed | Faster (closer to hardware) | Slower than C due to
abstraction |
| OOP | No | Fully supports OOP
|
| Use Cases | OS, embedded systems, low-level apps| Web, mobile, enterprise
applications |
✅ One-liner takeaway:
> “C is low-level and fast, ideal for system programming, while Java is high-level
and safer, perfect for large-scale applications.”
📘 Definition:
A constructor is a special method that is called automatically when an object is
created.
No, Java doesn’t have destructors like C++. Java uses an automatic Garbage
Collector to manage memory. It frees up objects that are no longer in use, which
makes Java memory-safe and developer-friendly. Earlier, Java had a finalize()
method, but it’s now deprecated due to performance and reliability issues.
✅ Can a Constructor Be Private?
> Yes. In Java, you can declare a constructor as `private`.
```java
public class Utility {
private Utility() {
// Prevent instantiation
}
```java
public class Singleton {
private static Singleton instance;
private Singleton() {
System.out.println("Private constructor called");
}
---
3. ✅ Factory Pattern
- Control how objects are created via a factory method.
If you try:
```java
Singleton s = new Singleton(); // ❌ Error: constructor Singleton() is not visible
```
You’ll get a compilation error because it’s not accessible outside its class.
> “Yes, constructors can be private in Java. It’s commonly used in design patterns
like Singleton to restrict object creation and ensure control over how instances
are managed. It’s also useful in utility or helper classes where object
instantiation isn’t required.”
📌 Explanation:
🔹 `private`
- Most restricted access.
- Can only be accessed within the same class.
```java
private int age;
```
🔹 `protected`
- Accessible within the same package and in subclasses (even if subclass is in a
different package).
```java
protected String name;
```
🔹 `public`
- Accessible from anywhere (any class, any package).
```java
public void showDetails() { ... }
```
🧠 Real-life Analogy:
> “Access specifiers in Java define the scope of visibility for classes, variables,
and methods. `private` is the most restrictive, `public` the most open. Using them
properly supports encapsulation and helps secure class internals.”
> The JVM needs to access the `main()` method to start execution.
If it's not `public`, the JVM can't see it, and you’ll get a runtime error.
✅ Correct Signature:
```java
public static void main(String[] args) {
System.out.println("Hello, Dhanish!");
}
```
❌ If you write:
```java
private static void main(String[] args) {
// JVM can't access this
}
```
🧨 You’ll get this error:
```
Error: Main method not found in class YourClassName, please define the main method
as:
public static void main(String[] args)
```
| Keyword | Meaning
|
|----------|-----------------------------------------------------------------------
--|
| `public` | Accessible by JVM from outside the class
|
| `static` | No object needed to run it
|
| `void` | Does not return any value
|
| `main` | Entry point of the program
|
| `String[] args` | Accepts command-line arguments
|
> “No, the `main()` method must be `public` because the JVM calls it from outside
the class. If it’s private, the JVM won’t be able to access it, and the program
won’t run.”
The break statement is used to completely exit a loop or switch case once a
condition is met. continue skips the current iteration and proceeds with the next
one. Both are useful for controlling the loop flow efficiently.
1. Real-world Modeling 🌍
> Objects help model real-world entities like students, cars, bank accounts, etc.
```java
class Car {
String brand;
int speed;
void drive() {
System.out.println("Driving...");
}
}
```
`Car` is a real-world object — and in Java, we represent it as an object.
2. Encapsulation
> Objects bundle data and behavior together — this protects internal state and
keeps code modular.
```java
class Animal {
void sound() { System.out.println("Makes sound"); }
}
4. Polymorphism
> One object can behave differently based on context.
```java
Animal a = new Dog(); // Object is Dog, reference is Animal
a.sound(); // Output: Barks
```
🧠 Real-life Analogy:
Imagine building a car 🚗 from parts like engine, tires, and seats.
- Procedural programming is like laying all parts on the ground — it’s messy.
- Object-Oriented programming bundles each car into an object with organized data
and functions.
💬 Interview-Ready Answer:
> “Java uses objects because it’s an Object-Oriented Programming language. Objects
help model real-world entities and allow us to organize data and behavior together
using principles like encapsulation, inheritance, and polymorphism. This makes the
code more reusable, modular, and easier to maintain.”
18. SuperClass:
A superclass is the parent class from which another class (subclass) inherits.
In Java:
- A subclass (child) can inherit the fields and methods of its superclass (parent).
- This enables code reusability and supports the inheritance feature of OOP.
✅ Basic Syntax:
```java
class Animal { // Superclass
void sound() {
System.out.println("Animal makes sound");
}
}
```java
class Dog extends Animal {
void makeSound() {
super.sound(); // Calls the superclass method
System.out.println("Dog barks too");
}
}
```
🧠 Real-life Analogy:
All vehicles have common properties (engine, wheels), but cars and bikes may add
their own features.
🧩 Keywords Related:
💬 Interview-Ready Answer:
> “A superclass in Java is a class whose properties and methods can be inherited by
another class. It helps promote code reuse. The `extends` keyword is used to create
a subclass, and the `super` keyword allows the subclass to access superclass
methods or constructors.”
```java
public void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Not eligible to vote");
}
}
```
```java
public void readFile() throws IOException {
// code that may throw IOException
}
```
- Tells the caller: "Hey, this method might throw this exception, be ready to
handle it!"
- Can declare multiple exceptions separated by commas.
🧠 Real-Life Analogy:
```java
public void validate(int age) throws ArithmeticException {
if (age < 18) {
throw new ArithmeticException("Age below 18");
}
}
```
💬 Interview-Ready Answer:
> “`throw` is used to actually throw an exception object during runtime, while
`throws` is used in a method declaration to indicate that the method may throw one
or more exceptions. `throw` is followed by an exception instance, and `throws` is
followed by exception class names.”
Array indexing starts from 0 because it's more efficient in memory address
calculation. With zero-based indexing, the index directly maps to the offset from
the base address, avoiding unnecessary subtraction. It also aligns with how
pointers work in low-level languages like C, from which Java inherits many core
concepts.
Java handles most of this automatically using the Java Virtual Machine (JVM) and
Garbage Collector (GC) — that’s why it’s known as a managed language.
1. Heap Area
- Stores objects and class instances
- Garbage Collected
- Biggest part of memory
2. Stack Area
- Stores method calls and local variables
- Each thread has its own stack
- Memory is automatically freed after method exits
Java automatically deletes unused objects from the heap when they’re no longer
reachable.
Example:
```java
Student s1 = new Student("Dhanish");
s1 = null; // Eligible for garbage collection
```
💬 Interview-Ready Answer:
> “Memory management in Java is handled by the JVM through areas like heap, stack,
and method area. The heap stores objects, and the stack stores method calls and
local variables. Java uses automatic garbage collection to remove unused objects,
making it safer and easier to manage memory compared to languages like C or C++.”
✅ Used to create:
- Class-level variables or methods (not object-specific)
- Shared among all instances of the class
- Can be accessed without creating an object
🔧 Example:
```java
class Student {
static String school = "CBSE"; // shared by all students
String name;
}
```
```java
System.out.println(Student.school); // Accessed directly using class name
```
✅ Used to:
- Make variables constant
- Prevent method overriding
- Prevent class inheritance
🔧 Examples:
1. Final Variable:
```java
final int roll = 101;
roll = 102; // ❌ Error: can't change final value
```
2. Final Method:
```java
class A {
final void show() { }
}
class B extends A {
void show() { } // ❌ Error: can't override final method
}
```
3. Final Class:
```java
final class Car { }
| Keyword | Analogy
|
|---------|------------------------------------------------------------------------
-|
| `static` | One common TV remote shared by all in the house 🛋 |
| `final` | Like a sealed bottle 🧴— you can't change its contents or reopen it |
💬 Interview-Ready Answer:
> “The `static` keyword is used to create class-level variables or methods shared
by all instances. It's memory-efficient and doesn’t require object creation. On the
other hand, the `final` keyword is used to declare constants, prevent method
overriding, or stop class inheritance. Both serve different purposes but are
commonly used in Java for enforcing rules and optimizing performance.”
23. Why is java platform independent?
✅ Key Points:
- Fixed size (defined at creation)
- Stores elements of the same type
- Accessed using index
- Fast for retrieval, but not great at insertions/deletions
```java
int[] numbers = new int[5];
numbers[0] = 10;
```
✅ Key Points:
- Resizable — size grows automatically
- Stores objects (non-primitive types like `Integer`, `String`, etc.)
- Internally uses an array
- Better for index-based access, not for frequent insert/delete
```java
ArrayList<Integer> list = new ArrayList<>();
list.add(10);
list.add(20);
```
✅ Key Points:
- Elements are stored in nodes (not continuous memory)
- Each node points to the next and previous node
- Great for frequent insertions/deletions
- Slower for index-based access
```java
LinkedList<String> names = new LinkedList<>();
names.add("Dhanish");
names.add("Java");
```
⚖ Quick Comparison Table:
🧠 Real-Life Analogy:
💬 Interview-Ready Answer:
> “Arrays are fixed-size and best for static data. ArrayLists are dynamic arrays
from the Java Collections Framework, good for random access but not efficient at
insertions or deletions. LinkedLists use nodes to store data and are efficient for
frequent additions or removals, especially from the start or end. The choice
depends on the use case.”
✅ What is it?
`Cloneable` is a marker interface (has no methods) that allows an object to be
cloned using the `Object.clone()` method.
🔧 Example:
```java
class Student implements Cloneable {
int id;
String name;
```java
Student s1 = new Student(1, "Dhanish");
Student s2 = (Student) s1.clone();
```
⚠ Important Notes:
- Performs a shallow copy by default (nested objects are not deeply copied)
- To perform deep copy, you must override `clone()` carefully
✅ What is it?
You manually write a copy constructor to copy one object’s values into another.
🔧 Example:
```java
class Student {
int id;
String name;
// Copy constructor
Student(Student s) {
this.id = s.id;
this.name = s.name;
}
}
```
```java
Student s1 = new Student(1, "Dhanish");
Student s2 = new Student(s1);
```
🧠 Real-Life Analogy:
- `clone()` is like photocopying a document — fast but might not capture inner
details (deep copy).
- Copy constructor is like manually rewriting the content — slower, but you have
control.
💬 Interview-Ready Answer:
> “The `Cloneable` interface allows objects to be cloned using the `clone()`
method, but it performs a shallow copy by default. For deep copying or more
control, it's better to use a copy constructor. Though `clone()` can be faster,
it's less flexible and harder to manage in complex object hierarchies.”
26. Reallocation:
is a super useful concept, especially when you're talking about arrays, memory, or
data structures like `ArrayList`
What is Reallocation?
✅ Reallocation means allocating a new chunk of memory when the existing one
isn’t enough to hold more data — and copying the old data into it.
1. In Arrays (manually)
- Arrays in Java are fixed in size, so if you need a bigger one, you have to:
- Create a new larger array
- Copy elements from the old array to the new one
```java
int[] oldArray = {1, 2, 3};
int[] newArray = new int[5];
2. In `ArrayList` (automatically)
- `ArrayList` handles reallocation for you
- Internally backed by an array
- When it reaches capacity:
- It creates a new larger array (usually 1.5x or 2x size)
- Copies old elements
- Updates internal reference
```java
ArrayList<Integer> list = new ArrayList<>();
list.add(10); // Under the hood: may reallocate if capacity exceeded
🧠 Real-Life Analogy:
💬 Interview-Ready Answer:
> “Reallocation is the process of allocating a new memory block when the current
one is full, and copying the existing data to it. In Java, arrays require manual
reallocation, but classes like `ArrayList` handle it internally by resizing their
internal array when needed. Though necessary, it’s computationally expensive due to
copying overhead.”
Java always passes a copy of the value to methods. Changing the value inside the
method doesn't affect the original.
🔧 Example:
```java
void changeValue(int x) {
x = 100;
}
int a = 50;
changeValue(a);
System.out.println(a); // Output: 50
```
> `a` is not changed because only a copy of `a` was passed.
Even for objects, Java passes a copy of the reference — not the actual object
reference itself. So you can modify object fields, but not reassign the reference.
🔧 Example:
```java
class Person {
String name;
}
void modify(Person p) {
p.name = "Dhanish"; // This works
p = new Person(); // This doesn’t affect original
p.name = "Changed"; // New object, not visible outside
}
> The object’s data was changed, but the new assignment didn’t affect the original
object.
🧠 Real-Life Analogy:
- Call by value → Giving someone a photocopy of your ID. They write on it, but your
original ID is untouched.
- Object in Java → Giving them a copy of your locker key. They can change what's
inside, but can’t swap your locker.
💬 Interview-Ready Answer:
> “Java is strictly call by value. For primitives, it passes the actual value. For
objects, it passes a copy of the reference, so changes to the object's internal
state reflect outside the method, but reassigning the reference inside the method
doesn't affect the original object.”
```java
String s = "Dhanish"; // "Dhanish" is a String literal
```
When you use a string literal like `"Hello"`, Java stores it in a special memory
area called the String Pool.
Example:
```java
String a = "Java";
String b = "Java";
Both `a` and `b` point to the same object in the String Pool.
```java
String a = new String("Java");
String b = new String("Java");
Even though the values are the same, `new` creates a new object in heap every time
— not reused.
- Always prefer string literals when you want performance and memory efficiency
- Great for immutable constant strings
💬 Interview-Ready Answer:
> “String literals are sequences of characters enclosed in double quotes. In Java,
they are stored in the String Pool, which helps save memory by reusing objects with
the same content. When we use the `new` keyword, a new object is created in the
heap even if an identical string exists in the pool.”
🌐 1. Servlets in Java
✅ What is a Servlet?
A Servlet is a Java class used to handle HTTP requests and responses — it's the
backbone of Java web applications running on a server.
🔧 How It Works:
🔁 Servlet Lifecycle:
1. Init() – Called once when the servlet is first loaded
2. Service() – Called every time a request is received
3. Destroy() – Called when servlet is unloaded
🔤 Simple Example:
```java
public class MyServlet extends HttpServlet {
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.getWriter().println("Hello, Dhanish!");
}
}
🔥 Real-Life Analogy:
> Like a waiter (Servlet) taking your order (request) and bringing your food
(response).
🔁 2. Streams in Java
Streams in Java represent a flow of data — used for input/output (I/O) operations
or for processing collections of data.
Two Categories:
Example:
```java
FileInputStream fis = new FileInputStream("data.txt");
int data = fis.read();
while(data != -1) {
System.out.print((char) data);
data = fis.read();
}
fis.close();
Example:
```java
List<String> names = Arrays.asList("Ram", "Sam", "Dhanish");
names.stream()
.filter(n -> n.startsWith("D"))
.forEach(System.out::println); // Output: Dhanish
💬 Interview-Ready Answer:
> “Servlets are Java classes used for building web applications — they handle HTTP
requests and generate dynamic responses. Streams, on the other hand, refer to
either I/O operations using InputStream/OutputStream or the Stream API introduced
in Java 8, which allows functional-style operations on collections. They serve
different purposes — web vs data handling.”
It helps:
- Store and retrieve data quickly
- Distribute keys evenly across memory (buckets)
- Avoid performance bottlenecks due to clustering
🔧 Example in Java:
```java
String key = "Dhanish";
int hash = key.hashCode(); // Java's built-in hash function
📦 Used In:
- `HashMap`
- `HashSet`
- `Hashtable`
These use:
1. `hashCode()` to calculate the hash
2. `equals()` to resolve collisions
```java
int hash = key.hashCode(); // Step 1: Get hash
int index = hash % numberOfBuckets; // Step 2: Map hash to a bucket index
```
> “A hash function in Java converts a key into a hash code, which is used by data
structures like HashMap to determine the bucket location for storing key-value
pairs. Java uses the `hashCode()` method internally. It ensures fast access by
evenly distributing keys, and collisions are handled using chaining or tree
structures.”
1. The declaration `String[10] args` **will not compile** in Java.
### Why?
Java syntax for declaring arrays is different. The correct way to declare a
`String` array is:
```java
String[] args = new String[10]; // Correct
```
```java
public static void main(String[] args) // Correct
```
🟢 **Example:**
```java
void show() {
int x = 10; // x is stored in stack
}
```
🟢 **Example:**
```java
Student s = new Student(); // Student object is created in heap
```