Java OOP Interview Questions – Part 01

Hello coders,

I am back with a new article series. In this series, I am going to focus on the interview questions you might have to face as a Java developer. These questions go over the basic concepts in Java and explain how exactly everything works so you could nail your interview.

I am going to try and explain each answer fully and attach a piece of code to help to grasp the concept easily. Let’s get into it.


1. What is an object in Java?

An object in Java is an instance of a class. It is something tangible that we can apprehend intellectually.

Java classes are like blueprints for creating objects. For example, Dog is a class where Oscar is an object created from that class.

every object inherits the methods and attributes of their classes. A constructor is used to create objects.

Dog oscar = new Dog();
Photo by Jamie Street on Unsplash

2. Why was OOP (Object Oriented Programming) introduced?

As the name suggests, this concept is built around objects.

In Object-Oriented Programming, we create objects that hold methods and attributes. The main reason to introduce OOP was that OOP helps us to implement solutions for everyday coding needs. Hiding data from the user, the ability to reuse the code, the ability to implement inheritance are some examples.

With the reusability of the code, OOP makes the code easier to maintain. OOP helps to make the design of the code simpler and structured. This paves the way for easier troubleshooting.

3. What is the difference between Array and ArrayList?

The main difference is that Array’s have a fixed size, while ArrayLists can shrink or expand accordingly. The length of the array needs to be defined once it is being initialized. If we try to store more elements than the length of an Array, the compiler throws an ArrayIndexOutOfBoundsException.

Primitive data types like int, double can’t be stored in ArrayLists. ArrayLists store the Wrapper classes or Objects. Arrays can be multidimensional, where ArrayLists can only be single-dimensional.

Arrays should be used when we know how many elements are there. If the number of elements is not known, the better option would be using ArrayLists since it can adjust automatically.

4. What is Polymorphism in Java?

Polymorphism is one of the core concepts that are there in object-oriented programming. Polymorphism is the ability of an object to have many forms. In UML terms, this is the number of IS-A relationships an object has. There are two types of Polymorphism.

All objects in Java are considered to be polymorphic since all objects are derived from the Object class and the class itself. For example, let’s say there is a laptop object. This object is created from the Laptop class (laptop IS-A Laptop). In addition, it is an object of the Object class (laptop IS-A Object).

There are two main ways

  1. Dynamic Polymorphism (Run time Polymorphism)

The reason why this is called run time polymorphism is that this concept talks about method overriding which happens at run time.

The simple idea can be explained like this. Let’s say there is a Java class called A and it has a subclass called B and both A and B classes have a method called run(). In this case, when we run the of B class, A’s run() method gets overridden.

Here is a small code snippet for the above example.

package polymorphism;
class A {
    public void run(){
        System.out.println("Running in A");
    }
}
class B extends A {
    public void run (){
        System.out.println("Running in B");
    }
}
class Main {
    public static void main(String[] args) {
        A obj = new B();
        obj.run();
    }
}

Basically why this is happening is that Java determines which method needs to be called in run time. Java does this by looking at the type of the object. In this case, since the object is type B, Java calls the run() method in the B class.

  1. Static Polymorphism (Compile time Polymorphism)

This is the concept of overloading the methods by changing the method signature. Java can determine which method needs to be called in compile-time, hence the name Compile time Polymorphism.

Method signature includes only the method name and the parameters. It does not include the return type of the method.

Let me explain this with an example as well.

package polymorphism;
public class Runtime {
    public static void main(String[] args) {
        MyClass.run();
        MyClass.run(10);
        MyClass.run(10, 12.5);
    }
}
class MyClass{
    public static void run(){
        System.out.println("Empty Method");
    }
    public static void run(int a){
        System.out.println("One Integer Parameter : " + a);
    }
    public static void run(int a, double b){
        System.out.println("With int and double parameters : " + a + " " + b);
    }
}

If you observe properly, each method signature is different from each other. This concept is called method overloading.

5. What is Abstraction in Java?

Abstraction in Java is the concept of hiding certain details from the user and only showing the essential information. This can be achieved using interfaces or abstract classes. Let’s talk about abstract classes first.

  1. Abstract Classes

Java abstract classes hold regular java methods and abstract methods. An abstract class is different from regular classes because we can’t create objects from abstract java classes. Even though we can have regular and abstract methods inside abstract classes, abstract methods can only be defined inside an abstract class.

The closest example I could think of explaining abstract classes is the class Animal. Abstract classes are like blueprints. There are no “animal” in the world, there are only classes like Cat, Dog, Lion that fall into the Animal superclass.

Let me create a simple Animal class and tell you how we can use abstract classes to our advantage.

Animal Class

package abstraction;
abstract class Animal {
    abstract void eat();
    abstract void sleep();
    
    public static void normalMethod(){
        System.out.println("Hey, I am a normal method");
    }
}

Cat Class

package abstraction;
public class Cat extends Animal{
    @Override
    void eat() {
        System.out.println("The cat is eating");
    }
    @Override
    void sleep() {
        System.out.println("The cat is sleeping");
    }
}

