Java Interview Questions

Java is a high-level programming language used for creating web applications. It runs on many different operating systems, including android. Prepare better with the best java interview questions and answers, and walk away with top interview tips. These java interview questions and answers will boost your core interview skills and help you perform better.

  • 4.6 Rating
  • 20 Question(s)
  • 30 Mins of Read
  • 3329 Reader(s)


We cannot override a public method by a protected method. The access modifiers of the method in the child class cannot limit the scope of the method of the parent class while overriding. This is because we call the method through a superclass reference which overrides the parent implementation by the child implementation. As the type of reference is of Parent class, the client code knows the API with the broader scope (public) and is prepared based on the parent API. So, it doesn’t make any sense to limit the scope in the overriding (child) method, but the opposite is possible, of course.

Strings are immutable in Java. When we make changes in a String, it creates a new String object. Our programs create a lot of String objects in the runtime. To offer optimum performance, JVM minimizes the String object creation maintaining a pool of String literals in the heap memory (Java 7 onwards). So, when it is required to create a String literal, it first checks in the pool, whether it exists there. If found, it returns the reference of that object. Otherwise, it creates the object and reserves it in the pool for reusing it in a later phase. 

An immutable class doesn’t allow to change the state of its objects after creation. If we need to change that state of an object it will create a new object. One of the most popular examples of an immutable class is String. We need to take care of several things to make a type immutable. 

  1.  The class needs to be final. The reason for not allowing to extend it is that a subclass may get access the sensitive fields or methods which may change the state of the object. 
  2.  The class should declare all its members as private. 
  3.  It should not offer APIs or public methods to change its state. For example setter methods. Even if it does, it should create a clone of its own, make the changes there and return the object. 
  4.  If any member of the class is mutable, we should declare it as final. 
  5. We should initialize the object through a constructor making a deep clone of the mutable objects passed as the constructor arguments. 
  6. we should not expose the references of the mutable members outside the class. If we need to do this, we need to clone the member properly and return it. This ensures even if the object is changed via its reference, it is not the same object. 

In the earlier versions of Java (up to 1.7), the interface was designed to have only method signatures. From Java 8 the interface is now able to contain method implementation as well. These methods should be marked with default keyword and are 

called default methods of an interface. This means it is not mandatory to override the default methods in the implementing classes. When an interface is widely used by many applications, it was very difficult to add a new method in the same, because, it can break the code. The implementers need to change their code in many places. To overcome this complexity and make interfaces backward compatible this change has been introduced. public interface Shape { 

default double area() { 
return 0.0; } default double volume() { 
return 0.0; } } 

Stack memory is used to create the local variables and object references while executing a method by a thread. This means each thread has a separate stack and set of local variables. Stack doesn’t contain the actual objects - it only contains the references. The memory space for the actual objects is allocated in the heap memory. Heap memory is composed of a number of parts - young generation (Eden and Survivor space) and old generation. For each method call JVM creates a new stack frame containing the local variables. Maintaining them as a stack helps to retrieve the most recent stack frame i.e., the set of variables of the caller method easily when a method returns. 

A set is a collection of unordered and unique elements. While adding an element a HashSet uses the hashCode() and equals() method to determine if the element already exists in the Set. If it doesn’t exist, it adds the element into the set. A HashSet uses a HashMap internally which uses the element as the key and keeps a fixed item as the value. If the element exists in the HashMap as a key, it simply returns with a boolean value false denoting it already exists in the set, otherwise puts the element in the map and returns true. 

Yes, String is an immutable class. String is widely used in different situations like sharing as a parameter of a method, loading a class by its name, returning as a value. So, there would be a huge possibility that a String object could be changed without any knowledge of its other users and result in creating difficult to catch bugs in the system. String has been a popular choice as a key in the HashMap or HashTable. A good candidate for a key in the HashMap should be immutable. If String had been mutable and changes its state, it might result in retrieving the wrong value for the same key or not finding it at all. String literals are fetched from the String pool instead of creating it every time. Had the String been mutable, this would not be possible as it could not identify whether the value exists in the pool after any change in its state.  

