Top 100 Java Interview Questions and Answers

Last updated on : Aug 11, 2024 by Shubham Srivastava

Java is the 2nd most popular programming languages as per StackOverflow.com survey report 2024. It is currently being used in over 4 billion devices (including mobile apps and web apps). That’s why we have collected latest Top 100 Core Java Interview Questions of 2024 with their answers and coding solutions. So without any delay, Let’s start preparing Java Interview Questions and Answers to crack any level of interview with so much ease –

Java Interview Questions in 2023 - Latest Java Interview Questions and Answers collection

Table of Contents

Java Interview Questions for Freshers

In this section, we will focus on most popular Java Interview Questions for Freshers having 0 to 2 years of experience in the industry. These questions are taken from different Java Interview Experiences, but there are chances your interviewer twist any of these question and ask it differently. So be little careful while answering. Let’s see the Java Interview Question for Freshers –

Q1. What is Java? Why is Java called as a platform independent language?

Ans –

What is Java?

  • Java is a high-level programming language.
  • It was developed by James Gosling in the year 1982.
  • Java follows the OOPs (Object-Oriented Programming) principles.
  • Java can be used to develop large-scale applications.
  • Currently, Java is owned by Oracle and latest available version was launched in September 2023, which is Java version 21.

Why is Java called a Platform Independent Language?

‘Platform’ means ‘Operating System’. So, Java is operating-system independent because it runs on the Java platform (the JVM): The mantra is “write once, run anywhere”.

Java is both the compiler and interpreter language. When you compile a Java program creates a .class file which is a collection of byte code, these byte codes are not machine instructions instead they are instructions which Java a virtual machine can understand. Since every Java program runs on Java virtual machine, the same byte code can be run on any platform.

The key is byte code is not machine instruction they are platform-independent instruction to JVM.
On another hand, JVM or Java virtual machine is platform-dependent because it converts byte code into
machine level instruction which is platform-specific and Byte code is created when you compile Java program using Java compiler “javac” and byte code runs on JVM which is created by running the “java” command. In detail when you run “java” command it creates Java virtual machine, loads Main class specified in the command line and calls the standard main method in java.

In short, the combination of byte code and JVM makes the Java program platform-independent. Write
once run everywhere was Java’s mantra when it started ruling the programming world in the mid and late ’90s.

Note 💡
Always remember, Java programs are platform independent but JVM is not. That’s why you have different JVM and JRE installations for different platforms like Mac, Windows, Linux, or Solaris. Similarly, there are different JVMs for 32-bit and 64-bit machines.

why java platform independent?

Q2) Why is Java not a pure object oriented programming language?

Ans –

No, Java is not a pure object oriented programming language. Because, we can create a Java Program with using primitive data types such as – byte, boolean, char, short, int, float, long, and double. Hence, it is not a pure Object Oriented Programming language.

Note 💡
Java is not a pure programming language due to presence of primitive data types. But, it also provides a solution to convert those primitive data types into non-primitive data types, using Wrapper classes (such as – Byte, Boolean, Character, etc). These wrapper classes are present in java.lang package, and are used to convert primitive data types into non-primitive data types, and vice-versa.


Q3) Explain the difference between JDK, JVM, JRE in Java?

Ans –

This is one of the most common Java Interview Questions that you might face in almost every Java Programming Interview round of any level (Fresher or Experienced). I’ll suggest you to remember below diagram on JDK, JRE, JVM in Java –

JDK JRE JVM JIT in Java - Explained with example
CategoryJDKJREJVMJIT
PlaceJDK contains JRE, JVM and JIT.

In short,
JDK = Dev. Tools + JRE
JRE contains JVM.

In short,
JRE = JVM + Library
Classes
JVM contains JIT and Interpreter.

In short,
JVM = JIT + Interpreter.
JIT is core part of JVM.
Stand forJDK stands for Java Development Kit.JRE stands for Java Run-Time Environment.JVM stands for Java Virtual Machine.JIT stands for Just-In-Time compiler.
Usagea) JDK provides
Development tools and
Run-time Environment.

Dev. tools refers to some small programs for various crucial tasks, such as –
Compilation, Preparation of
JAR, Docs etc.

b) JDK contains Java
Diff. Dev. Tools and
JRE.

c) Hence, Using JDK, we can develop, compile
and execute new Java
applications.
a) JRE provides only
Run-Time environment. It does not provide any development tools.

b) JRE contains only
JVM and Library classes.

c) Using JRE, we can only execute already developed Java apps, and we can NOT Develop Java apps.
a) JVM is a Java Platform.

b) JVM contains Interpreter + JIT.

c) Using JIT, we can run Java Byte code by converting them into current OS machine language.
a) It is responsible to help Interpreter for executing Java Byte code faster.

Basically, JIT improves the performance of Java Program Execution by compiling the Byte code at runtime.

Q4) How is Java different from C++?

Ans –

There are so many differences between C++ and Java, even if both of them are Object Oriented Programming Language. A few of the major differences are –

Sr. No.C++Java
1.C++ programs are machine dependent. Which means, it can run only in the machine in which the program is compiled.Java programs are machine-independent. Once the Java program gets compiled in a system, we get byte code (.class file). This byte code can be executed in any machine.
2.C++ supports the concept of Multiple inheritance.Java does not support concept of Multiple inheritance.
3.C++ allows users to use pointers in the program.Java does not allow users to use pointers in the program.
4.C++ has characteristics of procedural languages as well as object-oriented languages. Java only contains characteristics of object-oriented languages.
5.C++ supports Operator Overloading feature.Java does not supports Operator Overloading feature.
6.C++ supports both call by value and call by reference.Java supports call by value only. There is no call by reference in Java.
7.C++ is only a compiled language.Java is compiled as well as an interpreted language.

Q5) What are the Top 5 features of the Java 8?

Ans –

In every 6 month, a new Java version gets launch with so many new features. Let’s see what are the Top 5 features of Java 8 –

Top 5 features of Java 8

1. forEach() method in Iterable interface

Java 8 has launch with forEach method in java.lang.Iterable interface so that when we write code, we only focus on the core business logic. The forEach method takes java.util.function.Consumer object as an argument, so it helps in having our business logic at a separate location that we can reuse.

Example –

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

		Iterator<Integer> itr = myList.iterator();
		// Using simple while loop - 
		while(itr.hasNext()){
			Integer i = itr.next();
			System.out.println("Iterator Value::"+i);
		}
		
		// Using forEach method of Iterable with anonymous class -
		myList.forEach(new Consumer<Integer>() {

			public void accept(Integer t) {
				System.out.println("forEach anonymous class Value::"+t);
			}

		});

2. default and static methods in Interfaces

In above example, you might have noticed that forEach method is defined in Iterable interface but we know that interfaces can’t have a method body.

From Java 8, interfaces are upgraded to have a method with implementation as well. We can use default and static keyword to create interfaces with method implementation. forEach method implementation in Iterable interface is:

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

default void forEach(Consumer<? super T> action) {

    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }

}


// Another example of default method in an Interface -
public interface MyInterface {

	void myMethod();
	
	default void myLog(String str){
		System.out.println("MyInterface logging => "+str);
	}

}

3. Functional Interfaces and Lambda Expressions

In Java 8, Functional Interfaces are also a new concept introduced. An interface with exactly one abstract method, becomes a Functional Interface. If we want, we can use @FunctionalInterface annotation to mark an interface as a Functional Interface.

In above example the ‘MyInterface‘ interface is a perfect example of Functional Interface.

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */


// Example of default method in an Interface -
public interface MyInterface {

	void myMethod();
	
	default void myLog(String str){
		System.out.println("MyInterface logging => "+str);
	}

}

4. Java Stream API for Bulk Data Operations on Collections

In Java 8, a new java.util.stream has been added to perform filter / map / reduce like operations with the collection. Stream API allows sequential as well as parallel execution. This is one of the best features of Java 8 for me.

/* *********************************************************
********* Simple code snippet by - LogicalDuniya.com *******
********************************************************* */


import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;

public class StreamApiExample {

	public static void main(String[] theArgs) {
		
		List<Integer> theList = new ArrayList<>();
		for(int i=0; i<100; i++) myList.add(i);
		
		// sequential stream
		Stream<Integer> sequentialStream = theList.stream();
		
		// parallel stream
		Stream<Integer> parallelStream = theList.parallelStream();
		
		// using lambda with Stream API, filter example
		Stream<Integer> greaterNums = parallelStream.filter(p -> p > 90);

		// using lambda in forEach
		greaterNums.forEach(p -> System.out.println("Greater numbers parallel="+p));
		
		Stream<Integer> greaterNumsSeq = sequentialStream.filter(p -> p > 90);
		greaterNumsSeq.forEach(p -> System.out.println("Greater numbers sequential="+p));

	}
}

Output of program

After executing above program, you will get below like output –

Greater numbers parallel=93
Greater numbers parallel=96
Greater numbers parallel=91
Greater numbers parallel=98
Greater numbers parallel=94
Greater numbers parallel=95
Greater numbers parallel=97
Greater numbers parallel=92
Greater numbers parallel=99
Greater numbers sequential=91
Greater numbers sequential=92
Greater numbers sequential=93
Greater numbers sequential=94
Greater numbers sequential=95
Greater numbers sequential=96
Greater numbers sequential=97
Greater numbers sequential=98
Greater numbers sequential=99

5. Java Time API

One of the best features of Java 8 is the java.time package. It streamlines the process of working with time in java.

Java Time API has some sub-packages java.time.format that provides classes to print and parse dates and times. Also, the java.time.zone provides support for time zones and their rules.


Q6) What is JIT in Java?

Let’s try to understand, JIT (Just In Time compiler) from a diagram –

JIT in Java

JIT stands for (Just-in-Time) compiler, which is a part of JVM (Java Virtual Machine). It helps in better performance of the Java applications during run-time. The use of JIT is mentioned in step by step process is explained here in the context of Java programming:

  1. Java Compilation Process:
    • When a Java program is compiled using the javac command, it produces bytecode, which is a binary representation of the source code.
    • Bytecode is a simplified and compact form of the code, but it is not directly executable by computer processors.
  2. Interpretation by JVM:
    • To execute a Java program, the Java Virtual Machine (JVM) interprets the bytecode.
    • However, interpreters are generally slower than native code running directly on a processor.
  3. Role of JIT Compiler:
    • To overcome the performance limitations of interpretation, the JVM employs a Just-In-Time compiler.
    • The JIT compiler takes the bytecode and compiles it into machine code that can be directly executed by the processor.
    • This compilation step happens at runtime, translating portions of the bytecode into native machine code just before they are executed.
  4. Sophistication and Optimization:
    • The JIT compiler is described as much more sophisticated than the javac compiler.
    • It performs complex optimizations to generate high-quality machine code tailored to the specific runtime behaviour of the application.
    • These optimizations contribute to improved performance compared to simple interpretation.

Q7) What are Memory storages available with JVM?

JVM consists of multiple types memory storage techniques –

  1. Class (Method) Area –
    To store class-level data of every class.
  2. Heap area –
    To store all created Objects.
  3. Stack area –
    To store primitive values that are specific to a method.
  4. Program Counter Register:
    To Store the address of the Java virtual machine instruction currently being executed
  5. Native Method Stack:
    To store all the native methods used in the application.

Q8) What is ClassLoader in Java?

Ans –

The ClassLoader is an integral part of the Java Runtime Environment (JRE).

During the execution of Java bytecode or when a .class file is created, the ClassLoader is responsible for dynamically loading Java classes and interfaces into the Java Virtual Machine (JVM).

The primary responsibility of the ClassLoader is to locate and load class files into memory as they are referenced during the execution of a Java program.

The ClassLoader plays a crucial role in abstracting the process of loading classes from the underlying file system details.

It ensures that the Java runtime system does not need to have direct knowledge of files and file systems.

The dynamic loading facilitated by ClassLoaders enables flexibility in Java applications.

Classes can be loaded and added to the program at runtime, enhancing the adaptability of Java applications.


Q9) Explain public static void main(String args[]) in Java.

Ans –

In Java, each program should have main() method. This is a driver method, from which the execution always begins. The meaning of the terms ‘public static void main(String args[])‘ are –

Certainly! Let’s break down the parts of the public static void main(String args[]) method signature in Java:

1. public:

public is an access modifier, that indicates that the method can be accessed from any other class. The main method needs to be public because it is called by the JVM (Java Virtual Machine) to start the execution of a Java program.

2. static:

static is a keyword which denotes that the method belongs to the class itself rather than to instances of the class. In the context of the main method, it allows the JVM to call this method without creating an instance of the class.

3. void:

void is the return type of the main method, that indicates that the method does not return any value.

4. main:

main is the name of the method. The JVM looks for this main method signature to start the execution of a Java program.

5. (String args[]):

  • (String args[]) is the parameter for the main method.
  • String[] args is an array of strings that can be used to pass arguments to the Java program from the command line.
  • It’s not mandatory to name the parameter args; you could use any valid identifier such as arguments or myArgs.

Overall, the public static void main(String args[]) indicates that the main method is public, static, does not return any value, and can take an array of strings as a parameter. This is the entry point for Java programs, where execution begins.


Q10) What are Packages in Java, and what are advantages of Packages?

Ans –

As name suggests, Packages help in packaging of something. This something is classes, interfaces, etc. Packages in Java can be defined whenever we want to group all the related classes, interfaces, etc.

Example

package com.logicalduniya.interview.java;   // The 'package' statement should be on top all other statements..

class TestExample 
{
    // ... Some code-
}

interface ITestExample 
{
    // ...
}

Advantage of Package

There are various advantages of defining packages in Java.

  • To avoid name clashes of classes / interfaces.
  • The Package provides easier access control.
  • We can also have the hidden classes that are not visible outside and are used by the package.

Q11) Explain different data types in Java?

Ans –

In Java, There are 2 types of data types in Java as mentioned below:

  1. Primitive Data Type
  2. Non-Primitive Data Type or Object Data type

There are multiple Primitive and Non-Primitive data types available so far –

Primitive Data TypeNon-Primitive Data Type
1. boolean: stores value true or false
2. byte: stores an 8-bit signed two’s complement integer
3. char: stores a single 16-bit Unicode character
4. short: stores a 16-bit signed two’s complement integer
5. int: stores a 32-bit signed two’s complement integer
6. long: stores a 64-bit two’s complement integer
7. float: stores a single-precision 32-bit IEEE 754 floating-point
8. double: stores a double-precision 64-bit IEEE 754 floating-point.
1. Strings
2. Array
3. Class
4. Object
5. Interface

Q12) What is Wrapper class in Java?

Ans –

“What’s the purpose of a wrapper class” is a Most Common Java Interview Questions. So, Let’s understand this-

Wrapper classes help to create objects. These objects encapsulate primitive Java types. Each Java primitive has a corresponding wrapper:

PrimitiveNon-Primitive
booleanBoolean
byteByte
shortShort
charCharacter
intInteger
longLong
floatFloat
doubleDouble

In Java, generic classes only work with objects and don’t support primitives. In case, if we want to work with them, we have to convert primitive values into wrapper class-objects.

For example, the Java Collection Framework works with objects only.

In older version of Java (prior to Java 5, almost 16 years back) there was no autoboxing feature available and we, for example, couldn’t simply call add(5) on a collection of Integers.

At that time, those primitive values needed to be manually converted to it’s related wrapper classes and stored in collections.

But now, using Wrapper classes and their methods, we can easily convert (or type-cast) Primitives to Non-Primitive types. (Eg.: int variable to Integer object, float variable to Float object, etc.)

Examples : Wrapper class

ok

int age = 10;  // Primitive 

Integer objectAge = new Integer( age ); // Non-Primitive

Integer anotherObject = Integer.valueOf( 10 ); // Non-Primitive 

Useful Methods : Wrapper class

Wrapper classes have so many methods, but the mostly used 3 methods are: 

xxxValue()
// This method can be called using any object.
// Here, 'xxx' part refers to Primitive types. Eg: charValue(), intValue(), floatValue() and so on..


parseXxx() : 
// This method can be called using any Wrapper Class.
// Here, 'Xxx' part refers to Primitive types. Eg: Integer.parseInt(), Float.parseFloat() and so on.

valueOf() : 
// Eg: Integer.valueOf(), Character.valueOf()

