0% found this document useful (0 votes)
8 views

Java IQ by Pratap Sr

The document explains key Object-Oriented Programming (OOP) concepts in Java, including the differences between abstract classes and interfaces, polymorphism, encapsulation, method hiding, composition, and aggregation. It also covers garbage collection algorithms, memory management, exception handling, and the differences between JDK, JRE, and JVM. Additionally, it discusses exception types, the use of try-catch blocks, and how to create custom exceptions.

Uploaded by

Gaurav Dhakate
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)
8 views

Java IQ by Pratap Sr

The document explains key Object-Oriented Programming (OOP) concepts in Java, including the differences between abstract classes and interfaces, polymorphism, encapsulation, method hiding, composition, and aggregation. It also covers garbage collection algorithms, memory management, exception handling, and the differences between JDK, JRE, and JVM. Additionally, it discusses exception types, the use of try-catch blocks, and how to create custom exceptions.

Uploaded by

Gaurav Dhakate
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

Object-Oriented Programming (OOP) Concepts:

1. Explain the difference between abstract class and interface in Java.

An abstract class is like a blueprint for other classes. It can have both normal (fully defined)
methods and abstract (only declared, not defined) methods. You cannot create an object of
an abstract class directly.

An interface is like a contract. It only has method declarations, and the class that
implements the interface must provide the actual implementation.

• Abstract class can have both abstract and normal methods, while interface only has
abstract methods (till Java 8).
• A class can extend only one abstract class but can implement multiple interfaces.

Example:

abstract class Vehicle {


abstract void start(); // Abstract method (no body)

void stop() { // Normal method


System.out.println("Vehicle stopping...");
}
}
interface Engine {
void start(); // Only method declaration
}

class Car implements Engine {


public void start() {
System.out.println("Car engine starting...");
}
}
2. What is polymorphism in Java? How is it achieved?

Polymorphism means "many forms." It allows one method to behave differently based on
how it is used.

Two Types of Polymorphism:

1. Method Overloading (Compile-time Polymorphism):

o When multiple methods have the same name but different parameters.
Example:

class MathOperations {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
2. Method Overriding (Runtime Polymorphism):
• When a subclass provides a new definition of a method from the parent class.
Example:

class Animal {
void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void makeSound() {
System.out.println("Dog barks");
}
}
3. Explain the concept of encapsulation and how it can be achieved in Java.
Encapsulation means hiding the details of a class and allowing controlled access.
How to Achieve Encapsulation?
1. Declare variables as private.
2. Provide public getter and setter methods to access and update data.
Example:

class Person {
private String name; // Private variable
public String getName() { // Getter method
return name;
}
public void setName(String newName) { // Setter method
name = newName;
}
}
4. What is method hiding in Java?
Method Hiding happens when a static method in a child class has the same name as a static
method in the parent class. Unlike method overriding, here the method is hidden, not
overridden.
Example:
class Parent {
static void show() {
System.out.println("Static method in Parent");
}
}
class Child extends Parent {
static void show() {
System.out.println("Static method in Child");
}
}
public class Main {
public static void main(String[] args) {
Parent obj = new Child();
obj.show(); // Output: Static method in Parent (Method
Hiding)
}
}
5.Explain the concept of composition and aggregation in Java with examples.
Both describe relationships between objects, but they have different levels of dependency.
Composition (Strong Relationship - "Has-A")
• One object owns another, and if the owner is destroyed, the child object is also
destroyed.
• Example: A Car has an Engine. If the car is destroyed, the engine is useless.
class Engine {
void start() {
System.out.println("Engine starting...");
}
}
class Car {
private final Engine engine = new Engine(); //Strong
relationship
void startCar() {
engine.start();
}
}
Aggregation (Weak Relationship - "Has-A")

• One object uses another, but both can exist independently.

• Example: A Student has a College, but even if a student leaves, the college still exists.

class College {
String name;
College(String name) {
this.name = name;
}
}

class Student {
String studentName;
College college;

Student(String studentName, College college) {


this.studentName = studentName;
this.college = college;
}
}
6. What is abstraction? explain with example

Abstraction means hiding unnecessary details and showing only important features.

How to Achieve Abstraction?

• Abstract Classes (Partial abstraction)

• Interfaces (100% abstraction)

Example Using an Abstract Class:

abstract class Animal {


abstract void makeSound(); // Abstract method

void sleep() {
System.out.println("Sleeping...");
}
}
class Dog extends Animal {
void makeSound() {
System.out.println("Dog barks");
}
}
JVM and Performance
1. What Are the Different Garbage Collection Algorithms in Java?

