0% found this document useful (0 votes)
20 views37 pages

Java

The document covers key concepts in Java programming including threads, multithreading, garbage collection, multiple inheritance, JVM and JRE, string handling, HashMap functionality, OOP principles, method overloading and overriding, and the differences between interfaces and abstract classes. It provides definitions, examples, and real-world analogies to explain these concepts. The information is structured to facilitate understanding of Java's features and their practical applications.

Uploaded by

jdhanish123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
20 views37 pages

Java

The document covers key concepts in Java programming including threads, multithreading, garbage collection, multiple inheritance, JVM and JRE, string handling, HashMap functionality, OOP principles, method overloading and overriding, and the differences between interfaces and abstract classes. It provides definitions, examples, and real-world analogies to explain these concepts. The information is structured to facilitate understanding of Java's features and their practical applications.

Uploaded by

jdhanish123
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 37

1.

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."

💡 Real-world relatable example:

"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:

"Multithreading is a programming technique where multiple threads run concurrently


within a single process. It helps improve the performance of a program by allowing
multiple operations to happen at the same time."

"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:

"Garbage Collection is the process of automatically identifying and removing


objects from memory that are no longer used by the program. It helps manage memory
efficiently and prevents memory leaks."
"In Java, the garbage collector is a part of the Java Virtual Machine (JVM). It
automatically deallocates memory used by objects that are no longer reachable or
referenced in the program. This helps developers focus more on the logic without
worrying too much about memory management."

💡 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."

You can mention types of garbage collectors in Java (optional):


- Serial GC
- Parallel GC
- CMS (Concurrent Mark Sweep)
- G1 (Garbage First) GC

4. Implementationn of multiple inheritance:

"Multiple inheritance means a class can inherit features (methods or properties)


from more than one parent class. This allows a class to combine functionalities
from different sources."
\
"Java does not support multiple inheritance with classes to avoid ambiguity
problems, like the Diamond Problem. However, Java allows multiple inheritance
through interfaces."

🔧 Java Implementation Example (Using Interfaces):

```java
interface Animal {
void eat();
}

interface Bird {
void fly();
}

class Bat implements Animal, Bird {


public void eat() {
System.out.println("Bat eats insects.");
}

public void fly() {


System.out.println("Bat flies at night.");
}
}

public class Main {


public static void main(String[] args) {
Bat bat = new Bat();
bat.eat();
bat.fly();
}
}

🧠 Explanation to give the interviewer:

"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."

5. JVM and JRE:

"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:

You can break it down into 3 main parts:

1. Class Loader System


- Loads `.class` files (bytecode) into memory.
- Handles loading, linking, and initialization.
- Supports dynamic loading of classes.

2. Runtime Data Areas


- Memory areas used during execution:
- Method Area: Stores class-level data like method info, field info.
- Heap: Stores objects and class instances.
- Java Stack: Each thread has its own stack. Stores local variables and method
call data.
- PC Register: Stores the address of the current instruction.
- Native Method Stack: For native (non-Java) method calls.

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.

✅ Now explain JRE (Java Runtime Environment):

"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.”

🧠 How to connect JVM and JRE:


"You can think of it like this: JVM is a part of the JRE. JRE = JVM + Libraries +
Supporting files."

🔁 Optional Analogy (if needed):


"If Java is a car, then:
- JVM is the engine (executes the code),
- JRE is the entire vehicle (engine + parts needed to run),
- JDK (Java Development Kit) includes everything in JRE plus tools to build the car
(like `javac`, `javadoc`, etc)."

6. String Vs StringBuffer Vs StringBuilder:

"In Java, `String` is an immutable class. Once a `String` object is created, it


cannot be changed. Any modification like concatenation creates a new object."

🔍 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)

✅ Then explain `StringBuilder`:

"`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`:

"`StringBuffer` is also mutable like `StringBuilder`, but it is thread-safe —


meaning all its methods are synchronized. It’s used when multiple threads might be
accessing the same string content."

🔍 Example:
```java
StringBuffer sbf = new StringBuffer("Hello");
sbf.append(" World"); // Thread-safe version
```

🔹 Mutable
🔹 Thread-safe (due to synchronization)
🔹 Slightly slower than `StringBuilder`

🧠 Final Summary to Say in the Interview:

| Feature | String | StringBuilder | StringBuffer |


|-----------------|------------|---------------------|--------------------|
| Mutability | Immutable | Mutable | Mutable |
| Thread-Safe | Yes (indirectly) | No | Yes (synchronized) |
| Performance | Slow | Fast (single-threaded) | Slower (multi-threaded) |

7. Working of HashMap internally in java?

"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");
```

