Flipkart Java project based interview Questions and answers

Questions

  1. Explain how polymorphism was used to calculate ETAs differently for normal and priority deliveries.
  2. If a driver has to pick up vehicles from multiple locations, how would you implement route optimization using OOP?
  3. What is the purpose of super() in your child class? Provide an example from your project.
  4. How would you use the static keyword for utility functions in route optimization?
  5. Write a constructor for the Driver class to initialize the driver object with essential details (name, availability, assigned route). Use this to differentiate between local and instance variables.
  6. Can a static method access non-static variables? Why or why not?
  7. Why is the super keyword used in constructors? Can you provide an example where super was used to extend functionality in your project?
  8. What happens if a constructor doesn’t explicitly call super() in a child class?
  9. In your project, if you wanted to add a new delivery service with additional features, how would inheritance be used?

Real time:

  1. If two customers schedule pickups for the same time but only one driver is available, how would you prioritize one over the other? Implement this using OOP concepts.
  2. If a driver has started their route but a high-priority pickup request is added, how would you re-optimize the existing route?
  3. If the MySQL database becomes unavailable during scheduling, how would you ensure that requests are temporarily saved and retried later?
  4. If a driver assigned to a route becomes unavailable mid-route, how would you dynamically reassign tasks to another driver?

Programs:

  1. Write a utility method that takes a list of locations (latitude, longitude) and calculates the shortest route using a basic distance formula.
  2. Write a constructor for the Driver class that initializes the name, availability, and route, and use this to differentiate between instance and local variables.

Questions & Answers

  1. Explain how polymorphism was used to calculate ETAs differently for normal and priority deliveries.

In the Pickup and Drop-off project, polymorphism was applied to calculate the estimated time of arrival (ETA) for different types of deliveries (e.g., normal and priority deliveries).

We used method overriding in the delivery classes:

  • The Delivery class served as a base class with a method calculateETA().
  • The NormalDelivery and PriorityDelivery classes extended the Delivery class and provided their own implementation of calculateETA().

Example:

class Delivery {

    public int calculateETA(int distanceInKm) {

        return distanceInKm * 2; // Default speed is 30 km/h

    }

}

 

class NormalDelivery extends Delivery {

    @Override

    public int calculateETA(int distanceInKm) {

        return distanceInKm * 2; // Speed for normal deliveries

    }

}

 

class PriorityDelivery extends Delivery {

    @Override

    public int calculateETA(int distanceInKm) {

        return distanceInKm; // Speed for priority deliveries (faster service)

    }

}

In the project, this allowed us to dynamically calculate ETAs based on the type of delivery using polymorphism:

Delivery delivery;

if (isPriority) {

    delivery = new PriorityDelivery();

} else {

    delivery = new NormalDelivery();

}

int eta = delivery.calculateETA(10); // Calculate based on type

This approach improved maintainability, as new delivery types could be added easily by extending the Delivery class.

 

  1. If a driver has to pick up vehicles from multiple locations, how would you implement route optimization using OOP?

In the Pickup and Drop-off project, we implemented route optimization using an object-oriented approach. Each Location was represented as an object, and the RouteOptimizer class contained the logic to find the shortest path using algorithms like Dijkstra or A*.

Example:

class Location {

    private String name;

    private double latitude;

    private double longitude;

 

    public Location(String name, double latitude, double longitude) {

        this.name = name;

        this.latitude = latitude;

        this.longitude = longitude;

    }

 

    // Getters and distance calculation logic

    public double calculateDistance(Location other) {

        // Haversine formula to calculate distance

        return Math.sqrt(Math.pow(this.latitude – other.latitude, 2) + Math.pow(this.longitude – other.longitude, 2));

    }

}

 

class RouteOptimizer {

    public List<Location> optimizeRoute(List<Location> locations) {

        // Implement Dijkstra or A* to find the optimal route

        // Placeholder: Returning in the same order for simplicity

        return locations;

    }

}

In our project, drivers were assigned optimized routes to reduce travel time and fuel costs, ensuring efficiency. The RouteOptimizer class encapsulated the optimization logic, promoting reusability and modularity.

 

  1. What is the purpose of super() in your child class? Provide an example from your project.

The super() keyword is used to call the constructor or methods of the parent class. In the Pickup and Drop-off project, we used super() to initialize common properties in the base class when creating child classes.