Garbage Collection (GC) in Java automatically removes unused objects to free up memory.
The main GC algorithms are:

1. Serial GC → Best for small applications; uses a single thread for GC.

2. Parallel GC (Throughput Collector) → Uses multiple threads to speed up GC; best for
multi-core machines.

3. CMS (Concurrent Mark-Sweep) GC → Runs alongside the application to reduce


pause times.

4. G1 (Garbage First) GC → Default in Java 9+; divides heap into regions and cleans up
the most garbage-filled regions first.

5. ZGC (Z Garbage Collector) & Shenandoah GC → Low-latency collectors introduced in


later Java versions for large applications.

2. Difference Between Minor GC and Major GC in Java

Minor GC

• Happens in the Young Generation (Eden + Survivor Spaces).

• Quick and frequent.

• Moves surviving objects to the Old Generation.

Major GC (Full GC)

• Happens in the Old Generation.

• Slower and causes longer pauses.

• Can trigger compaction (removes fragmentation).

3. How Does JVM Handle Memory Management?

JVM divides memory into different areas:

1. Method Area → Stores class metadata, static variables, and method code.

2. Heap Memory → Stores objects. Divided into Young Generation (Eden, Survivor
Spaces) and Old Generation.

3. Stack Memory → Stores method execution details, local variables, and function calls.

4. PC Register → Tracks the current execution instruction.

5. Native Method Stack → Handles native (non-Java) method calls.


4. Explain the Concept of Class Loading in Java

Class loading is the process where JVM loads .class files into memory when needed. It
follows these steps:

1. Loading → Reads the .class file and loads it into memory.

2. Linking → Verifies bytecode and prepares memory layout.

3. Initialization → Runs static initializers (static {} blocks) and initializes static variables.

Class Loaders in Java:

• Bootstrap ClassLoader → Loads core Java classes (e.g., java.lang.*).

• Extension ClassLoader → Loads JDK extension classes (ext directory).

• Application (System) ClassLoader → Loads application-level classes (classpath).

Example:

Class.forName("com.example.MyClass"); // Manually loads a class


5. What is a Memory Leak, and How Can It Be Avoided in Java?

A memory leak happens when objects that are no longer needed remain in memory
because references to them still exist.

Common Causes:

• Using static collections (like List or Map) that hold objects indefinitely.

• Not closing resources like File, Socket, or Database Connections.

• Unused listeners (e.g., GUI event listeners).

How to Avoid Memory Leaks?

• Use WeakReference or SoftReference for cache-like objects.

• Close resources in finally block or use try-with-resources (AutoCloseable).

• Use memory profiling tools like VisualVM, JProfiler, or Eclipse MAT to detect leaks.

6. What is the Purpose of the System.gc() Method?

System.gc() requests garbage collection, but it does not guarantee it will run immediately.
JVM decides whether to execute it based on optimization.

Better Approach:

• Instead of using System.gc(), rely on proper memory management and avoid


unnecessary object creation.
7. What Are finalize() and cleanUp() Methods in Garbage Collection?

finalize() Method:

• A method in Object class that JVM calls before an object is garbage collected.

• Used to perform cleanup tasks (closing files, releasing connections).

• Not recommended in modern Java because it’s unpredictable and deprecated in Java
9.

Example:

protected void finalize() throws Throwable {


System.out.println("Object is being garbage collected");
}

cleanUp() Method (Custom Cleanup):

• Instead of finalize(), it's better to create a custom cleanup method and call it
manually.

• Example:

class Resource {
void cleanUp() {
System.out.println("Cleaning up resources...");
}
}
8. Difference Between JDK, JRE, and JVM

1. JDK (Java Development Kit)


o Includes JRE + development tools (compilers, debuggers).
o Required for writing and compiling Java programs.
2. JRE (Java Runtime Environment)
o Includes JVM + libraries to run Java programs.
o Cannot compile code, only executes Java applications.
3. JVM (Java Virtual Machine)
o Runs Java programs by converting bytecode to machine code.
o Handles memory management, security, and execution.
• JDK = JRE + Development Tools

• JRE = JVM + Libraries

• JVM = Runs Java programs


9. What Are the Different Types of Memory in Java? Explain Heap and Stack Memory.

Java memory is mainly divided into Heap and Stack.

Heap Memory

• Stores objects and class instances.

• Divided into Young Generation (Eden, Survivor) and Old Generation.

• Managed by Garbage Collector.

Stack Memory

• Stores method calls, local variables, and references to objects in the heap.

• Uses LIFO (Last-In, First-Out).

• Memory is automatically freed when a method exits.

Example of Heap & Stack Usage:

class Demo {
int x = 10; // Stored in Heap
void show() {
int y = 20; // Stored in Stack
}
}
Exception Handling
1. What is an exception in Java?
What: An exception is an event that occurs during program execution and disrupts
the normal flow of instructions.
Why: It helps in handling runtime errors and prevents abnormal termination of
programs.
Example:
int a = 5, b = 0;
int result = a / b; // This will throw ArithmeticException

2. What is the difference between checked and unchecked exceptions?

What is an Exception?
An exception is an error that happens during program execution and disrupts the
normal flow of the program.
What is a Checked Exception?
Checked exceptions are the ones that Java forces you to handle at compile-time. If
you don’t handle them using try-catch or declare them with throws, your program
won’t compile.
Example of a Checked Exception:
import java.io.*;
public class CheckedExceptionExample {
public static void main(String[] args) {
try {
FileReader file = new FileReader("data.txt"); // File
might not exist
} catch (IOException e) {
System.out.println("File not found: " + e.getMessage());
}
}
}
Why is this checked?
Because Java checks for IOException at compile-time, and you must handle it.
Some common checked exceptions:
• IOException (File not found, input/output issues)
• SQLException (Database-related errors)
• ClassNotFoundException (Class not found in classpath)
What is an Unchecked Exception?
Unchecked exceptions occur at runtime and are caused by logic errors, such as
accessing an invalid array index or dividing by zero. Java does not force you to handle
them, but you should do it for safer code.
Example of an Unchecked Exception:
public class UncheckedExceptionExample {
public static void main(String[] args) {
int[] numbers = new int[5];
System.out.println(numbers[10]); // Accessing an invalid
index
}
}
Why is this unchecked?
Because ArrayIndexOutOfBoundsException occurs only at runtime, and Java does
not check for it at compile-time.
Some common unchecked exceptions:
• NullPointerException (Accessing a null object)
• ArithmeticException (Dividing by zero)
• ArrayIndexOutOfBoundsException (Invalid array index access)
Why Does Java Have Both?
Java uses checked exceptions for errors beyond programmer control (like missing
files) so they must be handled.
Unchecked exceptions usually occur due to programming mistakes and should be
fixed by writing better code.

3. What is the use of the try-catch block in Java?


What: It is used to handle exceptions and prevent program crashes.
Why: It allows the program to continue execution even after an exception occurs.
Example:
try {
int num = 5 / 0; // ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Cannot divide by zero.");
}
4. What is the difference between throw and throws in Java?
What is throw in Java?
The throw keyword is used inside a method to manually throw an exception. You create an
exception object and throw it when a specific condition is met.
Example:
public class ThrowExample {
static void checkAge(int age) {
if (age < 18) {
throw new ArithmeticException("Not eligible to vote.");
}
System.out.println("You are eligible to vote.");
}

public static void main(String[] args) {


checkAge(16); // This will throw an exception
}
}
What happens here?
• If age is less than 18, the program throws an ArithmeticException.
• The program stops execution if not handled in a try-catch block.
What is throws in Java?
The throws keyword is used in a method signature to declare that a method might throw an
exception. It does not handle the exception but tells the caller that it must handle it.
Example:
import java.io.*;

public class ThrowsExample {


static void readFile() throws IOException {
FileReader file = new FileReader("data.txt"); // Might throw
IOException
}

public static void main(String[] args) {


try {
readFile(); // Method call
} catch (IOException e) {
System.out.println("File not found: " + e.getMessage());
}
}
}
What happens here?
• throws IOException in readFile() tells the caller that this method may throw an
exception.
• The main method handles it using a try-catch block.
Key Differences Between throw and throws

a. throw is used inside a method to explicitly throw an exception, while throws is used
in the method declaration to specify possible exceptions.

b. throw is followed by an exception object (throw new Exception();), whereas throws


is followed by exception class names (throws IOException, SQLException).

c. throw is used for triggering exceptions, while throws informs the caller that an
exception might occur and needs handling.

5. What is the finally block used for?


What: The finally block contains code that always executes, whether an exception
occurs or not.
Why: It is commonly used for resource cleanup like closing files, database
connections, etc.
Example:

try {
int num = 5 / 0;
} catch (ArithmeticException e) {
System.out.println("Exception caught.");
} finally {
System.out.println("Finally block executed.");
}
6. Can we have multiple catch blocks in Java? How?
What: Yes, multiple catch blocks can be used to handle different exceptions
separately.
Why: This ensures specific handling for different exceptions.
Example:

try {
int num = Integer.parseInt("abc"); // NumberFormatException
} catch (ArithmeticException e) {
System.out.println("Arithmetic error.");
} catch (NumberFormatException e) {
System.out.println("Number format error.");
} catch (Exception e) {
System.out.println("Some other exception.");
}
7. What is the StackOverflowError in Java?
What: It is an error that occurs when a method calls itself too many times (infinite
recursion).
Why: It happens when the stack memory is exhausted.
Example:

public class StackOverflowExample {

static void recursiveMethod() {


recursiveMethod(); // Infinite recursion
}
public static void main(String[] args) {
recursiveMethod();
}
}

8. How do you create custom exceptions in Java?


What: A custom exception is a user-defined exception class that extends Exception or
RuntimeException.
Why: It helps in creating meaningful error messages for business logic.
Example:
class InvalidAgeException extends Exception {
public InvalidAgeException(String message) {
super(message);
}
}
public class TestCustomException {
static void checkAge(int age) throws InvalidAgeException {
if (age < 18) {
throw new InvalidAgeException("Age must be 18 or
above.");
}
}
public static void main(String[] args) {
try {
checkAge(16);
} catch (InvalidAgeException e) {
System.out.println("Exception: " + e.getMessage());
}
}
}
Collection Framework
1. What is the difference between ArrayList and LinkedList in Java?
What:
• ArrayList is a resizable array implementation, whereas LinkedList is a doubly linked
list.
• ArrayList allows fast random access (O(1) time for get()), while LinkedList is faster for
insertions and deletions (O(1) for adding/removing at the start or middle).
Why:
• Use ArrayList when you need fast retrieval.
• Use LinkedList when you need frequent insertions/deletions.
Example:

List<Integer> arrayList = new ArrayList<>();


List<Integer> linkedList = new LinkedList<>();

2. What is the difference between HashMap and TreeMap?


What:
• HashMap stores key-value pairs unordered, while TreeMap maintains sorted order
(natural ordering).
• HashMap is faster (O(1) operations), while TreeMap is slower (O(log n) operations).
Why:
• Use HashMap for faster lookups.
• Use TreeMap if you need sorted keys.
Example:
Map<Integer, String> hashMap = new HashMap<>();

Map<Integer, String> treeMap = new TreeMap<>();


3. What is the difference between Set and List in Java?
What:
• List allows duplicates and maintains insertion order.
• Set does not allow duplicates and does not guarantee order.
Why:
• Use List when you need ordering and duplicates.
• Use Set when you need unique elements only.
Example:

List<String> list = new ArrayList<>();


Set<String> set = new HashSet<>();
4. What is a HashSet in Java?
What:
• HashSet is a collection that stores unique elements in an unordered way.
Why:
• Use HashSet when you don’t need duplicates and don’t care about order.
Example:
Set<String> names = new HashSet<>();
names.add("Alice");
names.add("Bob");
names.add("Alice"); // Duplicate, will not be added
5. How does a HashMap work internally?
What:
• HashMap uses hashing to store key-value pairs in an array of buckets.
• Each key’s hash code determines its bucket. If multiple keys have the same hash, they
are stored as a linked list (or a balanced tree if too many collisions).
Why:
• Hashing makes operations fast (O(1) on average).
Example:
Map<String, Integer> map = new HashMap<>();
map.put("Alice", 25);
map.put("Bob", 30);
6. What is the difference between HashMap and Hashtable?

What:
• HashMap is not synchronized (not thread-safe).
• Hashtable is synchronized (thread-safe but slower).
Why:
• Use HashMap for better performance in single-threaded applications.
• Use Hashtable if thread safety is required.
Example:
Map<String, String> hashMap = new HashMap<>();
Map<String, String> hashtable = new Hashtable<>();
7. What is the Iterator interface?

What:
• Iterator is an interface used to traverse (loop through) collections one by one.
Why:
• It is safer than using a for loop because it prevents modification issues.
Example:

Iterator<String> iterator = list.iterator();

while (iterator.hasNext()) {
System.out.println(iterator.next());
}
8. What is the difference between fail-fast and fail-safe iterators?
What:
• Fail-fast iterators throw a ConcurrentModificationException if the collection is
modified while iterating (ArrayList).
• Fail-safe iterators allow modifications (CopyOnWriteArrayList).
Why:
• Fail-fast helps detect issues early.
• Fail-safe helps avoid crashes in multi-threaded environments.
Example:

List<String> list = new ArrayList<>();


Iterator<String> iterator = list.iterator();
list.add("New Item"); // Causes ConcurrentModificationException
Threads and Concurrency
1. What is a thread in Java?
• A thread is a lightweight sub-process that allows a program to execute multiple tasks
at the same time (concurrently).
• Java supports multithreading, meaning multiple threads can run independently
within the same program.
Why?
• Threads improve performance by utilizing CPU better.
• They help in parallel execution, like handling user input while downloading a file.
Example:

class MyThread extends Thread {


public void run() {
System.out.println("Thread is running...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // Starts a new thread
}
}
2. How do you create a thread in Java?
You can create a thread in two ways:
1. By extending the Thread class.
2. By implementing the Runnable interface.
Why?
• Extending Thread is simple but prevents multiple inheritance.
• Implementing Runnable is more flexible and preferred in real-world applications.
Example 1: Using Thread class
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running...");
}
}
public class ThreadExample {
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
Example 2: Using Runnable interface

class MyRunnable implements Runnable {


public void run() {
System.out.println("Thread is running...");
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable());
t1.start();
}
}
3. What is the difference between Thread class and Runnable interface?

