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

java_oops

The document discusses multithreading in Java, explaining how threads can be created by extending the Thread class or implementing the Runnable interface. It also covers thread safety, methods to achieve it, and the importance of synchronization to prevent data inconsistency. Additionally, it explains string interning, the string constant pool, and compares String, StringBuilder, and StringBuffer in terms of mutability and thread safety.

Uploaded by

rastogi.mukta07
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

java_oops

The document discusses multithreading in Java, explaining how threads can be created by extending the Thread class or implementing the Runnable interface. It also covers thread safety, methods to achieve it, and the importance of synchronization to prevent data inconsistency. Additionally, it explains string interning, the string constant pool, and compares String, StringBuilder, and StringBuffer in terms of mutability and thread safety.

Uploaded by

rastogi.mukta07
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Q1.

What is multi threading in java


Multithreading is a Java feature that allows concurrent execution of two or
more parts of a program for maximum utilization of CPU. Each part of such
program is called a thread. So, threads are light-weight processes within a
process.
Threads can be created by using two mechanisms :
1. Extending the Thread class
2. Implementing the Runnable Interface
Thread creation by extending the Thread class
We create a class that extends the java.lang.Thread class. This class
overrides the run() method available in the Thread class. A thread begins its
life inside run() method. We create an object of our new class and call start()
method to start the execution of a thread. Start() invokes the run() method on
the Thread object.

// Java code for thread creation by extending


// the Thread class
class MultithreadingDemo extends Thread {
public void run()
{
try {
// Displaying the thread that is running
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
}
}
}
// Main Class
public class Multithread {
public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i = 0; i < n; i++) {
MultithreadingDemo object
= new MultithreadingDemo();
object.start();
}
}
}

Thread creation by implementing the Runnable Interface


We create a new class which implements java.lang.Runnable interface and
override run() method. Then we instantiate a Thread object and call start()
method on this object.

// Java code for thread creation by implementing


// the Runnable Interface
class MultithreadingDemo implements Runnable {
public void run()
{
try {
// Displaying the thread that is running
System.out.println(
"Thread " + Thread.currentThread().getId()
+ " is running");
}
catch (Exception e) {
// Throwing an exception
System.out.println("Exception is caught");
}
}
}
// Main Class
class Multithread {
public static void main(String[] args)
{
int n = 8; // Number of threads
for (int i = 0; i < n; i++) {
Thread object
= new Thread(new MultithreadingDemo());
object.start();
}
}
}

Thread Class vs Runnable Interface


1. If we extend the Thread class, our class cannot extend any other
class because Java doesn’t support multiple inheritance. But, if we
implement the Runnable interface, our class can still extend other
base classes.
2. We can achieve basic functionality of a thread by extending Thread
class because it provides some inbuilt methods like yield(),
interrupt() etc. that are not available in Runnable interface.
3. Using runnable will give you an object that can be shared amongst
multiple threads.

Q2. Thread Safety and how to achieve it in Java

As we know Java has a feature, Multithreading, which is a process of


running multiple threads simultaneously. When multiple threads are
working on the same data, and the value of our data is changing, that
scenario is not thread-safe and we will get inconsistent results. When a
thread is already working on an object and preventing another thread on
working on the same object, this process is called Thread-Safety.
There are four ways to achieve Thread Safety in Java. These are:
1. Using Synchronization.
2. Using Volatile Keyword.
3. Using Atomic Variable.
4. Using Final Keyword.

Using Synchronization
Synchronization is the process of allowing only one thread at a time to
complete the particular task. It means when multiple threads executing
simultaneously, and want to access the same resource at the same time,
then the problem of inconsistency will occur. so synchronization is used to
resolve inconsistency problem by allowing only one thread at a time.
Synchronization uses a synchronized keyword. Synchronized is the modifier
that creates a block of code known as a critical section.