Example from Project:

class Vehicle {

    private String vehicleId;

    private String model;

 

    public Vehicle(String vehicleId, String model) {

        this.vehicleId = vehicleId;

        this.model = model;

    }

}

 

class PickupVehicle extends Vehicle {

    private boolean isAvailable;

 

    public PickupVehicle(String vehicleId, String model, boolean isAvailable) {

        super(vehicleId, model); // Calls the constructor of the parent class

        this.isAvailable = isAvailable;

    }

}

In this example, the PickupVehicle class used super() to initialize vehicleId and model properties in the Vehicle class.

 

  1. How would you use the static keyword for utility functions in route optimization?

In the Pickup and Drop-off project, we used the static keyword to define utility methods for reusable functionalities like distance calculations, as these methods didn’t depend on instance variables.

Example:

class RouteUtils {

    public static double calculateDistance(Location loc1, Location loc2) {

        return Math.sqrt(Math.pow(loc1.getLatitude() – loc2.getLatitude(), 2) +

                         Math.pow(loc1.getLongitude() – loc2.getLongitude(), 2));

    }

}

Usage in the project:

double distance = RouteUtils.calculateDistance(location1, location2);

This approach reduced the need to instantiate utility classes, promoting code efficiency.

 

  1. Write a constructor for the Driver class to initialize the driver object with essential details (name, availability, assigned route). Use this to differentiate between local and instance variables.

Example:

class Driver {

    private String name;

    private boolean isAvailable;

    private String assignedRoute;

 

    public Driver(String name, boolean isAvailable, String assignedRoute) {

        this.name = name; // Assigning local variable to instance variable

        this.isAvailable = isAvailable;

        this.assignedRoute = assignedRoute;

    }

 

    public void displayDetails() {

        System.out.println(“Driver Name: ” + this.name);

        System.out.println(“Availability: ” + this.isAvailable);

        System.out.println(“Assigned Route: ” + this.assignedRoute);

    }

}

This constructor was used to create Driver objects with their attributes in the project.

 

  1. Can a static method access non-static variables? Why or why not?

No, a static method cannot access non-static variables directly because static methods belong to the class, not to any specific object. Non-static variables require an object instance to be accessed.

In the Pickup and Drop-off project, static methods (e.g., utility functions) only operated on parameters passed to them or static variables, ensuring separation of instance-specific data.

 

  1. Why is the super keyword used in constructors? Can you provide an example where super was used to extend functionality in your project?

The super keyword is used to invoke the parent class’s constructor or methods. It helps to initialize inherited properties and extend base functionality.

Example: In the Pickup and Drop-off project, we had a base class User and a derived class Driver:

class User {

    private String name;

    private String email;

 

    public User(String name, String email) {

        this.name = name;

        this.email = email;

    }

}

 

class Driver extends User {

    private String licenseNumber;

 

    public Driver(String name, String email, String licenseNumber) {

        super(name, email); // Calls the parent constructor

        this.licenseNumber = licenseNumber;

    }

}

The super() call ensured User properties were initialized while adding Driver-specific functionality.

 

  1. What happens if a constructor doesn’t explicitly call super() in a child class?

If a constructor doesn’t explicitly call super(), the compiler automatically inserts a call to the default (no-argument) constructor of the parent class. If the parent class doesn’t have a default constructor, it results in a compilation error.

 

  1. In your project, if you wanted to add a new delivery service with additional features, how would inheritance be used?

To add a new delivery service (e.g., “Eco Delivery”), I would extend the Delivery class to reuse existing logic while introducing new features.

Example:

class EcoDelivery extends Delivery {

    private boolean usesElectricVehicle;

 

    public EcoDelivery(boolean usesElectricVehicle) {

        this.usesElectricVehicle = usesElectricVehicle;

    }

 

    @Override

    public int calculateETA(int distanceInKm) {

        return usesElectricVehicle ? (distanceInKm * 3) : (distanceInKm * 2);

    }

}

By using inheritance, we can add new features without modifying the existing codebase, adhering to the Open/Closed Principle.

 

  1. Explain how polymorphism was used to calculate ETAs differently for normal and priority deliveries.