What:
• Thread class: You create a thread by extending Thread and overriding run().
• Runnable interface: You create a thread by implementing Runnable and passing it to
a Thread object.
Why:
• Runnable is better because Java does not support multiple inheritance.
• If you extend Thread, you cannot extend any other class.
Example (Preferred Approach - Runnable)
class MyTask implements Runnable {
public void run() {
System.out.println("Thread is running...");
}
}
public class RunnableExample {
public static void main(String[] args) {
Thread t = new Thread(new MyTask());
t.start();
}
}
4. What is the purpose of synchronized keyword in Java?

What?

• synchronized is used to prevent multiple threads from accessing a resource at the


same time.

• It ensures thread safety by allowing only one thread to execute a block of code at a
time.
Why?

• Prevents data inconsistency when multiple threads try to modify a shared resource.

Example:

class Counter {
private int count = 0;
public synchronized void increment() { // Only one thread can
access at a time
count++;
}
public int getCount() {
return count;
}
}
public class SyncExample {
public static void main(String[] args) {
Counter counter = new Counter();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 1000; i++) counter.increment();
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 1000; i++) counter.increment();
});
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final Count: " + counter.getCount());
}
}
5. What is thread synchronization in Java?
What?
• Synchronization is the process of controlling access to shared resources.
• It prevents race conditions, where multiple threads try to update a variable at the
same time.
Why?
• Without synchronization, the output can be inconsistent.
Example (Without Synchronization - Incorrect Output)

class SharedResource {
private int count = 0;
public void increment() {
count++;
}
public int getCount() {
return count;
}
}
• If multiple threads call increment(), count may not update correctly.

6. What is deadlock in Java and how do you prevent it?


What?
• Deadlock occurs when two or more threads wait indefinitely for each other’s locked
resources.
Why?
• It can freeze the application, making it unresponsive.
How to Prevent Deadlock?
• Avoid nested locks.
• Use lock ordering (always acquire locks in the same order).
Example (Deadlock Situation)
class Resource {
public synchronized void methodA(Resource other) {
System.out.println("Thread " +
Thread.currentThread().getName() + " is executing methodA");
other.methodB(this);
}

public synchronized void methodB(Resource other) {


System.out.println("Thread " +
Thread.currentThread().getName() + " is executing methodB");
}
}
7. What is a volatile variable in Java?
What?
• Volatile ensures that a variable’s value is always read from main memory,
preventing caching issues in multi-threaded applications.
Why?
• Ensures visibility of variable updates across threads.
Example:
class SharedData {
volatile int counter = 0;
}

8. What is the difference between wait() and sleep() in Java?