To convert from a wrapper object to a primitive value, we can use the methods such as intValue(), doubleValue() etc.

We can also convert boolean to Boolean, byte to Byte, char to Character, long to Long, float to Float, and double to Double. Though if we have to convert String to Integer then we need to use parseInt() method because String isn’t a wrapper class.

The valueOf() method returns an instance representing the specified int value.


Q13) Explain Autoboxing in Java? What is Autoboxing and Unboxing?

Ans –

The conversion from Primitive variables to Non-Primitive Objects, can also be done automatically by using features called autoboxing.

“Boxing” refers to converting a primitive value into a corresponding wrapper object. Because this can happen automatically, it’s known as autoboxing.

When a wrapper object is unwrapped into a primitive value then this is known as unboxing.

What this means in practice is that, we can pass a primitive value to a method which expects a wrapper object or assign a primitive to a variable which expects an object:

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

list.add(1);     // Autoboxing. Here, 1 would be converted to an Integer object having value 1.

Integer val = 2; // Autoboxing. Here, 2 would be converted to an Integer object having value 2.

In Unboxing, we fetch the Primitive value from a Wrapper Object –

Integer intObject = new Integer(1); 

int val1 = getSquareValue(intObject);      // Unboxing will happen here, bcoz we are passing object, but receiving it in a Primitive int variable..

int val2 = object; //unboxing

public static int getSquareValue(int i) {  // Primitive int variable..
    return i*i;
}

Q14) What is Upcasting in Java?

Ans –

Upcasting means – Casting from a subclass to a superclass is called upcasting.

Most of the times, we are unable to perform Upcasting as it is implicitly performed by the Java compiler.

Upcasting is closely related to inheritance. It’s common to use reference variables to refer to a more specific type. And every time we do this, implicit upcasting takes place.

Example : Upcasting in Java

To understand – How does upcasting happen, let’s create an Animal class:

// Created Animal class -

public class Animal {

    public void eat() {
        // ... 
    }
}


// Now let’s extend Animal:

public class Dog extends Animal {

    public void eat() {
         // ... 
    }

    public void bark() {
         // ... 
    }
}


// Now we can create an object of Dog class and assign it to the reference variable of type Dog:

Dog doggo = new Dog();


// And we can also assign it to the reference variable of type Animal:

Animal animal = doggo;


// In the above assignment, implicit upcasting takes place.
// We could do it explicitly as well -

animal = (Animal) cat;

Q15) Can we declare Pointer in Java?

Ans-

No, Java doesn’t provide the support of Pointer.

As Java has no pointer data types, it is impossible to use pointers in Java.

Java needed to be more secure and Pointers may lead to memory leak, that’s why the feature of the pointer is not available in Java.


Q16) Explain Constructor in Java. What is Copy Constructor in Java?

Ans-

Constructor :

Constructors are the gatekeepers of object-oriented programming approach.

A constructor in Java Programming is a block of code that initializes (constructs) the states (fields) and values during object creation. It is called every time an object with the help of a new() keyword.

Even if you haven’t specified any constructor in the code, the Java compiler adds a default constructor in the class and calls it.

class Student{

  private String rollNo;
  private String subject;

  Student()   // Creating a constructor
  { 
     // Some code to initialize the field / variables -
  }

}

Copy Constructor :

Constructors need not be limited to initialization alone. They can also be used to create objects in other ways. Imagine that we need to be able to create a new Student object from an existing object.

The new Student should have the same subject as the old Student.

Here, We can do that using a copy constructor :

class Student{

    private String rollNo;
    private String subject;
    
    public Student(Student otherStudent) {      // Created a Copy Constructor

        this.subject = otherStudent.subject;
        this.rollNo = otherStudent.rollNo;

    }
}

Q17) Explain static variable in Java?

Ans-

Mostly the static keyword is used to make the variable or method of a given class available / accessible for other Classes and Objects.

Static variables are the variables that once declared then a single copy of that variable is created and shared among all objects at the class level.

When we declare a field static, exactly a single copy of that field is created and shared among all instances of that class.

It doesn’t matter how many times we instantiate a class. There will always be only one copy of static field belonging to it. The value of this static field is shared across all objects of either the same class.

From the memory perspective, static variables are stored in the heap memory area.

public class Bike {                            // Created a Class = Bike

    private String name;
    private String engine;
    
    public static int numberOfBikes;           // Creating a Static Variable = numberOfBikes
    
    public Bike(String name, String engine) {
        this.name = name;
        this.engine = engine;
        numberOfBikes++;
    }

    // Other getters and setters methods
}

Q18) Can the main method be Overloaded in Java?

Ans-

Yes. It is possible to overload the main method. We can create as many overloaded main methods we want. However, JVM has a predefined calling method that JVM will only call the main method with the definition of – 

public static void main(string[] args)

Some exmples of overloaded main() method –

class MainExample {

    public static void main(String args[]) {
        System.out.println(" Main Method");
    }
    public static void main(int[] args){
        System.out.println("Overloaded Integer array Dummy Main Method");
    }
    public static void main(char[] args){
        System.out.println("Overloaded Character array Dummy Main Method");
    }
    public static void main(double[] args){
        System.out.println("Overloaded Double array Dummy Main Method");
    }
    public static void main(float args){
        System.out.println("Overloaded float Dummy Main Method");
    }
}

It would be really better if you are aware – What are the rules for creating Constructors in Java?
There are a total of three rules defined for creating a constructor –

  1. The constructor’s and class’s name must be same.
  2. You cannot define an explicit value to a Constructor.
  3. A Constructor cannot be any of these: static, synchronized, abstract, or final.

One thing to note here is that you can have a public, private, or protected constructor in Java by using access modifiers that controls the object creation.


Q19) How to Read and Write Text File in Java?

Ans-

The java.io package helps us to read / write in text file smoothly and fail proof fashion.

Reading from a Text File :

Reader is an abstract class for reading character streams. It implements the following fundamental methods:

  • read(): To read a single character.
  • read(char[ ]): To read an array of characters.
  • skip(long): To skip some characters.
  • close(): To close the stream.

BufferedReader reads text from a character stream with efficiency (characters are buffered to avoid frequently reading from the underlying stream) and provides a convenient method for reading a line of text readLine().

Writing into a Text File :

Writer is the abstract class for writing character streams. It implements the following fundamental methods:

  • write(int): writes a single character.
  • write(char[]): writes an array of characters.
  • write(String): writes a string.
  • close(): closes the stream.

BufferedWriter writes text to a character stream with efficiency (characters, arrays and strings are buffered to avoid frequently writing to the underlying stream) and provides a convenient method for writing a line separator: newLine().

Example : Program to Read and Write into a Text File

Following example uses a BufferedReader to read a text file line by line. This is the most efficient and preferred way :

package com.logicalduniya.java.interview;
 
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
 
/**
 *
 * This program demonstrates how to read / write characters from / to a text file
 * using a BufferedReader for efficiency.
 * @author www.LogicalDuniya.com
 *
 */

public class TextFileReadingWritingExample {
 
    public static void main(String[] args) {

        // Reading from a Text file - 
        try {
            FileReader reader = new FileReader("MyLogicalTextFile.txt");
            BufferedReader bufferedReader = new BufferedReader(reader);
 
            String line;
 
            while ((line = bufferedReader.readLine()) != null) {
                System.out.println(line);
            }
            reader.close();
 
        } catch (IOException e) {
            e.printStackTrace();
        }


        // Writing into a Text file -
        try {
            FileWriter writer = new FileWriter("MyLogicalTextFile.txt", true);
            BufferedWriter bufferedWriter = new BufferedWriter(writer);
 
            bufferedWriter.write("Hello World");
            bufferedWriter.newLine();
            bufferedWriter.write("See You Again!");
 
            bufferedWriter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

Q20) Explain final, finally and finalize in Java.

Ans-

The similarity among final, finally, and finalize is – all are reserved keywords. Which means, we cannot create variable with such names.

Now, let’s understand that, what are the usage of final, finally, and finalize –

final keyword :

final (lowercase) is a reserved keyword in Java. We can’t use it as an identifier, as it is reserved.

We can use final keyword with variables, methods, and also with classes. The final keyword in Java has a different meaning in different scenarios. Based upon whether we are using final keyword with variable, class, or methods.

Using final with Variables:
The value of the variable cannot be changed once initialized. If we declare any variable as final, we can’t modify its contents since it is final, and if we modify it then we get Compile Time Error.

Using final with Class:
The class cannot be subclassed. Whenever we declare any class as final, it means that we can’t extend that class or that class can’t be extended, or we can’t make a subclass of that class.

If a class is declared as final then by default all of the methods present in that class are automatically becomes final, But variables are not

Using final with Method:
The method cannot be overridden by a subclass. Whenever we declare any method as final, then it means that we can’t override that method. 

// An example of final keyword - 

class FirstLogicalClass {

	final void log() {}

	public static void main(String[] args)
	{
		// ...
	}
}

class SecondLogicalClass extends FirstLogicalClass {

	// Here we get compile time error
	// since can't extend log() since it is final.
	void log() {}

}

finally keyword :

Just as final is a reserved keyword, so in the same way finally is also a reserved keyword in Java i.e, we can’t use it as an identifier. The finally keyword is used in association with a try/catch block

The finally keyword guarantees that a section of code will be executed at any cost, even if an exception is thrown.

The finally block will be executed after the try-catch blocks, but before control transfers back to its origin. finally is executed even if try block has return statement.

class LogicalExample {

	public static void main(String[] args) {
 
        PrintWriter out = null;
        try {
            System.out.println("Entered try statement");
 
            // PrintWriter, FileWriter are classes in io package
            out = new PrintWriter(new FileWriter("OutFile.txt"));
        }
        catch (IOException e) {
            // Since the FileWriter in try block can throw IOException
        }
 
        // Following finally block cleans up and then closes the PrintWriter
        finally
        {
            if (out != null) {
                System.out.println("Closing PrintWriter");
                out.close();
            } else {
                System.out.println("PrintWriter not open");
            }
        }
    }
}

finalize :

If there is a method present with name finalize, then the Garbage Collector will call that method just before the deletion/destroying of the object which is eligible for Garbage Collection, so as to perform clean-up activity.

Clean-up activity means closing the resources associated with that object like Database Connection, Network Connection, or we can say resource de-allocation.

Remember, it is not a reserved keyword. Once the finalized method completes immediately Garbage Collector destroys that object.

finalize method is present in the Object class and its syntax is:

class LogicalExample {

	public static void main(String[] args){

		String s = new String("LogicalDuniya");
		s = null;

		// Requesting JVM to call Garbage Collector method
		System.gc();
		System.out.println("Main Completes");
	}

	// Here overriding finalize method
	public void finalize()
	{
		System.out.println("finalize method overridden");
	}
}

Q21) Explain the below Java program. What is the output of the program.?

Ans-

The Java program given by the interviewer –

import java.io.*; 

class LogicalDuniyaJavaInterview { 

	static int wish; 
    static boolean boolWish; 

	public static void main(String[] args) { 

            System.out.println("******** Output ********");

        if (wish==null)
            System.out.println("Good Morning!!");
        if (wish==0)
            System.out.println("Good Afternoon!!");
    
        if(boolWish==null)
            System.out.println("Happy New Year!!"); 
        if(boolWish==false)
            System.out.println("Marry Christmas!!"); 
	} 
}

Solution :

This Java program is to basically test your Core Java default value concept. Let’s first see, what will be the output of this Java Interview Question Program –

******** Output ********
Good Afternoon!!
Marry Christmas!!

If you have noticed, they have just declared an int and boolean variables, and not initialized with any value. So, in this case their default value gets assign to it.

So, as per their default values, the if statement condition gets calculated and prints the above output.

Default values of Java Data Types :

Data TypeDefault Value
byte0
short0
int0
long0
booleanfalse
char
float0.0
double0.0
Stringnull
Objectnull
Arraynull

Q22) What is transient keyword in Java?

Ans-

The transient keyword is primarily meant for ignoring fields during Java object serialization.

Serialization is the conversion of the state of an object into a byte stream. Serialization is the conversion of a Java object into a static stream (sequence) of bytes, which we can then save to a database or transfer over a network.

So, if we don’t want to save the value of a particular variable in database or in file, then the transient keyword can be used. When JVM comes across a transient keyword, it ignores the original value of the variable and saves the default value of that variable data type.

Example : Use of transient

public class Person implements Serializable {
    private static final long serialVersionUID = 1L;
    static String country = "INDIA";
    private int age;
    private String name;
    transient int height;         // Using transient, to ignore it's value during Person object serialization process.

    // getters and setters
}

Q23) Explain the difference between the methods sleep() and wait() in Java?

Ans-

There are multiple difference between sleep() and wait() methods –

sleep()wait()
1) The sleep() method belongs to the java.lang.Thread classThe wait() method belongs to the java.lang.Object class
2) This method is a static method.This method is not a static method.
3) sleep() does not throw an InterruptedException.InterruptedException is shown if the thread is interrupted while waiting.
4) Mainly used to delay a thread for some specific time duration.Mainly used to pause a thread until notified by another thread.
Sleep() Has Two Overloaded Methods:
5.a) sleep(long millis) millis: milliseconds
5.b) sleep(long millis, int nanos) nanos: Nanoseconds
Wait() Has Three Overloaded Methods:
5.a) wait()
5.b) wait(long timeout)
5.c) wait(long timeout, int nanos)

Some other diffeences that you can tell to interviewer –

6) A wait can be “woken up” by another thread calling notify on the monitor which is being waited on whereas a sleep cannot.

7) A wait (and notify) must happen in a block synchronized on the monitor object whereas sleep does not.


Q24) What are the differences between String and StringBuffer in Java?

Ans-

There are multiple difference between String and StringBuffer

StringStringBuffer
String object stores a sequence of characters internally.StringBuffer object provides functionality to work with the Strings.
String objects are immutable/non-changeable. Means, once they are created, they can not be modified.
Each modification will create a new String object.

StringBuffer objects are mutable/changeable (can be modified and other string operations could be performed on them.)
String is not thread-safe.It is thread-safe (two threads can’t call the methods of StringBuffer simultaneously) 

Q25) What are the differences between StringBuffer and StringBuilder in Java?

Ans-

There are multiple difference between StringBuffer and StringBuilder

StringBufferStringBuilder
StringBuffer provides functionality to work with the strings.StringBuilder is a class used to build a mutable /changeable string.
It is thread-safe (two threads can’t call the methods of StringBuffer simultaneously).It is not thread-safe (two threads can call the methods concurrently).
It increases waiting time of threads, and hence relatively performance is low.Threads are not required to wait to operate on StringBuilder object and hence relatively performance is high.
StringBuffer is introduced in Java version 1.0StringBuilder is introduced in Java version 1.5
All of StringBuffer methods are synchronized.All of StringBuilder methods are non-synchronized.

Q26) Explain : When to user String, StringBuffer, and StringBuilder?

Ans-

  1. If the content is fixed and won’t change frequently then we should go for String.
  2. If the content is not fixed and keep on changing but Thread Safety is required,
    then we should go for StringBuffer.
  3. If the content is not fixed and keep on changing and Thread safety is not required,
    then we should go for StringBuilder.

Q27) What are differences between Shallow Copy, Deep Copy and Lazy Copy?

Ans-

A quick answer –

  • In Shallow Copy, only fields of primitive data type are copied while the objects references are not copied.
  • Deep copy involves the copy of primitive data type as well as object references. There is no hard and fast rule as to when to do shallow copy and when to do a deep copy.
  • Lazy copy is a combination of both of these approaches.

An illustration –

An example with Code –

// Code illustrating shallow copy - 
public class LogicalEx { 

	private int[] array1; 

	// makes a shallow copy of values 
	public Ex(int[] array2) { 
		array2 = array1; 
	} 

	public void showData() { 
		System.out.println( Arrays.toString(array1) ); 
	} 
} 



public class LogicalUsesEx{ 

	public static void main(String[] args) { 
		int[] vals = {4,2,6}; 
		Ex e = new Ex(vals); 
		e.showData(); // prints out [4,2,6] 
		vals[0] = 14; 
		e.showData(); // prints out [14,2,6] 

		// Very confusing, because we didn't 
		// intentionally change anything about 
		// the object e refers to. 
	} 
} 


Now, let’s see an example of Deep copy –

