Home Computer Science Top 100+ Java Interview Questions And Answers (2024)

Top 100+ Java Interview Questions And Answers (2024)

Developed by James Gosling, Java is without a doubt one of the most popular programming languages for landing a rewarding career. Java is used in the development of software on more than 3 billion devices. It is a quick, dependable, and secure programming language and is utilized in every tiny detail, from desktops to online applications, scientific supercomputers to gaming consoles, and cell phones to the Internet.

Java developers can choose from a wide range of work options. So, here are some of the most common Java interview questions and answers that will help you land a job or, at the very least, improve your knowledge. These Java interview questions and answers will assist you in acing major interview processes and will put your skills and knowledge to the ultimate test.

Java interview questions and answers

Following are some important Java interview questions that one must revise before your technical job interview. 

Q1. What do you understand by Java?

Java is a popular high-level programming language developed by Sun Microsystems (now owned by Oracle) in the mid-1990s. It was designed to be platform-independent, meaning that the same code could be executed on different operating systems without any modification.

Java is an object-oriented language, which means that it focuses on objects and their interactions rather than just functions and procedures. It is also statically typed, which means that the data types of variables must be declared before they are used.

Java is widely used in various fields such as software development, mobile app development, web development, and scientific computing. It has a rich standard library that provides many useful functionalities, and there is a vast ecosystem of third-party libraries and tools available for Java development.

Q2. What is the difference between JDK and JRE?

Java Development Kit (JDK) is an acronym for Java Development Kit. It includes the tools and libraries needed to create Java programs. JRE stands for Java Runtime Environment, and it includes compilers and debuggers for compiling Java programs. This is a feature of JDK. JRE is a set of libraries and a virtual machine (JVM) that are necessary to run a Java program.

Here's a table summarizing the differences between JDK and JRE:

  JDK (Java Development Kit) JRE (Java Runtime Environment)
Purpose To develop and deploy Java applications To run Java applications
Components Includes the JRE, compilers, debuggers, and other development tools Includes the Java Virtual Machine (JVM) and class libraries
Usage Used by developers to create Java applications Used by end-users to run Java applications
Size Larger in size as it contains development tools Smaller in size compared to JDK
Installation Must be installed to develop and deploy Java applications Optional, but required to run Java applications
Example Used to create and compile Java code Used to run Java-based software or applets

Q3. What are the features of the Java Programming language?

Here are some of the key features of the Java programming language:

  1. Object-oriented: Java is a fully object-oriented language, which means it focuses on objects and their interactions rather than just functions and procedures. It supports the concepts of encapsulation, inheritance, and polymorphism, which enable developers to create reusable and modular code.

  2. Platform-independent: Java is designed to be platform-independent, which means that the same code can run on different operating systems without any modifications. This is possible due to the use of a virtual machine, which provides an abstraction layer between the code and the underlying hardware.

  3. Robust: Java is known for its robustness, which means it has a strong emphasis on reliability and error-free programming. It includes features such as automatic memory management, exception handling, and type checking to prevent errors and ensure stability.

  4. Multithreaded: Java supports multithreading, which means that multiple threads can run concurrently within a single program. This allows developers to create highly responsive and interactive applications.

  5. Secure: Java is designed with security in mind and includes features such as a security manager, which helps prevent unauthorized access to system resources. It also includes a sandbox model for running untrusted code, which can help protect against malicious code.

  6. Portable: Java is highly portable, which means that code written in Java can be easily moved from one system to another. This is possible due to the use of bytecode, which is a platform-independent format that can be executed on any system that has a Java Virtual Machine (JVM).

  7. Rich standard library: Java includes a rich standard library that provides many useful functionalities, such as I/O operations, networking, database access, and GUI programming. This makes it easier for developers to write complex applications without having to reinvent the wheel.

4. What are the different types of memory areas allocated by JVM?

The JVM (Java Virtual Machine) allocates memory for various purposes during the execution of a Java program. Here are the different types of memory areas allocated by the JVM:

  1. Heap memory: Heap memory is the runtime data area in which objects are allocated. When a new object is created, the JVM allocates memory from the heap. The heap is divided into two parts: the young generation and the old generation.

  2. Stack memory: Stack memory is used to store local variables and method call frames. Each thread of execution in a Java program has its own stack, which is created when the thread is started. The stack is used to keep track of method calls and to store the local variables of each method.

  3. Method area: The method area stores class structures, method code, and static variables. It is shared among all threads and is created when the JVM starts up.

  4. PC (Program Counter) registers: Each thread in a Java program has its own PC register, which stores the address of the currently executing instruction.

  5. Native method stacks: The native method stack is used to store data and information when native methods are called. Native methods are written in other programming languages, such as C or C++, and are accessed using the Java Native Interface (JNI).

These memory areas are managed by the JVM, which performs various memory management tasks, such as garbage collection, to ensure efficient use of memory and prevent memory leaks.

Q5. How Java platform is different from other platforms?

The Java platform is different from other platforms in several ways. Here are some of the key differences:

  1. Platform independence: Java is designed to be platform-independent, which means that Java code can run on any system with a Java Virtual Machine (JVM) installed, regardless of the underlying hardware and operating system. This makes Java programs highly portable and eliminates the need for developers to write separate code for different platforms.

  2. Security: Java includes a number of built-in security features that make it more secure than other programming languages. For example, Java code runs in a sandbox environment that restricts access to system resources, and Java's class loader ensures that code is only loaded from trusted sources.

  3. Automatic memory management: Java includes automatic memory management, which means that developers do not have to manually allocate and deallocate memory. Instead, the JVM automatically manages memory allocation and garbage collection, which makes Java programs more stable and less prone to memory-related errors.

  4. Large standard library: Java includes a large standard library that provides a wide range of useful classes and functions for tasks such as I/O operations, networking, and database access. This makes it easier for developers to write complex applications without having to reinvent the wheel.

  5. Object-oriented programming: Java is a fully object-oriented programming language, which means that everything in Java is an object. This approach encourages the development of reusable and modular code and makes it easier to write large-scale applications.

  6. Multithreading: Java supports multithreading, which means that multiple threads can run concurrently within a single program. This makes it easier to write complex, interactive applications that can handle multiple tasks simultaneously.

Q6. Can we write the main method as public void static instead of the public static void?

No, the correct syntax for the main method in Java is public static void main(String[] args). The order of the keywords public and static cannot be interchanged, as they each have a specific meaning in Java.

public is an access modifier that makes the method accessible to all other classes in the Java program, while static is a keyword that makes the method belong to the class rather than an instance of the class.

The keyword void indicates that the method does not return any value, and main is the name of the method. Therefore, if you write the main method as public void static main(String[] args), you will get a syntax error, as the order of the access modifier and the static keyword is incorrect.

Q7. What is Core Java?

Core Java refers to the fundamental components of the Java programming language, which includes the basic concepts, syntax, and libraries that are used to develop Java applications. It is the foundation upon which all other Java-related technologies and frameworks are built.

The core Java components include the following:

  1. Language basics: This includes the syntax, data types, operators, control structures, and exception-handling mechanisms of the Java language.

  2. Object-oriented programming: Java is a fully object-oriented programming language, which means that everything in Java is an object. The core Java components include concepts such as classes, objects, inheritance, encapsulation, and polymorphism.

  3. Java libraries: The core Java libraries include the Java Standard Library, which provides a wide range of classes and interfaces for common programming tasks, such as input/output operations, networking, and data manipulation.

  4. Multithreading: Java supports multithreading, which means that multiple threads can run concurrently within a single program. Core Java includes concepts such as thread synchronization, locks, and concurrency control.

  5. Collections: Java provides a rich set of collection classes, such as lists, sets, maps, and queues, that allow for efficient manipulation of data.

Overall, Core Java is essential for anyone who wants to learn Java programming and develop Java applications. It provides a solid foundation upon which developers can build more complex and advanced applications.

Q8. What is an array in Java?

A container object that stores a fixed number of values of a single type is called an array. The length of an array is determined at the time of its creation. Its length is set when it is created.

In Java, an array is an object that stores a fixed-size sequential collection of elements of the same type. The elements in an array are accessed using an index, which is an integer value that represents the position of an element in the array.

An array is declared by specifying the type of elements it contains, followed by square brackets [], and then the name of the array. For example, to declare an array of integers named "numbers" that can hold 5 elements, you would write:

int[] numbers = new int[5];

In this example, we declare an array of integers, and use the new keyword to allocate memory for 5 integer values. The elements in the array are initialized to their default value (which is 0 for integers) when the array is created.

To assign values to elements in an array, we use the index notation. For example:

numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;
numbers[3] = 40;
numbers[4] = 50;

This code assigns the values 10, 20, 30, 40, and 50 to the first five elements of the numbers array, respectively.

Arrays in Java have a fixed size, which means that once an array is created, its size cannot be changed. However, you can create a new array with a different size and copy the elements from the original array to the new array if you need to resize an array.

Q9. What is the difference between byte and char data types in Java?

In Java, byte and char are both primitive data types, but they have different characteristics and uses.

  1. Size: The byte data type is an 8-bit signed two's complement integer, which means that it can represent integer values in the range of -128 to 127. On the other hand, the char data type is a 16-bit Unicode character, which means that it can represent a single character from the Unicode character set.

  2. Usage: byte is mainly used to store small integer values, such as flags, or to read/write binary data from files or streams. The char data type is used to represent characters, and is commonly used in string manipulation and in graphical user interface (GUI) programming.

  3. Representation: byte values are represented in 2's complement binary form, whereas char values are represented in Unicode characters using a 16-bit representation.

  4. Default Value: byte has a default value of 0, while char has a default value of '\u0000' (null character).

Here's an example that demonstrates the differences between byte and char:


          byte b = 65; // Assigns the ASCII value for 'A'
char c = 'A'; // Assigns the character 'A'

System.out.println(b); // Prints 65
System.out.println(c); // Prints A
      

In this example, the byte variable b is assigned the value 65, which is the ASCII value for the character 'A'. The char variable c is directly assigned the character 'A', which is represented using Unicode. When we print b, it prints the integer value 65. When we print c, it prints the character 'A'.

Q10. Why do we need a constructor in Java?

Constructors are an essential part of the Java programming language and serve several purposes. Here are a few reasons why constructors are needed in Java:

  1. Object Initialization: Constructors are used to initialize the object's state, i.e., the instance variables of the object. When a new object is created using the new keyword, the constructor is automatically called to initialize the object's state. Without a constructor, the object's state would be undefined, and the program would likely crash.

  2. Provide Default Values: Constructors can provide default values for instance variables if no values are specified during object creation. This can help avoid errors or incorrect behavior in the program.

  3. Encapsulation: Constructors can be used to enforce encapsulation by ensuring that the object's state is properly initialized and validated before any other methods are called on the object.

  4. Inheritance: Constructors play a critical role in inheritance. When a subclass is created, the constructor of its superclass is automatically called first to initialize the inherited state. This process continues up the inheritance hierarchy until the root class's constructor is called.

  5. Polymorphism: Constructors can be used to create objects of different types and classes, allowing for polymorphic behavior in the program. For example, a constructor can be defined in an abstract class to create objects of its concrete subclasses.