class A {

synchronized void sum(int n)

// Creating a thread instance

Thread t = Thread.currentThread();

for (int i = 1; i <= 5; i++) {

System.out.println(

t.getName() + " : " + (n + i));

}
// Class B extending thread class

class B extends Thread {

// Creating an object of class A

A a = new A();

public void run()

// Calling sum() method

a.sum(10);

class Test {

public static void main(String[] args)

// Creating an object of class B

B b = new B();

// Initializing instance t1 of Thread

// class with object of class B

Thread t1 = new Thread(b);

// Initializing instance t2 of Thread

// class with object of class B

Thread t2 = new Thread(b);

// Initializing thread t1 with name

//'Thread A'
t1.setName("Thread A");

// Initializing thread t2 with name

//'Thread B'

t2.setName("Thread B");

// Starting thread instance t1 and t2

t1.start();

t2.start();

Introduction of Process Synchronization


Last Updated : 04 Oct, 2023

••
Process Synchronization is the coordination of execution of multiple processes in
a multi-process system to ensure that they access shared resources in a controlled
and predictable manner. It aims to resolve the problem of race conditions and
other synchronization issues in a concurrent system.
The main objective of process synchronization is to ensure that multiple processes
access shared resources without interfering with each other and to prevent the
possibility of inconsistent data due to concurrent access. To achieve this, various
synchronization techniques such as semaphores, monitors, and critical sections
are used.

Race Condition
When more than one process is executing the same code or accessing the
same memory or any shared variable in that condition there is a possibility
that the output or the value of the shared variable is wrong so for that all the
processes doing the race to say that my output is correct this condition known
as a race condition.
Critical Section Problem
A critical section is a code segment that can be accessed by only one process
at a time. The critical section contains shared variables that need to be
synchronized to maintain the consistency of data variables. So the critical
section problem means designing a way for cooperative processes to access
shared resources without creating data inconsistencies

Any solution to the critical section problem must satisfy three requirements:
• Mutual Exclusion: If a process is executing in its critical section,
then no other process is allowed to execute in the critical section.
• Progress: If no process is executing in the critical section and other
processes are waiting outside the critical section, then only those
processes that are not executing in their remainder section can
participate in deciding which will enter the critical section next, and
the selection can not be postponed indefinitely.
• Bounded Waiting: A bound must exist on the number of times that
other processes are allowed to enter their critical sections after a
process has made a request to enter its critical section and before
that request is granted.

Peterson’s Solution
Peterson’s Solution is a classical software-based solution to the critical
section problem. In Peterson’s solution, we have two shared variables:
• boolean flag[i]: Initialized to FALSE, initially no one is interested in
entering the critical section
• int turn: The process whose turn is to enter the critical section.
Peterson’s Solution preserves all three conditions:
• Mutual Exclusion is assured as only one process can access the
critical section at any time.
• Progress is also assured, as a process outside the critical section
does not block other processes from entering the critical section.
• Bounded Waiting is preserved as every process gets a fair chance.

Disadvantages of Peterson’s Solution


• It involves busy waiting. (In the Peterson’s solution, the code
statement- “while(flag[j] && turn == j);” is responsible for this.
Busy waiting is not favored because it wastes CPU cycles that
could be used to perform other tasks.)
• It is limited to 2 processes.
• Peterson’s solution cannot be used in modern CPU architectures
Semaphores
A semaphore is a signaling mechanism and a thread that is waiting on a
semaphore can be signaled by another thread. This is different than a mutex
as the mutex can be signaled only by the thread that is called the wait
function.
A semaphore uses two atomic operations, wait and signal for process
synchronization.
A Semaphore is an integer variable, which can be accessed only through two
operations wait() and signal().
There are two types of semaphores: Binary Semaphores and Counting
Semaphores.
• Binary Semaphores: They can only be either 0 or 1. They are also
known as mutex locks, as the locks can provide mutual exclusion.
All the processes can share the same mutex semaphore that is
initialized to 1. Then, a process has to wait until the lock becomes
0. Then, the process can make the mutex semaphore 1 and start its
critical section. When it completes its critical section, it can reset
the value of the mutex semaphore to 0 and some other process can
enter its critical section.
• Counting Semaphores: They can have any value and are not restricted
to a certain domain. They can be used to control access to a
resource that has a limitation on the number of simultaneous
accesses. The semaphore can be initialized to the number of
instances of the resource. Whenever a process wants to use that
resource, it checks if the number of remaining instances is more
than zero, i.e., the process has an instance available. Then, the
process can enter its critical section thereby decreasing the value of
the counting semaphore by 1. After the process is over with the
use of the instance of the resource, it can leave the critical section
thereby adding 1 to the number of available instances of the
resource.
Advantages of Process Synchronization
• Ensures data consistency and integrity
• Avoids race conditions
• Prevents inconsistent data due to concurrent access
• Supports efficient and effective use of shared resources

Using Volatile keyword


A volatile keyword is a field modifier that ensures that the object can be
used by multiple threads at the same time without having any problem.
volatile is one good way of ensuring that the Java program is thread-safe. a
volatile keyword can be used as an alternative way of achieving Thread
Safety in Java.

Using Atomic Variable


Using an atomic variable is another way to achieve thread-safety in java.
When variables are shared by multiple threads, the atomic variable ensures
that threads don’t crash into each other.

Using Final keyword


Final Variables are also thread-safe in java because once assigned some
reference of an object It cannot point to reference of another object.

Q What Is interning in Java ?


Interning of String in Java
Last Updated : 09 May, 2024

••
String Interning is a method of storing only one copy of each distinct String
Value, which must be immutable. Applying String.intern() on a couple of strings
will ensure that all strings having the same contents share the same memory.

This can be very useful to reduce the memory requirements of your


program. But be aware that the cache is maintained by JVM in a permanent
memory pool which is usually limited in size compared to the heap so you
should not use intern if you don’t have too many duplicate values
intern() Method
In Java, when we perform any operation using the intern() method, it returns
a canonical representation for the string object. A pool is managed by a
String class.
• When the intern() method is executed, it checks whether the String
equals to this String Object is in the pool.
• If it is available, then the string from the pool is returned.
Otherwise, this String object is added to the pool and a reference
to this String object is returned.
• It follows that for any two strings s and t, s.intern() == t.intern() is
true if and only if s.equals(t) is true.
It is advised to use equals(), not ==, to compare two strings. This is because
the == operator compares memory locations, while the equals() method
compares the content stored in two objects.

Explanation of the above method


Whenever we create a String Object, two objects will be created i.e. One in
the Heap Area and One in the String constant pool and the String object
reference always points to the heap area object. When line-1 executes, it
will create two objects and point to the heap area created object. Now
when line-2 executes, it will refer to the object which is in the SCP. Again
when line-3 executes, it refers to the same object which is in the SCP area
because the content is already available in the SCP area. No need to create
a new object.
Q How many Objects are created between String literal and
new String Object [duplicate]

Ans : When you create a String using a String Literal, the object is created on the heap and
the reference to that object is stored in the String Constant Pool. Hereafter, any references
to that String literal will not create new object but the reference from the String Constant
Pool is returned. When you create a String object using a new keyword, the object is
created on heap but no references are stored in the String Constant Pool.
In your case: 4 objects shall be created on the heap but only the references of the first three
objects will be stored in the String Constant Pool. The object created using
the new keyword will not have its reference stored in the String Constant Pool

Here's a concise explanation:

• String Literals:

• Example: String s1 = "Hello";


• Objects Created: One object, if the literal is not already in the string pool. Otherwise, no
new object is created.

• New Operator:

• Example: String s2 = new String("Hello");


• Objects Created: Two objects. One in the string pool (if "Hello" is not already there)
and one in the heap due to the new keyword.

Q3. How string constant pool works?

The String Constant Pool works as follows:

1. String Literals: When a string literal is created, Java checks the string pool.
2. Reusability: If the literal already exists in the pool, a reference to the existing string is
returned.
3. New Entry: If it doesn't exist, the string is added to the pool, and a reference to it is
returned.
4. Efficiency: This mechanism conserves memory by avoiding the creation of duplicate
string objects.

Q 4. Difference between equals and == operator?

• == Operator:

• Purpose: Compares references.


• Usage: Checks if two reference variables point to the same object in memory.
• Example:

java
Copy code
String s1 = new String("Hello");
String s2 = new String("Hello");
boolean result = (s1 == s2); // false

• equals Method:

• Purpose: Compares values/content.


• Usage: Checks if two objects have the same value.
• Example:

java
Copy code
String s1 = new String("Hello");
String s2 = new String("Hello");
boolean result = s1.equals(s2); // true
A string is a sequence of characters. In Java, objects of String are immutable
which means a constant and cannot be changed once created. Initializing a
String is one of the important pillars required as a pre-requisite with deeper
understanding.
Comparison between String, StringBuilder, and StringBuffer

Feature String StringBuilder StringBuffer

Introduced in JDK Introduced in JDK Introduced in JDK


Introduction 1.0 1.5 1.0

Mutability Immutable Mutable Mutable

Thread
Thread Safe Not Thread Safe Thread Safe
Safety

Memory
High Efficient Less Efficient
Efficiency

High(No- High(No- Low(Due to


Performance Synchronization) Synchronization) Synchronization)

This is used when This is used when This is used when


we want Thread safety is Thread safety is
Usage immutability. not required. required.

Now, we will be justifying. Let us do consider the below code with three
concatenation functions with three different types of parameters, String,
StringBuffer, and StringBuilder. Let us clear out the understanding between
them via a single Java program below from which we will be drawing out
conclusions from the output generated, to figure out differences between
String vs StringBuilder vs StringBuffer in Java.
Example
Java
// Java program to demonstrate difference between
// String, StringBuilder and StringBuffer
// Main class
class GFG {

// Method 1
// Concatenates to String
public static void concat1(String s1)
{
s1 = s1 + "forgeeks";
}

// Method 2
// Concatenates to StringBuilder
public static void concat2(StringBuilder s2)
{
s2.append("forgeeks");
}

// Method 3
// Concatenates to StringBuffer
public static void concat3(StringBuffer s3)
{
s3.append("forgeeks");
}

// Method 4
// Main driver method
public static void main(String[] args)
{
// Custom input string
// String 1
String s1 = "Geeks";

// Calling above defined method


concat1(s1);

// s1 is not changed
System.out.println("String: " + s1);

// String 1
StringBuilder s2 = new StringBuilder("Geeks");

// Calling above defined method


concat2(s2);

// s2 is changed
System.out.println("StringBuilder: " + s2);
// String 3
StringBuffer s3 = new StringBuffer("Geeks");

// Calling above defined method


concat3(s3);

// s3 is changed
System.out.println("StringBuffer: " + s3);
}
}

Output
String: Geeks
StringBuilder: Geeksforgeeks
StringBuffer: Geeksforgeeks

Output explanation:

Object:

1. Why is wrapper class required


1. • Object Representation: Primitive types (int, char, etc.) cannot be used where
objects are required, such as in collections (ArrayList, HashMap).
2. • Utility Methods: Wrapper classes provide useful methods for converting,
comparing, and manipulating primitive values.
3. • Autoboxing and Unboxing: Java automatically converts between primitives
and their corresponding wrapper classes (autoboxing) and vice versa (unboxing)
to simplify coding.
4. • Null Handling: Wrapper classes can be null, allowing the representation of the
absence of a value, which is not possible with primitive types.

1. Methods of Object class?

The Object class in Java is the root class of the Java class hierarchy. Every class in Java is a
subclass of Object, either directly or indirectly. It provides basic methods that all Java objects
inherit and can use.

Key Points:
• Root Class: All classes in Java inherit from Object.
• Fundamental Methods: Provides essential methods like equals(), hashCode(),
toString(), clone(), finalize(), getClass(), wait(), notify(), and notifyAll().
• Inheritance: Allows Java to treat any class as an Object type, enabling polymorphism
and providing a common interface for all objects.

The Object class in Java provides several methods that are fundamental to all Java objects. Here
are the key methods:

1. equals(Object obj)
o Checks if two objects are equal.
2. hashCode()
o Returns a hash code value for the object.
3. toString()
o Returns a string representation of the object.
4. clone()
o Creates and returns a copy of the object.
5. finalize()
o Called by the garbage collector before the object is destroyed.
6. getClass()
o Returns the runtime class of the object.
7. wait()
o Causes the current thread to wait until another thread invokes notify() or
notifyAll() on the same object.
8. notify()
o Wakes up a single thread that is waiting on the object's monitor.
9. notifyAll()
o Wakes up all threads that are waiting on the object's monitor.

Does java gives importance to primitive data types?

Yes, Java gives importance to primitive data types for several reasons:

1. Performance: Primitive data types are more efficient in terms of memory and processing
speed compared to their wrapper class counterparts.
2. Simplicity: They provide a straightforward way to represent basic values (e.g., int,
char, double), making them easy to use and understand.
3. Low-Level Operations: They are essential for low-level operations, such as arithmetic
calculations and bitwise operations.

However, Java also provides wrapper classes to allow primitives to be used in contexts that
require objects, ensuring flexibility and compatibility with Java's object-oriented features.
Q Is Java pass by value or pass by reference?

Java is strictly pass-by-value. Here’s how it works:

1. Primitive Data Types: When a primitive type is passed to a method, the actual value is
passed. Changes to the parameter inside the method do not affect the original variable.
o Example:

java
Copy code
void changeValue(int x) {
x = 10;
}

int a = 5;
changeValue(a);
// a remains 5

2. Object References: When an object reference is passed to a method, the reference


(address) is passed by value. The method can modify the object the reference points to,
but it cannot change the reference itself to point to a new object.
o Example:

java
Copy code
void modifyObject(MyObject obj) {
obj.value = 10; // This changes the object's value
}

MyObject myObj = new MyObject();


modifyObject(myObj);
// myObj.value is now 10

In summary, Java always passes arguments by value, meaning it passes a copy of the actual
value (for primitives) or a copy of the reference (for objects).

1. Q Types of oops

The four main types of Object-Oriented Programming (OOP) concepts are:

1. Encapsulation:
o Definition: Bundling the data (variables) and methods (functions) that operate on
the data into a single unit or class.
o Purpose: Restricts direct access to some of an object's components, which can
protect the integrity of the data.
o Example: Using private fields and public getter and setter methods.
2. Inheritance:
o Definition: Mechanism where one class (child/subclass) inherits the properties
and behavior of another class (parent/superclass).
o Purpose: Promotes code reusability and establishes a natural hierarchy.
o Example: class Dog extends Animal {}
3. Polymorphism:
o Definition: Ability of a single function or method to work in different ways based
on the object it is acting upon.
o Purpose: Enhances flexibility and integration of code.
o Types:
▪ Compile-Time (Method Overloading): Multiple methods with the same
name but different parameters.
▪ Run-Time (Method Overriding): Subclass provides a specific
implementation of a method already defined in its superclass.
o Example: animal.sound() can be different for Dog and Cat.
4. Abstraction:
o Definition: Hiding complex implementation details and showing only the
necessary features of an object.
o Purpose: Reduces complexity and increases efficiency by exposing only relevant
parts.
o Example: Using abstract classes and interfaces.

java
Copy code
abstract class Animal {
abstract void makeSound();
}

class Dog extends Animal {


void makeSound() {
System.out.println("Woof");
}
}

These concepts form the foundation of OOP and help in designing and building robust, reusable,
and maintainable software

Composition vs Aggregation vs Association?


• Association is a general connection between classes.
• Aggregation is a "whole-part" relationship where the part can exist independently.

• Composition is a "whole-part" relationship where the part cannot exist independently.


Composition vs Aggregation vs Association?

1. Association:
o Definition: A general relationship between two classes where one class uses or
interacts with another.
o Types: Can be one-to-one, one-to-many, many-to-one, or many-to-many.
o Example: A teacher and a student. The teacher teaches students, and students
attend classes taught by teachers.
o Code Example:

java
Copy code
class Teacher {
private String name;
// constructor, getters, and setters
}

class Student {
private String name;
// constructor, getters, and setters
}

2. Aggregation:
o Definition: A special type of association representing a "whole-part" relationship
where the part can exist independently of the whole.
o Lifespan: The part (child) can exist independently of the whole (parent).
o Example: A department and a teacher. A teacher can belong to multiple
departments and still exist if the department is deleted.
o Code Example:

java
Copy code
class Department {
private String name;
private List<Teacher> teachers;
// constructor, getters, and setters
}

class Teacher {
private String name;
// constructor, getters, and setters
}

3. Composition:
o Definition: A stronger type of association representing a "whole-part"
relationship where the part cannot exist independently of the whole.
o Lifespan: The part (child) depends on the whole (parent) for its existence. If the
whole is destroyed, the part is also destroyed.
o Example: A house and a room. A room cannot exist without the house.
o Code Example:

java
Copy code
class House {
private List<Room> rooms;
// constructor, getters, and setters
}

class Room {
private String name;
// constructor, getters, and setters
}

Q Function overloading vs overriding

Function Overloading

1. Definition:
o Multiple methods in the same class with the same name but different parameters
(type, number, or both).
2. Compile-Time:
o Resolved during compile time.
3. Usage:
o Provides multiple ways to perform a similar task with different inputs.
4. Example:

java
Copy code
class Example {
void display(int a) {
System.out.println("Argument: " + a);
}

void display(String b) {
System.out.println("Argument: " + b);
}
}

// Usage
Example obj = new Example();
obj.display(5); // Output: Argument: 5
obj.display("Hello"); // Output: Argument: Hello

Function Overriding

1. Definition:
o A subclass provides a specific implementation of a method that is already defined
in its superclass.
2. Run-Time:
o Resolved during runtime.
3. Usage:
o Achieves runtime polymorphism and allows a subclass to provide a specific
implementation for an inherited method.
4. Example:

java
Copy code
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}

class Dog extends Animal {


@Override
void sound() {
System.out.println("Dog barks");
}
}

// Usage
Animal myDog = new Dog();
myDog.sound(); // Output: Dog barks

Key Differences:

• Method Signature:
o Overloading: Methods have the same name but different parameter lists.
o Overriding: Methods have the same name and parameter list in both superclass
and subclass.
• Scope:
o Overloading: Occurs within the same class.
o Overriding: Occurs in a subclass relative to a superclass.
• Purpose:
o Overloading: Provides different ways to perform similar tasks with different
inputs.
o Overriding: Provides a specific implementation of a method in the subclass that
is already defined in the superclass.

4o

1.
2.
3.
4.
5. Q Difference between Abstract class and Interface?

Abstract Class

1. Definition:
o A class that cannot be instantiated and may contain both abstract methods
(without implementation) and concrete methods (with implementation).
2. Methods:
o Can have both abstract and non-abstract methods.
o Can provide method implementations.
3. Variables:
o Can have instance variables.
o Can have constants (static final variables).
4. Inheritance:
o A class can extend only one abstract class (single inheritance).
5. Constructors:
o Can have constructors.
6. Access Modifiers:
o Can have any access modifiers (public, protected, private) for methods and fields.
7. Usage:
o Used when classes share a common base class but need to provide specific
implementations.
8. Example:

java
Copy code
abstract class Animal {
String name;

abstract void sound();

void eat() {
System.out.println("This animal eats");
}
}

class Dog extends Animal {


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

Interface

1. Definition:
o A reference type in Java, similar to a class, that can contain only abstract methods
(until Java 8), default methods, static methods, and constants.
2. Methods:
o Before Java 8: Can have only abstract methods (implicitly public and abstract).
o From Java 8: Can have default and static methods with implementations.
3. Variables:
o Can have only constants (implicitly public, static, and final).
4. Inheritance:
o A class can implement multiple interfaces (multiple inheritance).
5. Constructors:
o Cannot have constructors.
6. Access Modifiers:
o Methods are implicitly public.
o Fields are implicitly public, static, and final.
7. Usage:
o Used to define a contract that implementing classes must adhere to, promoting
multiple inheritance and loose coupling.
8. Example:

java
Copy code
interface Animal {
void sound();

default void eat() {


System.out.println("This animal eats");
}
}

class Dog implements Animal {


public void sound() {
System.out.println("Dog barks");
}
}

Key Differences:

• Instantiation:
o Abstract Class: Cannot be instantiated directly.
o Interface: Cannot be instantiated.
• Method Implementation:
o Abstract Class: Can have both abstract and non-abstract methods.
o Interface: Before Java 8, only abstract methods; from Java 8, can have default
and static methods with implementations.
• Multiple Inheritance:
o Abstract Class: A class can extend only one abstract class.
o Interface: A class can implement multiple interfaces.
• Fields:
o Abstract Class: Can have instance variables.
o Interface: Can only have constants.
• Use Case:
o Abstract Class: When classes share a common base with some shared
implementation.
o Interface: When classes need to adhere to a contract or protocol, promoting
multiple inheritance and loose coupling.

4o

1. Can private method or static methods be overridden in Java?

No, private methods and static methods cannot be overridden in Java. Here’s why:

Private Methods

1. Private Methods:
o Definition: Methods that are declared private within a class and are not visible
outside of that class.
o Reason for Not Overriding: Private methods are not inherited by subclasses, so
they cannot be overridden.
o Example:

java
Copy code
class Parent {
private void display() {
System.out.println("Parent display");
}
}

class Child extends Parent {


private void display() {
System.out.println("Child display");
}
}

In this example, display in Child does not override display in Parent. They
are two separate methods.

Static Methods

2. Static Methods:
o Definition: Methods that belong to the class rather than any specific instance of
the class. They can be called without creating an instance of the class.
o Reason for Not Overriding: Static methods are not associated with any instance
of the class, so they are not subject to polymorphism. Instead, they are hidden if
redefined in a subclass (a process known as method hiding).
o Example:

java
Copy code
class Parent {
static void display() {
System.out.println("Parent display");
}
}

class Child extends Parent {


static void display() {
System.out.println("Child display");
}
}

public class Test {


public static void main(String[] args) {
Parent p = new Child();
p.display(); // Output: Parent display
}
}

In this example, display in Child hides display in Parent. The method called
is determined by the type of the reference, not the actual object.

Summary

• Private Methods: Cannot be overridden because they are not visible to subclasses.
• Static Methods: Cannot be overridden because they belong to the class itself and not to
instances of the class. They can be hidden by redefining them in a subclass, but this is not
the same as overriding.

Can main() method be overloaded?

Yes, the main() method can be overloaded in Java. However, the JVM (Java Virtual Machine)
looks for the specific signature public static void main(String[] args) to start the
application. Overloaded main() methods with different signatures will not be used as the entry
point of the application but can be called from the main(String[] args) method or elsewhere
in the code.

Example:
java
Copy code
public class MainExample {

// Standard main method recognized by JVM


public static void main(String[] args) {
System.out.println("Main method with String[] args");
main(5);
main("Hello");
}

// Overloaded main method with an integer argument


public static void main(int a) {
System.out.println("Main method with int argument: " + a);
}

// Overloaded main method with a string argument


public static void main(String a) {
System.out.println("Main method with String argument: " + a);
}
}

Output:
sql
Copy code
Main method with String[] args
Main method with int argument: 5
Main method with String argument: Hello

Key Points:

• Standard Entry Point: The JVM always looks for public static void
main(String[] args) to start execution.
• Overloading: You can define multiple main() methods with different parameter lists.
• Usage: Overloaded main() methods can be called from the standard main(String[]
args) or from other parts of the program.

In summary, while you can overload the main() method, only the public static void
main(String[] args) method will be used as the entry point by the JVM. Other overloaded
main() methods can be used like any other static methods in your program.

Can Abstract class have main method?

Yes, an abstract class can have a main method in Java. Although you cannot instantiate an
abstract class directly, the main method can be used to execute code, including creating instances
of concrete subclasses.

Example:
java
Copy code
abstract class AbstractExample {
public static void main(String[] args) {
System.out.println("Main method in abstract class");
ConcreteExample concrete = new ConcreteExample();
concrete.display();
}

abstract void display();


}

class ConcreteExample extends AbstractExample {


@Override
void display() {
System.out.println("Display method in concrete class");
}
}

Output:
csharp
Copy code
Main method in abstract class
Display method in concrete class

Key Points:

• Main Method: The main method in an abstract class can be used as the entry point for
running the program.
• Concrete Subclass: You can create instances of concrete subclasses within the main
method or elsewhere in the abstract class.
• Purpose: The main method in an abstract class can be useful for providing a test harness,
utility methods, or demonstrating the use of the abstract class and its subclasses.

In summary, while you cannot instantiate an abstract class, having a main method in it is
perfectly valid and can be used to run the program, test functionality, and create instances of
concrete subclasses.

Serialisation

• What is Serialisation and Deserialisation?

Serialization and deserialization are processes used to convert objects to and from a format that
can be easily stored or transmitted.

Serialization
Definition:

• The process of converting an object into a byte stream, which can then be easily saved to
a file, sent over a network, or stored in a database.

Purpose:

• To persist the state of an object so that it can be recreated later.

How it Works in Java:

• An object is serialized by implementing the java.io.Serializable interface.


• Java provides ObjectOutputStream to write the object to an output stream.

Example:

java
Copy code
import java.io.*;

class Person implements Serializable {


private static final long serialVersionUID = 1L;
String name;
int age;

Person(String name, int age) {


this.name = name;
this.age = age;
}
}

public class SerializationExample {


public static void main(String[] args) {
Person person = new Person("John", 30);

// Serialization
try (FileOutputStream fileOut = new FileOutputStream("person.ser");
ObjectOutputStream out = new ObjectOutputStream(fileOut)) {
out.writeObject(person);
System.out.println("Serialized data is saved in person.ser");
} catch (IOException i) {
i.printStackTrace();
}
}
}

Deserialization

Definition:

• The process of converting a byte stream back into a copy of the original object.
Purpose:

• To recreate the object from its serialized form.

How it Works in Java:

• Java provides ObjectInputStream to read the object from an input stream.

Example:

java
Copy code
import java.io.*;

public class DeserializationExample {


public static void main(String[] args) {
Person person = null;

// Deserialization
try (FileInputStream fileIn = new FileInputStream("person.ser");
ObjectInputStream in = new ObjectInputStream(fileIn)) {
person = (Person) in.readObject();
System.out.println("Deserialized Person:");
System.out.println("Name: " + person.name);
System.out.println("Age: " + person.age);
} catch (IOException | ClassNotFoundException i) {
i.printStackTrace();
}
}
}

Key Points:

• Serializable Interface: The class to be serialized must implement the Serializable


interface.
• serialVersionUID: A unique identifier for each class, used during deserialization to
verify that the sender and receiver of a serialized object maintain compatible versions.
• Transient Keyword: Fields marked as transient are not serialized.
• Custom Serialization: Classes can customize the serialization process by defining
writeObject and readObject methods.

In summary, serialization and deserialization are crucial for persisting and transferring object
states in Java, enabling objects to be saved and reconstructed across different contexts.

Use of transient keyword?

Use of transient Keyword


Definition:

• The transient keyword in Java is used to indicate that a field should not be serialized.

Purpose:

• To prevent sensitive data or temporary state information from being serialized.

Serializing a Class with a Non-Serializable Superclass

Yes, it is possible to serialize a class even if its superclass is not serializable. However, the non-serializable
superclass must have a no-argument constructor that is accessible (typically public or protected). The
fields of the non-serializable superclass will not be serialized, but the fields of the serializable subclass
will be.

Uninitialized Non-Serializable, Non-Transient Fields

Uninitialized non-serializable, non-transient fields will still be tolerated during serialization and
deserialization. However, they will not be part of the serialized state, and their default values will
be assigned during deserialization.

• For primitive types, this means the default values (e.g., 0 for int, false for boolean).
• For object references, this means null.

Cloning

• What is marker interface?

Marker Interface

Definition:

• A marker interface is an interface that does not contain any methods or constants. It is
used to "mark" or "tag" a class to indicate that it possesses some property or should be
treated in a certain way by the Java runtime or other components of the application.

Purpose:

• The primary purpose of a marker interface is to provide metadata about a class. The
presence of a marker interface can be checked at runtime to enable certain behavior.
Examples of Marker Interfaces in Java

1. java.io.Serializable:
o Indicates that a class can be serialized (i.e., converted into a byte stream).
2. java.lang.Cloneable:
o Indicates that a class allows for field-for-field copying (i.e., the clone method can
be called on instances of the class).
3. java.util.concurrent.locks.Lock:
o Indicates that a class supports a lock mechanism for thread synchronization.

What is shallow copy and Deep copy?

• Shallow Copy: Copies the object and references to the same objects.

• Uses the default implementation of the clone() method.


• Changes to mutable fields in the original object affect the shallow copy.

• Deep Copy: Copies the object and recursively copies all objects referenced by it.

• Requires custom implementation to recursively copy referenced objects.


• Changes to mutable fields in the original object do not affect the deep copy.

Difference between Error and Exception?

The main differences between Errors and Exceptions in Java are primarily related to their
intended use, handling, and impact on the program's execution:

Errors

1. Definition:
o Errors in Java represent serious, unrecoverable problems that typically arise from
the environment or the JVM itself rather than from the application code.
2. Types:
o Examples include OutOfMemoryError, StackOverflowError,
VirtualMachineError, etc.
3. Handling:
o Errors should not be caught or handled by typical application-level error handling
mechanisms because they indicate serious problems that usually cannot be
resolved programmatically.
4. Impact:
o Errors typically lead to termination of the application or the current thread. They
are meant to signal severe problems that usually require intervention at the system
or environment level.

Exceptions
1. Definition:
o Exceptions in Java represent conditions that occur due to problems in the
application code or unexpected conditions during program execution.
2. Types:
o Examples include NullPointerException, FileNotFoundException,
NumberFormatException, etc. Exceptions are further categorized into checked
exceptions (those that must be declared or handled) and unchecked exceptions
(runtime exceptions).
3. Handling:
o Exceptions are intended to be caught and handled within the application's error
handling mechanism using try-catch blocks or by declaring them in method
signatures (for checked exceptions).
4. Impact:
o Exceptions, depending on their type and severity, can often be recovered from or
handled gracefully within the application logic. They do not necessarily lead to
the termination of the entire application but might affect specific operations or
flows within the program.

Key Differences Summary:

• Origin:
o Errors typically originate from the JVM or the environment and indicate serious
problems beyond the control of the application.
o Exceptions are generally caused by problems within the application code or
unexpected conditions during execution.
• Handling:
o Errors are not meant to be caught or handled programmatically in most cases and
often lead to termination of the application or thread.
o Exceptions are meant to be caught, handled, or declared, depending on whether
they are checked or unchecked, to allow the application to recover from
unexpected conditions.
• Impact:
o Errors signal severe, usually irrecoverable issues that typically require
intervention outside the application.
o Exceptions represent conditions that can often be anticipated and handled within
the application's normal flow of control.

• Checked vs Unchecked Exception?

• Checked Exceptions:
o Checked at compile-time.
o Must be handled using try-catch or declared in method signature.
o Used for recoverable conditions that can reasonably be anticipated.
• Unchecked Exceptions:
o Not checked at compile-time.
o Optional handling; not required to be caught or declared.
o Typically used for programming errors or conditions that indicate serious
problems with the application's logic.

Choosing Between Checked and Unchecked Exceptions:

• Use Checked Exceptions When:


o The exception can be anticipated and handled gracefully within the application.
o The caller of the method must be aware of the possibility of the exception.
• Use Unchecked Exceptions When:
o The exception represents an error that generally cannot be handled by the
application.
o The exception indicates a bug or flaw in the application's logic that should be
fixed.

Understanding these distinctions helps in designing effective exception handling strategies and
ensuring that exceptions are appropriately managed in Java applications, balancing between
recoverable errors and serious application flaws

• Create custom Exception?

Creating a custom exception in Java involves creating a new class that extends either Exception
(for checked exceptions) or RuntimeException (for unchecked exceptions). Here’s how you can
create a custom exception:

Example of Custom Exception (Checked Exception)


java
Copy code
// Custom checked exception
class CustomCheckedException extends Exception {
public CustomCheckedException(String message) {
super(message);
}
}

// Example class using the custom checked exception


class CustomExceptionExample {
public void performOperation() throws CustomCheckedException {
// Simulate a condition that triggers the custom checked exception
boolean errorCondition = true;
if (errorCondition) {
throw new CustomCheckedException("Custom checked exception
occurred");
} else {
System.out.println("Operation performed successfully");
}
}

public static void main(String[] args) {


CustomExceptionExample example = new CustomExceptionExample();
try {
example.performOperation();
} catch (CustomCheckedException e) {
e.printStackTrace();
// Handle the exception (e.g., log, notify user, etc.)
}
}
}

Example of Custom Exception (Unchecked Exception)


java
Copy code
// Custom unchecked exception
class CustomUncheckedException extends RuntimeException {
public CustomUncheckedException(String message) {
super(message);
}
}

// Example class using the custom unchecked exception


class CustomExceptionExample {
public void performOperation() {
// Simulate a condition that triggers the custom unchecked exception
boolean errorCondition = true;
if (errorCondition) {
throw new CustomUncheckedException("Custom unchecked exception
occurred");
} else {
System.out.println("Operation performed successfully");
}
}

public static void main(String[] args) {


CustomExceptionExample example = new CustomExceptionExample();
try {
example.performOperation();
} catch (CustomUncheckedException e) {
e.printStackTrace();
// Handle the exception (e.g., log, notify user, etc.)
}
}
}

Key Points:

• Extending Exception Class: Custom exceptions extend either Exception (checked) or


RuntimeException (unchecked).
• Constructor: Custom exceptions typically define a constructor that calls the superclass
constructor (super(message)) with a descriptive message.
• Throwing Custom Exception: Use throw new CustomException(message) to throw
the custom exception when a specific condition or error occurs.
• Handling Custom Exception: Use try-catch blocks to handle the custom exception,
either checking for specific custom exceptions or catching more general Exception
types.

Custom exceptions allow you to define specific error conditions relevant to your application and
provide meaningful error messages to aid in debugging and handling exceptional cases.

• What is Runtime exception ?

A runtime exception in Java is a type of exception that occurs during the execution of a program,
typically due to logical errors, improper use of API, or other runtime conditions that violate the
application's normal flow. Unlike checked exceptions, which must be either caught or declared in
the method signature, runtime exceptions are unchecked and do not need to be explicitly handled
in the code.

Characteristics of Runtime Exceptions:

1. Unchecked Exception:
o Runtime exceptions extend RuntimeException or its subclasses.
o They are not checked at compile-time, meaning the compiler does not enforce
handling or declaration using throws.
2. Typical Causes:
o Common causes include attempting to access an array element beyond its bounds
(ArrayIndexOutOfBoundsException), accessing a null reference
(NullPointerException), dividing by zero (ArithmeticException), etc.
3. Impact on Program:
o When a runtime exception occurs, it typically indicates a serious problem with the
application's logic or environment.
o They can cause the program to terminate if not handled, although they are not
intended to be caught in every possible scenario.
4. Handling:
o While runtime exceptions do not require explicit handling, it is good practice to
anticipate and handle them where possible to provide robust error handling and
prevent unexpected program termination.
o They often indicate bugs or flaws in the program that should be addressed during
development and testing phases.

Example of Runtime Exception:


java
Copy code
public class RuntimeExceptionExample {
public static void main(String[] args) {
try {
int[] arr = new int[3];
System.out.println(arr[5]); // ArrayIndexOutOfBoundsException
} catch (ArrayIndexOutOfBoundsException e) {
System.out.println("Array index is out of bounds.");
e.printStackTrace();
}

try {
String str = null;
System.out.println(str.length()); // NullPointerException
} catch (NullPointerException e) {
System.out.println("Trying to invoke a method on a null object
reference.");
e.printStackTrace();
}

try {
int result = 10 / 0; // ArithmeticException: division by zero
} catch (ArithmeticException e) {
System.out.println("Attempted to divide by zero.");
e.printStackTrace();
}
}
}

Key Points:

• Unchecked Nature: Runtime exceptions do not need to be explicitly handled or declared


in method signatures.
• Common Causes: They often result from errors in program logic, misuse of APIs, or
unexpected conditions during execution.
• Impact: While not mandatory to handle, appropriate handling can prevent unexpected
program termination and improve application reliability.

Understanding runtime exceptions helps in effective debugging, error handling, and overall
robustness of Java applications, ensuring they can gracefully handle unexpected conditions
during execution.

• How does JVM handle Exception?

The Java Virtual Machine (JVM) handles exceptions in Java through a series of steps that
involve identifying, propagating, and potentially handling exceptions within the runtime
environment. Here’s an overview of how JVM handles exceptions:

Handling Process:
1. Exception Occurrence:
o When an exceptional condition occurs during the execution of a Java program
(such as dividing by zero, accessing an array out of bounds, or attempting to
invoke a method on a null object reference), the JVM creates an object
representing that exception.
2. Exception Object Creation:
o The JVM creates an instance of a subclass of Throwable (either Exception or
Error).
o This instance contains information about the type of exception, the point where
the exception occurred (stack trace), and any other relevant details.
3. Exception Propagation:
o The JVM then searches for a handler for this exception. It checks the method
where the exception occurred for a try-catch block that can handle this
particular type of exception.
4. Finding Exception Handler:
o If a suitable catch block is found within the method, the JVM transfers control to
that block to handle the exception.
o If no appropriate catch block is found within the method, the JVM propagates the
exception up the call stack to the calling method.
5. Propagation Up the Call Stack:
o The JVM continues to propagate the exception up the call stack, searching for an
appropriate handler in each method.
o If the exception reaches the top of the call stack (i.e., the main method in a
standalone application or the entry point in a web application), and if no handler
is found, the JVM prints the stack trace to the console and terminates the program
(unless the exception is caught by a global handler).
6. Uncaught Exception Handling:
o For exceptions that are not caught and handled explicitly, the JVM typically prints
the stack trace to the console, providing detailed information about where the
exception occurred and the sequence of method calls leading to it.

Example of Exception Handling in JVM:


java
Copy code
public class ExceptionHandlingExample {
public static void main(String[] args) {
try {
int result = divideByZero(); // This method throws
ArithmeticException
System.out.println("Result: " + result);
} catch (ArithmeticException e) {
System.out.println("Exception caught: Attempted to divide by
zero.");
e.printStackTrace();
}
}

public static int divideByZero() {


return 10 / 0; // This line throws ArithmeticException
}
}

Key Points:

• Exception Creation: JVM creates an exception object when an exceptional condition


occurs.
• Exception Propagation: JVM searches for a suitable handler, propagating the exception
up the call stack if no handler is found.
• Handling and Termination: Unhandled exceptions at the top of the call stack result in
printing the stack trace and termination of the program.

By understanding how the JVM handles exceptions, developers can design robust exception
handling strategies in their Java applications, ensuring that critical errors are properly managed
to maintain application stability and reliability.

Q Difference between Final, Finalise and Finally?

finalize()

1. Method:
o finalize() is a method defined in the Object class in Java. It's called by the
garbage collector before reclaiming the memory occupied by an object.
2. Usage:
o It's invoked automatically by the garbage collector, not explicitly by the
programmer.
o It can be overridden by a class to perform cleanup operations (like closing files or
releasing resources) before an object is garbage collected.
o It's not recommended to rely on finalize() for critical resource cleanup due to
unpredictable nature of when the garbage collector runs.

java
Copy code
class MyClass {
@Override
protected void finalize() throws Throwable {
// Cleanup code before garbage collection
// Close resources, etc.
super.finalize();
}
}
• final: Keyword used for constants, methods, and classes to indicate immutability, prevent
method overriding, or prevent subclassing.
• finalize(): Method in Object class for performing cleanup operations before object garbage
collection, invoked automatically by the JVM's garbage collector.
• finally: Block used in exception handling to ensure execution of cleanup code, whether an
exception is thrown or not, after a try block.

Super class of all exceptions?

n Java, the superclass of all exceptions is the Throwable class. The Throwable class is at the top
of the exception class hierarchy, and both Exception and Error classes extend from Throwable.

Here's a brief overview of the class hierarchy related to exceptions in Java:

1. Throwable Class:
o Throwableis the superclass of all exceptions and errors in the Java language.
oIt provides methods to get information about the exception (getMessage(),
printStackTrace(), etc.).
o Direct subclasses include Exception and Error.
2. Exception Class:
o Exception is a subclass of Throwable and represents conditions that a reasonable
application might want to catch.
o Examples include IOException, SQLException, NullPointerException, etc.
o Exceptions are further divided into checked exceptions (subclass of Exception)
and runtime exceptions (RuntimeException and its subclasses).
3. Error Class:
o Error is also a subclass of Throwable and represents serious problems that a
reasonable application should not try to catch.
o Examples include OutOfMemoryError, StackOverflowError,
VirtualMachineError, etc.
o Errors typically arise from problems outside the control of the application, such as
system resource exhaustion or JVM issues.

Example Usage:
java
Copy code
public class ThrowableExample {
public static void main(String[] args) {
try {
// Code that may throw an exception
int result = divideByZero();
} catch (ArithmeticException e) {
// Handle arithmetic exception
System.out.println("Arithmetic Exception occurred: " +
e.getMessage());
} catch (Throwable t) {
// Catching Throwable to handle all exceptions and errors
System.out.println("Throwable occurred: " + t.getMessage());
}
}

public static int divideByZero() {


return 10 / 0; // ArithmeticException: division by zero
}
}

• Is throwable an interface?

No, Throwable is not an interface in Java; it is a class. Specifically, Throwable is the superclass
of all exceptions and errors in Java. It is located at the root of the exception hierarchy in Java.

Key Points about Throwable:

• Class Nature: Throwable is defined as a class (public class Throwable extends


Object implements Serializable).
• Hierarchy: It serves as the base class for both Exception (checked exceptions) and
Error (unchecked exceptions).
• Methods: Throwable provides methods to retrieve information about the exception or
error, such as getMessage(), printStackTrace(), getCause(), etc.
• Usage: It is used to handle and manage exceptions and errors in Java applications
through try-catch blocks or by declaring exceptions in method signatures (throws
clause).

Example Usage:
java
Copy code
public class ThrowableExample {
public static void main(String[] args) {
try {
// Code that may throw an exception
int result = divideByZero();
} catch (ArithmeticException e) {
// Handle arithmetic exception
System.out.println("Arithmetic Exception occurred: " +
e.getMessage());
} catch (Throwable t) {
// Catching Throwable to handle all exceptions and errors
System.out.println("Throwable occurred: " + t.getMessage());
}
}

public static int divideByZero() {


return 10 / 0; // ArithmeticException: division by zero
}
}

• When Finally block doesn’t get executed?

In Java, the finally block associated with a try block is designed to execute under normal
circumstances, even when an exception is thrown. However, there are a few scenarios where the
finally block may not get executed:

1. System.exit():
o If the Java program calls System.exit() within the try block or catches a
SecurityException caused by System.exit(), the JVM terminates abruptly. In
this case, the finally block does not get a chance to execute.

java
Copy code
try {
// Code that may throw an exception
// Possibly calls System.exit(0);
} finally {
// This block will not execute if System.exit() is called
}

2. Infinite Loop or Endless Execution:


o If the try block or any code within it enters an infinite loop or otherwise prevents
the program from reaching the finally block, then the finally block will not
execute until the loop or blocking condition is resolved.

java
Copy code
try {
while (true) {
// Infinite loop or blocking condition
}
} finally {
// This block will not execute until the loop is terminated
}

3. Thread Termination:
o If a thread executing code within a try block is terminated abruptly (for example,
by calling Thread.stop()), the finally block associated with that try block
may not execute.

java
Copy code
try {
// Code that may throw an exception
Thread.currentThread().stop();
} finally {
// This block may not execute if the thread is terminated abruptly
}

4. Power Off or Kill Signal:


o If the underlying system is powered off, or if the process is killed externally (e.g.,
through task manager or command-line tools), the JVM may not have a chance to
execute the finally block.

In general, finally blocks are intended for cleanup and releasing resources, and they are crucial
in ensuring that important operations (like closing files or releasing locks) are performed
regardless of whether an exception occurs. However, developers should be aware of these
exceptional cases where the finally block may not execute as expected due to external or
abnormal conditions.

3.5
if i return 1 and -1 in try catch block will the finally execute
ChatGPT

Yes, the finally block will execute even if you return from within the try or catch blocks.
Here’s how it works:

java
Copy code
public class FinallyExample {
public static void main(String[] args) {
int result = divideNumbers(10, 0);
System.out.println("Result: " + result);
}

public static int divideNumbers(int dividend, int divisor) {


try {
return dividend / divisor; // This line throws
ArithmeticException
} catch (ArithmeticException e) {
System.out.println("Arithmetic Exception caught: " +
e.getMessage());
return -1; // Return -1 on exception
} finally {
System.out.println("Finally block executed.");
// This block always executes, regardless of whether an exception
occurs or not.
}
}
}

In the example above:

• If divisor is 0, the try block will throw an ArithmeticException.


• The catch block will catch this exception, print a message, and return -1.
• Despite the return statement in the catch block, the finally block still executes
immediately after the try or catch block completes.
Output:
vbnet
Copy code
Arithmetic Exception caught: / by zero
Finally block executed.
Result: -1

Key Points:

• Execution Guarantee: The finally block is designed to execute under normal and
exceptional circumstances, ensuring cleanup or finalization tasks are performed.
• Return Statement: Returning from within a try or catch block will cause the finally
block to execute before returning from the method.
• Exception Handling: Whether an exception is thrown or not, the finally block ensures
that its code is executed before control leaves the method.

Can subclass throw higher checked exception than base class?

No, in Java, a subclass cannot throw a checked exception that is broader (higher in the exception
hierarchy) than the checked exception thrown by its superclass. This rule ensures that subclasses do not
weaken the exception handling contract defined by their superclass. Here’s why:

Conclusion:

To maintain consistency and uphold the exception handling contract defined by the superclass,
Java enforces that a subclass cannot throw checked exceptions that are broader (higher in the
exception hierarchy) than those thrown by its superclass. This rule ensures type safety and helps
in maintaining robust exception handling in Java programs.

Can we throw an unchecked exception in child class if parent class doesn’t throw any exception?

Yes, in Java, a subclass can throw unchecked exceptions (subclasses of RuntimeException or


Error) even if its superclass does not declare any exceptions in its method signature. This is
allowed because unchecked exceptions do not need to be declared using throws in method
signatures, unlike checked exceptions.

Example Scenario:
Consider a superclass Parent without any exception declarations, and its subclass Child that
throws an unchecked exception:

java
Copy code
class Parent {
void method() {
// Method code that does not throw any checked exceptions
}
}

class Child extends Parent {


@Override
void method() {
// Method code that throws an unchecked exception
throw new RuntimeException("Unchecked exception thrown in Child");
}
}

In this example:

• Parent class defines method() without any throws declaration, indicating it does not
throw any checked exceptions.
• Child class overrides method() and throws a RuntimeException, which is an
unchecked exception.

Compiler and Runtime Behavior:

• Compile-time: The compiler allows Child to override method() and throw unchecked
exceptions without any issues related to method signature mismatch.
• Runtime: When method() is called on an instance of Child, and an unchecked
exception (RuntimeException in this case) is thrown, it does not need to be caught or
declared, as it is unchecked.

Difference between throw and throws()

• Function:

• throw is used to throw an exception instance explicitly within a method to indicate an


exceptional condition.
• throws is used in the method signature to declare the types of exceptions that a method
may throw, allowing the caller to handle or propagate those exceptions.

• Placement:

• throw is used within method bodies to throw exceptions.


• throws is used in method declarations (method signatures) to declare exceptions.
• Checked vs Unchecked:

• throws is typically used with checked exceptions (subclasses of Exception excluding


RuntimeException and its subclasses).
• throw can be used with both checked and unchecked exceptions (RuntimeException
and its subclasses).

Usage of Enum

• Why to use Enum?

Enums (short for Enumerations) in Java are used to define a collection of named constants,
which provide better type safety and readability compared to using primitive constants or strings
directly in code. Here are some key reasons why enums are used:

Reasons to Use Enums:

1. Readability and Maintainability:


o Enums improve code readability by providing meaningful names to constants.
o They make the code more maintainable because the constants are defined in one
place and can be easily referenced throughout the codebase.
2. Type Safety:
o Enums are type-safe, meaning they provide compile-time checking and prevent
invalid constants from being assigned or passed incorrectly.
o This reduces errors and enhances the robustness of the code.
3. No Magic Numbers or Strings:
o Enums eliminate the use of magic numbers (hard-coded integer constants) or
magic strings (hard-coded string constants) scattered throughout the code.
o Instead, constants are represented by named enum values, improving code clarity
and reducing potential errors from mistyped or mismatched values.
4. Enumerating Options:
o Enums are ideal for representing a fixed set of options or choices. For example,
days of the week, months of the year, HTTP status codes, etc.
o They provide a natural way to express a predefined list of related constants.
5. Switch Statements:
o Enums work well with switch statements, making the code more readable and
maintainable compared to using if-else chains or integer constants.
6. Behavior and State:
o Enums can have fields, constructors, and methods like any other Java class,
allowing them to encapsulate behavior and state associated with each enum
constant.
o This enables enums to be more than just named constants; they can also be used
to model more complex structures.
Garbage collection

• How does Garbage collection in Java works?

Garbage collection (GC) in Java is an automatic memory management process that handles the
reclamation of memory occupied by objects that are no longer in use. Here’s how garbage
collection works in Java:

Process of Garbage Collection:

1. Identifying Unreachable Objects:


o The Java Virtual Machine (JVM) periodically checks which objects in memory
are no longer reachable or referenced by any active part of the program.
o An object becomes eligible for garbage collection if there are no live threads that
can access it (i.e., no references to the object exist).
2. Mark and Sweep Algorithm:
o Mark Phase: The GC algorithm marks all objects that are reachable (i.e., still in
use) from the root objects (such as threads, static variables, and method calls).
o Sweep Phase: It then sweeps through the heap and deallocates memory occupied
by objects that are not marked (i.e., unreachable).
3. Memory Reclamation:
o Once the sweep phase completes, memory occupied by unreachable objects is
reclaimed and made available for future object allocations.
4. Types of Garbage Collectors:
o Java provides different garbage collection algorithms and collectors, such as:
▪ Serial GC: Uses a single thread for garbage collection (suitable for
smaller applications).
▪ Parallel GC: Uses multiple threads to perform garbage collection,
improving performance on multi-core systems.
▪ Concurrent Mark-Sweep (CMS) GC: Minimizes pauses by performing
most of the garbage collection work concurrently with the application
threads.
▪ Garbage-First (G1) GC: Divides the heap into regions and performs
concurrent garbage collection per region, aiming to minimize pauses and
achieve high throughput.
5. Tuning and Monitoring:
o Garbage collection in Java can be tuned using JVM options (-XX flags) to
optimize for throughput, latency, or memory footprint based on application
requirements.
o Tools like VisualVM, JConsole, and JVM monitoring APIs can be used to
monitor garbage collection behavior, heap usage, and performance metrics.

Example Scenario:
java
Copy code
public class GarbageCollectionExample {
public static void main(String[] args) {
// Creating objects
MyClass obj1 = new MyClass();
MyClass obj2 = new MyClass();

// Nullifying references
obj1 = null;
obj2 = null;

// Triggering garbage collection explicitly (not recommended in


general usage)
System.gc();
}
}

In the example above:

• obj1 and obj2 become eligible for garbage collection once their references are set to
null.
• System.gc() is called to suggest to the JVM that it should perform garbage collection,
but it doesn't guarantee immediate execution.

Conclusion:

Garbage collection in Java automates memory management by reclaiming memory occupied by


objects that are no longer needed, reducing manual memory management overhead and
preventing memory leaks. Understanding how garbage collection works helps in optimizing Java
applications for performance, responsiveness, and memory efficiency.

What is diamond problem in java and how it is resolved in error

Diamond Problem is a problem faced during Multiple Inheritance in Java.


Let’s see what is Diamond Problem and how to solve this problem.

What is a Diamond Problem in Java?


Inheritance in Java is when a child class inherits the properties of the parent
class. There are certain types of inheritance in Java as mentioned below:
1. Single Inheritance
2. Multilevel Inheritance
3. Hierarchical Inheritance
4. Multiple Inheritance
5. Hybrid Inheritance

Talking about Multiple inheritance is when a child class is inherits the


properties from more than one parents and the methods for the parents are
same (Method name and parameters are exactly the same) then child gets
confused about which method will be called. This problem in Java is called
the Diamond problem.

Solution of Diamond Problem in Java


Although Diamond Problem is a serious issue but we can create a solution
for it which is Interface. Interface are created by using interface keyword. It
contains all methods by default as abstract we don’t need to declared as
abstract ,compiler will do it implicitly. We can’t instantiate interface for this
we have to use a class which will implement the interface and will write the
definitions of its all functions.
Here below we will see , how can we implement multiple inheritance by
interface.

// Java Programs to illustrate

// use of Interface to solve

// Diamond Problem

import java.io.*;

// Interfaces Declared

interface Parent1 {

void fun();

}
// Interfaces Declared

interface Parent2 {

void fun();

// Inheritance using Interfaces

class test implements Parent1, Parent2 {

public void fun()

System.out.println("fun function");

// Driver Class

class test1 {

// main function

public static void main(String[] args)

test t = new test();

t.fun();

You might also like