What?
• wait() pauses a thread and releases the lock, allowing other threads to run.
• sleep() pauses a thread but keeps the lock, blocking other threads.
Why?
• wait() is used in thread communication.
• sleep() is used to pause execution temporarily.
Example:
synchronized void process() {
try {
wait(); // Releases lock
Thread.sleep(1000); // Holds lock
} catch (InterruptedException e) {
e.printStackTrace();
}
}
9. What is the ExecutorService in Java?
What?
• ExecutorService is a framework for managing multiple threads efficiently.
• It creates and manages thread pools, reducing overhead.
Why?
• Manages thread execution efficiently.
• Prevents excessive thread creation, improving performance.
Example:
import java.util.concurrent.*;
public class ExecutorExample {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i < 5; i++) {
executor.execute(() -> System.out.println("Thread
running: " + Thread.currentThread().getName()));
}
executor.shutdown();
}
}
Java I/O (Input/Output)
1. What is the difference between FileInputStream and FileReader in Java?
What?
• FileInputStream is used to read binary data (like images, audio, and videos).
• FileReader is used to read text files (character data).
Why?
• Use FileInputStream for binary files (e.g., PDFs, images).
• Use FileReader for character files (e.g., .txt, .csv).
Example:
import java.io.*;

public class FileExample {


public static void main(String[] args) throws Exception {
// Reading bytes using FileInputStream
FileInputStream fis = new FileInputStream("file.txt");
int i;
while ((i = fis.read()) != -1) {
System.out.print((char) i); // Reads byte-by-byte
}
fis.close();

// Reading characters using FileReader


FileReader fr = new FileReader("file.txt");
while ((i = fr.read()) != -1) {
System.out.print((char) i); // Reads character-by-
character
}
fr.close();
}
}
2. What is serialization in Java?
What?
• Serialization is the process of converting an object into a byte stream.
• The object can be saved to a file or sent over a network.
Why?
• Used for storing objects (e.g., saving user data).
• Helps in sending objects over a network (e.g., in distributed systems).
Example:
import java.io.*;

class Student implements Serializable { // Must implement


Serializable
int id;
String name;

Student(int id, String name) {


this.id = id;
this.name = name;
}
}

public class SerializationExample {


public static void main(String[] args) throws Exception {
Student s1 = new Student(1, "John");

// Serialization (Saving object to file)


FileOutputStream fos = new FileOutputStream("student.ser");
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close();
System.out.println("Object Serialized!");
}
}
3. What is the ObjectInputStream and ObjectOutputStream used for?
What?
• ObjectOutputStream is used to write an object to a file (serialization).
• ObjectInputStream is used to read an object from a file (deserialization).
Why?
• Helps in saving and restoring objects in Java.
• Used in networking and database operations.

Example (Deserialization):
import java.io.*;

public class DeserializationExample {


public static void main(String[] args) throws Exception {
// Deserialization (Reading object from file)
FileInputStream fis = new FileInputStream("student.ser");
ObjectInputStream ois = new ObjectInputStream(fis);
Student s2 = (Student) ois.readObject();
ois.close();
fis.close();
System.out.println("Student ID: " + s2.id + ", Name: " +
s2.name);
}
}

4. What is the difference between BufferedReader and Scanner in Java?


What?
• BufferedReader is used for fast reading of large text files.
• Scanner is used for reading user input from the console or small files.
Why?
• BufferedReader is faster for reading files.
• Scanner provides more functionality, like reading integers, doubles, and strings
easily.
Example using BufferedReader (Fast file reading)
import java.io.*;
public class BufferedReaderExample {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new
FileReader("file.txt"));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
br.close();
}
}
Example using Scanner (Reading user input)
import java.util.Scanner;

public class ScannerExample {


public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Enter your name: ");
String name = sc.nextLine();
System.out.println("Hello, " + name);
sc.close();
}
}

5. What is the role of PrintWriter in Java I/O?


What?
• PrintWriter is used to write formatted text to files or the console.
Why?
• It provides easy printing methods (print(), println()).
• Used when you need formatted output like in reports or logs.
Example:
import java.io.*;
public class PrintWriterExample {
public static void main(String[] args) throws Exception {
PrintWriter pw = new PrintWriter("output.txt");
pw.println("Hello, this is a test file.");
pw.println(100); // Can write numbers directly
pw.close();
System.out.println("Data written to file!");
}
}
Java 8 Features and Advanced Topics
1. What are lambda expressions in Java?
What?
• Lambda expressions provide a shorter way to write anonymous functions.
• They allow functional-style programming in Java.
• Introduced in Java 8 to make code more readable and concise.
Why?
• Reduces boilerplate code (no need to create extra classes).
• Makes it easier to write and use functional interfaces.
• Used in Streams, Collections, and Functional Programming.
Example:
Without Lambda:
interface MyInterface {
void sayHello();
}
public class LambdaExample {
public static void main(String[] args) {
MyInterface obj = new MyInterface() {
public void sayHello() {
System.out.println("Hello, World!");
}
};
obj.sayHello();
}
}
With Lambda Expression:
public class LambdaExample {
public static void main(String[] args) {
MyInterface obj = () -> System.out.println("Hello, World!");
obj.sayHello();
}
}
2. What is the Stream API in Java 8?
What?
• Stream API is used to process collections (like Lists, Sets, and Maps) efficiently.
• It provides functional operations such as map(), filter(), reduce(), and forEach().
Why?
• Reduces the need for loops and conditions.
• Improves readability and performance.
• Supports parallel processing for better speed.
Example:
Without Streams:
List<String> names = Arrays.asList("John", "Jane", "Jack");
for (String name : names) {
if (name.startsWith("J")) {
System.out.println(name);
}
}
With Streams:
List<String> names = Arrays.asList("John", "Jane", "Jack");
names.stream()
.filter(name -> name.startsWith("J"))
.forEach(System.out::println);

3. What is the difference between map() and flatMap() in Java 8 streams?


What?
• map() is used to transform data in a Stream.
• flatMap() is used to flatten nested structures.
Why?
• Use map() when you want one-to-one mapping.
• Use flatMap() when working with nested collections.

Example:
Using map():
List<String> names = Arrays.asList("John", "Jane");

List<Integer> lengths = names.stream()


.map(String::length)
.collect(Collectors.toList());

System.out.println(lengths); // Output: [4, 4]


Using flatMap():
List<List<String>> nestedList = Arrays.asList(
Arrays.asList("a", "b"),
Arrays.asList("c", "d")
);

List<String> flatList = nestedList.stream()


.flatMap(List::stream)
.collect(Collectors.toList());

System.out.println(flatList); // Output: [a, b, c, d]

• flatMap() is useful when dealing with nested lists!

4. What is the Optional class in Java?


What?
• Optional is a wrapper class to handle null values safely.
• Helps to avoid NullPointerException (NPE).
Why?
• Prevents crashes due to null references.
• Provides methods like isPresent(), orElse(), and ifPresent().
Example:
Without Optional (Risk of NullPointerException):
String name = null;

System.out.println(name.length()); // Throws NullPointerException


With Optional:
Optional<String> name = Optional.ofNullable(null);
System.out.println(name.orElse("Default Name")); // Output: Default
Name

5. What are default methods in Java interfaces?


What?
• Default methods allow you to add new methods to an interface without breaking
existing code.
Why?
• Helps in interface evolution (e.g., updating old interfaces without modifying all
implementations).
• Reduces code duplication.
Example:
interface Vehicle {
default void start() {
System.out.println("Vehicle is starting...");
}
}

class Car implements Vehicle {}

public class DefaultMethodExample {


public static void main(String[] args) {
Car myCar = new Car();
myCar.start(); // Output: Vehicle is starting...
}
}

6. What is method reference in Java 8?


What?
• Method reference is a shortcut for calling methods using :: instead of lambda
expressions.
Why?
• Makes code more readable.
• Avoids unnecessary lambda expressions.
Example:
Using Lambda Expression:
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.forEach(name -> System.out.println(name));

Using Method Reference:


names.forEach(System.out::println);
7. What is the difference between parallelStream() and stream() in Java?
What?
• stream() processes elements sequentially (one by one).
• parallelStream() processes elements in parallel (faster for large datasets).
Why?
• Use stream() when order matters.
• Use parallelStream() when performance is critical (e.g., processing large lists).
Example:
Using stream() (Sequential Processing):
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream()
.forEach(name ->
System.out.println(Thread.currentThread().getName() + " - " +
name));

Using parallelStream() (Parallel Processing):


names.parallelStream()
.forEach(name ->
System.out.println(Thread.currentThread().getName() + " - " +
name));
Miscellaneous

1. What is the difference between String, StringBuilder, and StringBuffer in Java?