In the Pickup and Drop-off project, we implemented polymorphism by creating a parent class Delivery with a method calculateETA(). The base implementation of calculateETA() was used for normal deliveries. For priority deliveries, we created a subclass PriorityDelivery that overrides the calculateETA() method to account for shorter waiting times and priority routes.

Example:

java

CopyEdit

class Delivery {

    public double calculateETA(double distance) {

        return distance / 50; // Normal deliveries assume an average speed of 50 km/h.

    }

}

 

class PriorityDelivery extends Delivery {

    @Override

    public double calculateETA(double distance) {

        return distance / 70; // Priority deliveries assume a faster average speed of 70 km/h.

    }

}

How it was applied: When scheduling a delivery, the system dynamically determined whether to use the Delivery or PriorityDelivery class based on the delivery type, ensuring an accurate ETA for both cases.

 

  1. If a driver has to pick up vehicles from multiple locations, how would you implement route optimization using OOP?

Route optimization was implemented using a RouteOptimizer utility class. The RouteOptimizer takes a list of locations and calculates the shortest route using the distance formula, applying the Traveling Salesman Problem (TSP) heuristic.

Example:

java

CopyEdit

class RouteOptimizer {

    public List<Location> optimizeRoute(List<Location> locations) {

        // Implement route optimization logic here (e.g., Nearest Neighbor Algorithm).

        return optimizedRoute;

    }

}

How it was applied: In the current project, the RouteOptimizer class was used to rearrange the sequence of vehicle pickups, reducing travel time and fuel costs. The optimizeRoute() method was called whenever multiple locations were involved in a driver’s route.

 

  1. What is the purpose of super() in your child class? Provide an example from your project.

The super() keyword is used to call the constructor or methods of the parent class. In the Pickup and Drop-off project, I used super() to initialize common properties of a delivery in the child classes NormalDelivery and PriorityDelivery.

Example:

java

CopyEdit

class Delivery {

    String deliveryType;

    public Delivery(String deliveryType) {

        this.deliveryType = deliveryType;

    }

}

 

class PriorityDelivery extends Delivery {

    public PriorityDelivery(String deliveryType) {

        super(deliveryType); // Initialize the parent class with the delivery type.

    }

}

How it was applied: In the project, super() ensured that properties like deliveryType were consistently initialized, even when subclass-specific properties were added.

 

  1. How would you use the static keyword for utility functions in route optimization?

Static methods were used for utility functions that did not require an instance of the class, such as calculating the distance between two locations.

Example:

java

CopyEdit

class RouteUtils {

    public static double calculateDistance(Location loc1, Location loc2) {

        double xDiff = loc1.latitude – loc2.latitude;

        double yDiff = loc1.longitude – loc2.longitude;

        return Math.sqrt(xDiff * xDiff + yDiff * yDiff);

    }

}

How it was applied: In the Pickup and Drop-off project, the RouteUtils class provided static methods like calculateDistance(), which were called whenever route optimization required distance calculations between locations.

 

  1. Write a constructor for the Driver class to initialize the driver object with essential details (name, availability, assigned route). Use this to differentiate between local and instance variables.

Example:

java

CopyEdit

class Driver {

    private String name;

    private boolean availability;

    private List<Location> assignedRoute;

 

    public Driver(String name, boolean availability, List<Location> assignedRoute) {

        this.name = name; // Instance variable

        this.availability = availability; // Instance variable

        this.assignedRoute = assignedRoute; // Instance variable

    }

}

How it was applied: In the project, each driver object was initialized with details about their availability and assigned route. Local variables helped distinguish between method parameters and instance variables.

 

  1. Can a static method access non-static variables? Why or why not?

No, a static method cannot access non-static variables directly because static methods belong to the class, while non-static variables belong to instances of the class.

How it was applied: In the Pickup and Drop-off project, utility functions like RouteUtils.calculateDistance() were static because they didn’t depend on any instance variables.

 

  1. Why is the super keyword used in constructors? Can you provide an example where super was used to extend functionality in your project?

super is used in constructors to call the parent class constructor, ensuring that the inherited properties are properly initialized.

Example:

java

CopyEdit

class Vehicle {

    String vehicleType;

    public Vehicle(String vehicleType) {

        this.vehicleType = vehicleType;

    }

}

 

class PickupVehicle extends Vehicle {

    String driverName;

 