// Code explaining deep copy 
public class LogicalEx { 
	
	private int[] array1; 

	// altered to make a deep copy of values 
	public Ex(int[] array2) { 
		data = new int[array2.length]; 
		for (int i = 0; i < array1.length; i++) { 
			array1[i] = array2[i]; 
		} 
	} 

	public void showData() { 
		System.out.println(Arrays.toString(data)); 
	} 
} 

public class LogicalUsesEx{ 

	public static void main(String[] args) { 
		int[] vals = {4,2,6}; 
		Ex e = new Ex(vals); 
		e.showData(); // prints out [4,2,6] 
		vals[0] = 14; 
		e.showData(); // prints out [4,2,6] 

	// changes in array values will not be 
	// shown in data values. 
	} 
} 

Q28) What is Stack memory vs Heap memory?

Ans-

JVM divides memory into stack and heap memory. Whenever we declare new variables and objects, call a new method, declare a String, or perform similar operations, JVM assigns memory to these operations from either Stack Memory area or Heap Space area.

Stack Memory :

  • Access to Stack memory is in Last-In-First-Out (LIFO) order. Whenever we call a new method, a new block is created on top of the stack which contains values specific to that method, like primitive variables and references to objects.
  • Variables inside the stack exist only as long as the method that created them is running.
  • It’s automatically allocated and deallocated when the method finishes execution.
  • If this memory is full, Java throws java.lang.StackOverFlowError.
  • Access to this memory is fast when compared to heap memory.
  • This memory is threadsafe, as each thread operates in its own stack.

Heap Memory :

  • Heap space is used for the dynamic memory allocation of Java objects and JRE classes at runtime. New objects are always created in heap space, and the references to these objects are stored in stack memory.
  • It’s accessed via complex memory management techniques. We can break this memory model down into smaller parts, called generations – Young Generation, Old or Tenured Generation, and Permanent Generation.
  • If heap space is full, Java throws java.lang.OutOfMemoryError.
  • Access to this memory is comparatively slower than stack memory.
  • This memory, in contrast to stack, isn’t automatically deallocated. It needs Garbage Collector to free up unused objects so as to keep the efficiency of the memory usage.
  • Unlike stack, a heap isn’t Thread safe and needs to be guarded by properly synchronizing the code.

Q29) What is the difference between the ‘throw’ and ‘throws’ keyword in Java?

Ans-

throw keyword:

The throw keyword in Java is used to explicitly throw an exception from a method or any block of code. We can throw either checked or unchecked exception.

The throw keyword is mainly used to throw custom exceptions. 

Example :

Here in below example, we are explicitly throwing an exception, due to which the statement with “main: Last Line” String, will not get printed.

// Java program that demonstrates the use of throw
class LogicalDuniyaThrowExample {

	// Java program to demonstrate working of throws
    public static void main(String args[])
    {
        try {
            System.out.println("First Line");

            if(true)
                throw new NullPointerException("Just for fun - Throwing Exception ");

            System.out.println("main : Last Line ");
        }
        catch (NullPointerException e) {
            System.out.println("Caught in main.");
            System.out.println("try-catch: Last Line");
        }
    }
}

Output :

First Line
Caught in main.
try-catch: Last Line

throws keyword:

The ‘throws’ keyword is used to tell the compiler that a method can throw some exception and I’m not handling that exception.

Example :

// Java program to demonstrate working of throws
class LogicalExampleThrowsExample {
 
    public static void main(String args[]) throws NullPointerException
    {
        System.out.println("First Line");

        if(true)
            throw new NullPointerException("Just for fun - Throwing NullPointerException ");

        System.out.println("Last Line ");
    }
}

Output :

First Line
Exception in thread "main" java.lang.NullPointerException: Just for fun - Throwing Exception 
	at LogicalExampleThrowsExample.main(LogicalExampleThrowsExample.java:9)

So, overall if a method is throwing an Exception, its always to better to use the try-catch mechanism to complete the execution of the method.


Q30) How to create a multi-dimensional array in Java?

Ans-

Multidimensional Arrays can be defined in simple words as array of arrays. Data in multidimensional arrays are stored in tabular form (in row major order). 

To create a multidimensional Array, follow the below syntax :

data_type[1st dimension][2nd dimension][]..[Nth dimension] array_name = new data_type[size1][size2]….[sizeN];

To create multidimensional Array, follow the below example :

Two dimensional array:
int[][] twoD_arr = new int[10][20];

Three dimensional array:
int[][][] threeD_arr = new int[10][20][30];

Size of multidimensional arrays: The total number of elements that can be stored in a multidimensional array can be calculated by multiplying the size of all the dimensions. 

For example: The array int[][] x = new int[10][20] can store a total of (10*20) = 200 elements. Similarly, array int[][][] x = new int[5][10][20] can store a total of (5*10*20) = 1000 elements.

Initialization – Syntax:
array_name[row_index][column_index] = value;

For example:
arr[0][0] = 1;

import java.io.*;
public class LogicalDuniya2dArrayExample {

	public static void main(String[] args) {

		int[][] arr = new int[10][20];
		arr[0][0] = 1223;

		System.out.println("The 2d Array arr[0][0] = " + arr[0][0]);
		// Output : 
		// The 2d Array arr[0][0] = 1223
	}
}

Java Interview Questions for Experienced

In this section, we will focus on most popular Java Interview Questions for Experienced Java Developers having 2 to 9 years of experience in the industry. These questions are taken from different Java Interview Experiences, but there are chances your interviewer twist any of these question and ask it differently. So be little careful while answering.

Let’s see and understand the Java Interview Question for Experienced Java Developers –


Q31) What is Exception, Checked Exception, and Un-Checked Exception with Examples in Java?

Ans-

What are exceptions in Java?

An exception is basically an unexpected event that occurs during a program execution. It affects the normal flow of the program instructions which can also cause the program to terminate abnormally or produce unwanted results.

Without handling Exceptions, even an healthy program may stop running altogether!! That’s why, we need to make sure that our code has a plan for when things go wrong.

Also, by doing exception handling, we get another benefit and that is the stack trace itself. It is nothing but a series of methods calls list, from where the exception has generated. Because of this stack trace, we can often pinpoint offending code without needing to attach a debugger.

An exception can occur for many reasons. Some of them are:

What are main reasons of exceptions in Java?

  • Invalid user input.
  • Loss of network connection.
  • Physical limitations (out of disk memory).
  • Code errors.
  • Opening an unavailable/corrupt file.

What is the hierarchy of Exception classes in Java?

Java Exception Hierarchy-Java Interview Questions

Types of Exceptions in Java and How to handle exceptions in Java?

Java exceptions fall into two main categories: checked exceptions and unchecked exceptions.

  1. Checked Exceptions
  2. Un-Checked Exceptions

1. Checked Exceptions :

In general, checked exceptions represent errors outside the control of the program. For example, the constructor of FileInputStream throws FileNotFoundException if the input file does not exist.

Java by default verifies checked exceptions at compile-time. It’s the duty of Java compiler before compiling code and duty of a developer to fix them before executing.

Therefore, we should use the throws keyword to declare a checked exception. If you do not write throws keyword with the exception name, which can be thrown during method call, then the Java compiler will throw a compile time error. An example –

private static void myCheckedExceptionWithThrows() throws FileNotFoundException {
    File myFile = new File("enter_wrong_file_name");
    FileInputStream stream = new FileInputStream(myFile);
}

Some common checked exceptions in Java are –

  • IOException,
  • SQLException and
  • ParseException.

The Exception class is the superclass of all checked & un-checked exceptions, so we can create a custom checked exception by extending Exception:

public class TheWrongFileNameException extends Exception {
    public myIncorrectFileNameException(String errorMessage) {
        super(errorMessage);
    }
}

2.. Un-Checked Exceptions :

A program throws an unchecked exception NOT at compile time, but it reflects some error inside the program logic when executing / running the code.

For example, if we divide a number by 0, Java will throw ArithmeticException :

public static void divideByZeroExample() {
    int numerator = 1;
    int denominator = 0;
    int result = numerator / denominator;       // Will throw ArithmeticException at execution time..
    System.out.println("Success");              // Will NOT be printed due to above Exception..
}

Unchecked exceptions are not checked by Java compiler at compile-time. That’s why such exceptions are called Unchecked exceptions.

Also, we DO NOT have to declare unchecked exceptions in a method with the throws keyword. And although the above code does not have any errors during compile-time, it will throw ArithmeticException at runtime.

Some common unchecked exceptions in Java are –

  • NullPointerException,
  • ArrayIndexOutOfBoundsException and
  • IllegalArgumentException.

The RuntimeException class is the superclass (or parent class) of all unchecked exceptions, so we can create a custom unchecked exception by extending RuntimeException :

public class NullOrEmptyException extends RuntimeException {     // Extending RuntimeException

    public NullOrEmptyException(String errorMessage) {
        super(errorMessage);
    }
}

Q32) How to Throw and Catch Exceptions?

Ans-

This is one of the super important Java Interview Questions, and can be asked as – How to handle exceptions in Java?

Java creates an exception object putting some useful information inside it, whenever any error occurs while executing a code statement. The exception object contains a lot of debugging information such as method hierarchy, variable values, line number where the exception occurred, type of exception with some other information.

If an exception occurs in a method, the process of creating the exception object and handing it over to the runtime environment is called “throwing the exception”.

As the exception is thrown, the normal flow of the program gets stop and the Java Runtime Environment (JRE) tries to find the handler for the exception. Exception Handler is the block of code that can process the exception object.

  • The logic to find the exception handler begins with searching in the method where the error occurred.
  • If no appropriate handler is found, then it will move to the caller method.
  • And so on.

Useful keywords to handle Exceptions –

Java by default verifies checked exceptions at compile-time. It’s the duty of Java compiler before compiling code and duty of a developer to fix them before executing. So, to handle Un-Checked Exceptions, we have try-catch mechanism. With try-catch mechanism, we have to work with some keywords –

Java provides specific keywords for exception handling purposes.

1. throw
We know that if an error occurs, an exception object is getting created and then Java runtime starts processing to handle them.

Sometimes we might want to generate exceptions explicitly in our code. For example, in a Calculator program, we should throw exceptions to screen if the denominator is Zero, because dividing a number by Zero will throw ArithmeticException. Here, the throw keyword is used to throw exceptions to the runtime to handle it.

2. throws
When we want to throw an exception in a method and NOT want to handle it, then we have to use the throws keyword in the method signature to let the caller program know the exceptions that might be thrown by the method.

The throws clause can be used with the main() method also.

3. try-catch :–
We use the try-catch block for exception handling in our code. try is the start of the block and catch is at the end of the try block to handle the exceptions. We can have multiple catch blocks after a try block.

The try-catch block can be nested too. The catch block requires a parameter that should be of type Exception or it’s sub-classes.

4. finally
The finally block is optional and can be used only with a try-catch block. As we know, when an exception occurs, it halts the process of execution. But, we might have some resources open (Files / Databases) that will not closed during the exception raised, so we can use the finally block.

The finally block ALWAYS gets executed, whether an exception occurred or not.

Example :

The try-catch block is used to handle exceptions in Java. Here’s the syntax of try...catch block:

Syntax :

try {
  // code
}
catch(Exception e) {
  // code
}

Let’s say, we want to handle ArithmeticException, then we have to write try-catch like this –

class LogicalDuniyaMain {

  public static void main(String[] args) {

    try {

      // Code that generate exception
      int divideByZero = 5 / 0;
      System.out.println("Execution Completed");
    }
      // Code that catches ArithmeticException
    catch (ArithmeticException ex) {
      System.out.println("Catching ArithmeticException => " + ex.getMessage());
    }
  }
}

Output :

Catching ArithmeticException => / by zero

Q33) Will the finally block get executed when the return statement is written at the end of try block and catch block as shown below?

public int someMethod(int i){
   try{
       //some statement
       return 1;             // Return statement before finally block..
   }catch(Exception e){
       //some statement
       return 999;
   }finally{
       //finally block statements
   }
}

Ans-

finally block will be executed in this case as well. No matter, what exception is occurring, any return statement is mentioned or not, the finally block will be executed.

The only case where finally block is not executed is when it encounters ‘System.exit(..)’ method anywhere in try..catch block.


Q34) What is Constructor Chaining?

Ans-

Calling a constructor of a class from another constructor of same Class, is known as Constructor Chaining.

The concept of Constructor Chaining can be achieved using this keyword –

Example – with Illustration :

Constructor Chaining Illustration in Java.

Output :

Hi LogicalDuniya.com !!!

Q35) What is Multi-Threading in Java? How to create Thread in Java?

Ans-

Java support Multithreading. It is a feature that allows executing two or more parts of a program parallelly for maximum utilization of CPU. Each part of such program is called a Thread.

So, threads are light-weight processes within a process.

Threads can be created by using two mechanisms : 

  1. Extending the Thread class 
  2. Implementing the Runnable Interface

1. Thread creation by extending the Thread class :

To create a Thread, first option is to create a class that extends the java.lang.Thread class. This class overrides the run() method available in the Thread class.

All threads begins thier life inside run() method. We create an object of our new class and call start() method to start the execution of a thread. The start() method invokes the run() method on the Thread object.

Example :

package com.logicalduniya.java.interview;

// ************************* A program to show - How does Multi-Threading works ?? ************************* //

// Java code for thread creation by extending the Thread class -
class MultiThreadingExample extends Thread {

	// Override the run() method of Thread class -
	public void run()
	{
		try {
			// Displaying the thread that is running
			System.out.println(
				"Currently, Thread " + Thread.currentThread().getId() + " is executing..");
		}
		catch (Exception e) {
			// Throwing an exception
			System.out.println("Exception happened..");
		}
	}
}

// Main Class
public class MainMultithread {
	public static void main(String[] args)
	{
		int n = 6; // Number of threads

		for (int i = 0; i < n; i++) {
			MultiThreadingExample threadObject= new MultiThreadingExample();

			// Start method will internally call the run() method, which we have overridden above..
			threadObject.start();     
		}
	}
}

Output:

Currently, Thread  22 is executing..
Currently, Thread  21 is executing..
Currently, Thread  20 is executing..
Currently, Thread  20 is executing..
Currently, Thread  22 is executing..
Currently, Thread  21 is executing..

Thread creation by implementing the Runnable Interface

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

The benefit of this technique to create Threads is that – we can still extend some other class, as multiple inheritance is not allowed in Java.

package com.logicalduniya.java.interview;

// ************** A program to show - How does Multi-Threading works ?? ************** //

// Java code for thread creation by implementing the Runnable Interface -
class MultiThreadingExample implements Runnable {

	public void run() {
		try {
			// Displaying the thread that is running
			System.out.println(
				"Currently, Thread " + Thread.currentThread().getId() + " is executing..");
		}
		catch (Exception e) {
			// Throwing an exception-
			System.out.println("Exception raised..");
		}
	}
}

// Main Class
class MainMultithread {
	public static void main(String[] args)
	{
		int n = 6; // Number of threads
		for (int i = 0; i < n; i++) {
			Thread object = new Thread(new MultiThreadingExample());
			object.start();
		}
	}
}

Output:

Currently, Thread  20 is executing..
Currently, Thread  21 is executing..
Currently, Thread  20 is executing..
Currently, Thread  22 is executing..
Currently, Thread  20 is executing..
Currently, Thread  22 is executing..

Q36) Explain Object Oriented Programming (OOPs) Concept in Java?

Ans-

Object-Oriented Programming aims to implement real-world entities like inheritance, hiding, polymorphism etc. in programming. The main aim of OOP is to bind together the data and the functions that operate on them so that no other part of the code can access this data except that function.

The basic concept of OOPs is to create objects, re-use them throughout the program, and manipulate these objects to get results.

OOPs Concepts in Java with Examples

The following are general OOPs concepts in Java:

1) Class

The class is one of the basic concepts of OOPs which is a group of similar entities. It is only a logical component and not the physical entity. We can understand more about Class concept with example.

Let’s say you had a class called “Expensive Cars”, then it could have objects like Mercedes, BMW, Toyota, etc. Its properties(data fields) can be ‘price’ and ‘speed’ of these cars. While the methods may be performed with these cars are driving(), doReverse(), applyBrakes() etc.

2) Object

An object can be defined as an instance of a class, and there can be multiple instances of a class in a program. It’s a real physical entity, which consumes memory in our RAM.