Overall, constructors are a critical part of the Java programming language and are necessary for proper object initialization, encapsulation, inheritance, and polymorphism.

Q11. How many types of constructors does Java support?

Java supports two types of constructors:

  1. Default Constructor: A default constructor is a constructor that is automatically generated by the compiler if no constructor is explicitly defined in the class. It has no arguments and does not perform any initialization. It is used to create an object with default values for all its instance variables.

  2. Parameterized Constructor: A parameterized constructor is a constructor that takes one or more parameters and is explicitly defined in the class. It is used to create an object with specific values for its instance variables. When a parameterized constructor is defined, the default constructor is not generated by the compiler.

Here is an example of a class with a default constructor and a parameterized constructor:


          public class Person {
String name;
int age;

// Default constructor
public Person() {
// No initialization performed
}

// Parameterized constructor
public Person(String name, int age) {
this.name = name;
this.age = age;
}
}
      

n this example, the Person class has a default constructor that does not perform any initialization and a parameterized constructor that takes two parameters (name and age) and initializes the instance variables with the passed values using the this keyword.

Q12. Why constructors cannot be final, static, or abstract in Java?

In Java, constructors cannot be declared as final, static, or abstract for several reasons:

  1. Final Constructors: Constructors are used to initialize objects and the primary purpose of a final keyword is to prevent further modifications to a variable, method or class. A final constructor would defeat the purpose of a constructor because if a constructor were declared final, it would not be possible to create a subclass and override the constructor. Therefore, final constructors are not allowed in Java.

  2. Static Constructors: Constructors are called when an object is created, and they initialize instance variables of the object. Since static members are associated with the class and not with objects, it does not make sense to have a static constructor. Static initializers, on the other hand, are used to initialize static variables and are run once when the class is loaded, not when objects are created.

  3. Abstract Constructors: An abstract class is a class that cannot be instantiated, so if a constructor was declared abstract, it would never be used. The abstract keyword is used to specify that a class or method should be implemented by subclasses, but since constructors are always implemented by the class that defines them, it is not possible to declare a constructor as abstract.

In summary, constructors cannot be final, static, or abstract because they have a specific purpose and behavior that does not fit with the semantics of those keywords.

Q13. How to implement constructor chaining using the Java super keyword?

Constructor chaining in Java is a technique that allows one constructor to call another constructor in the same class or in a parent class using the super keyword. This technique is useful when you want to reuse code from one constructor in another constructor or when you want to avoid duplicating code. Here's how you can implement constructor chaining using the super keyword in Java:

  1. Calling a Parent Class Constructor: You can call a constructor of a parent class using the super keyword followed by parentheses that contain the arguments passed to the constructor. Here's an example:

public class Parent {
public Parent(int arg1, int arg2) {
// constructor code
}
}

public class Child extends Parent {
public Child(int arg1, int arg2, int arg3) {
super(arg1, arg2); // call Parent constructor
// constructor code
}
}

In this example, the Child class extends the Parent class and calls the parent constructor using the super keyword with arg1 and arg2 arguments.

  1. Calling Another Constructor in the Same Class: You can also call another constructor in the same class using the this keyword followed by parentheses that contain the arguments passed to the constructor. Here's an example:
    
    public class Parent {
    public Parent(int arg1, int arg2) {
    // constructor code
    }
    }
    
    public class Child extends Parent {
    public Child(int arg1, int arg2, int arg3) {
    super(arg1, arg2); // call Parent constructor
    // constructor code
    }
    }
          

14. How aggregation and composition are different concepts?

Aggregation and composition are two concepts used in object-oriented programming to describe relationships between objects. While they are similar in some ways, there are important differences between the two concepts.

Aggregation is a type of relationship between objects where one object is composed of one or more other objects. In an aggregation relationship, the objects can exist independently of each other. In other words, the objects can be created and destroyed independently, without affecting the other object in the relationship. An example of aggregation could be a university that has multiple departments. The departments can exist independently of the university and can be created or destroyed without affecting the university.

Composition, on the other hand, is a more specific type of aggregation where one object is composed of one or more other objects, and the composed objects cannot exist independently of the main object. In other words, if the main object is destroyed, the composed objects are also destroyed. Composition is often used to model parts and whole relationships. An example of composition could be a car that is composed of an engine, wheels, and other parts. If the car is destroyed, the engine, wheels, and other parts are also destroyed.

Here are some key differences between aggregation and composition:

  • In aggregation, the objects can exist independently of each other, while in composition, the composed objects cannot exist independently of the main object.
  • In aggregation, the objects can be created and destroyed independently of each other, while in composition, the composed objects are created and destroyed with the main object.
  • Aggregation is often used to model relationships between similar objects, while composition is often used to model parts and whole relationships.

Overall, aggregation and composition are both important concepts in object-oriented programming, and understanding the differences between them is essential for designing effective object-oriented systems.

Q15. What is an association?

In object-oriented programming, an association is a relationship between two or more objects that reflects a meaningful connection or interaction between them. It is a way to describe how objects in a system relate to each other and interact with each other.

Associations are often represented in UML diagrams as a line between two classes, with optional symbols indicating the nature of the association. The symbols can include arrows, multiplicity indicators, and labels to describe the nature of the relationship.

There are several types of associations, including:

  • One-to-one: where one object is associated with one other object.
  • One-to-many: where one object is associated with multiple other objects.
  • Many-to-many: where multiple objects are associated with multiple other objects.
  • Aggregation: where one object is part of another object.
  • Composition: where one object is composed of other objects.

An association can also have additional attributes or behaviors associated with it, such as navigability, visibility, and constraints.

Overall, associations are an important concept in object-oriented programming as they help to model the relationships between objects in a system, and can help to make the system more flexible and adaptable to changing requirements.

Q 16. If there are no pointers in Java, then why do we get NullPointerException?

While Java does not have explicit pointers like other programming languages, it still has a concept of references. In Java, objects are always referred to by references, which are essentially variables that hold the memory address of the object. These references can be null, which means they don't refer to any object in memory.

A NullPointerException occurs when you try to access or dereference a null reference. For example, if you try to call a method on an object that is null, you will get a NullPointerException. This is because the null reference does not refer to any object in memory, and therefore cannot be used to call a method or access an instance variable.

Here's an example that demonstrates how a NullPointerException can occur:

String s = null;
int length = s.length(); // Throws NullPointerException because s is null

In this example, we declare a variable s of type String and initialize it to null. We then try to access the length() method of the string, but since s is null, we get a NullPointerException.

In summary, while Java does not have explicit pointers, it still has the concept of references and a NullPointerException occurs when you try to access or dereference a null reference.

Q17. What is object cloning in Java?

In Java, object cloning is the process of creating a copy of an existing object. The copy, or clone, is a new object with the same state as the original object. Object cloning can be useful in a variety of situations, such as when you need to create a backup copy of an object, or when you want to create a copy of an object to be used in a multi-threaded environment.

Java provides a mechanism for object cloning through the Cloneable interface and the clone() method. The Cloneable interface is a marker interface, which means it doesn't have any methods or fields, but it tells the JVM that the object implementing this interface can be cloned. The clone() method is used to create the clone of the object.

To make a class cloneable, you need to implement the Cloneable interface and override the clone() method. The clone() method should create a new object and copy the state of the current object to the new object.

Here is an example of a class that implements the Cloneable interface and overrides the clone() method:


public class MyClass implements Cloneable {
private int value;

public MyClass(int value) {
this.value = value;
}

public void setValue(int value) {
this.value = value;
}

public int getValue() {
return value;
}

@Override
public Object clone() throws CloneNotSupportedException {
return super.clone(); // Shallow copy
}
}
      

 

Q18. Is it possible to use this() and super() both in the same constructor?

No, it is not possible to use both this() and super() in the same constructor. The reason for this is that this() and super() must be the first statement in a constructor, and you can only have one first statement.

The this() constructor call is used to invoke another constructor in the same class, while the super() constructor call is used to invoke a constructor in the superclass. Since both of these calls must be the first statement in a constructor, it is not possible to use them both in the same constructor.

However, you can use this() or super() in a chain of constructor calls. For example, you can have one constructor that calls another constructor in the same class using this(), and that constructor in turn can call a constructor in the superclass using super(). Here is an example:


          class Main {
int empId;
String empName;
public Main(int id, String name) {
this.empId = id;
this.empName = name;
}

//Copy constructor
public Main(Main emp) {
empId = emp.empId;
empName = emp.empName;
}

public void displayDetails() {
System.out.println("Employee ID:" + empId);
System.out.println("Employee Name:" + empName);
}

public static void main(String[] args) {
Main e1 = new Main(85, "Saurav");
//Create a copy of another object
Main e2 = new Main(e1);
e1.displayDetails();
e2.displayDetails();
}
}
      

 

Q19. What is the difference between this() and super() in Java?

Below are the key differences between this and super.

This Super
1. The current class object is represented by this(). 1. The current instance of a parent/base class is represented by super().
2. used to call the same class's default constructor 2. To invoke the parent/base class's default constructor
3. Used to access the current class's methods. 3. Used to access parent class method.
4. Used for pointing the current class instance 4. Used for pointing the superclass instance
5. Must be the first line of a block 5. Must be the first line of a block

Q20. What is the difference between break and continue statements?

Below are the key differences between break and continue.

Break Continue
Switch and loop (for, while, do while) statements are supported. Only works with loop statements.
When it is executed, it causes the switch or loop statements to terminate. It does not end the loop but instead causes it to jump to the next iteration.
It immediately terminates the innermost enclosing loop or switch. When a continue is used within a loop that is nested with a switch statement, the next loop iteration is executed.

Q21. What is a copy constructor in Java?

A member function called copy constructor is used to initialize an object with another object of the same class. Because all objects in Java are passed by reference, there is no need for a copy constructor. Furthermore, Java does not provide automated pass-by-value pass-through.


          class Main {
int empId;
String empName;
public Main(int id, String name) {
this.empId = id;
this.empName = name;
}

//Copy constructor
public Main(Main emp) {
empId = emp.empId;
empName = emp.empName;
}

public void displayDetails() {
System.out.println("Employee ID:" + empId);
System.out.println("Employee Name:" + empName);
}

public static void main(String[] args) {
Main e1 = new Main(85, "Saurav");
//Create a copy of another object
Main e2 = new Main(e1);
e1.displayDetails();
e2.displayDetails();
}
}
      
  • Employee ID:85
  • Employee Name:Saurav
  • Employee ID:85
  • Employee Name:Saurav

Q22. Is it possible to use a non-static variable in a static context?

In Java, it is not possible to use a non-static variable in a static context. This is because non-static variables are associated with a specific instance of a class, while static variables are associated with the class itself. A static context is a context where there is no instance of the class available, such as in a static method or a static block.

Attempting to use a non-static variable in a static context will result in a compilation error. For example, consider the following code:


public class MyClass {

private int value;




public static void myStaticMethod() {

System.out.println(value); // Compilation error

}

}
      

In this code, we are attempting to use the non-static variable value in a static method myStaticMethod(). This will result in a compilation error, since value is not associated with the class itself, but with instances of the class.

Q23. Why do we mark the main method as static in Java?