Main Class

package abstraction;
public class Main {
    public static void main(String[] args) {
        Cat cat = new Cat();
        cat.eat();
        cat.sleep();
        Animal.normalMethod();
    }
}

Here what I did was that I created our Animal class which is abstract. Then I created a class called Cat which extends the Animal class. When a certain class extends an abstract class, that class has to override and implement all the abstract methods that have been defined in the abstract class. So, in this case, eat() and sleep() methods were implemented.

In addition, I added a regular method inside the Animal class just to show you the difference. Here is the console output of the above code.

The cat is eating
The cat is sleeping
Hey, I am a normal method
  1. Interfaces

Interfaces in Java are just like Abstract classes. They can hold regular methods and also abstract methods.

The methods in interfaces are generally public and abstract. All the variables in interfaces are public, static and final.

The main difference between interfaces and abstract classes is that a class can only extend one abstract class (since multiple inheritance concept is not allowed in Java). But if we use interfaces, we could implement multiple interfaces.

6. What is Encapsulation in Java?

Encapsulation is another core OOP concept that we use to achieve data hiding. Here what we do is that we declare variables as private variables and create getters and setters to modify the variables.

Here is a sample class where encapsulation has been implemented.

package encapsulation;
public class Encapsulation {
    
    private String name;
    private String address;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}
You Can’t See Me 😎

7. What is Inheritance in Java?

Inheritance in Java is a vital concept that helps us to reuse the code again and again. Inheritance basically means that java classes can inherit data from some other classes. All the methods and attributes in the superclass can be accessed by all the subclasses.

We use extends keyword in Java in order to implement inheritance.

8. Why are there two ways to implement threads?

There ways of implementing threads in Java. They are, by implementing the runnable interface and by extending the Thread class.

When we extend the Thread class, we are creating threads where each thread is associated with a unique object. But when we implement the Runnable interface, we are using the object instance.

Just because we implement the runnable interface in a class, it does not become a thread. We need to pass the runnable instance to an instance of Thread class in order to make it a thread

The runnable interface should be used if we are going to only modify the run() method. In addition, if we want to extend a superclass, we should utilize the runnable interface.

9. What is Multithreading in Java?

Multi-threading, as the name suggests, involves executing two or more threads simultaneously. Each thread runs parallel to each other. All these threads use a shared memory space, hence saves memory. Context-switching between the threads takes less time as well.

Java Multithreading is mostly used in games, animations and stuff.

10. How do we use threads synchronously?

The need to use threads synchronously arises in situations where we are trying to interact with the same resource. For example, if multiple threads try to save data to the same file, there is a possibility of some data getting overridden.

So, to solve this, we need to make these threads work synchronously so that they know when the other thread is using the resource. The core concept used here is that every object in Java has a something called monitor associated with it. Only one thread can hold a lock on a monitor at a given time. The other threads have to wait until the lock is unlocked.

The way we can achieve this is by using synchronized blocks. Here is a simple code snippet to explain the concept. Here is an example of what would happen if we do not use synchronized blocks.

Thread1 class

package multithreading;
import static multithreading.Main.myClass;
public class Thread1 implements Runnable{
    @Override
    public void run() {
        myClass.deposit(100);
    }
}

Thread2 class

package multithreading;
import static multithreading.Main.myClass;
public class Thread2 implements Runnable{
    @Override
    public void run() {
        myClass.deposit(500);
    }
}

Main Class

package multithreading;
public class Main {
    static final MyClass myClass = new MyClass();
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Thread1());
        Thread thread2 = new Thread(new Thread2());
        thread1.start();
        thread2.start();
    }
}

MyClass class (This includes the main method)

package multithreading;
import java.util.Date;
public class MyClass{
    double balance = 0;
    public void deposit(double amount){
        balance += amount;
        System.out.println("The balance at " + new Date() + " is : " + balance);
    }
}

Here what we are expecting is 100 and 600 respectively. But since we are using unsynchronized threads, the expected result does not come up. Here is the output of the given code.

The balance at Sat Jan 23 11:57:11 IST 2021 is : 600.0
The balance at Sat Jan 23 11:57:11 IST 2021 is : 600.0

So, to correct this code, we need to make the deposit() method synchronized. Let’s see the code and the output after adding the synchronized keyword.

    public synchronized void deposit(double amount){
        balance += amount;
        System.out.println("The balance at " + new Date() + " is : " + balance);
    }
The balance at Sat Jan 23 12:02:26 IST 2021 is : 100.0
The balance at Sat Jan 23 12:02:26 IST 2021 is : 600.0

This is how using synchronization can save us from a malfunctioning program.


I’ve discussed 10 questions so far. Hope you enjoyed it. I’ll come up with another set of questions in the next article. If you have anything to say where I could improve, please drop a comment below. See you soon 👌😎


Published by Thisura Thenuka

I am a passionate software engineering student. But cricket is my first love ❤

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: