Java中Account子类创建及账号前缀识别问题求助
Fixing Your Account Hierarchy & Account Type Recognition
Hey there! Let's work through fixing your code step by step. You're on the right track with subclassing Account for chequing and savings, but there are a few key issues in your current code, plus we need to add the account type recognition logic you want. Let's break this down:
First, Let's Identify Key Issues in Your Current Code
AccountclasssetAccountNumbermethod:- You're using
substring(0,1)which only gets the first character, but you need the first two (for "CA" or "SA"). - The logic is backwards—you're checking the existing account number (which isn't set yet) instead of the incoming parameter, and you're setting the account number to a string like "Chequing account" instead of validating/setting the provided number.
- You're using
- Missing methods in
Account: YourChequingAccountcallssuper.setBalance()andsuper.subtractFromBalance(), but these methods don't exist in your baseAccountclass. ChequingAccountconstructor: You're hardcodingsetNumberOfCheques(3)instead of using thenumberOfChequesparameter passed in.- No
SavingAccountsubclass: You mentioned needing this, so we'll add it. - Account type recognition: You want to create the correct subclass based on the account number prefix—we'll implement a static factory method in
Accountto handle this.
Corrected Code Implementation
1. Updated Account Class
This version adds missing methods, fixes account number validation, and includes a factory method to create the right account type based on the account number prefix:
import java.util.ArrayList; public class Account { private String accountNumber; private double balance; private boolean active; private ArrayList<String> transactionInfo; // Default constructor public Account() { this.transactionInfo = new ArrayList<>(); this.active = true; } // Overloaded constructor (called by subclasses) protected Account(String accountNumber, double balance) { this.transactionInfo = new ArrayList<>(); this.active = true; // Validate account number format before setting if (isValidAccountNumber(accountNumber)) { this.accountNumber = accountNumber; } else { throw new IllegalArgumentException("Invalid account number format. Must start with CA- or SA- followed by 3 digits."); } setBalance(balance); } // Factory method to create the correct account type based on prefix public static Account createAccount(String accountNumber, double balance, int numberOfCheques) { if (accountNumber.startsWith("CA-")) { return new ChequingAccount(accountNumber, balance, numberOfCheques); } else if (accountNumber.startsWith("SA-")) { return new SavingAccount(accountNumber, balance); } else { throw new IllegalArgumentException("Unsupported account type. Account number must start with CA- or SA-."); } } // Helper to validate account number format private boolean isValidAccountNumber(String accountNumber) { // Regex to check format: starts with CA- or SA-, followed by exactly 3 digits return accountNumber.matches("(CA|SA)-\\d{3}"); } // Getters and Setters public String getAccountNumber() { return accountNumber; } public void setAccountNumber(String accountNumber) { if (isValidAccountNumber(accountNumber)) { this.accountNumber = accountNumber; } else { throw new IllegalArgumentException("Invalid account number format. Must start with CA- or SA- followed by 3 digits."); } } public double getBalance() { return balance; } public void setBalance(double balance) { if (balance >= 0) { this.balance = balance; transactionInfo.add("Balance set to: " + balance); } else { System.out.println("Error: Balance cannot be negative."); } } public boolean isActive() { return active; } public void setActive(boolean active) { this.active = active; } public ArrayList<String> getTransactionInfo() { return transactionInfo; } // Core transaction methods public void addToBalance(double amount) { if (amount > 0 && active) { balance += amount; transactionInfo.add("Deposited: " + amount + ", New Balance: " + balance); } else { System.out.println("Error: Invalid deposit amount or account inactive."); } } public void subtractFromBalance(double amount) { if (amount > 0 && active && balance >= amount) { balance -= amount; transactionInfo.add("Withdrew: " + amount + ", New Balance: " + balance); } else { System.out.println("Error: Invalid withdrawal amount, insufficient funds, or account inactive."); } } @Override public String toString() { return "Account [accountNumber=" + accountNumber + ", balance=" + balance + ", active=" + active + "]"; } }
2. Corrected ChequingAccount Class
public class ChequingAccount extends Account { private final double FEE = 1.0; private int numberOfCheques; // Default constructor public ChequingAccount() { super(); } // Overloaded constructor public ChequingAccount(String accountNumber, double balance, int numberOfCheques) { super(accountNumber, balance); setNumberOfCheques(numberOfCheques); } // Override setBalance to add custom validation @Override public void setBalance(double balance) { if (balance > 0) { super.setBalance(balance); } else { System.out.println("Error: Chequing account balance must be greater than 0."); } } // Override subtractFromBalance to handle cheque limits @Override public void subtractFromBalance(double amount) { if (amount > 0 && isActive()) { if (numberOfCheques <= 2) { // First 3 cheques are free super.subtractFromBalance(amount); setNumberOfCheques(numberOfCheques + 1); } else { // Apply fee after exceeding limit if (getBalance() >= amount + FEE) { super.subtractFromBalance(amount + FEE); transactionInfo.add("Cheque fee applied: " + FEE); } else { System.out.println("Error: Insufficient funds including cheque fee."); } } } else { System.out.println("Error: Invalid withdrawal amount or account inactive."); } } // Getters and Setters for numberOfCheques public int getNumberOfCheques() { return numberOfCheques; } public void setNumberOfCheques(int numberOfCheques) { if (numberOfCheques >= 0) { this.numberOfCheques = numberOfCheques; } else { System.out.println("Error: Number of cheques cannot be negative."); } } @Override public String toString() { return "ChequingAccount [numberOfCheques=" + numberOfCheques + ", " + super.toString() + "]"; } }
3. New SavingAccount Class
public class SavingAccount extends Account { private double interestRate = 0.02; // 2% annual interest example // Default constructor public SavingAccount() { super(); } // Overloaded constructor public SavingAccount(String accountNumber, double balance) { super(accountNumber, balance); } // Method to apply interest to the account public void applyInterest() { if (isActive() && getBalance() > 0) { double interest = getBalance() * interestRate; addToBalance(interest); transactionInfo.add("Interest applied: " + interest); } else { System.out.println("Error: Cannot apply interest to inactive or zero-balance savings account."); } } @Override public String toString() { return "SavingAccount [interestRate=" + interestRate + ", " + super.toString() + "]"; } }
Key Explainers for Your Understanding
- Factory Method: The
createAccountstatic method inAccountchecks the account number's prefix ("CA-" or "SA-") and returns the correct subclass instance. This is how we implement the "recognize account type from account number" feature. - Account Number Validation: The
isValidAccountNumbermethod uses a regex ((CA|SA)-\\d{3}) to ensure the account number matches your required format (CA-### or SA-### where ### is 3 digits). - Subclass Overrides: Both
ChequingAccountandSavingAccountoverride methods fromAccountto add custom behavior (cheque limits/fees for chequing, interest for savings). - Transaction Tracking: The
transactionInfolist is initialized in all constructors to avoid null pointer exceptions, and all balance changes add entries to this list for audit purposes.
Example Usage
public class Main { public static void main(String[] args) { try { // Create a chequing account Account chequing = Account.createAccount("CA-123", 500.0, 0); System.out.println(chequing); // Withdraw 3 times (first 3 free) chequing.subtractFromBalance(100); chequing.subtractFromBalance(50); chequing.subtractFromBalance(75); // Fourth withdrawal should include fee chequing.subtractFromBalance(20); // Create a savings account Account savings = Account.createAccount("SA-456", 1000.0, 0); // Third param ignored for savings System.out.println(savings); ((SavingAccount)savings).applyInterest(); System.out.println(savings.getTransactionInfo()); } catch (IllegalArgumentException e) { System.out.println(e.getMessage()); } } }
内容的提问来源于stack exchange,提问作者fifthcali
相关产品推荐
相关产品推荐