- `"A".hashCode()` decides the bucket.


- Stored in a `Node<K,V>` object inside the array.
- If `"C"` also lands on the same index, it's linked using chaining.

⚠ Key points to highlight:

- `hashCode()` + `equals()` are essential for key comparison.


- Initial capacity and load factor (default 0.75) determine when the map resizes.
- Resizing (rehashing) happens when size exceeds `capacity load factor`.

🧠 Summary (say this at the end):

"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:

🚗 Real-Life Example: Car

🔹 1. Encapsulation – "Hiding the engine’s complexity"

- 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

public void accelerate() {


speed += 10;
}

public int getSpeed() {


return speed;
}
}
```
→ The internal data (`speed`) is hidden, and access is provided via methods — just
like using controls in a car.

🔹 2. Inheritance – "Cars, Trucks, and Bikes all are Vehicles"

- Vehicle is a generic category.


- Car, Bike, and Truck inherit properties from Vehicle.

In Java:
```java
class Vehicle {
void start() {
System.out.println("Vehicle started");
}
}

class Car extends Vehicle {


void honk() {
System.out.println("Car honks");
}
}
```
→ Car inherits `start()` from Vehicle and adds its own behavior.

🔹 3. Polymorphism – "Same action, different results"

- 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");
}
}

class Car extends Vehicle {


void start() {
System.out.println("Car starts with key");
}
}
class Bike extends Vehicle {
void start() {
System.out.println("Bike starts with kick");
}
}

public class Main {


public static void main(String[] args) {
Vehicle v1 = new Car();
Vehicle v2 = new Bike();
v1.start(); // Car starts with key
v2.start(); // Bike starts with kick
}
}
```
→ The same method name `start()` behaves differently depending on the object —
that's runtime polymorphism.

🔹 4. Abstraction – "Driving without knowing internal mechanics"

- 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();
}

class Car extends Vehicle {


void drive() {
System.out.println("Driving a car");
}
}
```
→ The implementation is hidden from the user. You only know what action you can
perform (`drive()`), not how it works internally.

✅ Final One-liner Summary:

> "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."

9. Method Overloading and Overriding:

✅ 1. Method Overloading (Compile-Time Polymorphism)


📘 Definition:
> Method Overloading happens within the same class, where multiple methods have the
same name but different parameters (number or type).

📌 Real-Life Example:
👉 ATM Machine – You can withdraw money in different ways:

- Withdraw by entering amount


- Withdraw using biometric + amount
- Withdraw using OTP + amount

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");
}

void withdraw(int amount, String otp) {


System.out.println("Withdraw " + amount + " using OTP");
}

void withdraw(int amount, boolean fingerprint) {


System.out.println("Withdraw " + amount + " using biometric");
}
}

✅ 2. Method Overriding (Run-Time Polymorphism)

📘 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

All have a `start()` method:


- Car: starts with a key
- Bike: starts with a kick
- Truck: starts with button

Same method, different behavior.

Java Example:
```java
class Vehicle {
void start() {
System.out.println("Vehicle starts");
}
}

class Car extends Vehicle {


@Override
void start() {
System.out.println("Car starts with key");
}
}