An Object is one of the Java OOPs concepts which contains both the data and the function, which operates on the data. For example – chair, bike, marker, pen, table, car, etc.

3) Inheritance

Inheritance is one of the Basic Concepts of OOPs in which one object acquires the properties and behaviours of the parent object. It’s creating a parent-child relationship between two classes. It offers robust and natural mechanism for organizing and structure of any software. Java only supports Single-Level and Multi-Level Inheritance with help of extends keyword.

4) Polymorphism

Polymorphism is the ability of a variable, object or function to take on multiple forms. As an example, Let’s say, there is a Shape class with multiple methods with same name area(...) but all methods take different parameters.

Class – Shape.java :

class Shapes {
    public void area(int r) {
        System.out.println("Circle area = " + 3.14 * r * r);
    }

    public void area(double b, double h) {
        System.out.println("Triangle area=" + 0.5 * b * h);
    }
}

Polymorphic Method – area(..) :

One area(..) method is taking one int parameter named as radius, and calculates the area of Circle –

public void area (int radius) {
    System.out.println("Circle area = " + 3.14 * radius * radius);
}

Another area(..) method is taking two double type parameters, and calculates area of a Triangle –

public void area (double b, double h) {
    System.out.println("Triangle area=" + 0.5 * b * h);
}

Here we are implementing Polymorphism in Shape class, with help of Method Overloading feature.

5) Abstraction

Abstraction is another key concept of OOPs in Java, which is an act of representing essential features without including background details. It is a technique of creating a new data type that is suited for a specific application.

Let’s understand this one of the OOPs Concepts with example, while driving a car, you do not have to be concerned with its internal working. Here you just need to concern about parts like steering wheel, Gears, accelerator, etc.

6) Encapsulation

Encapsulation is one of the core concepts of OOPs principals. Encapsulation helps in binding the data and code together inside the class.To allow outside access to the instance variables, public methods called getters and setters are defined, which are used to retrieve and modify the values of the instance variables, respectively. By using getters and setters, the class can enforce its own data validation rules and ensure that its internal state remains consistent.

7) Association

Association defines relationship between two objects. It is another important OOP Concepts in Java which defines the diversity between objects. In this OOP concept, all objects have their separate lifecycle, and there is no owner.

For example, many students can associate with one teacher, while one student can also associate with multiple teachers.

8) Aggregation

In this technique, all objects have their separate lifecycle. However, there is ownership such that child object can’t belong to another parent object.

For example, consider class and objects – department and teacher. Here, a single teacher can’t belong to multiple departments, but even if we delete the department, the teacher object will never be destroyed.

9) Composition

Composition is a specialized form of Aggregation. It is also called “death” relationship. As per this concept, all Child objects do not have their lifecycle so when parent object gets deleted, all of it’s child object will also get deleted automatically.

For that, let’s take an example of House and rooms. Any house can have several rooms. One room can’t become part of two different houses. So, if you delete the house, all of it’s room will also be deleted.


Q37) Is Java “pass-by-reference” or “pass-by-value”?

Ans-

The terms “pass-by-value” and “pass-by-reference” are talking about variables.

Pass-by-value means that the value of a variable is passed to a function/method.

Pass-by-reference means that a reference to that variable is passed to the function. This technique gives the function a way to change the contents of the variable.

So, we can conclude by saying – Java is always pass-by-value.

Example – Pass by value VS Pass by Reference

package com.logicalduniya.java.interview;

// ************** A program on - Call by Value and Call by Reference ************** //

public class LogicalDuniyaExample {

    public static void main(String[] args) {
        Dog aDog = new Dog("Max");
        Dog oldDog = aDog;

        // we pass the object to logicalFun()
        logicalFun(aDog);

        // aDog variable is still pointing to the "Max" dog when logicalFun(...) returns
        aDog.getName().equals("Max"); // true
        aDog.getName().equals("Fifi"); // false
        aDog == oldDog; // true
    }

    public static void logicalFun(Dog d) {
        d.getName().equals("Max"); // true

        // change d inside of logicalFun() to point to a new Dog instance "Fifi"
        d = new Dog("Fifi");

        d.getName().equals("Fifi"); // true
    }
}

In the example above aDog.getName() will still return "Max". The value aDog within main is not changed in the function logicalFun() with the Dog "Fifi" as the object reference is passed by value. If it were passed by reference, then the aDog.getName() in main would return "Fifi" after the call to logicalFun().


Q38) What will be the output of this Java Program?

package com.logicalduniya.java.interview;

public class LogicalDuniyaMain {

    public static void main(String[] args) {
        System.out.println("Hello LogicalDuniya.com - This is Main Method1.");
    }

    public static void main(int[] args) {
        System.out.println("Hello LogicalDuniya.com - This is Main Method2.");
    }
}

Ans-

First, let me share the output, then we will discuss why and how it happened?

Hello LogicalDuniya.com - This is Main Method1.

The reason for above output –

The output of the above program will be Hello. Main Method. This is because JVM will always call the main method based on the definition it already has. Doesn’t matter how many main methods we overload, it will only execute one main method based on its declaration in JVM.


Q39) What are the differences between Instance Variable and a Class Variable.

Ans-

Instance Variable :
These variables can have different values among different objects. A class variable WITHOUT a static modifier known as an instance variable.

It is typically shared by all instances of the class. The contents of an instance variable are completely independent of one object instance from another because they are related to a specific object instance of the class.

Example – Usage of Instance Variable :

// Java Program to Demonstrate Instance Variable -

class LogicalDuniyaExample { 

	private String name;             // Created the Instance Variable - 'name'

	public void setName(String name) { this.name = name; } 

	public String getName() { return name; } 

	public static void main(String[] args) 
	{ 
		LogicalDuniyaExample objOne = new LogicalDuniyaExample(); 
		LogicalDuniyaExample objTwo = new LogicalDuniyaExample(); 

		objOne.setName("This is our LogicalDuniya !!!");        // Setting value for objOne -
		objTwo.setName("We Learn Programming concepts here.");  // Setting value for objTwo -

		System.out.println("Hi. " + objOne.getName());          // Setting value from objOne -
		System.out.println("And, " + objTwo.getName());         // Getting value from objTwo -
	}
}

Output :

Hi. This is our LogicalDuniya !!!
We Learn Programming concepts here.

Class Variable :
Class Variable can be declared anywhere at the class level using the keyword static.

The static variables or Class level variables values are not different for multiple variables. These variables can be shared by all class members since they are not connected to any specific object of the class.

Example – Usage of Class Variables :

// Java Program to demonstrate Class Variable 

class LogicalDuniyaExample { 

	// class variable 
	private static final double PI = 3.14159; 

	private double radius; 

	public LogicalDuniyaExample(double radius) { this.radius = radius; } 

	public double getArea() { return PI * radius * radius; } 

	public static void main(String[] args) 
	{ 
		LogicalDuniyaExample obj = new LogicalDuniyaExample(5.0); 
		System.out.println("Area of circle: "
						   + obj.getArea()); 
	} 
}

Q40) What do you understand by an IO Stream?

Ans-

Java 8 and other future releases have Streams with its Input / Output package that helps the user to perform all the input-output operations. These streams support all types of objects, files, data types, characters etc to fully execute the I/O operations.

Java class InputStream is an abstract class. This serves as the superclass for all classes representing an input stream of bytes.

Some useful Input Stream classes –

  • FileInputStream
  • ByteArrayInputStream
  • ObjectInputStream

Java class OutputStream is an abstract class. This serves as the superclass for all classes representing an output stream of bytes.

Some useful Output Stream classes –

  • FileOutputStream
  • ByteArray<code>OutputStream
  • Object<code>OutputStream

Q41) What is an Array in Java? How many types of Array we can create in Java?

Ans-

Arrays in Java

An Array in Java is a data structure that is used to store a fixed-size sequence of elements of the same type. Elements of an array can be accessed by their index, which starts from 0 and goes up to array’s length minus 1. Array declaration in Java is done with the help of square brackets and size is also specified during the declaration. Here are how arrays get initialized in Java –

Declaration and Initialization of Array

// One-Dimensional Array declaration -
int[] the_Array = new int[5];

// Two Dimensional array declaration -
int[][] twoD_Array = new int[10][20];

// Three Dimensional array:
int[][][] threeD_Arr = new int[10][20][30];


// One-Dimensional Array initialization -
the_Array[0] = 102;
the_Array[1] = 1023;

// Two Dimensional array initialization -
twoD_Array[0][0] = 103
twoD_Array[0][1] = 1034

// Three Dimensional array initialization -
threeD_Array[0][0][0] = 104;
threeD_Array[0][0][1] = 1045;


Note💡
Arrays in Java are created in heap memory. When an array is created with the help of a new keyword, memory is allocated in the heap to store the elements of the array. In Java, the heap memory is managed by the Java Virtual Machine (JVM).

Q42) Why is processing a sorted array faster than processing an unsorted array?

Ans-

The answer is – Because of branch prediction failure.

The reason, why program’s performance improves drastically, when the data is sorted, is that – the branch prediction penalty is removed, as explained beautifully in Mysticial’s answer on Branch Prediction and performance comparison on Sorted Array vs Unsorted Array.

If we have a sorted array, the condition data[c] >= 128 is first false for a streak of values, then becomes true for all later values. That become super easy to predict. With an unsorted array, you pay for the branching cost. Check the above linked answer for more details.

Let’s see a Quick Demonstration of it’s prediction –

T = branch taken
N = branch not taken

data[] = 0, 1, 2, 3, 4, ... 126, 127, 128, 129, 130, ... 250, 251, 252, ...
branch = N  N  N  N  N  ...   N    N    T    T    T  ...   T    T    T  ...

       = NNNNNNNNNNNN   ... NNNNNNNTTTTTTTTTTT       ... TTTTTTTTTTTTTTTT  (easy to predict)

Q43) Is Java “pass-by-reference” or “pass-by-value”?

Ans-

First of all, Java is always PASS BY VALUE. The confusion generally occurs when we deal with variables holding objects. These variables are (also known as Reference Variables, and they) internally deal with object-handles (well known as- ‘References’), which are passed-by-value as well.

The phrases Java “pass-by-value” and “pass-by-reference” are basically talking about variables. Let’s first understand them only –

  • Pass-by-value :
    It simply means that the value of a variable is passed to a function/method.
  • Pass-by-reference:
    It simply means that a reference to that variable is passed to the function. Which later gives the function an opportunity to change the contents of the variable.
public static void main(String[] args) {
  Cat aCat = new Cat("Toni");
  Cat oldCat = aCat;

  // We pass the object to foo
  foo(aCat);
  
  // aCat variable is still pointing to the "Toni" cat when foo(...) returns
  aCat.getName().equals("Toni");     // Output = true
  aCat.getName().equals("Fifi");     // Output = false
  aCat == oldCat; // Output = true
}

public static void foo(Cat d) {
  d.getName().equals("Toni");        // Output = true
  
  // change d inside of foo() to point to a new Cat instance "Fifi"
  d = new Cat("Fifi");
  d.getName().equals("Fifi");        // Output = true
}

In the example above aCat.getName() will still return “Toni”. The value aCat within main is not changed in the function foo with the Cat “Fifi” as the object reference is passed by value. If it were passed by reference, then the aCat.getName() in main would return “Fifi” after the call to foo.


Q44) What is Collection in Java?

Ans-

Collection in Java :
Any group of “individual objects” that are defined or represented as a single unit is known as a Java Collection of Objects. In Java, there is a separate framework named as “Collection Framework”. This ‘Collection Framework’ is available from Java JDK 1.2 which contains all the various Java Collection Classes and Interfaces that help a developer to manage group of objects with so much ease.

Key Points of Java Collections Framework –

  • In Java, the Collection interface (java.util.Collection) and Map interface (java.util.Map) are the two main “root” interfaces of Java collection classes.
  • The Collection Framework has a basic set of interfaces like Collection, Set, List, or Map, all the classes (ArrayList, LinkedList, Vector, etc) that implement these interfaces have some common set of methods.
  • As a programmer, we do not need to worry about the design of the Collection but we only need to focus on – How can we use this pre-defined Collection classes and Methods.
  • The Collection Framework helps us to increase performance by utilizing various data-structures and algorithms which are already present in the framework.
  • This framework helps us to drastically upgrade our software development process as the major part ‘The Skeleton’ is already given to us in the form of classes (ArrayList, LinkedList, Vector, etc) and Interfaces.


Q45) What is the difference between static method and instance method?

Ans-

static methodinstance method
static methods can only accessible using class rather than an object.Instance methods can be accessible with an object rather than a class.
static methods can be called using the class name only without creating an instance of a class.Instance method can be called on a specific instance of a class using the object reference.
this keyword is NOT available and accessible in static method.Instance methods have access to this keyword.
static method can access only static members of the class.This method can access both static and non-static methods of the class.

Overall, Java Static methods are methods that belong to a class rather than to instances of the class, while the Java Instance methods are functions defined within a class that operate on instances (objects) of that class.


Q46) What do you understand with Error java.lang.OutOfMemoryError: GC overhead limit exceeded ?

Ans-

This error message means that for some reason the garbage collector is taking an excessive amount of time (by default 98% of all CPU time of the process) and recovers very little memory in each run (by default 2% of the heap).

This error tells that our program stops doing any progress and is busy running only the garbage collection at all time.

To prevent our application from soaking up CPU time without getting anything done, the JVM throws this Error so that you have a chance of diagnosing the problem –

Error java.lang.OutOfMemoryError: GC overhead limit exceeded.

This error also occurs where some code was creating tons of temporary objects and tons of weakly-referenced objects in an already very memory-constrained environment.


Q47) What are the Differences Between HashMap and Hashtable in Java?

Ans-

There are a few similarities between HashMap and Hashtable classes –

  • Hashtable and HashMap are collections that implement the Map interface.
  • Also, the put(), get(), remove() and a few other methods provide constant-time performance O(1).

But, these are different in various factors –

On basis ofHashtableHashMap
SynchronizationHashtable member variables are synchronized.HashMap is not synchronized and can’t be accessed by multiple threads without additional synchronization code.
Thread SafetyHashtable is thread-safe.HashMap is not thread-safe.
PerformanceHashtable methods operations are comparatively slow.HashMap is not synchronized, therefore it’s faster and uses less memory than Hashtable.
Null ValueHashtable object’s NEVER allow to store null values.HashMap allows adding one Entry with null as key as well as many entries with null as value.
Iteration methodHashtable has Enumerator for iterating over elements.HashMap uses Iterator to iterate over values.

Q48) What is the difference between Set and Map in Java?

Ans-

There are so many differences between Set and Map. Here are a few examples –

SetMap
Duplicate elements are not allowed in Set object.Duplicate elements are allowed in Map object.
Only one null value is allowed.Map allows only single null key, and any number of null values.
Implementation classes are HashSet, LinkedHashSet, and TreeSetMap implementation classes are HashMap, HashTable, TreeMap, ConcurrentHashMap, and LinkedHashMap.
Set does not provide get method to get the elements at a specified index.The map does not provide get method to get the elements at a specified index.
We can use Set to create a collection of unique elements.We can use the Map to store the data in the form of key/value pair.
Iterator can be used to traverse the Set elements.We need to call keyset, value, and entry methods to get required details.

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

Ans-

this()super()
It represents the current instance of the class.It represents the current instance of the parent class.
Calls the default constructor of the same class.Calls the default constructor of the base class.
Access the methods of the same class.Access the methods of the parent class.
Points current class instance.Points the superclass instance.

Q50) Do we have get() method in any Set implementation class of Java Collection?

Ans-

This is a very popular Java Interview Questions and Answers. Let’s understand this with examples –

Set or any of its implementation classes (HashSet / LinkedHashSet / TreeSet) do not provide any get() method.

However to work with values stored in Set object, we have a few other methods –

contains(element)This method is used to check whether a specific element is present in the Set or not.
iterator()This method is used to return the ‘iterator’ of the Set. The elements from the Set are returned in a random order.
// Java Program Demonstrating Creation of Set object 
// Using the TreeSet class 

// Importing utility classes 
import java.util.*; 

// Main class 
public class LogicalDuniyaSetExample { 

