500+ Java/JEE Interview Questions and Answers

Use the discount coupon number "3D20455432" on Interview-Prep-90-Day, Interview-Prep-365-Day, and Interview-Prep-180-Day subscriptions. The coupon expires soon.

Java OO Interview Questions and Answers

If you asked me to pick a section that is most popular with the interviewers, this is it. If you don't perform well in Object Oriented (i.e. OO) programming , your success rate in interviews will be very low. Good interviewers will be getting you to analyze or code for a particular scenario. They will be observing your decisions with interfaces and classes, and question your decisions to ascertain your technical skills, analytical skills, and communication skills. You can't memorize your answers. This section requires some level of experience to fully understand.

In this blog, I cover some OO interview questions and answers. If you are interested in more questions and answers, the "Core Java Career Essentials" book has a whole chapter dedicated for OO questions and answers with enough examples to get through your OO interview questions with flying colors.

Q. How do you know that your classes are badly designed?
A.

  • If your application is fragile – when making a change, unexpected parts of the application can break.
  • If your application is rigid – it is hard to change one part of the application without affecting too many other parts.
  • If your application is immobile – it is hard to reuse the code in another application because it cannot be separated.

Overly complex design is as bad as no design at all. Get the granularity of your classes and objects right without overly complicating them. Don't apply too many patterns and principles to a simple problem. Apply them only when they are adequate. Don't anticipate changes in requirements ahead of time. Preparing for future changes can easily lead to overly complex designs. Focus on writing code that is not only easy to understand, but also flexible enough so that it is easy to change if the requirements change.


Q. Can you explain if the following classes are badly designed?
The following snippets design the classes & interfaces for the following scenario. Bob, and Jane work for a restaurant. Bob works as manager and a waiter. Jane works as a waitress. A waiter's behavior is to take customer orders and a manager's behavior is to manage employees.


package badrestaurant;

public interface Person {}


package badrestaurant;

public interface Manager extends Person {
    public void managePeople( );
}

package badrestaurant;

public interface Waiter extends Person {
    public void takeOrders( ); 
}


package badrestaurant;

public class Bob implements Manager, Waiter {

    @Override
    public void managePeople( ) {
        //implementation goes here
    }

    @Override
    public void takeOrders( ) {
        //implementation goes here
    }
}


package badrestaurant;

public class Jane implements Waiter {

    @Override
    public List<string> takeOrders( ) {
        //implementation goes here
    }
}

The Restaurant class uses the above classes as shown below.

package badrestaurant;

public class Restaurant {
    
    public static void main(String[ ] args) {
        
        Bob bob = new Bob( );
        bob.managePeople( );
        bob.takeOrders( );
        
        Jane jane = new Jane( );
        jane.takeOrders( );
    }
}


A. The above classes are badly designed for the reasons described below.

The name should be an attribute, and not a class like Bob or Jane. A good OO design should hide non-essential details through abstraction. If the restaurant employs more persons, you don't want the system to be inflexible and create new classes like Peter, Jason, etc for every new employee.

The above solution's incorrect usage of the interfaces for the job roles like Waiter, Manager, etc will make your classes very rigid and tightly coupled by requiring static structural changes. What if Bob becomes a full-time manager? You will have to remove the interface Waiter from the class Bob. What if Jane becomes a manager? You will have to change the interface Waiter with Manager.

The above drawbacks in the design can be fixed as shown below by asking the right questions. Basically waiter, manager, etc are roles an employee plays. You can abstract it out as shown below.


package goodrestuarant;

public interface Role {
    public String getName( );
    public void perform( );
}


package goodrestuarant;

public class Waiter implements Role {
    
    private String roleName;
    
    public Waiter(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String getName( ) {
       return this.roleName;
    }

    @Override
    public void perform( ) {
       //implementation goes here
    }
}

package goodrestuarant;

public class Manager implements Role {
    
    private String roleName;   
    
    public Manager(String roleName) {
        this.roleName = roleName;
    }

    @Override
    public String getName( ) {
       return this.roleName;
    }

    @Override
    public void perform( ) {
       //implementation goes here
    }
}



The Employee class defines the employee name as an attribute as opposed to a class. This makes the design flexible as new employees can be added at run time by instantiating new Employee objects with appropriate names. This is the power of abstraction. You don't have to create new classes for each new employee. The roles are declared as a list using aggregation (i.e. containment), so that new roles can be added or existing roles can be removed at run time as the roles of employees change. This makes the design more flexible.

package goodrestuarant;

import java.util.ArrayList;
import java.util.List;

public class Employee {
    
    private String name;
    private List<role> roles = new ArrayList<role>(10);
    
    public Employee(String name){
        this.name = name;
    }

    public String getName( ) {
        return name;
    }

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

    public List<role> getRoles( ) {
        return roles;
    }

    public void setRoles(List<role> roles) {
        this.roles = roles;
    }
    
    public void addRole(Role role){
        if(role == null){
            throw new IllegalArgumentException("Role cannot be null");
        }
        roles.add(role);
    }
    
    public void removeRole(Role role){
        if(role == null){
            throw new IllegalArgumentException("Role cannot be null");
        }
        roles.remove(role);
    }
}

The following Restaurant class shows how flexible, extensible, and maintainable the above design is.

package goodrestuarant;

import java.util.List;

public class Restaurant {
    
    public static void main(String[ ] args) {
        
        Employee emp1 = new Employee ("Bob");
        Role waiter = new Waiter("waiter");
        Role manager = new Manager("manager");
        
        emp1.addRole(waiter);
        emp1.addRole(manager);
        
        Employee emp2 = new Employee("Jane");
        emp2.addRole(waiter);
        
        List<role> roles = emp1.getRoles( );
        for (Role role : roles) {
            role.perform( );
        }
        
        //you can add more employees or change roles based on 
        //conditions here at runtime. More flexible.   
    }
}



Q. What do you achieve through good class and interface design?
A.

  • Loosely coupled classes, objects, and components enabling your application to easily grow and adapt to changes without being rigid or fragile.
  • Less complex and reusable code that increases maintainability, extendability and testability.

Q. What are the 3 main concepts of OOP?
A. Encapsulation, polymorphism, and inheritance are the 3 main concepts or pillars of an object oriented programming. Abstraction is another important concept that can be applied to both object oriented and non object oriented programming. [Remember: a pie ? abstraction, polymorphism, inheritance, and encapsulation.]


Q. What problem(s) does abstraction and encapsulation solve?
A. Both abstraction and encapsulation solve same problem of complexity in different dimensions. Encapsulation exposes only the required details of an object to the caller by forbidding access to certain members, whereas an abstraction not only hides the implementation details, but also provides a basis for your application to grow and change over a period of time. For example, if you abstract out the make and model of a vehicle as class attributes as opposed to as individual classes like Toyota, ToyotaCamry, ToyotaCorolla, etc, you can easily incorporate new types of cars at runtime by creating a new car object with the relevant make and model as arguments as opposed to having to declare a new set of classes.


Q. How would you go about designing a “farm animals” application where animals like cow, pig, horse, etc move from a barn to pasture, a stable to paddock, etc? The solution should also cater for extension into other types of animals like circus animals, wild animals, etc in the future.


A.

package subclass0;

public abstract class Animal {
    private int id;                                // id is encapsulated

    public Animal(int id) {
        this.id = id;
    }

    public int getId( ) {
        return id;
    }

    public abstract void move(Location location);
}


package subclass0;

public class FarmAnimal extends Animal {

    private Location location = null;                   // location is encapsulated

    public FarmAnimal(int id, Location defaultLocation) {
        super(id);
        validateLocation(defaultLocation);
        this.location = defaultLocation;
    }

    public Location getLocation( ) {
        return location;
    }

    public void move(Location location) {
        validateLocation(location);
        System.out.println("Id=" + getId( ) + " is moving from "
                + this.location + " to " + location);
        this.location = location;
    }

    private void validateLocation(Location location) {
        if (location == null) {
            throw new IllegalArgumentException("location=" + location);
        }
    }
}

package subclass0;

public enum Location  {
    Barn, Pasture, Stable, Cage, PigSty, Paddock, Pen
}



package subclass0;

public class Example {

    public static void main(String[ ] args) {
        Animal pig = new FarmAnimal(1, Location.Barn);
        Animal horse = new FarmAnimal(2, Location.Stable);
        Animal cow = new FarmAnimal(3, Location.Pen);

        pig.move(Location.Paddock);
        horse.move(Location.Pen);
        cow.move(Location.Pasture);
    }
}  


Output:

Id=1 is moving from Barn to Paddock
Id=2 is moving from Stable to Pen
Id=3 is moving from Pen to Pasture

In the above example, the class FarmAnimal is an abstraction used in place of an actual farm animal like horse, pig, cow, etc. In future, you can have WildAnimal, CircusAnimal, etc extending the Animal class to provide an abstraction for wild animals like zebra, giraffe, etc and circus animals like lion, tiger, elephant, etc respectively. An Animal is a further abstraction generalizing FarmAnimal, WildAnimal, and CircusAnimal. The Location is coded as an enumeration for simplicity. The Location itself can be an abstract class or an interface providing an abstraction for OpenLocation, EnclosedLocation, and SecuredLocation further abstracting specific location details like barn, pen, pasture, pigsty, stable, cage, etc. The location details can be represented with attributes like “name”, “type”, etc.

The FarmAnimal class is also well encapsulated by declaring the attribute “location” as private. Hence the “location” variable cannot be directly accessed. Assignment is only allowed through the constructor and move(Location location) method, only after a successful precondition check with the validateLocation(...) method. The validateLocation(...) itself marked private as it is an internal detail that does not have to be exposed to the caller. In practice, the public move(..) method can make use of many other private methods that are hidden from the caller. The caller only needs to know what can be done with an Animal. For example, they can be moved from one location to another. The internal details as to how the animals are moved is not exposed to the caller. These implementation details are specific to FarmAnimal, WildAnimal, and CircusAnimal classes.

The above code does not satisfy the following questions.

1) Why does the Employee class need to be mutable?
2) Why aren't the roles defensive copied?
3) Why would the Employee need to know how to add and remove roles?
4) Waiter and Manager are placed in a collection but don't override hashcode and equals. That will cause the contains method on a List to not behave as expected.
5) You check if the role is null then throw an IllegalArgumentException, that should instead be a NullPointerException.
6) The code that checks for null roles being added is duplicated, thus defeating the DRY principle.