Cloning means creating a copy of an object or creating a duplicate object - the state of them should be the same. An object may be composed of several other objects. Shallow cloning creates a new object and assigns its field values to the corresponding fields of the new object. As the fields contain only the references of the objects which reside in the heap, fields of the new object also point to the same component instances. Shallow cloning is fast but has a serious downside in that if any of the component objects is changed, it reflects in the cloned object as well, because both of them holds the references of the same objects. 

Deep Cloning, on the other side, doesn’t copy the references from the fields, it creates a duplicate of the component objects as well. As in Deep cloning, all the component objects are cloned it’s comparatively slow but creates a true duplicate of the actual object. 


Java supports programming in the Object-Oriented paradigm, but it is not fully object-oriented. Java has a set of primitive data types - byte, short, char, int, long, float, double, boolean. Any variable of this type is not an object. That’s why Java is not purely an object-oriented. 

The wrapper classes wrap the primitive data types to introduce them as objects. The primitive values are not objects and the developer needs to write many boilerplate codes to convert them to each other and using them in collections. To overcome these problems, Java introduced wrapper classes. These classes provide with polymorphic APIs for data type conversions and the utility methods like hashCode() and equals(). These make the values very useful members in the object-oriented environment. 

Polymorphism is a property of object-oriented programming paradigm which denotes that an object or a method can have different forms in different contexts. In Java, we can define a method in a class with different implementations based on its arguments. In this way, when the client code calls the method using the same interface with a different set of parameters, but internally it decides which implementation needs to be invoked. Let’s take an example: 