	// Main driver method 
	public static void main(String[] args) 
	{ 
		// Creating a Set object and declaring it of String type with reference to a Set Implementation TreeSet 
		Set<String> treeSet = new TreeSet<String>(); 

		// Adding elements into the TreeSet using method add() 
		treeSet.add("India"); 
		treeSet.add("USA"); 
		treeSet.add("Switzerland"); 

		// Adding the duplicate element 
		treeSet.add("India"); 

		// Displaying the TreeSet 
		System.out.println("Set = " + treeSet); 

		// Removing items from TreeSet using remove() 
		treeSet.remove("Switzerland"); 
		System.out.println("Set after removing "
						+ "Switzerland:" + treeSet); 

		// Iterating over Tree set items 
		System.out.println("Iterating over set:"); 
		Iterator<String> i = treeSet.iterator(); 

		while (i.hasNext()) 
			System.out.println(i.next()); 
	} 
}

Output –

Set = [India, Switzerland, USA]
Set after removing Switzerland:[India, USA]
Iterating over set:
India
USA

Q51) What should you choose between Map.clear() vs new Map() ? Which one will be better?

Ans-

Java Interviewers ask such popular Java Interview Questions and Answers to know whether you are aware about the best practices or not. So, let’s understand this with an example –

There are 2 ways to get a fresh and blank Map object –

Way 1 – Map<String, String> myNewMap = new HashMap<String, String>();.

Way 2 – oldMap.clear();

In above 2 ways, when You choose the way 1 to instantiate a new instance, which is backed with new array. Then, garbage collector should clear all the key and values from the previous map, and clear the reference to itself. So O(n) algorithm is executed anyway, but in the garbage collector thread. For 1000 records you won’t see any difference. BUT. The android developer performance guide tells you that it is always better not to create new objects, if you can.

So, you should go with clear() method.


Q52) What do you understand about Java Multi-threading? Explain its different terminologies.

Ans-

Multi-threading in Java allows concurrent execution of multiple threads within the same program. It enables developers to write programs that can perform multiple tasks simultaneously, enhancing performance and responsiveness.

Here are some key concepts and features of Java multi-threading:

  1. Thread:
    A thread is the smallest unit of execution within a process. Java provides built-in support for creating and managing threads using the Thread class or implementing the Runnable interface.
  2. Thread Lifecycle:
    Threads in Java go through several states in their lifecycle, including new, runnable, blocked, waiting, timed waiting, and terminated.
  3. Thread Synchronization:
    When multiple threads access shared resources concurrently, synchronization mechanisms such as locks, synchronized blocks, and semaphores are used to ensure data consistency and prevent race conditions.
  4. Concurrency Utilities:
    Java provides a rich set of concurrency utilities in the java.util.concurrent package, including ExecutorService, ThreadPoolExecutor, Future, Semaphore, CountDownLatch, and more, to simplify multi-threaded programming.
  5. Thread Safety:
    Thread safety is a critical consideration when writing multi-threaded code to ensure that shared data structures and resources are accessed safely by multiple threads.
  6. Thread Communication:
    Threads can communicate and synchronize with each other using techniques such as wait and notify, condition variables, and message passing.
  7. Thread Pools:
    Thread pools manage a pool of worker threads, allowing for efficient reuse of threads and better resource management.
  8. Atomic Operations:
    Java provides atomic data types and classes in the java.util.concurrent.atomic package, such as AtomicInteger, AtomicLong, and AtomicReference, to perform atomic operations without the need for explicit synchronization.
  9. Fork/Join Framework:
    Introduced in Java 7, the Fork/Join framework provides a high-level abstraction for parallelizing recursive algorithms by dividing tasks into smaller subtasks and merging their results.


Q53) Why, String is immutable in Java?

Ans-

In Java, String objects are immutable for several reasons:

  1. Caching and Reusability:
    Immutable strings can be cached and reused, which can lead to performance improvements and reduced memory usage. For example, the JVM can reuse existing string literals instead of creating new ones when the same literal is encountered again.
  2. Thread Safety:
    String immutability ensures that strings are inherently thread-safe. Since strings cannot be modified after creation, they can be safely shared between multiple threads without the risk of concurrency issues like race conditions.
  3. Security:
    Immutable strings are inherently more secure because they cannot be modified once created. This prevents malicious code from tampering with string values and helps prevent certain types of attacks, such as buffer overflow attacks.
  4. Hash code Consistency:
    As we know, string objects are immutable, their hash codes remain constant throughout their lifetime. This ensures that strings can be reliably used as keys in hash-based data structures like HashMap.
  5. Simplifies Memory Management:
    Immutable strings simplify memory management because they can be safely shared and reused across different parts of an application without worrying about unintended side effects due to modification.

Q54) Explain Enumeration in Java? What is ‘enum’ in Java?

Ans-

In Java, an enumeration (enum) is a special data type that represents a group of constants (enumerated values). Enumerations are defined using the enum keyword and are useful when you have a fixed set of related constants that belong together.

Here’s an example of how you can define and use an enumeration in Java:

// Define an enumeration called DayOfWeek
enum DayOfWeek {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
}

public class LogicalDuniyaEnumExample {

    public static void main(String[] args) {

        // Access individual values of the DayOfWeek enumeration
        DayOfWeek today = DayOfWeek.WEDNESDAY;
        System.out.println("Today is: " + today);

        // Use switch statement with enum
        switch (today) {
            case MONDAY:
                System.out.println("It's Monday!");
                break;
            case TUESDAY:
                System.out.println("It's Tuesday!");
                break;
            case WEDNESDAY:
                System.out.println("It's Wednesday!");
                break;
            // Handle other cases as needed
            default:
                System.out.println("It's another day of the week!");
        }

        // Iterate over all values of the DayOfWeek enumeration
        System.out.println("All days of the week:");
        for (DayOfWeek day : DayOfWeek.values()) {
            System.out.println(day);
        }
    }
}

Explanation Step-by-Step :

In this example:

  • We define an enumeration called DayOfWeek, which represents the days of the week.
  • We declare a variable today of type DayOfWeek and assign it the value DayOfWeek.WEDNESDAY.
  • We use a switch statement to perform different actions based on the value of today.
  • We iterate over all values of the DayOfWeek enumeration using the values() method.

Enumerations provide a type-safe way to work with predefined constants and can improve the readability and maintainability of your code by providing meaningful names to groups of related constants.


Q55) Can you execute any commented statement in Java?

Ans-

Yes. Hare is an example code snippet –

public class LogicalDuniyaTesting 
{ 
	public static void main(String[] args) 
	{ 
		// the line below this gives an output 
		// \u000d System.out.println("Hello LogicalDuniya. I'm a Comment..."); 
	} 
} 

Output :

Hello LogicalDuniya. I'm a Comment...

Q56) What are named loops in Java?

Ans-

In Java, named loops (also known as labelled loops) allow you to assign a label to a loop or a block of code. This label can then be used with certain control flow statements like break and continue to specify which loop to break out of or continue to. This is particularly useful when you have nested loops and want to break or continue a specific loop rather than just the innermost one.

Syntax :

A named loop is created by placing an identifier followed by a colon (:) before the loop statement. Here’s an example of the syntax:

labelName: for (initialization; condition; update) {
    // loop body
}

Example :

public class LogicalDuniyaNamedLoopsExample {

    public static void main(String[] args) {

        // Named loop 'outer'
        outer: for (int i = 1; i <= 5; i++) {
            for (int j = 1; j <= 5; j++) {
                if (i * j == 12) {
                    System.out.println("Breaking out of outer loop when i*j equals 12");
                    break outer;  // Breaks out of the 'outer' loop
                }
                System.out.println("i = " + i + ", j = " + j);
            }
        }
        System.out.println("Loop terminated.");
    }
}

Output :

i = 1, j = 1
i = 1, j = 2
i = 1, j = 3
i = 1, j = 4
i = 1, j = 5
i = 2, j = 1
i = 2, j = 2
i = 2, j = 3
i = 2, j = 4
i = 2, j = 5
i = 3, j = 1
i = 3, j = 2
i = 3, j = 3
Breaking out of outer loop when i*j equals 12
Loop terminated.

Explanation :

  • Label Definition: The outer loop is labelled outer.
  • Using the Label with break: When i * j == 12 is true, the program breaks out of the loop labelled outer, which terminates both the inner and outer loops.

Q57) How to Find and Remove Duplicate Elements from List in Java?

Ans-

Below is Java program to Find and Remove Duplicate Elements from List –

File name = LogicalDuniyaRemoveDuplicatesFromList.java :

import java.util.HashSet;
import java.util.LinkedList;
import java.util.Iterator;

public class LogicalDuniyaRemoveDuplicatesFromList {
    public static void main(String[] args) {
        // Create a LinkedList and add some elements (including duplicates)
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(2);
        list.add(4);
        list.add(1);
        list.add(5);
        
        System.out.println("Original LinkedList: " + list);
        
        // Remove duplicates
        removeDuplicates(list);
        
        System.out.println("LinkedList after removing duplicates: " + list);
    }
    
    public static void removeDuplicates(LinkedList<Integer> list) {
        // Create a HashSet to track seen elements
        HashSet<Integer> seen = new HashSet<>();
        
        // Use an iterator to traverse the LinkedList
        Iterator<Integer> iterator = list.iterator();
        
        while (iterator.hasNext()) {
            Integer current = iterator.next();
            
            // If the element is already in the HashSet, it's a duplicate; remove it
            if (!seen.add(current)) {
                iterator.remove();
            }
        }
    }
}

Explanation:

1. LinkedList Creation:

  • A LinkedList of integers is created and populated with elements. Some of these elements are duplicates (e.g., 1 and 2 appear more than once).

2. Printing the Original LinkedList:

  • The original LinkedList is printed to the console to show the elements before removing duplicates.

3. removeDuplicates Method:

  • This method takes a LinkedList as input and removes any duplicate elements.
  • A HashSet named seen is used to keep track of elements that have already been encountered. Since a HashSet only allows unique elements, it helps in identifying duplicates.
  • An Iterator is used to traverse through the LinkedList. The iterator provides a safe way to remove elements while iterating.
  • The iterator.next() method retrieves the next element from the LinkedList.
  • The HashSet.add(current) method tries to add the current element to the HashSet. If the element is already present in the HashSet, add() returns false, indicating it’s a duplicate.
  • If the element is a duplicate (i.e., seen.add(current) returns false), the iterator.remove() method removes it from the LinkedList.

4. Printing the LinkedList After Removing Duplicates:

  • Finally, the modified LinkedList, now free of duplicates, is printed.

Output:

When you run this program, the output will be:

Original LinkedList: [1, 2, 3, 2, 4, 1, 5]
LinkedList after removing duplicates: [1, 2, 3, 4, 5]

Q58) What are lambda expressions in Java 8, and how do they improve code readability and conciseness?

Ans-

Lambda expressions were introduced in Java 8 as a key feature to support functional programming. They allow you to write more concise, readable, and flexible code, especially when working with collections or functional interfaces.

What are Lambda Expressions?

A lambda expression in Java is essentially an anonymous function (a function without a name) that can be treated as an instance of a functional interface. A functional interface is an interface with exactly one abstract method, like Runnable, Callable, Comparator, or the custom functional interfaces you might define.

The syntax of a lambda expression is as follows:

(parameters) -> expression

Or, if you need a block of statements:

(parameters) -> { statements; }

Example of a Lambda Expression

Consider a simple example where you want to sort a list of strings by their lengths. Before Java 8, you would do this using an anonymous inner class:

List<String> strings = Arrays.asList("abc", "abcd", "ab");
Collections.sort(strings, new Comparator<String>() {
    @Override
    public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
});

With lambda expressions in Java 8, you can achieve the same result in a much more concise way:

List<String> strings = Arrays.asList("abc", "abcd", "ab");
strings.sort((s1, s2) -> Integer.compare(s1.length(), s2.length()));

Or even more concisely using method references:

List<String> strings = Arrays.asList("abc", "abcd", "ab");
strings.sort(Comparator.comparingInt(String::length));

How Lambda Expressions Improve Code Readability and Conciseness

1. Eliminates Boilerplate Code:

  • Lambda expressions reduce the need for boilerplate code, like anonymous inner classes. In the example above, the lambda expression (s1, s2) -> Integer.compare(s1.length(), s2.length()) replaces the entire Comparator anonymous class.

2. Focus on What Instead of How:

  • With lambda expressions, you can focus more on the logic of what you want to achieve rather than the details of how to implement an interface. This shifts the focus from how the sorting is done to what the criteria for sorting are.

3. Improves Readability:

  • Shorter, more declarative code is generally easier to read and understand. This can lead to fewer bugs and easier maintenance. For example, the lambda expression is straightforward and tells you directly that the list is being sorted by string length.

4. Facilitates Functional Programming:

  • Lambda expressions are the foundation of functional programming in Java. They allow you to pass behavior (like a comparison function) as data, making it easier to write flexible and reusable code.

More Examples of Lambda Expressions

Example 2: Runnable with Lambda

Before Java 8:

Runnable r = new Runnable() {
    @Override
    public void run() {
        System.out.println("Running in a thread");
    }
};
new Thread(r).start();

With Java 8 Lambda:

Runnable r = () -> System.out.println("Running in a thread");
new Thread(r).start();

In Java 8, Lambda expressions enable more concise and readable code by reducing the verbosity associated with anonymous classes and by allowing you to focus on expressing what you want the code to do rather than how it should do it. They are a key feature that supports functional programming and allows for more flexible and reusable code.


Q59) Explain key terminologies of Multi-Threading in Java.

Ans-

Here are the key concepts regarding multi-threading in Java –

1. Thread Creation

In Java, there are two main ways to create a thread:

A. By Extending the Thread Class:

  • You can create a new thread by extending the Thread class and overriding its run() method.

B. By Implementing the Runnable Interface:

  • Another way to create a thread is by implementing the Runnable interface and passing an instance of it to a Thread object.

2. Thread Lifecycle

The lifecycle of a thread in Java includes several states:

  • New: When a thread is created, it is in the “New” state. It hasn’t started running yet.
  • Runnable: When the thread’s start() method is called, it goes into the “Runnable” state. The thread is ready to run but may not be running immediately (it is waiting for CPU time).
  • Running: The thread is in the “Running” state when the CPU starts executing its code.
  • Blocked/Waiting: A thread enters this state when it is waiting for a resource, such as I/O or another thread. It remains in this state until the resource becomes available.
  • Terminated: A thread enters the “Terminated” state when its run() method has finished executing, either naturally or due to an unhandled exception.

3. Thread Synchronization

Synchronization is a mechanism that ensures that two or more concurrent threads do not simultaneously execute some particular program segment known as a critical section. In Java, this is done using the synchronized keyword.

  • Synchronized Methods: To synchronize an entire method, you can declare it with the synchronized keyword.
  • Synchronized Blocks: You can synchronize a specific block of code instead of the entire method.

Example syntax :

// Sync. Methods - 
public synchronized void syncMethod() {
    // synchronized code
}

// Sync. Blocks - 
public void someMethod() {
    synchronized(this) {
        // synchronized code
    }
}

4. Thread Communication

Thread communication in Java is achieved using methods like wait(), notify(), and notifyAll():

  • wait(): A thread that calls wait() goes into a waiting state until another thread calls notify() or notifyAll() on the same object.
  • notify(): Wakes up a single thread that is waiting on the object’s monitor.
  • notifyAll(): Wakes up all the threads that are waiting on the object’s monitor.

5. Thread Interruption

Thread interruption is a way to signal a thread to stop its current task. This is often used for managing long-running tasks.

  • interrupt() method: You can interrupt a thread by calling interrupt() on the Thread object.
  • Handling Interruptions: A thread can check if it has been interrupted by calling Thread.interrupted() or isInterrupted().

6. Thread Priorities

Java allows you to set the priority of a thread using the setPriority(int priority) method. Thread priorities determine the relative importance of threads; however, they don’t guarantee the order of thread execution, as this is dependent on the operating system’s thread scheduler.

  • The priority is set using integer values ranging from Thread.MIN_PRIORITY (1) to Thread.MAX_PRIORITY (10). The default priority is Thread.NORM_PRIORITY (5).

Example Code :

class MyLogicalDuniyaThread extends Thread {
    public void run() {
        System.out.println("Thread running with priority: " + getPriority());
    }
}