    public PickupVehicle(String vehicleType, String driverName) {

        super(vehicleType); // Calls the parent constructor

        this.driverName = driverName;

    }

}

How it was applied: In the project, super was used in classes like PickupVehicle to ensure that shared properties such as vehicleType were initialized in the parent class.

 

  1. What happens if a constructor doesn’t explicitly call super() in a child class?

If a constructor doesn’t explicitly call super(), the compiler automatically adds a no-argument call to the parent class’s constructor. If the parent class does not have a no-argument constructor, a compile-time error occurs.

 

  1. In your project, if you wanted to add a new delivery service with additional features, how would inheritance be used?

Inheritance would be used to create a new subclass of Delivery. For example, we could create a LuxuryDelivery class for high-end clients.

Example:

class LuxuryDelivery extends Delivery {

    private String luxuryFeatures;

 

    public LuxuryDelivery(String deliveryType, String luxuryFeatures) {

        super(deliveryType);

        this.luxuryFeatures = luxuryFeatures;

    }

}

How it was applied: This design allows new delivery types to reuse and extend the existing functionality of the Delivery class.

 

  1. If two customers schedule pickups for the same time but only one driver is available, how would you prioritize one over the other? Implement this using OOP concepts.

We used a priority queue to manage scheduling. Customers with higher priority (e.g., based on request type) were served first.

Example:

class Customer implements Comparable<Customer> {

    int priority;

    String name;

 

    public Customer(int priority, String name) {

        this.priority = priority;

        this.name = name;

    }

 

    @Override

    public int compareTo(Customer other) {

        return Integer.compare(other.priority, this.priority); // Higher priority first

    }

}

How it was applied: In the project, customer requests were added to a priority queue, and the driver was assigned to the highest-priority request.

 

  1. If a driver has started their route but a high-priority pickup request is added, how would you re-optimize the existing route?

Problem: A driver is already executing their route, but a high-priority request (e.g., a VIP customer or emergency situation) needs to be added. The driver’s existing route must be dynamically adjusted to accommodate this new request while minimizing delays.

Solution: Dynamic Route Recalculation

  1. Insert the High-Priority Pickup Location:
    • Use the driver’s current location and their remaining route.
    • Add the high-priority location to the route.
  2. Re-optimize the Route:
    • Utilize a route optimization algorithm to re-order the stops in the route for efficiency.
    • The RouteOptimizer utility recalculates the shortest or fastest path based on the new list of locations, including the high-priority pickup.
  3. Implementation:
    • The existing route is represented as a list of locations.
    • The RouteOptimizer takes the current route and recalculates the optimal sequence after adding the high-priority location.

Example Code (Java):

class RouteOptimizer {

    public List<Location> reOptimizeRoute(List<Location> currentRoute, Location newHighPriorityLocation) {

        currentRoute.add(newHighPriorityLocation); // Add high-priority stop

        return optimizeRoute(currentRoute); // Recalculate using an optimization algorithm

    }

 

    private List<Location> optimizeRoute(List<Location> locations) {

        // Simplified optimization logic (e.g., Nearest Neighbor Algorithm)

        // In real implementation, more advanced algorithms like Dijkstra or A* could be used.

        // Returning reordered locations based on efficiency

        return reorderedLocations;

    }

}

How it would work in the project:

  • When a high-priority pickup request is received, the system:
    1. Identifies the nearest driver already on a route.
    2. Calls the reOptimizeRoute() method to adjust the route.
    3. Updates the driver’s route dynamically in the backend system.

 

  1. If the MySQL database becomes unavailable during scheduling, how would you ensure that requests are temporarily saved and retried later?

Problem: If the MySQL database becomes unavailable (e.g., network issues or server downtime), customer requests could be lost unless there’s a mechanism to temporarily save them and retry later.

Solution: Temporary Storage with Retry Mechanism

  1. Temporary Storage:
    • Use an in-memory data store such as Redis or local files to store customer requests temporarily.
    • These systems ensure data persistence until the database becomes available.
  2. Retry Mechanism:
    • Implement a background process (e.g., scheduled tasks) to continuously retry saving requests to the MySQL database.
    • Use exponential backoff logic for retries to prevent overwhelming the database when it comes back online.
  3. Implementation:
    • When the database is unavailable, requests are pushed to the temporary storage.
    • A retry service checks the storage periodically and attempts to insert the data back into MySQL.