class AreaCalculator { 
  double calculate(Circle c)
     { return 3.14*c.getRadius()*c.getRadius(); 
double calculate(Square s) 
     {  return s.getLength()*s.getLength();

//Client code 
AreaCalculator ac = new AreaCalculator(); 
ac.calculate(new Circle(10)); 
ac.calculate(new Square(5)); 

As you see, in the AreaCalculator class, there are separate implementations for calculate(), but from the client’s point of view, the interface is the same. 

There are several ways we can create an object in java. 

  1.  A new object can be created using the new operator on the class calling one of 

its constructors. MyClass o = new MyClass(); 

2. We can create an object using the Java reflection API - Class.newInstance() if the class has a default constructor. If the class has multiple constructors that take parameters, we can get the corresponding constructor using Class.getConstructor() method and invoke that to create a new object. MyClass o = MyClass.class.newInstance(); MyClass o = MyClass.class 

.getConstructor(int.class) .newInstance(10);  

3. We can invoke clone method on an object to create a duplicate object. 

MyClass o = new MyClass(); MyClass b = (MyClass)o.clone(); 

4. If a state of that object is available in a serialized form, we can deserialize it to 

create a new object having the same state. ObjectInputStream is = new ObjectInputStream(anIStream); MyClass o = (MyClass) is.readObject(); 

Polymorphism or static polymorphism decides which method needs to be invoked at the time of compilation and bind the method invocation with the call. However, there are some situations where the static binding doesn’t work. As we know, a parent class reference can point to a parent object as well as a child object. Now, if there is a method which exists in both the parent class and the child class with the same signature and we invoke the method from parent class reference, the compiler cannot decide which method to bind with the call. This will depend on which type of object the reference is pointing to at the time of running. If the reference is pointing to a parent object, then the method in the parent class will be invoked. If the pointed object is an instance of the Child class, then the child-class implementation is invoked. That’s why this is called dynamic binding or runtime polymorphism and it is said that the child class method has overridden the parent class method. Let’s take an example of this: class Animal { 

public void makeSound() { 
System.out.println(“My sound varies based on my type”); } } class Dog extends Animal { 
@Override public void makeSound() { 
System.out.println(“I bark”); 
} } Animal a = new Animal(); a.makeSound(); a = new Dog(); a.makeSound(); 

If we run the code snippet, we’ll find that a.makeSound() printing different messages based on the object-type pointed by reference. Please note that the Override annotation is required in the child class to notify the compiler that this method is overriding the parent implementation. 

StringBuffer and StringBuilder expose the same kind of APIs to build a String and both are mutable classes. There is a big difference in them, though. StringBuffer is thread-safe which means it can be used as a shared object among multiple threads. On the other hand, StringBuilder is not thread-safe and should not be allowed to be modified by multiple threads without proper synchronization techniques. That’s why StringBuilder is faster than StringBuffer. In the scenario where we need to build a String object local to a method or local to a particular thread, we should prefer StringBuilder over StringBuffer. 

A class can inherit from both an abstract class and an interface, but there are some differences. A class can extend only one abstract class while can implement multiple interfaces. An interface cannot have a constructor whereas the abstract class can have constructors which the child classes need to invoke in their constructors. An abstract class may contain fields which may be accessible by child classes to change its state. Interface, on the other hand, can contain only final variables. So, abstract class lets the child class to inherit the state and behavior while the interface is mainly used for implementing a set of behaviors in a child class. An abstract class should be preferred where there is a direct IS-A relationship between the parent and the child. We use abstract class when the different implementations have most of the behaviors common and defined by the abstract class. An interface is preferred while exposing a public API to the client code and if a class can behave differently in different context. 

Java doesn’t support multiple inheritance completely as a class can extend only one class. This is not supported as this can cause ambiguity in accessing inherited fields or methods if the same member exists in the other parent class. However, the facility is provided partially through the interfaces. 

We declare a member as static if it doesn’t depend on any instance of the class, i.e., independent of any objects. These members are bound to the type and usually accessed using the type name (rather than the object references). Static methods and fields are shared between all the objects of a class and can be accessed from any of them, whereas we cannot access the non-static members from a static method. As static methods are not bound to an object, they cannot be overridden. Static fields are initialized through a static block which is executed when a class is loaded by the class loader. Let’s see an example: 

public class Countable { 
private static int count; private int x; static { 
count = 0; // initialize static member } public Countable(int x) { 
this.x = x; Count++; // non-static can access static member } public int getX() { return x; } public static int getCount() { 
return count; // only static can access static member } } Countable c1 = new Countable(10); 
Countable c2 = new Countable(20); System.out.println("Object count " + Countable.getCount()); 
// should print 2 

ArrayList and LinkedList both represent a list of numbers but differ in their internal implementation. ArrayList uses an array internally to store the elements added to it. When the number of elements is about to exceed the size of the array, it allocates a new array and copies the elements to the new location. It gives constant time access to add (if it doesn’t need to expand) and get an element, but for deletion, it gives linear time complexity as it needs to shift its elements to the left. LinkedList, on the other hand, maintains a sequence of linked nodes internally for storing the elements. So, retrieves an element in linear time whereas addition and deletion take a constant time to execute.

HashTable and HashMap both store key-value pairs and take a constant time to put or get operations. However, Hashtable is synchronized and can be shared to get modified by multiple threads while HashMap is not synchronized and performs better, but not suitable for the multithreaded environment as a shared object. HashTable doesn’t allow Null keys or values, bur a HashMap allows a Null key and more than one Null values.

For retrieval or storing a value, a HashMap uses two methods of its Key class - hashCode() and equals(). HashMap stores its entries in a large collection of buckets which can be randomly accessed using an index. To retrieve a value, first, the hashCode() method of the Key is invoked to get the hash value. This hash value is used to identify the bucket where the value would be retrieved from. While storing an entry, there might be some scenario where the calculated hash value is the same for more than one keys. This results in to enter multiple key-value pairs in the same bucket. 

A bucket keeps its entries as a Linked List. So, while retrieving, after finding out the appropriate bucket, this linked list needs to be traversed to find the actual entry for the key. This time, the equals() method is used to compare the key of each entry in the list. Once it finds a key equal, the value from the entry is returned. There is a contract between these two methods which says if two objects are equal based on equals() method, their hashCode() value must be the same. So, if we plan to use objects of a class as the key of a HashMap, we should override both the methods - hashCode() and equals() so that this contract is maintained. 


Java is a high-level programming language used for creating web applications. It runs on many different operating systems, including android. 

Prepare better with the best java interview questions and answers, and walk away with top interview tips. These java interview questions and answers will boost your core interview skills and help you perform better. 

We have compiled a set of frequently asked java interview questions to help you crack your interview with conviction. These java interview questions for experienced as well as freshers roles will enable you to face the toughest of interviews confidently. Prepare yourself well with these Java interview questions and open new doors to your dream job.