public class Main {
    public static void main(String[] args) {
        MyLogicalDuniyaThread t1 = new MyLogicalDuniyaThread();
        MyLogicalDuniyaThread t2 = new MyLogicalDuniyaThread();
        
        t1.setPriority(Thread.MIN_PRIORITY); // Set priority to 1
        t2.setPriority(Thread.MAX_PRIORITY); // Set priority to 10
        
        t1.start();
        t2.start();
    }
}

Q60) What will be the output of below program?

public class LogicalDuniyaCode { 

	public static void main(String[] args) { 
		if (true) 
			break; 
	} 
} 

Ans –

The code, which is provided will not compile and throw a compile-time error. Here’s why:

Explanation :

  1. break Statement:
    • The break statement in Java is used to exit a loop (like for, while, or do-while) or to exit a switch statement.
    • The break statement cannot be used outside of a loop or a switch statement. It must be inside a loop or switch to indicate which control flow structure it should break out of.
  2. In Given Code:
    • The break statement is used within an if block, but it’s not inside a loop or a switch statement. This is not allowed in Java, so the compiler will throw an error.

Q61) What will be the Output of the below code?

public class LogicalDuniyaCode { 
    public static void main(String[] args) 
    { 
        int $_ = 1; 
        System.out.println("LogicalDuniya Platform is Number " + $_ );
    } 
}

Ans-

The code you provided will compile and run successfully, producing the following output:

LogicalDuniya Platform is Number 1

Explanation:

  1. Variable Naming:
    • As mentioned earlier, the variable name $_ is valid in Java because it starts with a dollar sign ($) and ends with an underscore (_). Java allows variable names to start with a letter, dollar sign ($), or underscore (_), and they can contain digits after the first character.
  2. Variable Initialization:
    • The variable $_ is declared and initialized with the value 1.
  3. Output Statement:
    • The System.out.println statement prints the string "LogicalDuniya Platform is Number " followed by the value of $_, which is 1.
  4. Output:
    • The program outputs the concatenated string "LogicalDuniya Platform is Number 1" to the console.


Q62) Give examples of overloading and overriding in Java.

Ans-

When a class has more than one method with same name with different arguments, they are called overloaded methods. The following example code shows as overloaded method called print:

class LogicalDuniyaOne {
	void print(String s) {
		System.out.println(s);
	}

	void print(String s, int count) {
		while (count > 0) {
			System.out.println(s);
			count--;
		}
	}
}

When a superclass method is also implemented in the child class, it’s called overriding. The following example code shows how to annotate the printname() method that’s implemented in both classes:

class Parent {
	void printName() {
		System.out.println("Base Class");
	}
}

class Child extends Parent {
	@Override
	void printName() {
		System.out.println("Child Class");
	}
}

Q63) How do you create a functional interface?

Ans-

In Java, a functional interface is an interface that has exactly one abstract method. Functional interfaces are used as the basis for lambda expressions and method references in Java 8 and later. A functional interface can also contain default methods and static methods, but it should have only one abstract method.

Here’s a step-by-step guide on how to create a functional interface:

  1. Define an Interface:
    • Start by defining an interface using the interface keyword.
  2. Declare a Single Abstract Method:
    • Inside the interface, declare a single abstract method. This is the only method that must be implemented when the interface is used.
  3. Use the @FunctionalInterface Annotation (Optional but Recommended):
    • You can annotate the interface with @FunctionalInterface to indicate that it is intended to be a functional interface. The annotation is optional but recommended because it helps catch errors at compile-time if you accidentally add more than one abstract method.
@FunctionalInterface
interface MyFunctionalInterface {
    void execute(); // Single abstract method

    // You can also have default methods
    default void show() {
        System.out.println("This is a default method in a functional interface.");
    }

    // And static methods
    static void staticMethod() {
        System.out.println("This is a static method in a functional interface.");
    }
}

public class Main {
    public static void main(String[] args) {
        // Using a lambda expression to implement the functional interface
        MyFunctionalInterface func = () -> System.out.println("Executing the functional interface's abstract method!");

        // Call the method
        func.execute(); // Output: Executing the functional interface's abstract method!

        // You can also call the default method
        func.show(); // Output: This is a default method in a functional interface.

        // Static methods are called on the interface itself
        MyFunctionalInterface.staticMethod(); // Output: This is a static method in a functional interface.
    }
}

Built-In Functional Interfaces in Java 8:

Java 8 provides several built-in functional interfaces, such as:

  • Runnable: Represents a task that does not return a result.
  • Callable<V>: Represents a task that returns a result.
  • Comparator<T>: Compares two objects.
  • Predicate<T>: Evaluates a condition on an object and returns a boolean.
  • Function<T, R>: Represents a function that accepts one argument and returns a result.
  • Supplier<T>: Represents a supplier of results.
  • Consumer<T>: Represents an operation that accepts a single input and returns no result.


Q64) What are the differences between List and Set in Java?

Ans-

There are various differences between List and Set –

ListSet
List interface allows duplicate elements.Set interface does not allow duplicate elements.
Insertion order is preserved in List.Insertion order is not preserved in Set.
We can add any number of null values in List object.We can add only one null value.
The List provides get(..) method to fetch the element at a specified index.Set does not provide any get(..) method to fetch an element at a specified index.
We can use the List, if we need to access the elements frequently by using the index.We can use Set, if you want to create a collection of unique elements.

Q65) Explain the difference between Iterator and ListIterator.

Ans-

In Java, both Iterator and ListIterator are interfaces used to iterate over collections like lists. They are primarily used to fetch objects / values from the List, but they also have some differences in terms of features and capabilities –

IteratorListIterator
Iterator is a universal interface that allows you to traverse through elements in a collection in a forward direction.ListIterator is a child interface of Iterator and provides more functionality than Iterator.
It is available for all collections in the Java Collections Framework, including lists, sets, and maps.It is specific to list collections like ArrayList and LinkedList.
Iterator supports only forward traversal; you cannot traverse backward or modify the underlying collection while iterating.Unlike Iterator, ListIterator allows bidirectional traversal, meaning you can traverse both forward and backward through the list.
It has three main methods: hasNext(), next(), and remove().
In addition to the methods provided by Iterator, ListIterator has additional methods such as hasPrevious(), previous(), add(), set(), and previousIndex(), nextIndex().
You can obtain an Iterator instance using the iterator() method of the collection.

ListIterator also allows you to modify the underlying list during iteration, such as adding, removing, or modifying elements.
The standard Collection interface extends Iterable. Further, the Iterable interface defines the iterator() method to return an Iterator instance:

public interface Iterable<T>
{
Iterator<T> iterator();
...
}
The ListIterator is a subtype of Iterator. Therefore, all the features Iterator offers are also available in ListIterator.
ListItrator is used explicitly with lists.
Apart from the three methods from the Iterator interface [ hasNext(), next(), and remove() ].

Java Interview Questions for Masters

In this section, we will focus on most popular Java Interview Questions for Master Java Developers having more than 10 years of experience in the industry. These questions are taken from different Java Interview Experiences, but there are chances your interviewer twist any of these question and ask it differently. So be little careful while answering.

Let’s see and understand the Java Interview Question for Master Java Developers –

Q66) Why is synchronization necessary? How will you implement synchronization in Java?

Ans-

Synchronization is necessary in multithreaded programming to ensure that multiple threads operate correctly and safely when accessing shared resources or critical sections of code. Without synchronization, concurrent access to shared resources can lead to data corruption, race conditions, and other unexpected behaviours.

Java provides several mechanisms to address synchronization:

  1. Synchronized Methods:
    In Java, you can declare methods as synchronized to ensure that only one thread can execute the method at a time. When a thread enters a synchronized method, it acquires the intrinsic lock associated with the method’s object, preventing other threads from executing synchronized methods of the same object concurrently.
  2. Synchronized Blocks:
    Java allows you to create synchronized blocks of code using the synchronized keyword. This allows for finer-grained control over synchronization compared to synchronized methods. Threads must acquire the lock associated with the specified object before entering the synchronized block.
  3. Volatile Keyword:
    The volatile keyword is used to indicate that a variable’s value may be modified by multiple threads. It ensures that changes made by one thread to the variable’s value are visible to other threads immediately. However, it does not provide atomicity or mutual exclusion like synchronized methods or blocks.
  4. Locks:
    Java provides explicit lock objects through classes such as ReentrantLock and ReadWriteLock in the java.util.concurrent.locks package. These locks offer more flexibility and functionality compared to intrinsic locks obtained by synchronized methods and blocks.
  5. Atomic Variables:
    The java.util.concurrent.atomic package provides classes such as AtomicInteger, AtomicBoolean, and AtomicReference, which offer atomic operations on their values. These classes can be used to perform thread-safe operations without the need for explicit synchronization.

So, Java’s synchronization mechanisms help developers create robust multithreaded applications by ensuring thread safety and preventing data corruption or inconsistencies caused by concurrent access to shared resources.


Q67) What is the difference between public, protected, package-private and private in Java?

Ans-

Let’s understand this with an example illustration –

  • A private member (i) – is only accessible within the same class as it is declared.
  • A member with no access modifier (j) – is only accessible within classes in the same package.
  • A protected member (k) – is accessible within all classes in the same package and within subclasses in other packages.
  • A public member (l) – is accessible to all classes (unless it resides in a module that does not export the package it is declared in).

Q68) When to use LinkedList over ArrayList in Java?

Ans-

ArrayList with ArrayDeque are preferable in many more use-cases than LinkedList.

Most of the times, ArrayList accessing an element takes constant time [O(1)] and adding an element takes O(n) time [worst case]. In LinkedList inserting an element takes O(n) time and accessing also takes O(n) time but LinkedList uses more memory than ArrayList.

LinkedList and ArrayList are two different implementations of the List interface. LinkedList implements it with a doubly-linked list. ArrayList implements it with a dynamically re-sizing array.

Overall, depending on the operations we intend to do, we should choose the implementations accordingly.

  • Iterating over either kind of List is practically equally cheap.
  • Iterating over an ArrayList is technically faster, but unless we’re doing something really performance-sensitive, we shouldn’t worry about this.

Q69) What is the difference between Comparable and Comparator?

Ans-

Both

ComparableComparator
This interface is present in java.lang package.This interface is present in java.util package.
Contains compareTo() method to sort elements.Contains compare() method to sort elements.
The definition of objects sorting must be in the same class whose object you are going to sort.Sorting should be in a separate class to write different sorting based on different attributes of objects.
Method sorts the data according to fixed sorting order.The compare() method sorts the data as per customized sorting order.
It affects the original class.It does not affect the original class.

Q70) How to convert an Array to a Set in Java

Ans-

To create a Set object from Array, we can follow multiple approaches –

Set<T> mySet = new HashSet<>(Arrays.asList(someArray));

In Java 9+ :

Set<T> mySet = Set.of(someArray);

Note💡
Set.of throws IllegalArgumentException – if there are any duplicate elements in someArray. See more details: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/Set.html#of(E…)

For JDK >= 8, an attractive option is something like:

Arrays.stream(intArray).boxed().collect(Collectors.toSet());

Q71) How many types of exceptions can occur in a Java program?

Ans-

There are 2 types of Exceptions in Java –

Checked ExceptionsUncheck Exceptions
Checked exceptions are those exceptions that are checked at compile time by the compiler.Unchecked exceptions are those exceptions that are not checked at compile time by the compiler.
These exceptions are subclasses of Exception but not subclasses of RuntimeException.These exceptions are subclasses of RuntimeException.
Checked exceptions are typically exceptions that a program should anticipate and handle gracefully, such as file I/O errors, network errors, database errors, etc.Unchecked exceptions usually indicate programming errors or exceptional conditions that a program might not be able to recover from, such as divide by zero, null pointer dereference, array index out of bounds, etc.
Methods that might throw checked exceptions must declare them in their throws clause or handle them using a try-catch block.Unlike checked exceptions, methods are not required to declare unchecked exceptions in their throws clause or handle them using a try-catch block. However, they can still be caught and handled if desired.
Examples of Checked Exceptions –
IOException, SQLException, ClassNotFoundException etc.
Examples of Unchecked Exceptions –
subclasses of RuntimeException (ArithmeticException, NullPointerException, NumberFormatException, etc.)

Q72) Explain Runtime Exceptions in Java.

Ans-

Runtime exceptions, also known as unchecked exceptions, are a type of exception in Java that occur at runtime and are not checked by the compiler at compile time. Unlike checked exceptions, which must be declared or handled by the calling method, runtime exceptions do not need to be declared or caught explicitly.

Here are some key points about runtime exceptions in Java:

  1. Inheritance:
    Runtime exceptions are subclasses of the RuntimeException class or one of its subclasses. They are part of the java.lang package.
  2. Unchecked:
    Runtime exceptions are unchecked exceptions, which means the compiler does not enforce handling or declaration of these exceptions. This makes them convenient for handling programming errors or exceptional conditions that may not be anticipated by the programmer.
  3. Causes:
    Runtime exceptions often arise due to errors in program logic, such as null pointer dereferences, division by zero, array index out of bounds, or invalid type casting. They may also occur due to environmental factors such as resource exhaustion.
  4. Handling:
    While it’s not required to catch or declare runtime exceptions, it’s still a good practice to handle them if appropriate. Handling runtime exceptions can help improve the robustness and reliability of the application by gracefully recovering from unexpected errors.
  5. Examples:
    Common examples of runtime exceptions in Java include NullPointerException, ArrayIndexOutOfBoundsException, ArithmeticException, ClassCastException, and IllegalArgumentException, among others.

Here’s an example demonstrating a runtime exception:

public class LogicalDuniyaExample 
{
    public static void main(String[] args) 
    {
        // Attempting to divide by zero
        int result = 10 / 0; // This line will throw an ArithmeticException at runtime
    }
}

In this example, the division by zero operation will throw an ArithmeticException at runtime because it is not allowed in Java. Since ArithmeticException is a subclass of RuntimeException, it is a runtime exception, and the compiler does not enforce handling or declaration of this exception.


Q73) What is difference between Arrays.asList(array) and new ArrayList(Arrays.asList(array))?

Ans-

Let’s first understand Arrays.asList(arr)

It takes an array <code>arr and creates a wrapper that implements List<Integer>, which makes the original array available as a list.

Nothing is copied and all, only a single wrapper object is created. Operations on the list wrapper are propagated to the original array. This means that if you shuffle the list wrapper, the original array is shuffled as well, if you overwrite an element, it gets overwritten in the original array, etc.

Of course, some List operations aren’t allowed on the wrapper, like adding or removing elements from the list, you can only read or overwrite the elements.

Also note that the list wrapper doesn’t extend ArrayList – it’s a different kind of object. ArrayLists have their own, internal array, in which they store their elements, and are able to resize the internal arrays etc. The wrapper doesn’t have its own internal array, it only propagates operations to the array given to it.

Now, let’s understand the other side –

<code>new ArrayList<Integer>(Arrays.asList(arr))

Here if you subsequently create a new array as above, then you create new ArrayList, which is a full, independent copy of the original one.

Although here you create the wrapper using Arrays.asList as well, it is used only during the construction of the new ArrayList and is garbage-collected afterwards. The structure of this new ArrayList is completely independent of the original array.

It contains the same elements (both the original array and this new ArrayList reference the same integers in memory), but it creates a new, internal array, that holds the references. So when you shuffle it, add, remove elements etc., the original array is unchanged.


Q74) When do you understand with singletonMap() method of Java Collection Framework?

Ans-

In Java, the singletonMap() method is a utility method provided by the Collections class in the java.util package. It is used to create an immutable map (a key-value pair collection) that contains only one mapping.

Here’s a brief explanation of the singletonMap() method:

  • Purpose:
    The singletonMap() method is used to create a map with a single entry (key-value pair) where both the key and the value are specified.
  • Immutable Map:
    The map returned by singletonMap() is immutable, meaning that once created, its contents cannot be modified. Attempts to add, remove, or update elements in the map will result in an UnsupportedOperationException.
  • Memory Efficiency:
    Since the map contains only one entry, it is memory-efficient for cases where you need to represent a single key-value mapping without creating a larger data structure.
  • Syntax:
static <K,V> Map<K,V> singletonMap(K key, V value)
  • Parameters:
    key: The key with which the specified value is to be associated in the map.
    value: The value to be associated with the specified key in the map.
  • Return Value:
    The singletonMap() method returns an immutable map containing the specified key-value mapping.

Example :

import java.util.Collections;
import java.util.Map;

public class LogicalDuniyaExample {
    public static void main(String[] args) {

        // Creating a singleton map with key="name" and value="John"
        Map<String, String> singleton = Collections.singletonMap("name", "John");

        // Printing the contents of the map
        System.out.println("Singleton Map: " + singleton);
    }
}

Output :

Singleton Map: {name=John}

So, the singletonMap() is a convenient way to create a simple, immutable map with a single key-value pair. It is particularly useful in scenarios where you need to represent a constant mapping or pass a single key-value pair to a method that expects a map.


Q75) What are the advantages of Multi-threading in Java?

Ans-

Multithreading in Java allows multiple tasks or processes to run concurrently within a single program. Here are some advantages of multithreading –

Benefits Description
Improved PerformanceMultithreading can lead to improved performance by allowing multiple tasks to execute simultaneously.

For example, in a web server application, multithreading allows the server to handle multiple client requests concurrently, thereby increasing throughput and reducing response times.
Increased ResponsivenessMultithreading can make an application more responsive by allowing it to continue performing other tasks while waiting for slow operations to complete.

For instance, in a graphical user interface (GUI) application, multithreading allows the user interface to remain responsive even when performing time-consuming operations in the background.
Resource UtilizationMultithreading enables better utilization of available resources such as CPU cores.

By dividing tasks into multiple threads, a multithreaded application can make use of idle CPU cycles, ensuring that the CPU is constantly engaged in productive work.
Simplified DesignMultithreading can simplify the design of complex applications by allowing them to be broken down into smaller, more manageable units of execution.

Each thread can focus on a specific task, making the overall design easier to understand and maintain.
ConcurrencyMultithreading enables concurrent execution of tasks, which can lead to more efficient resource usage and better overall system performance.

Tasks that can run independently of each other can execute simultaneously, maximizing throughput and minimizing wait times.

Multithreading in Java provides several benefits, including improved performance, increased responsiveness, better resource utilization, simplified design, and concurrency, making it a valuable tool for developing efficient and scalable applications.


Q76) Explain the difference between process and thread in Java.

Ans-

There are many differences between the process and thread –

ProcessThread
A process is a program in execution.A thread is a single sequence of instructions within a process.
The process takes more time for context switching.The thread takes less time for context switching.
The process takes more time to terminate.The thread takes less time to terminate.
The process is less efficient in terms of communication.Thread is more efficient in terms of communication.
The process is isolated.Threads share memory.
The process has its own Process Control Block, Stack, and Address Space.                   Thread has Parents’ PCB, its own Thread Control Block, and Stack and common Address space.
The process does not share data with each other.Threads share data with each other.

Q77) How do you write an interface with default and static method?

Ans-

Java 8 introduced default and static methods in interfaces. This bridged the gap between interfaces and abstract classes. The following example code shows one way to write an interface with the default and static method –

public interface LogicalDuniyaInterface1 {
	
	// regular abstract method
	void method1(String str);
	
	default void log(String str) {
		System.out.println("I1 logging::" + str);
	}
	
	static boolean isNull(String str) {
		System.out.println("Interface Null Check");

		return str == null ? true : "".equals(str) ? true : false;
	}

}

Q78) What is the difference between Queue and Deque?

Ans-

Here are a few basic differences between Queue and Deque –

QueueDeque
The queue is basically a linear Data structure that is used to store a collection of elements.Deque is also known as a Double-ended queue is also a linear data structure that stores a collection of elements with operations to remove and add from both ends.
Elements in a queue can only be inserted at the end of the data structure.Elements can be inserted from both the ends of the data structure.
Queue can be implemented using Array or LinkedList.Dequeue can be implemented using Circular Array or DoublyLinkedList.
Queues are generally used to implement a waiting list or task queue.Deque is basically used to implement a stack or dequeuing elements from both ends.

Q79) How do you use the forEach() method in Java?

Ans-

The forEach() method provides a shortcut to perform an action on all the elements of an iterable. The following example code shows how to iterate over the list elements and print them:

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

list.forEach(System.out::print);

Q80) How do you create an enum in Java?

Ans-

In Java, an enum (short for “enumeration”) is a special data type that represents a group of constants (unchangeable variables, like final variables). An enum in Java is a type used to define a collection of constants, which can be accessed in a type-safe manner.

How to Create an Enum? :

Here’s a step-by-step guide on how to create an enum in Java:

  1. Define an Enum:
    • Use the enum keyword to define a new enum type. This is similar to defining a class, but instead of the class keyword, you use enum.
  2. Add Constants:
    • Inside the enum, define the constants, which are usually written in uppercase letters and separated by commas.
  3. (Optional) Add Fields, Constructors, and Methods:
    • Enums can have fields, constructors, and methods, just like regular classes. The constructor is private by default because enum types are implicitly final.
enum Day {
    SUNDAY,
    MONDAY,
    TUESDAY,
    WEDNESDAY,
    THURSDAY,
    FRIDAY,
    SATURDAY
}

public class LogicalDuniyaMain {

    public static void main(String[] args) {

        Day today = Day.WEDNESDAY;
        
        // Print the enum constant
        System.out.println("Today is: " + today); // Output: Today is: WEDNESDAY
        
        // Use enum in a switch statement
        switch (today) {
            case MONDAY:
                System.out.println("Mondays are tough.");
                break;
            case FRIDAY:
                System.out.println("Fridays are fun!");
                break;
            case SATURDAY: case SUNDAY:
                System.out.println("Weekends are the best!");
                break;
            default:
                System.out.println("Midweek days are okay.");
                break;
        }
    }
}


Q81) What are the Differences between HashSet and TreeSet?

Ans-

Here are basic differences between HashSet and TreeSet –

HashSetTreeSet
HashSet is unordered.TreeSet is based on natural ordering.
HashSet is Implemented by the HashSet class.TreeSet is Implemented by TreeSet class.
HashSet allows null elements.TreeSet does not allow null elements.
HashSet<String> hs = new HashSet<>();TreeSet<String> ts = new TreeSet<>();

Q82) How do you create text blocks in Java?

Ans-

Text blocks in Java were introduced in Java 13 as a preview feature and became a standard feature in Java 15. They provide a way to write multi-line string literals in Java without needing to manage escape sequences for newlines and other special characters. This makes code more readable and easier to maintain.

Syntax of Text Blocks :

