Java Question Bank with Answers
Answers for Core Java Question Bank –
Chapter 3: Inheritance and Interfaces
Difficult Level Questions
18. Design a Java program using inheritance to model a "University Employee" system.
·
Create an abstract class Employee with
common attributes (e.g., name, employeeId) and
an abstract method calculateSalary().
·
Create two concrete subclasses: Faculty (with
additional attributes like department, designation) and Staff (with
additional attributes like jobTitle).
·
Implement calculateSalary()
uniquely for Faculty (e.g., based on designation)
and Staff
(e.g., based on fixed monthly salary).
·
Demonstrate runtime polymorphism by creating an
array of Employee
objects, populating it with Faculty and Staff
instances, and calling calculateSalary() on
each.
Answer:
import java.util.ArrayList;import java.util.List; // Abstract Superclass: Employeeabstract class Employee { private String name; private String employeeId; // Parameterized Constructor public Employee(String name, String employeeId) { this.name = name; this.employeeId = employeeId; } // Abstract method: calculateSalary public abstract double calculateSalary(); // Concrete method: display basic employee info public void displayEmployeeInfo() { System.out.println("Name: " + name + ", ID: " + employeeId); } // Getters public String getName() { return name; } public String getEmployeeId() { return employeeId; }} // Concrete Subclass 1: Facultyclass Faculty extends Employee { private String department; private String designation; public Faculty(String name, String employeeId, String department, String designation) { super(name, employeeId); this.department = department; this.designation = designation; } @Override public double calculateSalary() { double baseSalary = 50000.0; switch (designation.toLowerCase()) { case "professor": return baseSalary + 20000.0; case "associate professor": return baseSalary + 10000.0; case "assistant professor": return baseSalary + 5000.0; default: return baseSalary; } } @Override public void displayEmployeeInfo() { super.displayEmployeeInfo(); System.out.println(" Department: " + department + ", Designation: " + designation); }} // Concrete Subclass 2: Staffclass Staff extends Employee { private String jobTitle; private double monthlyRate; public Staff(String name, String employeeId, String jobTitle, double monthlyRate) { super(name, employeeId); this.jobTitle = jobTitle; this.monthlyRate = monthlyRate; } @Override public double calculateSalary() { return monthlyRate; } @Override public void displayEmployeeInfo() { super.displayEmployeeInfo(); System.out.println(" Job Title: " + jobTitle); }} // Main classpublic class UniversityEmployeeSystem { public static void main(String[] args) { List<Employee> universityEmployees = new ArrayList<>(); // Adding Faculty universityEmployees.add(new Faculty("Dr. Alice Smith", "F001", "Computer Science", "Professor")); universityEmployees.add(new Faculty("Dr. Bob Johnson", "F002", "Physics", "Associate Professor")); universityEmployees.add(new Faculty("Dr. Carol White", "F003", "Mathematics", "Assistant Professor")); // Adding Staff universityEmployees.add(new Staff("David Brown", "S001", "Administrative Assistant", 35000.0)); universityEmployees.add(new Staff("Eve Green", "S002", "Lab Technician", 40000.0)); universityEmployees.add(new Staff("Frank Black", "S003", "Security Guard", 30000.0)); System.out.println("--- University Employee Payroll ---"); for (Employee emp : universityEmployees) { emp.displayEmployeeInfo(); System.out.printf(" Calculated Salary: $%.2f%n", emp.calculateSalary()); System.out.println("----------------------------------"); } }}
19. Evaluate the benefits and drawbacks of using multiple interfaces versus a single abstract class for achieving polymorphism in complex Java applications. Under what specific conditions would multiple interfaces be a superior design choice, and when would an abstract class be more appropriate? Provide a detailed justification with examples.
Answer:
Both multiple interfaces and abstract classes are powerful mechanisms for
achieving polymorphism and abstraction in Java. The choice between them depends
on the specific design requirements, the nature of the "is-a" versus
"can-do" relationships, and the flexibility needed in the system.
Multiple Interfaces:
· Benefits:
1. Supports Multiple Behavioral Contracts: A class can implement any number of interfaces, allowing it to conform to multiple distinct behavioral contracts without the limitations of single inheritance . This is crucial for designing highly flexible and extensible systems.
2. Achieves Multiple Inheritance of Type: Effectively allows a form of multiple inheritance, where a class can inherit behaviors (method signatures) from several sources.
3. Loose Coupling: Interfaces enforce a contract without dictating implementation details (before Java 8 default methods), promoting loose coupling between the interface and its implementations.
4. Flexibility in Class Hierarchy: Interfaces can be implemented by classes anywhere in the inheritance hierarchy, regardless of their superclass.
5. API Definition: Excellent for defining public APIs and frameworks where implementers need freedom to structure their concrete classes.
· Drawbacks:
1. No
Shared Implementation: Historically, interfaces could not
provide any shared code, leading to code duplication if multiple implementing
classes needed identical default behavior. (Mitigated by Java 8 default
methods, but they come with their own considerations like potential ambiguity
if conflicting default methods are inherited.)
2. All
Fields are static final:
Cannot define non-constant fields (instance variables), which means interfaces
cannot hold state.
3. No Constructors: Cannot define constructors, making common initialization logic impossible.
Single Abstract Class:
· Benefits:
1. Shared Implementation: Can provide a partial implementation (concrete methods) that can be inherited and reused by all subclasses . This reduces code duplication for common behaviors.
2. Shared State: Can define and hold instance variables (state) that are common to all its subclasses.
3. Constructors: Can have constructors, allowing for common initialization logic for the abstract class’s fields.
4. "Is-A" Relationship: Best suited for defining a strong "is-a" relationship within a tightly coupled hierarchy.
· Drawbacks:
1. Single Inheritance Limit: A class can extend only one abstract class, limiting its ability to inherit common implementations or states from multiple parents.
2. Tighter Coupling: Due to shared implementation and state, subclasses are more tightly coupled to the abstract class’s design.
3. Less Flexible: Can constrain the design if a class needs to inherit behavior from multiple, disparate sources that don’t fit into a single "is-a" hierarchy.
When Multiple Interfaces are Superior:
· Conditions:
1. Behavioral
Contracts for Unrelated Classes: When defining common
behaviors that can be implemented by classes from entirely different
inheritance hierarchies. For example, Flyable might
be implemented by Bird, Airplane, and Superman.
2. Adding Capabilities to Existing Classes: If a class already extends another class, it can still implement new interfaces to gain additional capabilities without changing its superclass.
3. API Design for Extensibility: When designing a flexible API or framework where you want to specify "what" services are available without dictating "how" they are implemented, allowing maximum freedom to implementers.
4. Mimicking
Multiple Inheritance of Behavior: When a class needs to exhibit
characteristics of several distinct types (e.g., an AmphibiousVehicle might
implement Driveable and Swimmable).
·
Example: A system where
different objects can be Savable, Printable, and Searchable.
Instead of a complex abstract class hierarchy, interfaces ISavable, IPrintable, and ISearchable can
be implemented by various classes (Document, Image, Report) as
needed.
When an Abstract Class is More Appropriate:
· Conditions:
1. Strong "Is-A" Relationship with Common Implementation: When there’s a clear hierarchical relationship where subclasses share significant common state and behavior, and you want to provide a base implementation that subclasses can inherit or override.
2. Code Reusability for Default Behavior: When you want to provide common methods and fields that most subclasses will use, but also allow for specialized behaviors via abstract methods.
3. Version
Control of API: When adding new methods to an abstract class,
existing concrete subclasses might need to be updated, which is a stronger
coupling than interfaces typically offer (though Java 8 default
methods have blurred this line for interfaces).
4. Classes with Common State and Constructor Logic: When the base type needs common instance fields that are initialized through a constructor shared by all subclasses.
·
Example: A hierarchy for BankAccount. An abstract BankAccount could
have accountNumber, balance, deposit() and withdraw()
(concrete methods), and an abstract calculateInterest()
method. SavingsAccount and CheckingAccount would
extend BankAccount,
inheriting the common features and implementing calculateInterest()
uniquely.