Some of the above questions are answered in How to write immutable Java classes?

27 comments:

  1. well written....
    helped me a lot..

    ReplyDelete
    Replies
    1. Indeed very well written. sometime they also ask questions like which pattern you used and why? like if you said you have used Factory than what benefit it offer, which OOPS concept it support etc. Factory is based upon Encapsulation quite well to encapsulate object creation code. By the way I also shared few Java design pattern questions, may help.

      Delete
    2. Thanks, the "Core Java Essentials" book has a lot more OO examples with design principles. Good to hear that you have blogged about the design patterns.

      Delete
  2. Thank you for providing this detail. It is very helpful to me

    ReplyDelete
  3. It's said that java is a highly secure language. Why does it call so?

    ReplyDelete
  4. It is not true that Java is highly secured. It depends on how you use the language. But here are some features that makes it more secured than some other languages.

    --The fact that Java does not allocate direct pointers to memory and does not allow you to access out of bound arrays to cause buffer overflow security threats, make Java more secured than some of the other languages like C.


    --The Automatic Garbage Collection minimizes the chances of accidental errors that can cause security vulnerabilities.

    --The Java String class is immutable, hence the password value cannot be modified.

    --The Java applications have to run on a JVM, which performs byte code verification.

    --Java applets/applications can execute within a sand box. The Security Manager concept makes it relatively easy to run a Java application within a "sandbox" that prevents it from any security vulnerabilities from the system it is running on.

    ReplyDelete
  5. hai,you have assigned the local variable location to an instance variable and every time ie.,when you call FarmAnimal constructor and move method every time the instance variable ie., this.location values will vary why you have did like that can you explain me and explain me about how to use setter and getters.

    ReplyDelete
  6. explain me how to use setters and getters

    ReplyDelete
  7. very well explained, Thanks a lot for your books and blogs... may be you can write a book on "how to program in java".

    ReplyDelete
  8. Thanks for the compliments. The core java career essentials book is detailed enough to meet that title :)

    ReplyDelete
    Replies
    1. plz explain me oop ....and example for each features of oop

      Delete
    2. Core Java Career Essentials book has many examples.

      Delete
  9. Bori Konstantinov3:11 AM, June 18, 2012

    Thank you so much for posting this. As I have a 2nd Round Java Interview soon, I found this to be very helpful! Cheers!

    ReplyDelete
  10. Very well Explained specially stuff regarding good restaurant and bad restaurant

    ReplyDelete
  11. Arul,

    Where can i find ur book?

    ReplyDelete
  12. Thanks a lot! The design questions were very well explained.
    Can you please provide some more related links.
    Thanks again!

    ReplyDelete
  13. This comment has been removed by a blog administrator.

    ReplyDelete
  14. Thumbs up for that Manager waiter example!

    ReplyDelete
  15. great article. Thanks

    -Mahesh Bharathi


    ReplyDelete
  16. It is very helpful for me. Please keep posting this type of questions...

    ReplyDelete
  17. Very helpful interview questions...

    ReplyDelete
  18. 1) Why does the Employee class need to be mutable?
    2) Why aren't the roles defensive copied?
    3) Why would the Employee need to know how to add and remove roles?
    4) Waiter and Manager are placed in a collection but don't override hashcode and equals. That will cause the contains method on a List to not behave as expected.
    5) You check if the role is null then throw an IllegalArgumentException, that should instead be a NullPointerException.
    6) The code that checks for null roles being added is duplicated, thus defeating the DRY principle.
    The issues above indicate a bad design for other reasons.

    ReplyDelete
  19. awsome explanation..very helpful

    ReplyDelete

5 recent Java developer posts