class Bike extends Vehicle {


@Override
void start() {
System.out.println("Bike starts with kick");
}
}
```

👇 Run:
```java
Vehicle v = new Car();
v.start(); // Output: Car starts with key
```

---

🧠 Key Differences (Say this to summarize):

| Feature | Method Overloading | Method Overriding


|
|-----------------------|------------------------------|---------------------------
---|
| Where it occurs | Same class | Parent-child classes
|
| Parameters | Must be different | Must be same
|
| Return Type | Can be same or different | Must be same or covariant
|
| Polymorphism type | Compile-time | Run-time
|
| Use case | Same action, different input | Same action, different
behavior |

---

💬 What to say to the interviewer:

> “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.”

10. Interface and Abstract Class:

> An interface is a blueprint of a class. It contains only abstract methods (until


Java 7), and from Java 8 onwards, it can also contain default and static methods.

- Cannot have constructor


- No method implementation (except default/static)
- Variables are `public static final` by default

📌 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();
}

class TV implements Remote {


public void turnOn() {
System.out.println("TV turned on");
}
public void turnOff() {
System.out.println("TV turned off");
}
}

✅ What is an Abstract Class in Java?

📘 Definition:
> An abstract class is a class that cannot be instantiated, and can have both
abstract methods (no body) and concrete methods (with body).

- Can have constructors


- Can have instance variables
- Can have access modifiers

📌 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;

abstract void withdraw(int amount);

void checkBalance() {
System.out.println("Balance: " + balance);
}
}

class SavingsAccount extends BankAccount {


void withdraw(int amount) {
balance -= amount;
System.out.println("Withdrawn: " + amount);
}
}

🔥 When to use what?

- 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.

💬 What you can say to the interviewer:

> “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.”

11. == and .equals():

== 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().

12. This and Super Keyword:

> `this` refers to the current object of the class.

🔧 Common Uses of `this`:


1. To refer to current class variables when there's a name conflict
2. To call current class methods or constructors
3. To pass current object as a parameter
🧪 Example 1: Resolving variable conflict
```java
class Student {
String name;

Student(String name) {
this.name = name; // refers to the instance variable
}
}
```

Without `this`, it would refer to the constructor parameter, not the instance
variable.

✅ `super` Keyword in Java

📘 Definition:
> `super` refers to the parent (superclass) object.

🔧 Common Uses of `super`:


1. To call the superclass constructor
2. To access superclass methods or variables when overridden

🧪 Example 2: Calling superclass constructor


```java
class Animal {
Animal() {
System.out.println("Animal constructor");
}
}

class Dog extends Animal {


Dog() {
super(); // calls Animal's constructor
System.out.println("Dog constructor");
}
}
```

🧪 Example 3: Calling overridden method from parent class


```java
class Animal {
void sound() {
System.out.println("Animal sound");
}
}

class Dog extends Animal {


void sound() {
super.sound(); // calls Animal's sound()
System.out.println("Dog barks");
}
}

🧠 Real-life Analogy

🧍♂ `this`: Referring to yourself


> Imagine you’re filling out a form and you write “I, Dhanish…” — you're referring
to yourself.

👴 `super`: Referring to your parent


> Imagine you say, “My father’s name is...” — here you’re referring to the parent
(superclass).

💬 What you can say to the interviewer:

> “`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.”

13. pyhton and java , c and java:

🔁 Python vs Java

| Feature | Python | Java


|
|----------------------|------------------------------------|----------------------
------------------|
| Type | Interpreted, dynamically typed | Compiled (to bytecode),
statically typed |
| Syntax | Simple, concise, readable | Verbose, requires strict
structure |
| Speed | Slower (interpreted) | Faster than Python
(JVM-compiled) |
| Indentation | Used for blocks (mandatory) | Uses curly braces `{}`
|
| OOP Support | Supports OOP but flexible | Purely Object-Oriented
|
| Memory Management| Automatic (Garbage Collection) | Automatic (Garbage
Collection via JVM) |
| Use Cases | AI, ML, scripting, automation | Enterprise apps, Android,
Web backend |
| Platform | Cross-platform | Cross-platform
|
| Compilation | Line-by-line interpretation | Compiled into bytecode by
`javac` |
✅ One-liner takeaway:
> “Python is great for rapid development and data tasks, while Java is strong for
enterprise-level, performance-critical apps.”

🔁 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.”

💬 What to say to interviewer:


> “Python is dynamically typed and easier for quick scripting and AI, while Java is
statically typed, better for scalable enterprise apps. Compared to C, Java provides
higher abstraction,
built-in memory management, and OOP features, which makes it safer and more
portable.”

14. Constructor in Java:

📘 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`.

🤔 Why Use a Private Constructor?

1. ✅ To Prevent Object Creation


- Useful when you want to restrict object creation from outside the class.
- Example: In utility classes like `Math`, all methods are static — no need to
create an object.

```java
public class Utility {
private Utility() {
// Prevent instantiation
}

public static int add(int a, int b) {


return a + b;
}
}

2. ✅ Singleton Design Pattern


- Ensures only one instance of the class is created.
- Constructor is private, and object is accessed through a static method.

```java
public class Singleton {
private static Singleton instance;

private Singleton() {
System.out.println("Private constructor called");
}

public static Singleton getInstance() {


if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
```

---

3. ✅ Factory Pattern
- Control how objects are created via a factory method.

🚫 What Happens If You Try to Create Object from Outside?

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.

💬 What to Say in Interview:

> “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.”

15. Access Specifier:

Access specifiers control the visibility of classes, methods, and variables.

📌 Explanation:

🔹 `private`
- Most restricted access.
- Can only be accessed within the same class.
```java
private int age;
```

🔹 Default (no keyword)


- Accessible within the same package.
```java
int rollNumber; // no modifier = default
```

🔹 `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 Modifier | Analogy |


|-----------------|-------------------------------------------|
| `private` | Like your phone PIN – only you can access it |
| Default | Like an office – only coworkers (same package) can enter |
| `protected` | Like a family album – your relatives (subclasses) can see it |
| `public` | Like your social media post – anyone can view it |

💬 Interview Tip – How to Answer:

> “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.”

15. In public static void main, can we use private ?

❌ No, you should NOT make `main()` private


If you do, Java won't be able to run your program.

🔍 Why does `main()` have to be `public`?

> 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)
```

✅ Breakdown of `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
|

💬 What to Say in Interview:

> “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.”

16. Break and Continue:

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.

17. why java uses Objects?

🔑 Because Java is an Object-Oriented Programming (OOP) language.

✅ Here’s Why Java Uses Objects:

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.

3. Reusability via Inheritance


> Objects enable reusable and extensible code using inheritance.

```java
class Animal {
void sound() { System.out.println("Makes sound"); }
}

class Dog extends Animal {


void sound() { System.out.println("Barks"); }
}
```

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
```

5. Better Code Organization & Maintenance


> With objects, code is easier to manage, test, and scale, especially for large
applications.

🧠 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");
}
}

class Dog extends Animal { // Subclass


void bark() {
System.out.println("Dog barks");
}
}
```

✅ Using Superclass Members in Subclass:

```java
class Dog extends Animal {
void makeSound() {
super.sound(); // Calls the superclass method
System.out.println("Dog barks too");
}
}
```

🧠 Real-life Analogy:

| Term | Real Life Example |


|------------|--------------------------|
| Superclass | Vehicle |
| Subclass | Car, Bike, Truck |

All vehicles have common properties (engine, wheels), but cars and bikes may add
their own features.

🧩 Keywords Related:

- `extends`: Used to create a subclass


- `super`: Used to access superclass methods or constructors

💬 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.”

19. Throw and Throws:


⚠ `throw` vs `throws` in Java

| Keyword | Purpose | Used For | Placement


|
|----------|----------------------------------|----------------------|-------------
------|
| `throw` | Actually throws an exception | Throwing exceptions | Inside a method
|
| `throws`| Declares exceptions | Method declaration | In method
signature |

✅ `throw` – Used to manually throw an exception

```java
public void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Not eligible to vote");
}
}
```

- You are explicitly creating and throwing an exception.


- Only one object can be thrown at a time.
- Follows this syntax:
`throw new ExceptionType("message");`

✅ `throws` – Used to declare that a method might throw an exception

```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:

- 🔹 `throw`: You actually throw the ball 🎾.


- 🔹 `throws`: You warn someone that the ball might be thrown 🧤.

🔀 Use Both Together

```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.”

20. Why does array indexing starts from 0 not 1?

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.

21. Memory Management:

🧠 What is Memory Management in Java?

Memory management is the process of allocating, using, and freeing up memory


efficiently during program execution.

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.

🧱 Java Memory Model (Divided by JVM)

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

3. Method Area (MetaSpace in newer versions)


- Stores class definitions, static variables, and constants

4. Program Counter Register


- Keeps track of which instruction is being executed (per thread)

5. Native Method Stack


- For methods written in native languages like C/C++

🧹 Garbage Collection (GC)

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
```

GC automatically frees up that memory.

🔄 Process of Memory Management in Java

1. Object created → stored in heap


2. Method invoked → stack frame created
3. Method ends → stack frame removed
4. Unused objects → collected by Garbage Collector

💬 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++.”

22. Static and Final Keyword:

🔹 `static` Keyword in Java

✅ 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
```

🔹 `final` Keyword in Java

✅ 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 { }

class SportsCar extends Car { } // ❌ Error: can't extend final class


```
🧠 Real-Life Analogy:

| 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?

Java is platform-independent because it compiles source code into bytecode, which


is not tied to any specific operating system. The bytecode is executed by the JVM,
which is platform-dependent. As long as the JVM exists for a platform, the same
Java program can run on it without any changes.

24. Difference between Array, ArrayList, and LinkedList:

📦 1. Array (Core Java, fixed-size)

✅ 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;
```

🧰 2. ArrayList (Dynamic array from `java.util` package)

✅ 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);
```

🔗 3. LinkedList (Doubly Linked List from `java.util`)

✅ 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:

| Feature | Array | ArrayList | LinkedList |


|----------------|-------------|------------------|------------------|
| Size | Fixed | Dynamic | Dynamic |
| Access Time | Fast (O(1)) | Fast (O(1)) | Slow (O(n)) |
| Insert/Delete | Difficult | Medium (shifts) | Easy (O(1) at ends) |
| Memory | Compact | Uses backing array | More (nodes & pointers) |
| Primitives | Yes | No (only objects) | No (only objects) |

🧠 Real-Life Analogy:

- Array → Like a row of lockers 🧳 — fixed number and fixed order.


- ArrayList → Like a stretchy shelf 📚 — expands as you add more.
- LinkedList → Like a treasure hunt map 🗺 — each clue (node) tells you where the
next one is.

💬 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.”

25. Cloneable` interface and copying via constructors :