A text block is defined using three double-quote characters (""") as delimiters. The content of the text block can span multiple lines, and the formatting of the text block will be preserved when it is compiled and run.

Here’s the basic syntax:

String logicalDuniyaTextBlock = """
    Hey there. This is a text block.
    It can span multiple lines.
    Newlines are preserved, and "quotes" don't need escaping.
    """;

Q83) How do you create a record in Java?

Ans-

In Java, a record is a special kind of class introduced in Java 14 as a preview feature and became a standard feature in Java 16. Records are designed to be a concise way to create classes that are primarily used to store data. A record automatically provides implementations for several methods, including the constructor, equals(), hashCode(), and toString().

To create a record in Java, you use the record keyword followed by the name of the record and a list of its components (fields) inside parentheses. Here’s a basic example:

public record Person(String name, int age) {
}

Explanation :

  • record: This keyword declares a new record class.
  • Person: The name of the record.
  • String name, int age: These are the components (fields) of the record. They are implicitly private and final.


Q84) What are the differences between HashMap and TreeMap?

Ans-

Both these classes HashMap and TreeMap are present in java.util package, they are different in many points –

HashSetTreeSet
HashMap uses a hashtable in order to store key-value pairs.TreeMap uses Red-black trees to store key-value pair.
HashMap does not maintain any specific order for key-value pairs.TreeMap maintains a natural ordering based on the keys.
HashMaps are faster for retrieval compared to Treemap.Retrieval in TreeMap is slower as it uses tree traversal to find keys.
Order of iteration is not guaranteed in the HashMap.Iteration is of sorted order based on keys.

Q85) How do you show a diamond problem with multiple inheritance in Java?

Ans-

What is the Diamond Problem?

The diamond problem occurs when a class inherits from two classes (or interfaces) that both have a method with the same signature. This creates ambiguity for the compiler because it doesn’t know which version of the method to use.

Example of the Diamond Problem in Java Using Interfaces :

interface A {
    default void show() {
        System.out.println("Interface A");
    }
}

interface B extends A {
    default void show() {
        System.out.println("Interface B");
    }
}

interface C extends A {
    default void show() {
        System.out.println("Interface C");
    }
}

public class DiamondProblemExample implements B, C {
    public static void main(String[] args) {
        DiamondProblemExample example = new DiamondProblemExample();
        example.show();       // This creates ambiguity due to the diamond problem.
    }

    @Override
    public void show() {
        // Resolving the ambiguity by explicitly choosing which interface's method to call
        B.super.show();       // or C.super.show();
    }
}

Explanation :

  1. Interface A: Has a default method show() that prints “Interface A”.
  2. Interface B and Interface C: Both extend A and override the show() method. B prints “Interface B”, and C prints “Interface C”.
  3. DiamondProblemExample: Implements both B and C. Here, Java will not know whether to use B‘s show() method or C‘s show() method. This is the diamond problem.

Resolution :

Java allows you to resolve the diamond problem by explicitly specifying which method you want to use. You can do this using the super keyword along with the interface name.

@Override
public void show() {
    B.super.show(); // This resolves the ambiguity by choosing B's show method.
    // Alternatively, you could use C.super.show();
}

Q86) How will you achieve Multiple Inheritance through interfaces in Java?

Ans-

Java does not support multiple inheritance with classes to avoid ambiguity (diamond problem). However, it supports multiple inheritance through interfaces.

interface Animal {
    void eat();
}

interface Pet {
    void play();
}

class Dog implements Animal, Pet {
    public void eat() {
        System.out.println("Dog is eating");
    }

    public void play() {
        System.out.println("Dog is playing");
    }
}

public class MultipleInheritance {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // Implemented from Animal interface
        dog.play(); // Implemented from Pet interface
    }
}

Output :

Dog is eating
Dog is playing

Q87) What are the differences between the Singly Linked List and Doubly Linked List?

Ans-

A Singly Linked List and a Doubly Linked List are both types of linked lists that are used to store a collection of elements. They differ in their structure, performance, and usage. Here are the key differences between them:

Singly Linked ListDoubly Linked List
Each node contains data and a reference (or pointer) to the next node in the sequence.
The last node has a reference to null, indicating the end of the list.
Each node contains data, a reference to the next node, and a reference to the previous node.
The first node’s prev reference is null, and the last node’s next reference is null.
Navigation is unidirectional (forward only). You can traverse the list from the head to the end but not backward.Navigation is bidirectional. You can traverse the list forward and backward, which makes certain operations more efficient.
Uses less memory because each node only stores one reference (to the next node).Uses more memory because each node stores two references (to the next and previous nodes).
Insertion and deletion operations are generally more complex if done in the middle of the list since you need to manage only the next pointers.Insertion and deletion are easier and more efficient, especially in the middle of the list, because you have both next and prev pointers.
Used when memory is a concern and the operations predominantly involve forward traversal or when the list is primarily read-only.Used when frequent insertion and deletion operations are required, especially in the middle of the list.

Q88) How do you get distinct characters and their count in a string in Java?

Ans-

To get distinct characters and their count in a string in Java, you can use a HashMap to store each character as a key and its corresponding count as the value. Below is an example of how you can achieve this –

import java.util.HashMap;
import java.util.Map;

public class LogicalDuniyaDistinctCharCount {
    public static void main(String[] args) {
        String input = "programming";

        // Call the method to get the distinct characters and their count
        Map<Character, Integer> charCountMap = getCharacterCount(input);

        // Print the result
        for (Map.Entry<Character, Integer> entry : charCountMap.entrySet()) {
            System.out.println("Character: " + entry.getKey() + ", Count: " + entry.getValue());
        }
    }

    public static Map<Character, Integer> getCharacterCount(String input) {
        // Create a HashMap to store the characters and their counts
        Map<Character, Integer> charCountMap = new HashMap<>();

        // Convert the input string to a character array
        char[] charArray = input.toCharArray();

        // Iterate over the character array
        for (char c : charArray) {
            // Check if the character is already in the map
            if (charCountMap.containsKey(c)) {
                // If the character is already in the map, increment its count
                charCountMap.put(c, charCountMap.get(c) + 1);
            } else {
                // If the character is not in the map, add it with a count of 1
                charCountMap.put(c, 1);
            }
        }

        return charCountMap;
    }
}

Output :

Character: p, Count: 1
Character: r, Count: 2
Character: o, Count: 1
Character: g, Count: 2
Character: a, Count: 1
Character: m, Count: 2
Character: i, Count: 1
Character: n, Count: 1

Q89) How do you remove all occurrences of a given character from an input string in Java?

Ans-

To remove all occurrences of a given character from an input string in Java, you can use the replace() method or replaceAll() method of the String class. Below is an example using both methods.

Example 1: Using replace() Method

The replace() method replaces all occurrences of a specified character with another character or an empty string.

public class RemoveCharacter {
    public static void main(String[] args) {
        String input = "Hello World";
        char charToRemove = 'o';

        // Use the replace() method to remove the character
        String result = input.replace(Character.toString(charToRemove), "");

        System.out.println("Original String: " + input);
        System.out.println("String after removing '" + charToRemove + "': " + result);
    }
}

Output:

For the input string "Hello World" and the character 'o', the output will be:

Original String: Hello World
String after removing 'o': Hell Wrld

Example 2: Using replaceAll() Method

The replaceAll() method can be used if you want to remove a character using a regular expression.

public class RemoveCharacter {
    public static void main(String[] args) {
        String input = "Hello World";
        char charToRemove = 'o';

        // Use the replaceAll() method to remove the character
        String result = input.replaceAll(Character.toString(charToRemove), "");

        System.out.println("Original String: " + input);
        System.out.println("String after removing '" + charToRemove + "': " + result);
    }
}

Output:

The output will be the same as with the replace() method:

Original String: Hello World
String after removing 'o': Hell Wrld

Q90) Difference between the final method and the abstract method in Java?

Ans-

final Method

  • Definition: A final method is a method that cannot be overridden by subclasses.
  • Purpose: It is used to prevent subclasses from modifying or changing the behavior of the method.
  • Usage: When you want to ensure that a method’s implementation remains unchanged in any subclass.
  • Implementation: A final method must have a complete implementation; you cannot declare it without a body.
class Parent {
    public final void display() {
        System.out.println("This is a final method.");
    }
}

class Child extends Parent {
    // This will cause a compile-time error
    // public void display() {
    //     System.out.println("Trying to override final method.");
    // }
}

abstract Method

  • Implementation: An abstract method can only exist within an abstract class. Subclasses that extend the abstract class must provide an implementation for the abstract method.
  • Definition: An abstract method is a method that is declared without an implementation (i.e., it does not have a body).
  • Purpose: It is used to declare a method that must be implemented by subclasses. It defines a contract that all concrete (non-abstract) subclasses must fulfil.
  • Usage: When you want to force subclasses to provide specific implementations of the method.
abstract class Animal {
    public abstract void makeSound();  // Abstract method

    public void sleep() {  // Regular method
        System.out.println("This animal sleeps.");
    }
}

class Dog extends Animal {
    @Override
    public void makeSound() {
        System.out.println("Bark");
    }
}

Q91) Write a Java program that sorts HashMap by value.

Ans-

To sort a HashMap by its values, you can follow these steps:

  1. Convert the HashMap entries into a list.
  2. Sort the list using a custom comparator that compares the values.
  3. Optionally, convert the sorted list back into a LinkedHashMap to maintain the order of elements.

Here’s a Java program that demonstrates how to do this:

import java.util.*;

public class LogicalDuniyaSortHashMapByValue {

    public static void main(String[] args) {

        // Create a HashMap with some values
        HashMap<String, Integer> map = new HashMap<>();
        map.put("Apple", 50);
        map.put("Banana", 10);
        map.put("Orange", 20);
        map.put("Mango", 40);
        map.put("Grapes", 30);

        System.out.println("Original HashMap:");
        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }

        // Sort the HashMap by value
        LinkedHashMap<String, Integer> sortedMap = sortByValue(map);

        System.out.println("\nSorted HashMap by value:");
        for (Map.Entry<String, Integer> entry : sortedMap.entrySet()) {
            System.out.println(entry.getKey() + " : " + entry.getValue());
        }
    }

    // Method to sort the HashMap by value
    public static LinkedHashMap<String, Integer> sortByValue(HashMap<String, Integer> map) {
        // Convert the HashMap into a list of Map.Entry
        List<Map.Entry<String, Integer>> list = new LinkedList<>(map.entrySet());

        // Sort the list using a comparator
        list.sort(Map.Entry.comparingByValue());

        // Create a LinkedHashMap to preserve the order of elements
        LinkedHashMap<String, Integer> sortedMap = new LinkedHashMap<>();
        for (Map.Entry<String, Integer> entry : list) {
            sortedMap.put(entry.getKey(), entry.getValue());
        }

        return sortedMap;
    }
}

Output :

The sorted map is printed, showing the entries in ascending order of their values.

Original HashMap:
Apple : 50
Banana : 10
Orange : 20
Mango : 40
Grapes : 30

Sorted HashMap by value:
Banana : 10
Orange : 20
Grapes : 30
Mango : 40
Apple : 50

Q92) Explain Single, Multilevel and Hierarchical Inheritance in Java.

Ans-

1. Single Inheritance :

In single inheritance, a class (child class) inherits from one parent class.

class Animal {
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog is barking");
    }
}

public class SingleInheritance {
    public static void main(String[] args) {
        Dog dog = new Dog();
        dog.eat();  // Inherited method
        dog.bark(); // Method of Dog class
    }
}

Output :

Animal is eating
Dog is barking

2. Multilevel Inheritance :

In multilevel inheritance, a class inherits from a child class, making it a grandchild class.

class Animal {
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog is barking");
    }
}

class Puppy extends Dog {
    void weep() {
        System.out.println("Puppy is weeping");
    }
}

public class MultilevelInheritance {
    public static void main(String[] args) {
        Puppy puppy = new Puppy();
        puppy.eat();   // Inherited from Animal
        puppy.bark();  // Inherited from Dog
        puppy.weep();  // Method of Puppy class
    }
}

Output :

Animal is eating
Dog is barking
Puppy is weeping

3. Hierarchical Inheritance

In hierarchical inheritance, multiple child classes inherit from a single parent class.

class Animal {
    void eat() {
        System.out.println("Animal is eating");
    }
}

class Dog extends Animal {
    void bark() {
        System.out.println("Dog is barking");
    }
}

class Cat extends Animal {
    void meow() {
        System.out.println("Cat is meowing");
    }
}

public class HierarchicalInheritance {
    public static void main(String[] args) {
        Dog dog = new Dog();
        Cat cat = new Cat();
        
        dog.eat();  // Inherited method
        dog.bark(); // Method of Dog class
        
        cat.eat();  // Inherited method
        cat.meow(); // Method of Cat class
    }
}

Output:

Animal is eating
Dog is barking
Animal is eating
Cat is meowing

Q93) How will you prove that a String object in Java is immutable programmatically?

Ans-

To prove that a String object in Java is immutable programmatically, you can show that once a String object is created, any modification operations do not alter the original object but instead create a new String object.

Here’s an example that demonstrates this –

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

public class StringImmutabilityTest {
    public static void main(String[] args) {
        // Create a String object
        String originalString = "Hello";

        // Attempt to modify the String object
        String modifiedString = originalString.concat(", World!");

        // Print the original and modified strings
        System.out.println("Original String: " + originalString);
        System.out.println("Modified String: " + modifiedString);

        // Check if originalString and modifiedString point to the same object
        if (originalString == modifiedString) {
            System.out.println("The original string was modified.");
        } else {
            System.out.println("The original string was not modified.");
        }
    }
}

Output :

Original String: Hello
Modified String: Hello, World!
The original string was not modified.

Explanation:

1. Creating the Original String:

  • String originalString = "Hello"; creates a String object with the value "Hello".

2. Attempting to Modify the String:

  • String modifiedString = originalString.concat(", World!"); attempts to concatenate the string ", World!" to originalString. However, because String is immutable, this operation does not modify originalString but instead creates a new String object (modifiedString) that contains the concatenated result.

3. Comparing the Original and Modified Strings:

  • The original string originalString remains unchanged with the value "Hello", while modifiedString contains "Hello, World!".

4. Memory Address Comparison:

  • The comparison originalString == modifiedString checks if both variables point to the same memory address (i.e., are they the same object). In this case, they are not, which proves that originalString was not altered.

Q94) Java program to Add two Binary Strings and return a Binary String as a result. The addition should be performed as per the rules of binary addition.

Ans-

Here’s a Java program to add two binary strings and return the result as a binary string. The addition is performed according to the rules of binary addition:

  1. 0 + 0 = 0
  2. 0 + 1 = 1
  3. 1 + 0 = 1
  4. 1 + 1 = 10 (0 with a carry of 1)

The program handles binary addition, including carrying over when needed.

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

public class LogicalDuniyaBinaryAddition {

    public static void main(String[] args) {

        String binary1 = "1101";  // Binary representation of 13
        String binary2 = "1011";  // Binary representation of 11

        String result = addBinaryStrings(binary1, binary2);
        System.out.println("Sum: " + result);  // Output should be 11000 (Binary for 24)
    }

    public static String addBinaryStrings(String binary1, String binary2) {
        // Initialize result string
        StringBuilder result = new StringBuilder();

        // Initialize carry
        int carry = 0;

        // Start from the end of both strings
        int i = binary1.length() - 1;
        int j = binary2.length() - 1;

        // Process both strings from end to start
        while (i >= 0 || j >= 0) {
            // Get the current digits
            int bit1 = (i >= 0) ? binary1.charAt(i) - '0' : 0;
            int bit2 = (j >= 0) ? binary2.charAt(j) - '0' : 0;

            // Calculate the sum of the current digits and the carry
            int sum = bit1 + bit2 + carry;

            // If the sum is 2 or 3, we have a carry for the next step
            carry = sum / 2;

            // The current digit is the remainder when dividing by 2
            result.append(sum % 2);

            // Move to the next digits
            i--;
            j--;
        }

        // If there's a carry left, append it
        if (carry != 0) {
            result.append(carry);
        }

        // Reverse the result, as we appended digits in reverse order
        return result.reverse().toString();
    }
}

Explanation:

  1. Initialization:
    • The StringBuilder is used to build the result string in reverse order.
    • A carry variable is used to store any carry generated during the addition of the binary digits.
  2. Loop Through Both Strings:
    • The program processes both binary strings starting from the least significant bit (rightmost) to the most significant bit (leftmost).
    • At each step, it adds the corresponding bits from both strings, along with any carry from the previous step.
  3. Carry Handling:
    • If the sum of the bits plus carry is 2 or 3, it means there is a carry (either 1 or 2). The carry is stored and used in the next addition.
    • The current bit of the result is obtained using sum % 2 (remainder when divided by 2).
  4. Final Carry:
    • If there’s any carry left after processing all the bits, it’s added to the result.
  5. Reverse the Result:
    • The result is constructed in reverse order, so it needs to be reversed before returning.

Output :

Sum: 11000

This result is the binary sum of 1101 (13 in decimal) and 1011 (11 in decimal), which is 11000 (24 in decimal).


Q95) What is the output of the following code?

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

class Main {
	public static void main(String args[]) {
		// Your code goes here
		final int x = 10;
		int y = x++;
		System.out.println(y);
	}
}

Ans-

The code will not compile successfully. This is because you are attempting to use the post-increment operator (++) on a final variable.

Explanation :

int y = x++;: The post-increment operator (x++) attempts to increment the value of x by 1. However, since x is final, its value cannot be changed. Hence, using x++ is illegal and results in a compilation error.

final int x = 10;: This declares x as a final variable with a value of 10. Once a variable is marked as final, its value cannot be changed.

Compilation Error :

error: cannot assign a value to final variable x
int y = x++;
        ^

Q96) Explain Hybrid Inheritance Using Interfaces in Java.

Ans-

Hybrid inheritance is a combination of two or more types of inheritance. It can lead to complexity and ambiguity, so Java handles it using interfaces. Here is an example of hybrid inheritance involving multiple inheritance with interfaces and single inheritance with classes –

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

interface Animal {
    void eat();
}

interface Pet {
    void play();
}

class Dog implements Animal {
    public void eat() {
        System.out.println("Dog is eating");
    }
}

class Beagle extends Dog implements Pet {
    public void play() {
        System.out.println("Beagle is playing");
    }
}

public class HybridInheritance {
    public static void main(String[] args) {
        Beagle beagle = new Beagle();
        beagle.eat();  // Inherited from Dog class, which implements Animal interface
        beagle.play(); // Implemented from Pet interface
    }
}

Output:

Dog is eating
Beagle is playing


Q97) Difference between static loading and dynamic class loading in Java?

Ans-

Static Loading –

  • In static loading, classes are loaded into memory at compile time, and the loading process occurs before the program starts executing.
  • The class loading process is determined by the classloader hierarchy and classpath configuration.
  • Static loading is typically used for classes that are known and required by the application at startup.
  • Once loaded, the classes remain in memory for the entire duration of the program’s execution.
  • Example: Loading standard Java classes like java.lang.String or user-defined classes defined in the application source code.

Dynamic Loading –

  • In dynamic class loading, classes are loaded into memory at runtime, during the execution of the program.
  • Dynamic class loading allows classes to be loaded on-demand, based on runtime conditions or user input.
  • Classes are loaded using the ClassLoader mechanism, and the loading process can be customized to load classes from different sources, such as files, databases, or network locations.
  • Dynamic class loading is useful for scenarios where the classes to be loaded are not known in advance or need to be loaded based on runtime conditions.
  • Example: Loading JDBC drivers dynamically based on the database type specified in a configuration file, loading plugins or modules based on user preferences, or implementing a classpath scanner to load classes from external libraries or directories.
/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

// Example of Dynamic Class Loading in Java -

public class LogicalDuniyaExample {

    public static void main(String[] args) throws ClassNotFoundException {

        // Create a ClassLoader instance - 
        ClassLoader classLoader = LogicalDuniyaExample.class.getClassLoader();

        // Dynamically load a class using Class.forName() method
        Class<?> dynamicClass = Class.forName("com.example.DynamicClass", true, classLoader);
    }
}

In this example, the Class.forName() method is used for dynamic class loading. The method dynamically loads the class named "com.example.DynamicClass" at runtime using the provided ClassLoader. This allows the application to load classes based on runtime conditions or user input, providing flexibility and extensibility.


Q98) When is the ArrayStoreException thrown?

Ans-

The ArrayStoreException is thrown in Java when an attempt is made to store an object of an incompatible type into an array. This exception typically occurs when you try to assign an object of one type to an array that is declared to hold objects of another type.

Here’s a more detailed explanation:

  1. Array Type: In Java, arrays are homogeneous data structures, meaning they can only hold elements of a single type. When you create an array, you specify the type of elements it can hold.
  2. Assignment: If you attempt to store an object of a different type into an array, the Java runtime system will throw an ArrayStoreException at runtime.
  3. Casting: In some cases, you might encounter an ArrayStoreException when casting an array to a different type and then trying to store incompatible objects in the array.

Here’s an example to illustrate when ArrayStoreException can occur:

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

public class ArrayStoreExceptionExample {
    public static void main(String[] args) {
        // Create an array of integers
        Object[] array = new Integer[5];

        // Attempt to store a string in the array
        array[0] = "Hello"; // This line will throw ArrayStoreException
    }
}

In this example, we declare an array of Integer objects but try to store a String object (“Hello”) in the array. Since String is not a subclass of Integer, this assignment is not allowed, and it results in an ArrayStoreException being thrown at runtime.

To avoid ArrayStoreException, ensure that you only store objects of compatible types in the array or that you correctly cast objects to the appropriate type before storing them in the array


Q99) Write a Java program to Find the Longest Substring Without Repeating Characters.

Ans-

Here is the program –

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

import java.util.*;

public class LongestSubstringWithoutRepeating {
    public static void main(String[] args) {
        String s = "abcabcbb";
        int length = longestSubstringWithoutRepeating(s);
        System.out.println("Length of the longest substring without repeating characters: " + length);
    }
    
    public static int longestSubstringWithoutRepeating(String s) {
        int maxLength = 0;
        int start = 0;
        Map<Character, Integer> map = new HashMap<>();
        
        for (int end = 0; end < s.length(); end++) {
            char ch = s.charAt(end);
            if (map.containsKey(ch)) {
                start = Math.max(start, map.get(ch) + 1);
            }
            map.put(ch, end);
            maxLength = Math.max(maxLength, end - start + 1);
        }
        
        return maxLength;
    }
}

Q100) Write Java program to implement binary search algorithm to find the index of a target element in a sorted array?

Ans-

1. Class and Main Method =

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

public class BinarySearch {
    public static void main(String[] args) {
        int[] nums = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
        int target = 23;
        int index = binarySearch(nums, target);
        if (index != -1) {
            System.out.println("Element found at index: " + index);
        } else {
            System.out.println("Element not found.");
        }
    }
}
  • public class BinarySearch:** This defines a class named BinarySearch.
  • public static void main(String[] args):** This is the main method where the program execution starts.
  • int[] nums = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};:** Here, an integer array nums is initialized with sorted elements.
  • int target = 23;:** The target element 23 is defined, which we want to search in the nums array.
  • int index = binarySearch(nums, target);:** The binarySearch method is called with nums and target as arguments. The result (index of the target) is stored in the variable index.
  • if (index != -1):** If the index is not -1, it means the element was found, and its position (index) is printed. Otherwise, it prints “Element not found.”

2. Binary Search Method

/* *********************************************************
********** Simple code snippet by - Logical Duniya *********
********************************************************* */

public static int binarySearch(int[] nums, int target) {
    int left = 0;
    int right = nums.length - 1;
    
    while (left <= right) {
        int mid = left + (right - left) / 2;
        if (nums[mid] == target) {
            return mid;
        } else if (nums[mid] < target) {
            left = mid + 1;
        } else {
            right = mid - 1;
        }
    }
    
    return -1; // Element not found
}
  • public static int binarySearch(int[] nums, int target):** This is the binary search method, which takes a sorted array nums and an integer target as inputs and returns the index of the target element if found, otherwise returns -1.

Key Variables:

  • int left = 0;: The left pointer starts at the beginning of the array (index 0).
  • int right = nums.length - 1;: The right pointer starts at the end of the array (last index).

While Loop:

  • while (left <= right): The loop runs as long as the left pointer is less than or equal to the right pointer.

Midpoint Calculation:

  • int mid = left + (right - left) / 2;: The midpoint (mid) is calculated to avoid potential overflow when using large index values. It finds the middle index between left and right.

Comparison and Adjusting Pointers:

  • if (nums[mid] == target) { return mid; }: If the value at the midpoint (nums[mid]) is equal to the target, it returns the index mid because the target is found.
  • else if (nums[mid] < target) { left = mid + 1; }: If the value at mid is less than the target, it adjusts the left pointer to mid + 1 because the target can only be in the right half of the array.
  • else { right = mid - 1; }: If the value at mid is greater than the target, it adjusts the right pointer to mid - 1 because the target can only be in the left half of the array.

Returning -1:

  • return -1;: If the loop finishes without finding the target, the method returns -1, indicating the target element is not in the array.

This Java program implements the binary search algorithm to efficiently find the index of a target element in a sorted array. Binary search works by repeatedly dividing the search interval in half and comparing the target value to the middle element, significantly reducing the number of comparisons needed to find the target.


Final Points

We have seen latest Top 100 Core Java Interview Questions of 2024 with their answers, explanations and simple but logical coding solutions.

In case, if you have any questions, Please comment them below, and I will try my level best to answer them as soon as possible.

There are other Interview Questions and Answers available at LogicalDuniya, so go and check them now to upskill yourself and increase your chances of cracking your next interview.

All the very best…
Cheers..
Shubham !!

Shubham

Shubham Srivastava

Hey there, my name is Shubham and I'm working as an SDET at a US based FinTech company. I've more than 7 years of working experience and using my knowledge - I want make this platform super helpful for those, who want to solve any software development and testing related problems. Comment your query / request or suggestion in the below section, and I'll try to respond within 24 hours. Keep improving, Keep coding !!

Recommended Posts :


0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Press ESC to close