What?
• String is immutable (cannot be changed once created).
• StringBuilder is mutable (can be changed) and not thread-safe.
• StringBuffer is mutable and thread-safe (synchronized).
Why?
• Use String when the value does not change.
• Use StringBuilder for better performance (single-threaded).
• Use StringBuffer when multiple threads need to modify the same string.
Example:
public class StringExample {
public static void main(String[] args) {
// String (Immutable)
String s1 = "Hello";
s1.concat(" World");
System.out.println(s1); // Output: Hello (Unchanged)

// StringBuilder (Mutable)
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World");
System.out.println(sb); // Output: Hello World

// StringBuffer (Thread-Safe)
StringBuffer sbf = new StringBuffer("Hello");
sbf.append(" World");
System.out.println(sbf); // Output: Hello World
}
}
2. What is a singleton class in Java? How do you implement it?
What?
• A singleton class ensures only one instance exists.
Why?
• Used for logging, database connections, thread pools.
• Saves memory and prevents multiple instances.
Example (Lazy Initialization Singleton):
class Singleton {
private static Singleton instance;

private Singleton() {} // Private constructor

public static Singleton getInstance() {


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

public class SingletonExample {


public static void main(String[] args) {
Singleton obj1 = Singleton.getInstance();
Singleton obj2 = Singleton.getInstance();
System.out.println(obj1 == obj2); // Output: true (Same
instance)
}
}
3. What is reflection in Java?
What?
• Reflection allows inspecting and modifying classes, methods, and fields at runtime.
Why?
• Used in frameworks, dependency injection (Spring), and serialization.
• Helps in accessing private fields and methods.
Example:
import java.lang.reflect.*;

class Test {
private String message = "Hello, Reflection!";

private void display() {


System.out.println(message);
}
}

public class ReflectionExample {


public static void main(String[] args) throws Exception {
Test obj = new Test();
Field field = Test.class.getDeclaredField("message");
field.setAccessible(true);
field.set(obj, "Changed using Reflection!");

Method method = Test.class.getDeclaredMethod("display");


method.setAccessible(true);
method.invoke(obj); // Output: Changed using Reflection!
}
}
4. What is the use of instanceof operator in Java?
• instanceof checks if an object is an instance of a class or subclass.
• Used in type checking before casting.
• Prevents ClassCastException errors.
Example:
class Animal {}
class Dog extends Animal {}
public class InstanceofExample {
public static void main(String[] args) {
Animal obj = new Dog();
System.out.println(obj instanceof Dog); // Output: true
System.out.println(obj instanceof Animal); // Output: true
}
}
5. What is the clone() method in Java?
• clone() creates a copy of an object.
• Defined in Object class and used by implementing Cloneable interface.
• Used for creating duplicates of objects.
• Helps in prototype design pattern.
Example:
class Student implements Cloneable {
int id;
String name;
Student(int id, String name) {
this.id = id;
this.name = name;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
public class CloneExample {
public static void main(String[] args) throws
CloneNotSupportedException {
Student s1 = new Student(1, "John");
Student s2 = (Student) s1.clone();

System.out.println(s1.id + " " + s1.name); // Output: 1 John


System.out.println(s2.id + " " + s2.name); // Output: 1 John
}
}
6. How do you create an immutable class in Java?
What?
• An immutable class does not allow modifications after creation.
Why?
• Used in multi-threading (Thread safety).
• Example: String class is immutable.
Example
final class Immutable {
private final String name;
public Immutable(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
public class ImmutableExample {
public static void main(String[] args) {
Immutable obj = new Immutable("Hello");
System.out.println(obj.getName()); // Output: Hello
}
}
7. What is the difference between System.out.println() and System.err.println()?
What?
• System.out.println() prints normal output.
• System.err.println() prints error messages.
Why?
• Used to differentiate logs and errors in the console.
Example:

public class SystemOutErrExample {

public static void main(String[] args) {


System.out.println("This is normal output");
System.err.println("This is an error message");
}
}
8. What is the java.lang.Math class used for?

What?
• The Math class provides mathematical functions like sqrt(), pow(), random(), etc.
Why?
• Used for calculations in scientific, financial, and gaming applications.
Example:
public class MathExample {
public static void main(String[] args) {
System.out.println(Math.sqrt(16)); // Output: 4.0
System.out.println(Math.pow(2, 3)); // Output: 8.0
System.out.println(Math.random()); // Output: Random value
between 0.0 and 1.0
}
}
9. What are the different types of inner classes in Java?
What?
• Member Inner Class - Defined inside another class.
• Static Nested Class - Uses static keyword, behaves like a normal class.
• Local Inner Class - Inside a method, limited scope.
• Anonymous Inner Class - No name, used for short-lived tasks.
Why?
• Used to group related classes for better readability and organization.
Example (Member Inner Class):
class Outer {
class Inner {
void display() {
System.out.println("Inside Inner Class");
}
}
}
public class InnerClassExample {
public static void main(String[] args) {
Outer.Inner obj = new Outer().new Inner();
obj.display(); // Output: Inside Inner Class
}
}

You might also like