🔄 1. `Cloneable` Interface in Java

✅ What is it?
`Cloneable` is a marker interface (has no methods) that allows an object to be
cloned using the `Object.clone()` method.

> Without implementing `Cloneable`, calling `clone()` will throw a


`CloneNotSupportedException`.

🔧 Example:
```java
class Student implements Cloneable {
int id;
String name;

Student(int id, String name) {


this.id = id;
this.name = name;
}
public Object clone() throws CloneNotSupportedException {
return super.clone(); // Shallow copy
}
}
```

```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

🏗 2. Copying Objects Using Constructor

✅ 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;

Student(int id, String name) {


this.id = id;
this.name = 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);
```

⚔ `Cloneable` vs Copy Constructor

| Feature | `Cloneable` Interface | Copy Constructor


|
|-------------------------|-------------------------------------|------------------
----------------------|
| Type | Interface (uses `clone()` method) | Custom
constructor |
| Deep/Custom Copy | Requires manual work (default is shallow) | Fully
customizable |
| Flexibility | Less flexible | More flexible
|
| Error-Prone | Yes (needs careful override) | Safer and cleaner
|
| Need to implement | `Cloneable` + override `clone()` | Only constructor
|
| Readability | Less readable | More readable
|

🧠 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.

💡 Where Does Reallocation Happen?

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];

for (int i = 0; i < oldArray.length; i++) {


newArray[i] = oldArray[i];
}

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

⚠ Why is Reallocation Costly?

- Time Complexity: Copying all elements = O(n)


- Memory Usage: New memory allocation + old reference held temporarily

🧠 Real-Life Analogy:

Reallocation is like upgrading your phone storage:

- You fill up 64GB


- Buy a 128GB phone
- Transfer all your data over
- Start using the new one

💬 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.”

27. Call by Value vs Call by Reference:

☕ First: How Java Works?

> ✅ Java is strictly “Call by Value” — even for objects!

But… there’s a twist when it comes to objects — so let’s break it down. 👇

📌 1. Call by Value (Primitives)

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.

📌 2. Call by Value with Objects (NOT Reference)

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
}

Person person = new Person();


person.name = "Original";
modify(person);
System.out.println(person.name); // Output: Dhanish
```

> 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.”

28. Features of Java:

Java is a simple, object-oriented, and platform-independent language. It’s secure,


robust, and supports multithreading and high performance via JIT. Its dynamic and
distributed nature also makes it ideal for modern software development.

29. String Literals:

🔤 What is a String Literal in Java?

A String literal is any sequence of characters enclosed in double quotes.

```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.

🧠 What's the String Pool?

- It's part of the heap memory


- Stores unique string literals
- If you create a string with a literal and that value already exists in the pool,
Java reuses the same object

Example:
```java
String a = "Java";
String b = "Java";

System.out.println(a == b); // true (same reference in pool)


```

Both `a` and `b` point to the same object in the String Pool.

❌ What if You Use `new` Keyword?

```java
String a = new String("Java");
String b = new String("Java");

System.out.println(a == b); // false (different objects)


```

Even though the values are the same, `new` creates a new object in heap every time
— not reused.

✅ When to Use String Literals?

- 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.”

30. Servlets and streams:

🌐 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:

- Runs on a Java-enabled web server (like Apache Tomcat)


- Handles HTTP requests (GET, POST, etc.)
- Returns HTTP responses (like HTML or JSON)

🔁 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

✅ What are Streams?

Streams in Java represent a flow of data — used for input/output (I/O) operations
or for processing collections of data.

Two Categories:

📥 a. I/O Streams (java.io)


- Handle reading/writing data to files, keyboard, network, etc.
- Two types:
- Byte Streams: `InputStream`, `OutputStream`
- Character Streams: `Reader`, `Writer`

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();

📊 b. Stream API (java.util.stream) – Java 8+


- For processing data in a functional style
- Common with `List`, `Set`, etc.

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.”

31. Hash and Lambda Function:


A hash function is a method that takes an input (usually a key) and returns an
integer hash code — used to determine where that key-value pair should be stored in
a hash table (like in `HashMap`).

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

System.out.println("HashCode: " + hash); // e.g., 2044061247


```

The `hashCode()` method returns a unique (but not guaranteed to be collision-free)


integer for the key.

📦 Used In:

- `HashMap`
- `HashSet`
- `Hashtable`

These use:
1. `hashCode()` to calculate the hash
2. `equals()` to resolve collisions

🔁 Hash Function Process in HashMap (Simplified):

```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
```

or when used in the `main` method:

```java
public static void main(String[] args) // Correct
```

### What's wrong with `String[10] args`?


- `String[10] args` looks like C/C++ style array declaration.
- Java expects the type first (`String[]`), not the size inside square brackets.

So, **`String[10] args` will give a compile-time error**.

2. What is heap and a stack ?

### 🧠 **Stack Memory:**


- **Used for:** Storing **method calls**, **local variables**, and **reference
variables**.
- **Structure:** It works on **LIFO** (Last-In-First-Out) principle.
- **Thread-specific:** Each thread in Java has its own stack.
- **Memory management:** Memory is **automatically managed**; space is freed once
the method finishes.
- **Speed:** Very fast due to simple access pattern.

🟢 **Example:**
```java
void show() {
int x = 10; // x is stored in stack
}
```

### 🧠 **Heap Memory:**


- **Used for:** Storing **objects**, **class-level variables**, and **arrays**.
- **Shared:** Common for the **entire application** and **all threads**.
- **Memory management:** Controlled by the **Garbage Collector**.
- **Size:** Larger than stack and more flexible but **slower**.

🟢 **Example:**
```java
Student s = new Student(); // Student object is created in heap
```

You might also like