Example (Java with Redis):

class TemporaryStorageHandler {

    private RedisClient redisClient;

 

    public void saveRequestToTempStorage(Request request) {

        redisClient.save(request.getId(), request); // Save the request in Redis

    }

 

    public void retryRequests() {

        List<Request> pendingRequests = redisClient.getAll();

        for (Request request : pendingRequests) {

            try {

                database.save(request); // Attempt to save to MySQL

                redisClient.delete(request.getId()); // Remove from Redis if successful

            } catch (Exception e) {

                // Log error and keep in Redis for next retry

            }

        }

    }

}

Fallback Options:

  • Local File Storage: If Redis isn’t available, requests can be saved as JSON files on the server and processed later.
  • Circuit Breaker: A circuit breaker pattern ensures the system doesn’t keep sending requests to an unavailable database.

How it works in the project:

  1. When the database is unavailable:
    • Requests are temporarily saved in Redis.
  2. When the database becomes available:
    • The retry mechanism processes all pending requests.
  3. Users experience no downtime, as requests are guaranteed to be processed later.

 

  1. If a driver assigned to a route becomes unavailable mid-route, how would you dynamically reassign tasks to another driver?

Problem: If a driver becomes unavailable mid-route (e.g., due to a breakdown, emergency, or personal issue), their remaining tasks (pickup and drop-off locations) must be reassigned to other available drivers.

Solution: Dynamic Driver Reassignment

  1. Identify the Remaining Tasks:
    • Retrieve the list of locations the driver has not yet visited.
    • This information can be fetched from the system’s route tracker.
  2. Find an Available Driver:
    • Use a driver pool to locate the nearest available driver(s) with enough capacity to take on additional tasks.
    • Drivers can be ranked based on proximity to the next task or their availability status.
  3. Merge and Optimize Routes:
    • Assign the remaining tasks to the selected driver(s).
    • Use the RouteOptimizer utility to merge the new tasks with their existing route and re-optimize it.
  4. Implementation:
    • The system dynamically reassigns tasks and notifies the new driver about the updated route.

Example Code (Java):

class DriverReassignmentHandler {

    private List<Driver> driverPool;

 

    public void reassignTasks(Driver unavailableDriver) {

        List<Location> remainingTasks = unavailableDriver.getRemainingTasks();

        Driver nearestDriver = findNearestAvailableDriver(remainingTasks.get(0));

       

        if (nearestDriver != null) {

            List<Location> updatedRoute = mergeRoutes(nearestDriver.getRoute(), remainingTasks);

            nearestDriver.setRoute(optimizeRoute(updatedRoute));

        }

    }

 

    private Driver findNearestAvailableDriver(Location nextTask) {

        // Find the nearest available driver to the task

        return availableDriver;

    }

 

    private List<Location> mergeRoutes(List<Location> currentRoute, List<Location> newTasks) {

        currentRoute.addAll(newTasks);

        return currentRoute;

    }

}

How it works in the project:

  1. Real-Time Monitoring:
    • The system tracks each driver’s location and availability status.
  2. Task Reassignment:
    • When a driver is marked unavailable, their remaining tasks are retrieved.
    • Another driver is dynamically assigned, and their route is recalculated.
  3. Driver Notification:
    • The newly assigned driver receives the updated route on their app.

Real-Life Example:

  • If Driver A is delivering three vehicles but breaks down after the first drop-off, the remaining two pickups are reassigned to Driver B, who is closest and available.

 

Programs

  1. Write a utility method that takes a list of locations (latitude, longitude) and calculates the shortest route using a basic distance formula.

class RouteUtils {

    public static double calculateDistance(Location loc1, Location loc2) {

        double xDiff = loc1.latitude – loc2.latitude;

        double yDiff = loc1.longitude – loc2.longitude;

        return Math.sqrt(xDiff * xDiff + yDiff * yDiff);

    }

}

  1. Write a constructor for the Driver class that initializes the name, availability, and route.

class Driver {

    private String name;

    private boolean availability;

    private List<Location> route;

 

    public Driver(String name, boolean availability, List<Location> route) {

        this.name = name;

        this.availability = availability;

        this.route = route;

    }

}