In Java, we mark the main method as static because it allows the method to be called without creating an instance of the class. When a Java program is run, the JVM looks for a main method with a specific signature (public static void main(String[] args)) to begin executing the program. Since the main method is the entry point of the program, it must be accessible without creating an object of the class.

Marking the main method as static ensures that the method belongs to the class itself, and not to a specific instance of the class. This allows the JVM to call the method without creating an instance of the class first. If the main method were not static, the JVM would have to create an instance of the class to call the method, which would be unnecessary since the main method typically does not require access to instance variables or methods.

Q24. What is Inheritance?

Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class to inherit properties and behavior from a parent class. In Java, inheritance is implemented using the extends keyword.

When a class inherits from a parent class, it automatically includes all the public and protected members of the parent class in its own definition. This includes fields, methods, and nested classes. The child class can also define its own fields and methods, and can override the behavior of the parent class methods using the @Override annotation.

Inheritance creates a hierarchical relationship between classes, where each child class is more specialized than its parent class. This allows for code reuse and modularization, since common functionality can be defined in a parent class and inherited by multiple child classes.

Q25. What are the different types of inheritance in Java?

In Java, there are five types of inheritance:

  1. Single inheritance: This is the most common type of inheritance, where a subclass extends a single parent class. The subclass inherits all the fields and methods of the parent class, and can also override the parent class methods.

  2. Multilevel inheritance: This is where a subclass inherits from a parent class, and then another subclass inherits from that subclass. In this way, a chain of inheritance is created, where each subclass inherits from its immediate parent class.

  3. Hierarchical inheritance: This is where multiple subclasses inherit from a single parent class. In other words, a single-parent class is the superclass of multiple subclasses.

  4. Multiple inheritance (through interfaces): This is where a subclass implements multiple interfaces, each of which defines a set of methods that the subclass must implement. This allows the subclass to inherit behavior from multiple sources, without the potential conflicts that can arise with multiple inheritance of implementation.

  5. Hybrid inheritance: This is a combination of any two or more types of inheritance. For example, a subclass might use single inheritance to inherit from a parent class, and then use multiple inheritance through interfaces to inherit from multiple interfaces.

It's important to note that Java does not support multiple inheritance of implementation (i.e., where a subclass inherits from multiple parent classes that define the same method with different implementations). However, it does allow multiple inheritance through interfaces, as described above.

Q26. Why is multiple inheritances not supported in Java?

Multiple inheritances occur when a child class inherits properties from several other classes. Extending several classes in Java is not possible.

Multiple inheritances have the drawback of making it difficult for the compiler to decide which method from the child class to execute at runtime if multiple parent classes have the same method name.

As a result, multiple inheritances in Java are not supported. The Diamond Problem is a well-known name for the issue. If you have any difficulties answering these Java interview questions, please leave a remark below.


import java.io.*;

class classP {
public void display() {
System.out.println("Class P");
}
}
class classQ {
public void display() {
System.out.println("Class Q");
}
}
class Main extends classP, classQ {
public static void main(String[] args) {
Main obj = new Main();
obj.display();
}
}
      

Q27. How will you implement method overloading in Java?

Method overloading is a feature in Java that allows a class to have multiple methods with the same name, but different parameter lists. This allows a class to provide different methods that perform similar operations, but with different inputs.

To implement method overloading in Java, you can define multiple methods with the same name in a class, but with different parameters. The parameters can differ in their number, type, or order. When you call the method, Java determines which method to call based on the number and types of the arguments passed to the method.

Here is an example of method overloading in Java:


public class MathUtils {
public static int add(int x, int y) {
return x + y;
}

public static double add(double x, double y) {
return x + y;
}

public static int add(int x, int y, int z) {
return x + y + z;
}
}
      

 

In this example, the MathUtils class defines three methods with the same name, add(), but with different parameter lists. The first add() method takes two int parameters and returns an int result. The second add() method takes two double parameters and returns a double result. The third add() method takes three int parameters and returns an int result.

When you call the add() method, Java determines which method to call based on the types of the arguments you pass to it. For example, if you call MathUtils.add(1, 2), Java will call the first add() method, which takes two int parameters. If you call MathUtils.add(1.0, 2.0), Java will call the second add() method, which takes two double parameters. And if you call MathUtils.add(1, 2, 3), Java will call the third add() method, which takes three int parameters.

By overloading the add() method with different parameter lists, the MathUtils class provides a flexible and convenient way to perform addition with different types and numbers of inputs.

Q28. What is Polymorphism?

"One interface, many implementations" is a precise description of polymorphism. Polymorphism is the ability to ascribe a distinct meaning or usage to something in different situations - especially, the ability to have many forms for an item such as a variable, a function, or an object. There are two types of polymorphism

Compile-Time Polymorphism: Method overloading is compile-time polymorphism


          class Calculator

{

int add(int a, int b) {

return a + b;

}

int add(int a, int b, int c) {

return a + b + c;

}

}

public class Main

{

public static void main(String args[]) {

Calculator obj = new Calculator();

System.out.println(obj.add(15, 20));

System.out.println(obj.add(14, 36, 30));

}

}
      
  • 35
  • 80

Run time polymorphism or Dynamic Polymorphism: Inheritance and interfaces are used to implement runtime time polymorphism.


          class A {

public void my() {

System.out.println("Overridden Method");

}

}

public class Main extends A {

public void my() {

System.out.println("Overriding Method");

}

public static void main(String args[]) {

A obj = new Main();

obj.my();

}

}
       

Q29. Can we change the scope of the overridden methods in the subclass?

No, we cannot change the scope of the overridden methods in the subclass. In Java, when a subclass overrides a method of its parent class, it must provide the same method signature (i.e., same method name, return type, and parameter list) as the parent class method. The only thing that can be changed in the overridden method is its implementation.

The scope of a method (i.e., its access modifier) is part of its method signature, and changing the scope of an overridden method in the subclass would change its signature, which would break the inheritance contract.

For example, if a method in the superclass is declared as public, the same method in the subclass cannot be overridden with a narrower scope, such as protected or private. Similarly, if a method in the superclass is declared as protected, the same method in the subclass cannot be overridden with a wider scope, such as public.

However, it is possible to provide a new method in the subclass with a different scope that has the same name as the method in the superclass. This is not overriding, but rather method hiding. Method hiding occurs when a subclass defines a static method with the same name and signature as a static method in the superclass. In this case, the subclass method "hides" the superclass method, and the scope of the subclass method can be different from that of the superclass method.

Q30. What is the difference between method overloading and method overriding in Java?

In Method Overloading, method signature of the same class share the same name but each method must have a different number of parameters or parameters having different types and order.

Method Overloading is to “add” or “extend” more to the method’s behavior.

  • It is a compile-time polymorphism.
  • The methods must have a different signature.
  • It may or may not need inheritance in Method Overloading.

In Method Overriding, the subclass has the same method with the same name and exactly the same number and type of parameters, and the same return type as a superclass.

Method Overriding is to “Change” the existing behavior of the method.

  • It is a run time polymorphism.
  • The methods must have the same signature.
  • It always requires inheritance in Method Overriding.

Q31. What is encapsulation in Java?

Encapsulation in Java is the concept of bundling data (i.e., variables) and methods that operate on that data within a single unit, typically a class. It is one of the fundamental principles of object-oriented programming (OOP) and is often described as "data hiding".

Encapsulation provides several benefits in Java programming, including:

  1. Improved maintainability: Encapsulating data and methods within a class helps to reduce code complexity and makes it easier to maintain and modify the code.

  2. Improved security: By hiding implementation details and providing controlled access to data through methods, encapsulation helps to prevent unintended modifications to the data.

  3. Improved reusability: Encapsulated classes can be easily reused in different programs and systems without the risk of affecting other parts of the code.

In Java, encapsulation is achieved through the use of access modifiers, such as public, private, and protected, to control the visibility of the data and methods within a class. Typically, instance variables are declared as private, and public getter and setter methods are provided to access and modify the data.

Q32. What is an abstraction in Java?

Abstraction in Java is the process of hiding implementation details while showing only the necessary features of an object to the user. It is one of the fundamental concepts of object-oriented programming (OOP) and is used to create simplified and reusable models of complex systems.

In Java, abstraction is achieved through the use of abstract classes and interfaces. Abstract classes are classes that cannot be instantiated directly but can be subclassed to provide concrete implementations of their abstract methods. Abstract methods are methods that are declared in the abstract class but have no implementation. Subclasses of the abstract class must provide concrete implementations of all abstract methods.

Interfaces, on the other hand, are like abstract classes in that they cannot be instantiated directly, but they only contain method signatures and constant values. Interfaces define a set of methods that a class must implement in order to be considered an implementation of the interface.

The main benefit of abstraction is that it helps to manage complexity by hiding implementation details and providing a simplified view of an object or system to the user. Abstraction also makes it easier to modify and maintain code, since changes to the implementation of an abstract class or interface can be made without affecting the rest of the system.

Q33. How to create a singleton class in Java?

A singleton class is one for which only one object can be created. You can make a singleton class by making its constructor private, which restricts the object's creation. Provide a static method for getting an object instance, so you may handle object creation entirely within the class. We're using a static block to create an object in this example.


          public class Main {

private static Main myObj;

static{
myObj = new Main();
}
private Main(){

}
public static Main getInstance(){
return myObj;
}

public void test(){
System.out.println("Hello");
}

public static void main(String a[]){
Main ms = getInstance();
ms.test();
}
}
      

Q34. Can you override a private or static method in Java?

In Java, it is not possible to override a private method in a subclass because private methods are not visible to subclasses. Private methods are only accessible within the class where they are declared, and they cannot be accessed or overridden by any other class, including subclasses.

Similarly, it is not possible to override a static method in a subclass because static methods are associated with a class, not an instance of a class. When a subclass defines a static method with the same signature as a static method in the superclass, it simply hides the superclass method instead of overriding it.

However, it is possible to provide a new implementation for a static method in a subclass by declaring a static method with the same name and signature in the subclass. In this case, the static method in the subclass will be called instead of the static method in the superclass when the method is invoked on the subclass.

In summary, it is not possible to override a private or static method in Java. Private methods are not visible to subclasses, and static methods are associated with a class, not an instance of a class. However, it is possible to provide a new implementation for a static method in a subclass by declaring a static method with the same name and signature in the subclass.

Q35. Explain the difference between static and dynamic binding

In Java, binding is the process of connecting a method call to the method code that implements it. There are two types of binding in Java: static binding and dynamic binding.

Static binding, also known as early binding, is a type of binding that occurs at compile time. In static binding, the method call is bound to the method implementation based on the type of the reference variable used to invoke the method. The method to be called is determined at the time of compilation, and the same method is called every time the program runs.

For example, consider the following code:


          public class A {
public void method() {
System.out.println("Method in class A");
}
}

public class B extends A {
public void method() {
System.out.println("Method in class B");
}
}

public class Main {
public static void main(String[] args) {
A obj = new B();
obj.method();
}
}
      

In this example, the method call obj.method() is statically bound to the method() implementation in class A at compile time because the reference variable obj is of type A. Therefore, the output of this program will be "Method in class A", even though the object being referred to is of type B.

