Java Object-Oriented Programming Concepts and Solutions
Core Concepts of Object-Oriented Programming
False. An abstract class cannot be instantiated directly. You cannot create an object of an abstract class using new. You must create an object of a concrete subclass.
False. Java does not allow a class to extend more than one class. However, a class can implement multiple interfaces.
False. Method overloading means having the same method name but different parameter lists. A different return type alone is not enough.
True. The reference type determines which methods are available at compile time. The actual object determines which overridden method runs at runtime.
True. A static field belongs to the class rather than to individual objects. Therefore, all objects of that class share the same static field.
Encapsulation means hiding and protecting an object’s data and controlling how that data can be accessed or modified. Example: Making balance private and allowing it to be changed only through methods such as deposit() or withdraw().
Abstraction means hiding implementation details and showing only the essential behavior. Example: An abstract Account class can define a monthlyUpdate() method without specifying exactly how every type of account performs the update.
Method Overriding Versus Overloading
Overriding happens when a subclass provides a new implementation of a method inherited from its parent class.
The method name and parameter list must be the same.
Overloading happens when a class has multiple methods with the same name but different parameter lists.
Analysis of Account Execution and Static Counters
a. 2:2/ 91.29/ 87.0
b. For a, the actual object is a SavingsAccount, so the overridden withdraw() and monthlyUpdate() methods from SavingsAccount run.
For b, the actual object is an Account, so the methods from Account run.
c. It tracks the total number of withdrawals made by all Account objects.
It is static, so there is only one shared counter for the entire class.
The final value is: 2
Input Validation and Rule Enforcement
c1. I would use both if/else checks and try/catch.
try/catch should be used to handle invalid input that cannot be converted from text to a number, such as "abc".
After successfully converting the input, if/else checks can validate business rules, such as making sure the amount is greater than zero.
For example, if the user enters "abc", a number-formatting exception should be handled and the user should be asked to enter a valid number.
c2. The rules should be enforced in the Account class methods.
First, this ensures correctness because every withdrawal goes through the same rules, even if the Account is used by a different part of the program.
Second, it avoids duplicating the same validation logic in the UI or other classes and makes the rules easier to test and maintain.
Reading Accounts from a File
static List<Account> readAccounts(String fileName) {
List<Account> accounts = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
// Skip header
br.readLine();
String line;
while ((line = br.readLine()) != null) {
try {
String[] parts = line.split(",");
// Must have 5 fields
if (parts.length != 5) {
continue;
}
String accountNo = parts[0];
String type = parts[1];
String owner = parts[2];
double balance = Double.parseDouble(parts[3]);
double extra = Double.parseDouble(parts[4]);
if (type.equals("SAVINGS")) {
accounts.add(
new SavingsAccount(accountNo, owner, balance, extra)
);
}
else if (type.equals("CHECKING")) {
accounts.add(
new CheckingAccount(accountNo, owner, balance, extra)
);
}
}
catch (NumberFormatException e) {
// Invalid numeric data -> skip this row
continue;
}
}
}
catch (IOException e) {
e.printStackTrace();
}
return accounts;
}Splitting and Updating Accounts
Splitting Accounts by Balance
static void splitAccounts(List<Account> accounts) {
List<CheckingAccount> low = new ArrayList<>();
List<CheckingAccount> medium = new ArrayList<>();
List<CheckingAccount> high = new ArrayList<>();
for (Account account : accounts) {
if (account instanceof CheckingAccount) {
CheckingAccount checking = (CheckingAccount) account;
if (checking.getBalance() < 500) {
low.add(checking);
}
else if (checking.getBalance() < 2000) {
medium.add(checking);
}
else {
high.add(checking);
}
}
}
}Applying Monthly Updates
static void applyMonthlyUpdate(List<Account> accounts) {
for (Account account : accounts) {
account.monthlyUpdate();
}
}