You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

  • Account class setAccountNumber method:
    • 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.
  • Missing methods in Account: Your ChequingAccount calls super.setBalance() and super.subtractFromBalance(), but these methods don't exist in your base Account class.
  • ChequingAccount constructor: You're hardcoding setNumberOfCheques(3) instead of using the numberOfCheques parameter passed in.
  • No SavingAccount subclass: 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 Account to 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

  1. Factory Method: The createAccount static method in Account checks 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.
  2. Account Number Validation: The isValidAccountNumber method uses a regex ((CA|SA)-\\d{3}) to ensure the account number matches your required format (CA-### or SA-### where ### is 3 digits).
  3. Subclass Overrides: Both ChequingAccount and SavingAccount override methods from Account to add custom behavior (cheque limits/fees for chequing, interest for savings).
  4. Transaction Tracking: The transactionInfo list 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 20:07:33