Dynamic binding, also known as late binding, is a type of binding that occurs at runtime. In dynamic binding, the method call is bound to the method implementation based on the actual type of the object at runtime. The method to be called is determined at runtime, and the same method may not be called every time the program runs.

Q36. What do you mean by an interface in Java?

In Java, an interface is a collection of abstract methods and constant variables that can be implemented by a class. An interface specifies a set of behaviors that a class must implement if it claims to implement that interface.

An interface can be declared using the interface keyword and can contain method signatures, default methods, static methods, and constant variables. A method signature in an interface is a method declaration without an implementation, which means that the method does not have a body. The class that implements the interface must provide the implementation for all of the methods in the interface.

Q37. Is it allowed to mark a method abstract as well as a final?

No, it is not possible to mark a method as both abstract and final in Java.

An abstract method is a method that does not have a body and is intended to be overridden by the implementing class, while a final method is a method that cannot be overridden by any subclass. These two modifiers have opposite meanings and cannot be used together in the same method declaration.

When a method is marked as abstract, it means that the method must be implemented by the subclass, whereas marking a method as final means that it cannot be overridden by the subclass. Therefore, it would be contradictory to mark a method as both abstract and final.

If a class has an abstract method that needs to be implemented by the subclass but should not be overridden by any further subclass, then the method can be marked as final in the subclass, but not in the abstract superclass.

Q38. Is it allowed to mark an interface method as static?

Yes, it is allowed to mark an interface method as static in Java.

In Java 8 and later versions, interfaces can contain static methods. A static method in an interface is declared using the static keyword and can have a body.

Here is an example of an interface with a static method:


          public interface ExampleInterface {
void exampleMethod();
static void staticMethod() {
System.out.println("This is a static method in the interface.");
}
}
      

In this example, the ExampleInterface interface contains an abstract method exampleMethod() and a static method staticMethod().

Q39. What is the difference between abstract class and interface in Java?

Below are the key differences between abstract class and interface

Abstract Class Interface
An abstract class can include both complete default code and information that must be customized. An interface can only give the signature, not any code.
Non-abstract methods can exist in an abstract class. An Interface's methods are all abstract.
A class can only extend one abstract class in the case of an abstract class Several interfaces can be implemented by a single class.
Instance variables can exist in an abstract class. Instance variables are not allowed in an interface.
The abstract keyword is used to declare an abstract class. The interface keyword is used to declare the interface.

Q40. What are the main uses of the 'this' keyword?

In Java, the this keyword refers to the current instance of the class in which it appears. Here are some of the main uses of the this keyword:

  1. To differentiate between instance variables and local variables: If a method or constructor parameter has the same name as an instance variable, the this keyword can be used to refer to the instance variable instead of the local variable. For example, this.name refers to the instance variable name, whereas name refers to the local variable.

  2. To call another constructor in the same class: Using this() with appropriate arguments can call another constructor in the same class. This is called constructor chaining and is a useful technique for avoiding code duplication and ensuring that all constructors initialize the object consistently.

  3. To pass the current object as a parameter: The this keyword can be used to pass the current object as a parameter to a method or constructor. This can be useful in situations where the current object needs to be used in the method or constructor, such as when setting up listeners or callbacks.

  4. To return the current object from a method: The this keyword can be used to return the current object from a method, which allows for method chaining. Method chaining is a technique where multiple method calls are chained together in a single statement, which can improve code readability and reduce the amount of code required.

Overall, the this keyword is a powerful tool for working with Java classes and instances, and is commonly used to differentiate between local and instance variables, call other constructors, pass the current object as a parameter, and return the current object from a method.

Q41. Can a class be marked final in java?

In Java, a class can be tagged as final. A class that has been declared as final cannot be extended or inherited. Trying to do so will result in compilation error. 


final class Vehicle {

public void speed() {

System.out.println("Default speed");

}

}

public class Car extends Vehicle{

public static void main(String[] args) {

}

}
      

 

The type Car cannot subclass the final class Vehicle

Q42. Is it allowed to declare the main method as final?

Yes, it is allowed to declare the main method as final in Java. However, it doesn't have any practical use because the main method is typically the entry point for a Java program and is called by the Java Virtual Machine (JVM) to start the program. Since the main method is called by the JVM and not by any other part of the program, there is no need to override or prevent it from being overridden using the final keyword.

In general, the final keyword is used to prevent a method, class, or variable from being modified or overridden. While it is allowed to use the final keyword with the main method, it is not a common practice and does not have any practical benefits in most cases.

Q43. What is the purpose of package in Java?

In Java, a package is a namespace that helps to organize related classes and interfaces. The purpose of a package is to group related classes, interfaces, and other resources together in a single, named unit, which can be used to avoid naming conflicts and provide better organization and modularity for the code.

Here are some of the main purposes of packages in Java:

  1. Avoiding naming conflicts: Since package names are unique, using packages can help to avoid naming conflicts between classes and interfaces that have the same name in different packages. This is particularly useful when integrating third-party libraries into a project, as it can help to avoid naming conflicts between different libraries.

  2. Better organization and modularity: By grouping related classes and interfaces together in a single package, it can be easier to understand and navigate the codebase. This can also help to improve modularity, as packages can be used to separate different parts of the code and provide a clear separation of concerns.

  3. Access control: Packages can be used to control access to classes and interfaces by using access modifiers such as public, private, protected, and default. This allows you to restrict access to certain classes and interfaces to specific packages or modules, which can help to improve security and encapsulation.

  4. Improved code reuse: By grouping related classes and interfaces together in a package, it can be easier to reuse code across different parts of the codebase. This is particularly useful when creating libraries or frameworks that can be reused across different projects or modules.

Overall, packages are an important concept in Java that help to provide better organization and modularity for code, avoid naming conflicts, control access to classes and interfaces, and improve code reuse.

Q44. What is a static import in Java?

Static import is similar to normal import declaration. Normal import allows us to import classes from packages without using package qualifiers. A static import allows us to import static members from a class without using a class qualifier.


          import static java.lang.Math.*;
import static java.lang.System.*;
public class Main {
public static void main(String[] args) {
out.println(sqrt(16));
out.println(abs(6.9));
out.println(pow(5, 2));
}
}
  • 4.0
  • 6.9
  • 25.0

Q45. What is the purpose of the process of serialization?

Serialization is the process of converting an object into a byte stream that can be saved to a file, sent over a network, or stored in a database. The main purpose of serialization is to enable the state of an object to be saved and restored at a later time, without losing any of its data or functionality.

Here are some of the main purposes of serialization in Java:

  1. Persistence: By serializing objects, you can save their state to a file or database, and then reload the state at a later time. This is useful for applications that need to store data between sessions or across different instances of the application.

  2. Network communication: By serializing objects, you can send them over a network as a byte stream, and then deserialize them on the other end to reconstruct the original object. This is useful for client-server applications that need to exchange data over a network.

  3. Caching: By serializing objects, you can cache them in memory or on disk, and then reload the serialized state when needed. This can help to improve performance and reduce the amount of time needed to recreate the object from scratch.

  4. Deep cloning: By serializing and deserializing an object, you can create a deep copy of the object, which can be useful for creating copies of complex objects that would be difficult or time-consuming to recreate from scratch.

Overall, the main purpose of serialization is to enable the state of an object to be saved and restored at a later time, which can be useful for persistence, network communication, caching, and deep cloning.

Q46. What are the uses of Reflection in Java?

Reflection is a powerful feature in Java that allows you to inspect and manipulate the runtime behavior of a program. Here are some of the main uses of reflection in Java:

  1. Dynamic loading: Reflection allows you to load classes and invoke their methods dynamically, without knowing the names of the classes or methods at compile time. This can be useful for creating flexible, configurable applications that can load and execute code at runtime.

  2. Debugging: Reflection allows you to inspect the properties and methods of objects at runtime, which can be useful for debugging and troubleshooting applications.

  3. Introspection: Reflection allows you to examine the structure and properties of classes and objects at runtime, which can be useful for building tools and frameworks that need to work with complex, dynamic data structures.

  4. Frameworks: Reflection is used extensively in many Java frameworks, such as Spring and Hibernate, to provide flexible, customizable behavior based on the runtime state of the application.

  5. Testing: Reflection can be used in testing frameworks to create and manipulate objects at runtime, allowing you to test different scenarios and edge cases that might be difficult to simulate otherwise.

Q47. What is Garbage Collection in Java?

Garbage Collection in Java is the automatic process of reclaiming the memory occupied by the objects that are no longer in use by the program. In Java, the memory is allocated on the heap for the objects created by the program. However, it is the responsibility of the JVM to manage the memory on the heap and release it when it is no longer needed. This is where Garbage Collection comes into play.

The Garbage Collection process identifies the objects that are no longer in use by the program and deallocates the memory associated with them. This process is automatic and transparent to the developer. The developer does not need to explicitly free the memory occupied by the objects, as it is done by the Garbage Collector.

The Garbage Collector works by periodically scanning the heap for objects that are no longer in use. When it identifies such objects, it marks them as "garbage" and releases the memory occupied by them. The Garbage Collector uses different algorithms to identify the objects that are no longer in use, such as reference counting and tracing.

One of the main advantages of Garbage Collection in Java is that it eliminates the need for manual memory management, which can be error-prone and time-consuming. It also reduces the risk of memory leaks and other memory-related issues, which can cause the program to crash or behave unpredictably.

However, Garbage Collection also has some drawbacks, such as the fact that it can affect the performance of the program by introducing pauses during the Garbage Collection process. To mitigate these issues, Java provides various options for tuning the Garbage Collection process, such as setting the heap size and choosing different Garbage Collector algorithms.

Q48. What are the different types of garbage collectors in Java?

Garbage collection is Java software that aids in the management of implicit memory. Because the new keyword in Java allows you to build dynamically formed objects, which will use memory once they are created. When the operation is finished and there are no more references to the object, Java uses garbage collection to delete it and free up the memory it has taken up. Garbage collectors come in four types in Java:

  • Serial Garbage Collector
  • Parallel Garbage Collector
  • CMS Garbage Collector
  • G1 Garbage Collector

Q49. Why do we use finalize() method in Java?

The finalize() method in Java is a method that is invoked by the garbage collector before an object is reclaimed by the memory. The purpose of the finalize() method is to provide an opportunity for an object to perform any necessary cleanup actions before it is destroyed.

The finalize() method is called by the garbage collector when it determines that there are no more references to the object. This can happen when the object is no longer in use by the program or when the program is terminated.

Some common uses of the finalize() method include releasing resources such as file handles, database connections, or network connections. It can also be used to perform any necessary cleanup actions that need to be performed before an object is destroyed, such as closing streams or freeing memory.

However, it is important to note that the finalize() method should be used with caution. In general, it is not recommended to rely on the finalize() method for important cleanup tasks, as it is not guaranteed to be called in a timely manner or at all. Instead, it is recommended to use other mechanisms such as try-finally blocks or the AutoCloseable interface to ensure that resources are properly released.

Furthermore, the use of the finalize() method can also negatively impact the performance of the program, as it can cause delays in the garbage collection process. Therefore, it is generally recommended to avoid using the finalize() method unless it is absolutely necessary.

Q50. What is the difference between an Inner class and subclass in Java?

In Java, an inner class and a subclass are two different concepts, although they share some similarities.

An inner class is a class that is defined inside another class. It has access to the variables and methods of the outer class, and can be used to encapsulate related functionality within the outer class. Inner classes are often used to implement callbacks or event handlers, as well as to implement data structures such as linked lists or trees.

On the other hand, a subclass is a class that is derived from another class, called the superclass. The subclass inherits all the variables and methods of the superclass, and can also add new variables and methods or override the ones inherited from the superclass.

The main difference between an inner class and a subclass is that an inner class is defined within the scope of another class, while a subclass is defined in a separate file or in the same file as the superclass but outside its scope.

Another important difference is that an inner class can access the private variables and methods of its outer class, while a subclass can only access the protected and public variables and methods of its superclass.

In summary, an inner class is used to encapsulate related functionality within an outer class, while a subclass is used to extend and modify the behavior of a superclass.

Q51. What is Java String Pool?

The Java String Pool is a pool or a cache of String literals stored in the heap memory. In other words, it is a collection of String objects that are stored in a special memory area in the heap memory called the String constant pool.

The String constant pool is a part of the JVM's memory where String literals are stored. When a String literal is declared in a Java program, it is stored in the String constant pool instead of the heap memory. This is done to improve performance and conserve memory.

When a new String object is created using a String literal, the JVM first checks the String constant pool to see if the String object already exists. If it does, the existing object is returned. If it doesn't exist, a new String object is created and added to the pool.

The String constant pool is a special feature of Java and is used to optimize the use of memory. Because String objects are used frequently in Java programs, storing them in a separate memory area allows for faster access and better performance.

It's important to note that the String constant pool is different from the regular heap memory used to store other objects. While objects in the regular heap can be garbage collected when they are no longer needed, objects in the String constant pool remain there until the program terminates.

Q52. Why is a string object considered immutable in Java?

A string object is considered immutable in Java because once it is created, its state cannot be changed. This means that the value of the private string object cannot be modified, and any attempt to modify it will result in the creation of a new string object.

There are several reasons why private strings are made immutable in Java:

  1. Security: Because strings are used to store sensitive information such as passwords or user credentials, making them immutable ensures that their actual values cannot be changed accidentally or intentionally, which helps to improve security.

  2. Thread-safety: Because strings are immutable, they can be safely shared among multiple threads without the risk of data corruption or synchronization issues.

  3. Performance: Immutable objects are often more efficient because they can be cached and reused, which reduces memory usage and improves performance.

  4. Simplifies coding: Immutable strings simplify coding by eliminating the need to worry about accidental modification or synchronization issues, which makes code easier to write and debug.

In summary, the immutability of string objects in Java provides several benefits in terms of security, thread-safety, performance, and simplicity, making them a valuable tool in Java programming.

Q53. What is bufferreader in Java?

BufferedReader is a class in Java that is used to read text from a character-input stream, such as a file or network connection, and buffer the input for efficient reading.

BufferedReader provides a readLine() method which reads a line of text from the input stream and returns it as a String. It also provides other methods for reading individual characters or byte arrays.

The advantage of using BufferedReader is that it reads data from a file or input stream in a buffered way, which means that it reads larger chunks of data at once, reducing the number of I/O operations and improving performance.

Here is an example of using BufferedReader to read text from a file in Java:


try (BufferedReader br = new BufferedReader(new FileReader("file.txt"))) {
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
      

Q54. What is the basic difference between a String and StringBuffer object?

The main difference between a String and a StringBuffer object in Java is that a String object is immutable, while a StringBuffer object is mutable.

This means that when you create a String object, you cannot change its contents once it has been created. Any operation that appears to modify the string actually creates a new String object.

On the other hand, when you create a StringBuffer object, you can modify its contents without creating a new object. This is because the StringBuffer class provides methods for appending, inserting, deleting, and replacing characters in the buffer.

Another important difference is that String objects are thread-safe, while StringBuffer objects are not. This means that if multiple threads access a StringBuffer object concurrently, you may get unexpected results.

Q55. What is the use of the toString() method in Java?

In Java, the toString() method is used to get a string representation of an object. By default, the toString() method returns a string that includes the class name, followed by an "at" sign (@), followed by the hexadecimal representation of the object's hash code.

However, the toString() method can be overridden by a class to provide a more meaningful string representation of the object. For example, a Person class might override toString() to return a string that includes the person's name and age.

The toString() method is commonly used in Java to print objects to the console or to concatenate objects into strings. Many Java classes, such as ArrayList and HashMap, override toString() to provide a string representation of their contents.

In addition, some Java libraries and frameworks, such as Jackson and Gson, use toString() to serialize Java objects to JSON or other formats. By providing a custom toString() method, a class can control how it is represented in the serialized output.

56. What is the difference between String Buffer and StringBuilder?

Below are the key differences between StringBuffer and StringBuilder

No. StringBuffer StringBuilder
1) StringBuffer is thread-safe since it is synchronized. It indicates that two threads can't call the StringBuffer functions at the same time.  StringBuilder is not thread-safe since it is not synchronized. It indicates that two threads can call StringBuilder's methods at the same time.
2) StringBuffer is less efficient than StringBuilder. StringBuilder is more efficient than StringBuffer.
3) In Java 1.0, the StringBuffer class was introduced In Java 1.5, the StringBuilder class was introduced.

57. What is the difference between an Error and an Exception?

Here's a table summarizing the key differences between Error and Exception in Java:

Error Exception
Extends the Throwable class Also extends the Throwable class
Indicates a severe system-level error that should not be caught or recovered from Indicates a less severe error that can be caught and potentially recovered from
Examples include OutOfMemoryError, StackOverflowError, NoClassDefFoundError Examples include NullPointerException, ArrayIndexOutOfBoundsException, IOException
Typically caused by circumstances outside the control of the program Typically caused by incorrect usage of a library or API, or incorrect program logic
Generally indicates a serious problem that may require intervention by a system administrator Generally indicates a recoverable problem that can be handled by the program itself
Usually cannot be handled or recovered from within the program Usually can be handled or recovered from within the program, either by catching the exception or allowing it to propagate up the call stack

In summary, Error indicates a severe system-level error that generally cannot be handled within the program, while Exception indicates a less severe error that can often be caught and handled within the program.

58. In Java, what are the differences between a Checked and an Unchecked Exception?

  • Checked Exception: Checked exceptions are all classes that extend the Throwable class except RuntimeException and Error. Checked exceptions are checked during the compilation process. IOException, SQLException, and other exceptions are examples.
  • Unchecked Exception: Unchecked exceptions are the classes that extend RuntimeException. At compilation time, unchecked exceptions are not checked. ArithmeticException, NullPointerException, and other exceptions are examples.

59. What are the differences between 'throw' and 'throws'?

Below are the key differences between throw and throws keyword:

throw keyword throws keyword
To explicitly throw an exception, use the throw keyword. For method declaration; to declare an exception, use the throws keyword.
Throwing only will not propagate checked exceptions. Throws can be used to propagate checked exceptions.
Throw is followed by an instance. Throws is followed by class.
Throw is used within the method. The method signature includes the keyword throws.
You cannot throw multiple exceptions. Multiple method declaration- many exceptions can be declared, for example, public void method() throws IOException, SQLException.

60. What is the use of finally block in Java?

A finally block is always performed in Java, according to the standard, whether or not an error happens, or if an exception is handled or not handled. It aids in the cleaning of transactions such as rollbacks and closes. Make a connection, close a file, and so forth.


          try {

int var = 6;

} catch (Exception exception) {

System.out.println("Exception occurred");

} finally {

System.out.println("Execution of finally block");

}
       

61. What is the exception hierarchy in Java?

In Java, the Throwable class is the root of the exception hierarchy. The Throwable class has two main subclasses:

  1. Error: This class represents serious problems that a reasonable application should not try to catch. Examples of Error include OutOfMemoryError and StackOverflowError.
  2. Exception: This class represents problems that can be caught and handled by an application. The Exception class has many subclasses that are used to represent different types of exceptions, such as IOException and NullPointerException.

The RuntimeException class is a subclass of Exception and represents exceptions that can occur during the normal operation of the JVM. Examples of RuntimeException include NullPointerException, IllegalArgumentException, and ArrayIndexOutOfBoundsException.

62. Do we have to always put a catch block after a try block?

No, it's not always necessary to put a catch block after a try block in Java. However, if a try block is used, then one of the following must be included:

  1. A catch block: This is used to handle any exceptions that may be thrown within the try block. The catch block must specify the type of exception it is catching, and can include code to handle the exception.
  2. A finally block: This is used to ensure that certain code is executed regardless of whether an exception is thrown or not. The finally block is always executed, even if an exception is thrown and caught by a catch block.

It's also possible to use both a catch block and a finally block together.

However, if neither a catch block nor a finally block is used after a try block, then the code will not compile. In this case, the try block is unnecessary and can be removed.

63. How Multi-threading works in Java?

In Java, multi-threading allows multiple threads of execution to run concurrently within a single program. Each thread is an independent path of execution that runs concurrently with other threads in a program, allowing for better utilization of CPU resources and improved application performance.

Java implements multi-threading using the Thread class and the Runnable interface. The Thread class represents a single thread of execution, and the Runnable interface defines the run() method that is executed when a thread is started.

To create a new thread in Java, you can either extend the Thread class and override its run() method, or you can implement the Runnable interface and pass an instance of the implementation to a Thread constructor. Once a thread is created, it can be started by calling its start() method. This causes the run() method to be executed on a separate thread of execution.

Java provides various methods for controlling the execution of threads, such as sleep(), wait(), and notify(). These methods allow threads to synchronize and communicate with each other, as well as pause and resume their execution.

However, multi-threading can also introduce concurrency issues, such as race conditions and deadlocks, if not properly managed. It's important to use synchronization and other thread-safe programming techniques to avoid these issues and ensure correct program behavior.

64. What is a Thread? What are the two ways to create a thread?

In Java, a thread is an independent path of execution within a program. A thread represents a single sequential flow of control within a program's execution.

There are two ways to create a thread in Java:

  1. By extending the Thread class: You can create a new thread by extending the Thread class and overriding its run() method to define the code that will be executed by the thread. You can then create an instance of the subclass and start the thread using the start() method.

    
              public class MyThread extends Thread {
    public void run() {
    // code to be executed by the thread
    }
    }
    
    // create and start a new thread
    MyThread thread = new MyThread();
    thread.start();
          
  2. By implementing the Runnable interface: You can also create a new thread by implementing the Runnable interface and defining the code to be executed by the thread in the run() method. You can then create an instance of the implementation and pass it to a new Thread object, which can be started using the start() method.
    
              class Animal {
    public Animal getAnimal() {
    return this;
    }
    }
    
    class Cat extends Animal {
    public Cat getAnimal() {
    return this;
    }
    }
          

Both methods are equally valid, but implementing the Runnable interface is often preferred over extending the Thread class, as it allows for greater flexibility and better separation of concerns. Additionally, Java only allows single inheritance, so extending the Thread class may not be possible in certain situations where you need to inherit from another class.

65. What is a Thread’s priority and how it is used in scheduling?

In Java, a thread's priority is an integer value that represents the relative importance of the thread to the thread scheduler. Thread priority values range from 1 (lowest priority) to 10 (highest priority), and can be set using the setPriority() method of the Thread class.

When multiple threads are ready to execute, the thread scheduler selects one thread to execute based on its priority and other factors such as the availability of system resources. Generally, threads with higher priority values are more likely to be selected for execution before threads with lower priority values. However, the actual behavior of thread scheduling is dependent on the underlying operating system and JVM implementation and may vary.

It's important to note that thread priority is not a guarantee of execution order or behavior, and should not be relied on to ensure correct program behavior. In addition, setting thread priority to maximum or minimum values may cause unexpected behavior or performance issues.

In general, thread priority should be used judiciously and only when necessary. In most cases, it is better to write code that is independent of thread priority and can execute correctly regardless of the scheduling order of threads.

66. Explain the thread lifecycle in Java?

In Java, a thread goes through several states during its lifecycle, which are represented by the Thread.State enumeration. The possible states are:

  1. NEW: A thread is in this state when it has been created but not yet started with the start() method.
  2. RUNNABLE: A thread is in this state when it has been started and is ready to run, but may or may not be currently executing depending on the thread scheduler.
  3. BLOCKED: A thread is in this state when it is waiting for a monitor lock to be released by another thread.
  4. WAITING: A thread is in this state when it is waiting indefinitely for another thread to perform a specific action.
  5. TIMED_WAITING: A thread is in this state when it is waiting for a specific period of time for another thread to perform a specific action.
  6. TERMINATED: A thread is in this state when it has completed execution either by reaching the end of its run() method or by being terminated prematurely.

The transition between these states is controlled by the JVM and the thread scheduler. When a thread is created with the new keyword, it is in the NEW state. After calling the start() method, the thread transitions to the RUNNABLE state and is added to the thread scheduler's queue of ready threads.

When a thread is executing, it can transition back and forth between the RUNNABLE state and other states such as BLOCKED, WAITING, and TIMED_WAITING, depending on the actions of other threads and the availability of system resources.

Finally, when a thread completes its execution, it transitions to the TERMINATED state and is removed from the thread scheduler's queue.

It's important to note that the exact behavior and timing of thread state transitions is dependent on the underlying operating system and JVM implementation, and may vary. In addition, thread synchronization and communication mechanisms such as wait(), notify(), and notifyAll() can affect the state transitions of threads.

67. What is synchronization?

In Java, synchronization refers to the coordination of multiple threads to ensure that they access shared resources (such as variables or objects) in a safe and predictable manner. When multiple threads access a shared resource simultaneously, it can lead to race conditions, where the result of the program depends on the order in which the threads execute. Synchronization helps to prevent race conditions by enforcing mutual exclusion: only one thread can access the shared resource at a time.

Java provides several mechanisms for synchronization, including the synchronized keyword, which can be used to create synchronized blocks or methods. When a thread enters a synchronized block or method, it acquires the lock associated with the object that the block or method is synchronized on. Other threads that try to access the same synchronized block or method are blocked until the lock is released by the first thread.

Synchronization can help to ensure that a program is thread-safe, meaning that it works correctly and predictably even when multiple threads are executing concurrently. However, synchronization can also introduce overhead and potential performance issues, especially when multiple threads are contending for the same lock. As a result, it is important to use synchronization judiciously and only when necessary.

68. What is a collection class in Java? List down its methods and interfaces

The collection is a framework in Java that works as an architecture for storing and managing a collection of objects. You may use collections to conduct a variety of operations like searching, sorting, insertion, manipulation, and deletion. The following are some of the features of the Java collection framework:

  • Classes
  • Methods
  • Interfaces

The Java Collection hierarchy is depicted in the graphic below.

69. What is the difference between Collection and Collections Framework in Java?

A Collection is a Java object that holds several elements of the same type in one unit. A single Collection object can access all of these aspects.

Collections Framework in Java is a library that provides a standard architecture for building, updating, and accessing many sorts of collections. There are standard ways for working on a Collection object in the Collections framework that is often used by developers.

70. What are the differences between a List and a Set collection in Java?

 

List

Set

1.

The list implementation allows us to add the same or duplicate elements.

The set implementation doesn't allow us to add the same or duplicate elements.

2.

The insertion order is maintained by the List.

It doesn't maintain the insertion order of elements.

3.

List allows us to add any number of null values.

Set allows us to add at least one null value in it.

4.

The List implementation classes are LinkedList and ArrayList.

The Set implementation classes are TreeSet, HashSet, and LinkedHashSet.

71. In Java, how will you decide when to use a List, Set, or a Map collection

In Java, you would choose to use a List, Set, or Map collection based on the requirements of your specific use case. Here are some guidelines to help you decide which collection to use:

  • List: Use a List when you need to maintain elements in a specific order and allow duplicates. List is an ordered collection that allows you to access elements by their index. If you need to add, remove, or access elements frequently by their position in the list, a List is a good choice. Examples of List implementations include ArrayList, LinkedList, and Vector.

  • Set: Use a Set when you want to maintain a unique set of elements without duplicates. Set does not allow duplicates and does not maintain order. If you need to check whether an element is in the collection, or if you need to add and remove elements frequently without worrying about their order, a Set is a good choice. Examples of Set implementations include HashSet, TreeSet, and LinkedHashSet.

  • Map: Use a Map when you need to associate keys with values, and you want to look up values based on their keys. Map allows you to store key-value pairs, and you can look up the value of a specific key quickly. If you need to add, remove, or look up values frequently based on their keys, a Map is a good choice. Examples of Map implementations include HashMap, TreeMap, and LinkedHashMap.

72. What is the difference between ArrayList and vector in Java?

Below are the key differences between ArrayList and vector

ArrayList Vector
There is no synchronization in the Array List. The vector is synchronized.
Because it is non-synchronized, the Array List is quick. Because Vector is thread-safe, it is sluggish.
When an element is added to the Array List, it increases its Array size by 50%. By default, a vector's array is doubled in size.
The increment size is not specified in the Array List. The increment size is defined by a vector.
Array List can only use an iterator for traversing an Array List. Vector can use both Enumeration and Iterator for traversing.

73. What are the differences between Comparable and Comparator?

Comparable and Comparator are two interfaces in Java that are used to sort objects in a collection based on a specific ordering. The main differences between the two are as follows:

  1. Implementation: The Comparable interface is implemented by the class whose objects need to be sorted, while the Comparator interface is implemented by a separate class that defines the ordering of objects.

  2. Method: The Comparable interface has one method, compareTo(), which compares the current object with another object of the same class. The Comparator interface has one method, compare(), which takes two objects of any class and compares them based on a specific ordering defined by the comparator.

  3. Natural ordering vs custom ordering: The Comparable interface provides a natural ordering for the objects based on the class's internal definition, while the Comparator interface provides a custom ordering that can be defined by the programmer.

  4. Flexibility: The Comparator interface provides more flexibility than Comparable because it allows multiple ways of sorting objects, depending on the specific needs of the program. For example, you can define multiple comparators for the same class to sort objects in different ways.

74. What are the differences between a HashMap and a Hashtable in Java?

Below are the key differences between HashMap and HashTable

HashMap Hashtable
HashMap is not a synchronized collection. If it is used in a multi-thread environment, it may not provide thread safety. A Hashtable is a synchronized collection. Not more than one thread can access a Hashtable at a given moment in time.
One null key and numerous null values are allowed in HashMap There is no such thing as a null key or value in a hashtable.
HashMap is a new class introduced in JDK 1.2. Hashtable is a legacy class.
A HashMap implementation by LinkedHashMap maintains the insertion order of elements A TreeMap sorts the mappings based on the ascending order of keys.
Iterator traverses the HashMap. Enumerator and Iterator traverse the hashtable.
HashMap inherits AbstractMap class. Hashtable inherits Dictionary class.

75. What are the differences between a HashMap and a TreeMap?

Below are the key differences between HashMap and TreeMap

HashMap TreeMap
The Java HashMap implementation of the Map interface is based on hashtables Java TreeMap is a Map interface implementation based on a Tree structure.
HashMap implements Map, Cloneable, and Serializable interfaces. TreeMap implements NavigableMap, Cloneable, and Serializable interfaces.
A single null key and numerous null values are allowed in HashMap TreeMap does not allow null keys, however, multiple null values are allowed.
HashMap allows heterogeneous elements because it does not perform sorting on keys. TreeMap allows homogeneous actual values as a key because of sorting.
The HashMap class uses the hash table. TreeMap internally uses a Red-Black tree, which is a self-balancing Binary Search Tree.
A HashMap uses equals() method to compare keys. A TreeMap uses compareTo() method for maintaining natural ordering.
A HashMap gives constant time performance for operations like get() and put(). A TreeMap gives the order of log(n) time performance for get() and put() methods.

76. What are Wrapper classes in Java?

Wrapper classes are used in Java to allow primitive types to be accessed as objects. Boolean, Integer, Double, Float, and other primitive types have corresponding Wrappers classes – Boolean, Integer, Double, Float, and so on. The automatic conversion of primitive data types into their equivalent Wrapper type is known as boxing and the opposite operation is known as unboxing.

The java.lang. package contains many of these Wrapper classes.

In Java 5.0, the idea of Autoboxing and Unboxing for Wrapper classes was introduced.

77. What is the purpose of the native method in Java?

In Java, the native method is a method that is implemented in a platform-dependent manner, typically in a non-Java programming language such as C or C++. The purpose of the native method is to provide a way to access system-level resources or to perform operations that are not possible or efficient in Java.

Java's platform-independent nature is one of its key features, but there are certain situations where access to system-level resources or native code is required. For example, a native method might be used to interact with hardware devices, such as a printer or a camera, or to perform complex mathematical calculations that are not easily done in Java.

Native methods are declared using the native keyword, and their implementation is typically provided in a shared library or dynamic link library (DLL) that is loaded at runtime. When a native method is called, the Java Virtual Machine (JVM) transfers control to the native implementation, which then executes the code using system-level resources.

Native methods are often used in conjunction with the Java Native Interface (JNI), which provides a way for Java code to interact with code written in other programming languages. JNI allows Java to call native methods and provides a way for native code to call Java code.

78. What is the difference between Shallow Copy and Deep Copy in Java?

In Java, shallow copy and deep copy are two different techniques to copy objects. The main difference between shallow copy and deep copy is that shallow copy only creates a new object that references the original object's memory location, while deep copy creates a new object with a new memory location that has the same values as the original object.

In a shallow copy, the new object that is created shares the same memory location as the original object, so any changes made to the original object will also be reflected in the new object. Shallow copy is performed using the clone() method or copy constructor, which creates a new object and copies the references to the data members of the original object.

In contrast, in a deep copy, a new object is created with its own memory location and all the data members are copied to the new object. Deep copy is performed by manually copying all the fields of the original object into the new object or by implementing the Serializable interface and using object serialization to create a deep copy.

To summarize, the key difference between shallow copy and deep copy in Java is that shallow copy creates a new object that references the same memory location as the original object, while deep copy creates a completely new object with its own memory location and values that are equal to the original object's values to maintain code reusability.

79. What is the difference between Collection and Collections Framework in Java?

In Java, Collection and Collections Framework are related concepts but have different meanings.

Collection is an interface in the Java programming language that represents a group of objects, where each object is a separate entity and can be accessed and manipulated independently of the others. Examples of Collection classes in the Java Collections Framework (JCF) include List, Set, and Queue.

On the other hand, the Collections Framework in Java refers to a set of interfaces, classes, and algorithms provided by the Java library to manipulate collections of objects. The Collections Framework includes several core interfaces such as Collection, List, Set, Queue, Map, and others, as well as their implementing classes such as ArrayList, HashSet, and TreeMap.

80. Why Map interface does not extend the Collection interface in the Java Collections Framework?

The Map interface in the Java Collections Framework (JCF) does not extend the Collection interface because it represents a different kind of data structure than the Collection interface.

A Collection represents a group of objects, where each object is a separate entity and can be accessed and manipulated independently of the others. Examples of Collection classes in the JCF include List, Set, and Queue.

On the other hand, a Map represents a mapping between keys and values, where each key is associated with a single value. The key-value pairs in a Map are not considered separate entities that can be accessed or manipulated independently of each other. Examples of Map classes in the JCF include HashMap, TreeMap, and LinkedHashMap.

Because Maps and Collections represent different kinds of data structures with different characteristics and behaviors, it would not make sense for Map to extend Collection or vice versa. However, both interfaces do share some common methods, such as size() and isEmpty(), which are inherited from the parent interface, Iterable.

81. What is the difference between an Iterator and a ListIterator in Java?

Here is a table that summarizes the main differences between Iterator and ListIterator interfaces in Java:

Iterator ListIterator
Used to iterate over a collection of objects. Used to iterate over a list of objects.
Can only traverse a collection in a forward direction. Can traverse a list in both forward and backward directions.
Provides methods to check if the iteration has more elements, to retrieve the next element, and to remove the current element. Provides methods to check if the iteration has more elements in both forward and backward directions, to retrieve the next and previous elements, and to add and remove elements at the current position.
Cannot modify the underlying collection during iteration. Can modify the underlying list during iteration.
Implemented by the Iterator interface. Implemented by the ListIterator interface, which extends Iterator.

In summary, an Iterator is used to traverse any collection in a forward direction and provides a limited set of methods to retrieve and remove elements, while a ListIterator is used specifically for traversing a list in both directions and provides additional methods to modify the list while iterating.

82. What is the difference between a Set and a Map in Java?

In Java, a Set and a Map are both collection interfaces, but they have some fundamental differences in their usage and behavior.

A Set is a collection that contains unique elements. In other words, it does not allow duplicate elements. The elements in a Set are not ordered, which means they are not stored in any particular order. The most commonly used implementation of the Set interface is the HashSet, which uses a hash table to store the elements. Other implementations of Set include TreeSet and LinkedHashSet.

On the other hand, a Map is a collection that stores key-value pairs. It allows you to retrieve a value based on its corresponding key. Unlike a Set, a Map can contain duplicate values, but it cannot contain duplicate keys. The elements in a Map are not ordered by default. The most commonly used implementation of the Map interface is the HashMap, which uses a hash table to store the key-value pairs. Other implementations of Map include TreeMap and LinkedHashMap.

83. What is Hash Collision? How Java handles hash-collision in HashMap?

Hash Collision occurs when two or more keys in a hash table get the same hash value, resulting in a collision. Java's HashMap uses an array of buckets to store key-value pairs. The hash function is used to map each key to an index in the array. If two keys have the same hash code, they will be stored in the same bucket.

To handle hash collisions in Java's HashMap, the bucket uses a linked list data structure. When a collision occurs, the new key-value pair is added to the bucket's linked list. When retrieving a value, the hash code of the key is used to find the appropriate bucket, and the linked list in that bucket is searched for the key.

In Java 8 and later, if a bucket's linked list grows too long, the list is converted into a balanced tree to improve performance. This is called treeification, and it reduces the search time for keys with hash collisions from O(n) to O(log n).

84. What is the difference between Queue and Stack data structures?

Queue and Stack are both data structures in Java, but they differ in their ordering of elements and the methods used to access those elements.

A Queue is a collection of elements in which an element is added to the end of the queue and removed from the beginning of the queue. It follows the "first-in, first-out" (FIFO) principle. This means that the first element that is added to the queue will be the first one to be removed. In Java, the Queue interface is implemented by classes like LinkedList, PriorityQueue, and ArrayDeque.

On the other hand, a Stack is a collection of elements in which an element is added and removed from the top of the stack. It follows the "last-in, first-out" (LIFO) principle. This means that the last element that is added to the stack will be the first one to be removed. In Java, the Stack class is available in the java.util package.

To summarize, the main difference between a Queue and a Stack is the order in which elements are added and removed. A Queue follows the FIFO principle, whereas a Stack follows the LIFO principle.

85. What is a classloader?

In Java, a class loader is a part of the Java Runtime Environment (JRE) that loads compiled Java classes into the Java Virtual Machine (JVM). It is responsible for loading classes from their bytecode representation and linking them into a running program. The JVM has three built-in class loaders:

  1. Bootstrap Class Loader: It is responsible for loading the core Java classes, such as java.lang, java.util, etc. It is implemented in native code and is a part of the JVM.

  2. Extension Class Loader: It loads classes from the extension directory, which is defined by the java.ext.dirs system property. It is implemented in Java and is a child of the bootstrap class loader.

  3. Application Class Loader: It loads classes from the classpath, which is defined by the java.class.path system property. It is implemented in Java and is a child of the extension class loader.

Class loaders provide a way to dynamically extend the functionality of Java applications by allowing new classes to be loaded at runtime. They also provide a level of security by separating the classes of different applications or modules.

86. What is the covariant return type?

The covariant return type is a feature introduced in Java 5 that allows a subclass method to return a subtype of the return type of the overridden method in the superclass. In simple terms, it allows a method in a subclass to return a more specific type than the method it overrides in the superclass.

For example, consider a class hierarchy where Animal is a superclass and Cat is a subclass. Suppose Animal has a method called getAnimal() that returns an Animal object. If we override this method in the Cat class and return a Cat object instead, then we are using covariant return types.

Here is an example:


class Animal {
public Animal getAnimal() {
return this;
}
}

class Cat extends Animal {
public Cat getAnimal() {
return this;
}
}
      

87. How to create an immutable class in Java?

To create an immutable class in Java, we need to follow the below steps:

  1. Make the class final so that it cannot be extended.

  2. Make all the fields private and final so that they cannot be modified.

  3. Do not provide any setters for the fields.

  4. If the class has mutable fields, then make sure to return a deep copy of the fields in the getter methods.

  5. Provide a public constructor to initialize the final fields.

  6. Override the equals() and hashCode() methods to ensure that the object can be used in collections such as HashSet or HashMap.

  7. Do not provide any methods that can change the state of the object.

Example:


          public final class ImmutablePerson {
private final String name;
private final int age;

public ImmutablePerson(String name, int age) {
this.name = name;
this.age = age;
}

public String getName() {
return name;
}

public int getAge() {
return age;
}

// Override equals() and hashCode() methods

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ImmutablePerson that = (ImmutablePerson) o;
return age == that.age && Objects.equals(name, that.name);
}

@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
      

88. Can you have virtual functions in Java?

Java does not have a virtual keyword like C++ to indicate that a method should be dynamically bound at runtime. However, in Java, all non-private, non-static, and non-final methods are by default virtual functions, which means that the actual method to be called is determined at runtime based on the actual type of the object.

This is because Java uses dynamic method dispatch to resolve the appropriate method to be executed at runtime. When a method is invoked on an object, the JVM determines the actual type of the object and then looks up the appropriate method implementation for that type at runtime.

So, in Java, all non-private, non-static, and non-final methods can be considered virtual functions, since their actual implementation is determined at runtime based on the type of the object they are called on.

89. Mention the uses of the synchronized block

In Java, the synchronized block is used to ensure that only one thread at a time can execute a critical section of code. The synchronized block uses a monitor lock to achieve this, which allows only one thread at a time to acquire the lock and execute the code enclosed in the block.

Here are some of the common uses of the synchronized block in Java:

  1. Thread safety: The synchronized block is commonly used to ensure that access to shared resources is synchronized across multiple threads. This helps prevent race conditions and other synchronization issues that can occur when multiple threads access the same resource concurrently.

  2. Deadlock prevention: The synchronized block can also be used to prevent deadlocks in multi-threaded applications. By ensuring that only one thread at a time can acquire a lock on a shared resource, the likelihood of two threads becoming deadlocked is reduced.

  3. Performance optimization: In some cases, the synchronized block can be used to optimize performance in multi-threaded applications. For example, by synchronizing access to a resource only when necessary, the overhead of locking and unlocking the resource can be reduced, improving the overall performance of the application.

Overall, the synchronized block is a powerful tool for synchronizing access to shared resources in multi-threaded applications, and is commonly used in Java programs to ensure thread safety and prevent synchronization issues.

90. Distinguish between static loading and dynamic class loading?

In Java, class loading is the process of loading a Java class into memory at runtime. There are two types of class loading: static loading and dynamic loading.

  1. Static loading: In static loading, classes are loaded at compile time, and the Java compiler includes them in the byte code of the application. This means that all the classes required by the application are loaded into memory at startup, even if they are not used during the execution of the program. Static loading is the default behavior in Java.

  2. Dynamic loading: In dynamic loading, classes are loaded at runtime when they are needed. Dynamic loading is useful in situations where classes are large or rarely used because it reduces the memory footprint of the application. Dynamic loading is achieved using the Java Class.forName() method or by creating an instance of the ClassLoader class. When the Class.forName() method is called, the class is loaded into memory and initialized. When the ClassLoader class is used, the class is loaded into memory, but not initialized until it is used.

Overall, static loading and dynamic loading are two different approaches to class loading in Java, and both have their own advantages and disadvantages. Static loading is simpler and faster, but requires more memory. Dynamic loading is more flexible and efficient, but requires more complex programming techniques.

91. What are the different scenarios causing "Exception in thread main"?

The following are some examples of frequent main thread exceptions:

  • Exception in thread main java.lang.UnsupportedClassVersionError: This exception occurs when you try to run a java class that was compiled with a different JDK version.
  • Exception in thread main java.lang.NoClassDefFoundError: This exception comes in two flavors. The first is where you give the whole name of the class, including the.class extension. When Class is not identified, the second situation occurs.
  • Exception in thread main java.lang.NoSuchMethodError: main: When you try to launch a class that doesn't have a main function, you'll get this exception.
  • Exception in thread "main" java.lang.ArithmeticException: When an exception is thrown from the main method, the exception is sent to the console. The first section specifies that the main method throws clause an custom exception, the second part publishes the custom exception class name, and the third part displays the exception message after a colon.

92. Explain the externalizable interface.

In Java, the Externalizable interface is an extension of the Serializable interface that provides a way to customize the serialization and deserialization process for an object. Unlike the Serializable interface, which uses a default mechanism for serialization, the Externalizable interface requires that the class explicitly implement the serialization and deserialization methods.

The Externalizable interface defines two methods that must be implemented by the class:

  1. writeExternal(ObjectOutput out): This method is called during serialization and is responsible for writing the object's state to the specified ObjectOutput stream. The order in which the object's state is written is important because it must match the order in which the state is read during deserialization.

  2. readExternal(ObjectInput in): This method is called during deserialization and is responsible for reading the object's state from the specified ObjectInput stream. The order in which the object's state is read must match the order in which the state was written during serialization.

By implementing the Externalizable interface, the class can provide custom logic for serialization and deserialization, such as encrypting or decrypting sensitive data or compressing or decompressing large data objects.

It's important to note that objects that implement the Externalizable interface must have a public no-argument constructor, which is used during deserialization to create a new instance of the object.

Overall, the Externalizable interface provides a way to customize the serialization and deserialization process for Java objects, giving developers greater control over how their objects are stored and transmitted.

93. Can we execute any code, even before the main method?

Yes, we may run any code before calling the main function. When constructing objects at class load time, we will use a static piece of code in the class. Any statements included in this static block of code block will be performed at the same time as the class is loaded, even before any objects are created in the main function.


          public class Main {
static int k;
static {
System.out.println("Inside static block");
k = 10;
}
public static void main(String[] args) {
System.out.println("Inside main method");
System.out.println("Value of k: " + k);
}
}
      
  • Inside static block
  • Inside main method
  • Value of k: 10

94. What is the difference between transient and volatile variables in Java?

  • Transient: The transient modifier instructs the Java object serialization subsystem to skip the field while serializing a class instance. The field will be initialized to the default value when the object is deserialized, which is null for a reference type and zero or false for a primitive type.
  • Volatile: The volatile variable modifier instructs the JVM that updates to the field should always be synchronously flushed to memory, while reads should always be read from memory. This implies that fields defined as volatile in a multi-thread program can be reliably accessed and modified without the need for native or standard library-based synchronization.

95. What is a functional interface in Java?

In Java, a functional interface is an interface that contains exactly one abstract method. Functional interfaces are also known as "SAM" interfaces, which stands for Single Abstract Method interfaces.

Functional interfaces are used to represent functions as objects in Java. They can be used with lambda expressions or method references to create compact, expressive code for functional programming tasks, such as event handling or processing collections of data.

Java 8 introduced the @FunctionalInterface annotation, which can be used to mark an interface as a functional interface. This annotation is not strictly necessary, but it helps to make the intent of the interface clear and enables the Java compiler to check that the interface satisfies the requirements of a functional interface.

Functional interfaces can be found in many places in the Java API, such as the java.util.function package, which provides a set of commonly used functional interfaces, such as Predicate, Function, and Consumer.

Overall, functional interfaces are an important part of modern Java programming and enable developers to write concise and readable code for functional programming tasks.

96. What are the uses of the Java super keyword?

In Java, the super keyword is used to refer to the parent class or superclass. It can be used in various ways to access or invoke members of the parent class. Some of the common uses of the super keyword are:

  1. Invoking a parent class constructor: The super() keyword can be used to call a constructor in the parent class. This is useful when the subclass needs to initialize some of the parent class's fields before continuing with its own initialization.

  2. Accessing parent class members: The super keyword can be used to access the methods and fields of the parent class that are not visible to the subclass due to access static modifiers. This is useful when the subclass needs to override a method or field from the parent class but still needs to access the parent class's version of the method or field.

  3. Overriding parent class methods: The super keyword can be used in a subclass to call a method in the parent class that has been overridden by the subclass. This is useful when the subclass needs to extend or modify the behavior of the parent class's method.

  4. Invoking parent class static members: The super keyword can be used to access static members of the parent class from a subclass. This is useful when the subclass needs to reference a static method or field of the parent class.

Overall, the super keyword is a powerful tool in Java that allows subclasses to access and modify the behavior of their parent classes. It is commonly used in object-oriented programming to implement inheritance and code reuse.

97. What is method overloading with type promotion?

Method overloading with type promotion means, when no matching parameter type of method is found, it implicitly promotes the data type to the next level and calls that corresponding method. For example, if we call a method with a short parameter data type and if there is no matching method with a short type but if Int is present, then it calls the method with Int parameter datatype.


          class Main{
void show(int a){
System.out.println("int method");
}
void show(String a){
System.out.println("string method");
}
public static void main(String[] args) {
Main s = new Main();
s.show('a');
}
}
      

98. What is the Java instanceOf operator?

Java instanceOf operator is a comparison operator that checks if the object is an instance of some type of class. The return value is either true or false. If there is no value, then it returns false. Here is the code for the same: 


public class Main {
public static void main(String[] args) {
String value = "";
Boolean k;
k = (value instanceof String);
System.out.println(k);
}
}
       

99. What is the use of the System class and Runtime class?

The System and Runtime classes in Java are used to interact with the operating system and perform system-level tasks.

The System class provides a set of static methods and variables that allow you to access and modify system properties, environment variables, and standard input/output streams. Some common uses of the System class include:

  • Getting and setting system properties (e.g., System.getProperty() and System.setProperty())
  • Accessing environment variables (e.g., System.getenv())
  • Reading from and writing to the standard input/output streams (e.g., System.out.println() and System.in.read())

The Runtime class provides a way to execute external processes and manage the Java Virtual Machine (JVM) environment. Some common uses of the Runtime class include:

  • Running external processes (e.g., Runtime.getRuntime().exec())
  • Terminating the JVM (e.g., Runtime.getRuntime().exit())
  • Getting the amount of free and total memory available to the JVM (e.g., Runtime.getRuntime().freeMemory() and Runtime.getRuntime().totalMemory())

Both the System and Runtime classes are part of the Java core API and are widely used in Java applications to perform system-level tasks.

100. What is the difference between abstraction and encapsulation?

Abstraction Encapsulation
Abstraction is the process of hiding implementation details from the user and only displaying functionality. The technique of encapsulating code and data into a single unit is known as encapsulation.
Abstraction allows you to concentrate on the object's function rather than how it performs it. Encapsulation gives you control over your data while also protecting it from outside threats.
At the Design Level, abstraction solves the problem. The problem at the Implementation Level is solved through encapsulation.
Interfaces and Abstract Classes are used to implement abstraction. Access Static Modifiers are used to implement encapsulation (private, default, protected, public)
Abstraction refers to the use of interfaces and abstract classes to hide implementation difficulties. Encapsulation refers to the use of setters and getters to hide data.

101. What are the different types of access specifiers in Java?

There are four different types of access specifiers in Java:

  • public: Any class in any package can see it. For a class, variable, or method, we can declare a public access type.
  • protected: It can be accessed from any class in the same package or from the subclass of the declared class. We can gain access to the outside world through inheritance.
  • default: The scope is contained within the package and does not require the use of any keywords.
  • private: It can only be accessible by members of the same class.

Java's easy-to-use syntax and built-in capabilities, as well as the reliability it gives to applications, are the primary reasons for its growing popularity in the software community. These 101 questions will cover the important topics of Java and will surely help you in acing the java interview.

102. What is the difference between the equals () method and the equality operator (==) in Java?

They are used for comparison, however, there are some fundamental differences:

  • Equals () method: This is used to compare the actual content of the object and this type of method cannot be used with primitives. This method can compare conflicting objects utilizing the equals () method and returns “false”. The equals () method can be overridden. 
  • Equality operator (==): This can be used to compare the actual objects and reference values. You can also employ this operator with actual objects and non-primitive data types. However, this operator cannot compare conflicting objects. Therefore, the time compiler surrounds the compile-time error. This operator cannot be overridden.

103. What is Stack Memory?

In Java, stack memory is a region of memory used by the JVM to store method-specific variables and method call information. Each thread in a Java application has its own stack, which is created when the thread is started and destroyed when the thread completes.

The stack memory is used to store local variables, method arguments, and method call frames, which are used to keep track of the current method call and its state. When a method is called, a new stack frame is created on the stack to store the method's local variables and arguments. When the method completes, the stack frame is popped off the stack, and its memory is freed.

The size of the stack memory is determined at the time the JVM is started and can be configured using the -Xss command-line option. By default, the size of the stack memory is relatively small, typically a few hundred kilobytes to a few megabytes, depending on the JVM implementation and platform.

It's important to note that stack memory is different from heap memory, which is used to store actual objects and other data that is not method-specific. The stack memory is generally faster than the heap memory because it uses a last-in first-out (LIFO) data structure that is optimized for rapid allocation and deallocation of memory. However, the stack memory is also more limited in size and cannot be used to store large amounts of data.

104. What is Double Brace Initialisation?

Double brace initialization is a technique in Java that allows you to create and initialize a collection in a single statement using nested braces. The outer braces define an anonymous subclass of the collection type, and the inner braces define an initializer block that adds elements to the collection. Here's an example:


          List names = new ArrayList() {{
add("Alice");
add("Bob");
add("Charlie");
}};
      

In this example, we create a new ArrayList and add three String objects to it using the double brace initialization syntax. The outer braces create an anonymous subclass of ArrayList, and the inner braces define an initializer block that calls the add() method three times to add the String objects.

While double brace initialization can be useful for creating and initializing collections in a concise way, it has some drawbacks. One potential issue is that it creates a new subclass of the collection type for each initialization, which can lead to increased memory usage and slower performance. Additionally, the use of anonymous subclasses can make the code more difficult to read and understand, particularly for developers who are not familiar with the technique hence decreasing the code reusability.

105. Give an instance of dependency injection.

Dependency injection (DI) is a technique used in software engineering to reduce the coupling between different components of a system. It involves injecting the dependencies of an object rather than allowing the object to create them itself. Here's an example of dependency injection in Java:


public class Car {
private Engine engine;

public Car(Engine engine) {
this.engine = engine;
}

public void start() {
engine.start();
}
}

public interface Engine {
void start();
}

public class GasEngine implements Engine {
public void start() {
System.out.println("Starting Gas Engine");
}
}

public class ElectricEngine implements Engine {
public void start() {
System.out.println("Starting Electric Engine");
}
}

public class Main {
public static void main(String[] args) {
// Create a GasEngine object
Engine engine = new GasEngine();

// Create a Car object and inject the GasEngine dependency
Car car = new Car(engine);

// Start the car
car.start();
}
}
      

Practicing these top 100+ Java interview questions and answers will definitely sharpen your knowledge of the subject matter and prep you well to deal with the curveballs your interviewer will throw at you. If you wish to gain insights on newer topics, you might want to check these out:

  1. 8 Highest Paying Jobs For Computer Science Professionals In India
  2. Test Plan vs Test Strategy: What Makes The Two Different?
  3. The Difference Between Static And Dynamic Website Explained!
  4. Difference Between Mealy Machine And Moore Machine [With Comparison Table]
  5. Difference Between Paging And Segmentation Explained!
Umme Kulsum
Associate Content Writer @Unstop

I am a lifelong student of languages, English being the pet favorite, exploring my creative side through content writing. I also like to boogie. When I am not reading, binge-watching, and dancing, you can spot me doing pspspspspss to cats and dogs on the streets.

TAGS
Interview Preparation Computer Science
Updated On: 14 May'23, 11:15 PM IST