0

I have a program nearly complete - it creates a bank object which creates within it customers and accounts of multiple types and can successfully load this information to display on the screen. The problem is that I am now trying to deposit or withdraw a given balance which has already been created, but I am unable to because "Non-Static Method Cannot be referenced from static context." which I know generally means that the instance has not been created yet, but in this case it has. It's just that I can't seem to do anything with it and I don't know why.

Here's what I have so far. It compiles and it runs. It's just the processTransactionsInFile() method in the Main.java class which is incomplete. (see line 247 of Main.ajava - I commented out the portions giving me trouble) oh, and the withdraw/deposit methods are in Account.java. I have been wracking my head on this for a few days and could really use some direction at least. Since I am not sure where my problem is I am posting the entire intact program code below:

Main.java class:

package mp04;

import java.io.File;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Main 
{
    private final static String INPUT_ACCOUNT_FILE = "accountInfo.txt";
    private final static String INPUT_TRANSACTIONS_FILE = "transactions.txt";


    // If I don't initialize the bank object at the class level it won't be accessible by the other methods.
    protected static Bank bank = new Bank();


    public static void main(String[] args) 
    {

        // I used the following to trouble shoot file names and location.

//        File file = new File(".");
//        for(String fileNames : file.list()) System.out.println(fileNames);

        // Open file
        try 
            {
            loadAccountInformationFromFile();
            } 
        catch (Exception e) 
            {
                    System.err.println("error: " + e.getMessage()); 
                    System.exit(1);
            }

        try 
            {
            processTransactionsInFile();
            }
        catch (Exception e) 
            {
                    System.err.println("error: " + e.getMessage()); 
                    System.exit(1);
            }

        displayBankRecords();



//        System.out.printf("%s\n%s\n%s", "Customer list:","--------------", bank.customerList());
//        System.out.println("");
//        System.out.printf("%s\n%s\n%s", "Account list:","-------------", bank.accountList());
//        System.out.printf("\n%s\n%s\n%s", "Bank record:","------------", bank);
//        System.out.println("");
    }
        protected static void loadAccountInformationFromFile() throws Exception 
        {
            // These correspond with the positions of the contents of the text file.
            // This is based on the knowledge that each line has only 5 values,
            // but in practice I could easily add an additional variable with an
            // additional number value and it would definately work.

            // They may be the same, but setting them differently allows me some
            // versatility in future edits.
            final int ACCOUNT_NUMBER = 0;
            final int FIRST_NAME = 1;
            final int LAST_NAME = 2;
            final int BALANCE = 3;
            final int LAST_VARIABLE = 4; 

            final int ACCOUNT_NUMBER_COUNT = 0;
            final int FIRST_NAME_COUNT = 1;
            final int LAST_NAME_COUNT = 2;
            final int BALANCE_COUNT = 3;
            final int LAST_VARIABLE_COUNT = 4; 

            List<String> accountNumbers = new ArrayList<>();
            List<String> firstNames = new ArrayList<>();
            List<String> lastNames = new ArrayList<>();
            List<String> balances = new ArrayList<>();
            List<String> lastVariables = new ArrayList<>();

        try (Scanner account = new Scanner(new File(INPUT_ACCOUNT_FILE))) 
        {
            do {

                String[] temp1 = account.next().split(",");


                if (ACCOUNT_NUMBER_COUNT == ACCOUNT_NUMBER)
                {
                    accountNumbers.add(temp1[ACCOUNT_NUMBER]);
                }
                if (FIRST_NAME_COUNT == FIRST_NAME)
                {
                    firstNames.add(temp1[FIRST_NAME]);
                }
                if (LAST_NAME_COUNT == LAST_NAME)
                {
                    lastNames.add(temp1[LAST_NAME]);
                }
                if (BALANCE_COUNT == BALANCE)
                {
                    balances.add(temp1[BALANCE]);
                }
                if (LAST_VARIABLE_COUNT == LAST_VARIABLE)
                {
                    lastVariables.add(temp1[LAST_VARIABLE]);
                }

            } while (account.hasNext());
        }

            // Given the above logic, each ArrayList would have to be the same size.
            int arraySize = lastVariables.size();

            // Given that the Checking Account class has a definate boolean value
            // whereas the Savings Account class requires a double which can be
            // anything I can use the boolean to sort the data being sent to bank.

            for (int i=0; i < arraySize; i++)
            {
                // Alternatively, I could have focused on the fact that a 1
                // seems to prefix a checking account while a 2 is for savings.
                if (("N".equals(lastVariables.get(i))) || ("Y".equals(lastVariables.get(i))))
                {                    
                    // convert the String ArrayLists to the correct variable types to be
                    // accepted by the Bank class without changing it.

                    String accountNumberString = accountNumbers.get(i);
                    int accountNumberInt = Integer.parseInt(accountNumberString);

                    String firstNameString = firstNames.get(i);
                    String lastNameString = lastNames.get(i);

                    String balanceString = balances.get(i);
                    double balanceDouble = Double.parseDouble(balanceString);

                    String lastVariableString = lastVariables.get(i);

                    // Initialize boolean as anything to avoid compiler error
                    boolean freeChecks = true;

                    if (lastVariableString == "N")
                    {
                        freeChecks = Boolean.parseBoolean("false");
                    }
                    else
                    {
                        freeChecks = Boolean.parseBoolean("true");
                    }

                    bank.openAccount(new CheckingAccount(accountNumberInt, new Customer(firstNameString, lastNameString),balanceDouble,freeChecks));

                } 
                else 
                {

                    // convert the String ArrayLists to the correct variable types to be
                    // accepted by the Bank class without changing it.

                    String accountNumberString = accountNumbers.get(i);
                    int accountNumberInt = Integer.parseInt(accountNumberString);

                    String firstNameString = firstNames.get(i);
                    String lastNameString = lastNames.get(i);

                    String balanceString = balances.get(i);
                    double balanceDouble = Double.parseDouble(balanceString);

                    String lastVariableString = lastVariables.get(i);
                    double interestDouble = Double.parseDouble(lastVariableString);

                    bank.openAccount(new SavingsAccount(accountNumberInt, new Customer(firstNameString, lastNameString),balanceDouble,interestDouble));

                }
            }

              // Used the following to test to make sure that the ArrayLists work:
//            System.out.println(accountNumbers.get(0));
//            System.out.println(firstNames.get(4));

        }




//        Add the method void processTransactionsInFile(). This void method declares that it
//throws an Exception object, which the caller (main()) will handle. This method will open the
//input file, transactions.txt, and process each transaction.

        protected static void processTransactionsInFile() throws Exception
        {
            final int ACCOUNT_NUMBER_COUNT = 1;
            final int TRANSACTION_COUNT = 0;

            final int ACCOUNT_NUMBER = 1;
            final int TRANSACTION = 0;

            List<String> transactionList = new ArrayList<>();
            List<String> accountNumberList = new ArrayList<>();



            try (Scanner transactions = new Scanner(new File(INPUT_TRANSACTIONS_FILE))) 
            {
                do {

                    String[] temp1 = transactions.next().split(",");

                    if (ACCOUNT_NUMBER_COUNT == ACCOUNT_NUMBER)
                        {
                            transactionList.add(temp1[ACCOUNT_NUMBER]);
                        }
                    if (TRANSACTION_COUNT == TRANSACTION)
                        {
                            accountNumberList.add(temp1[TRANSACTION]);
                        }         

                    } while (transactions.hasNext());
            }

            // test:
             System.out.println(accountNumberList.get(1));
             System.out.println(accountNumberList.get(2));

            int arraySize = transactionList.size();


                for (int i=0; i < arraySize; i++)
                    {

                        String transactionString = transactionList.get(i);
                        double transactionDouble = Double.parseDouble(transactionString);

                        String accountNumberString = accountNumberList.get(i);
                        int accountNumberInt = Integer.parseInt(accountNumberString);

                        // bank.getAccountWithNumber(accountNumberInt);

                        System.out.println(transactionDouble);

                        if (transactionDouble < 0)
                            {
                                // This doesn't work
                                //Account.withdraw(transactionDouble);
                            }
                        else
                            {
                                //Account.deposit(transactionDouble);
                            }
                     }

             // Used the following to test to make sure that the ArrayLists work:
//             System.out.println(transactionList.get(1));



        }

        private static void displayBankRecords()
        {

        System.out.printf("%s\n%s\n%s\n%s", "Bank Record:","--------------", "Customers:(" + bank.getCustomerSize() + ") " , bank.customerList());
        System.out.println("");
        System.out.printf("%s\n%s\n%s\n%s", "Account list:","-------------", "Accounts:(" + bank.getAccountSize() + ") " , bank.accountList());
        }

}

Bank.java class:

package mp04;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Bank 
{ 
    private List<Customer> customers = new ArrayList<>();
    private List<Account> accounts = new ArrayList<>();

    public int getCustomerSize()
    {
        return customers.size();
    }

        public int getAccountSize()
    {
        return accounts.size();
    }

    public Customer getCustomerAtIndex(int index) 
        { 
            return customers.get(index); 
        }
    public Account getAccountAtIndex(int index)   
        { 
            return accounts.get(index);  
        }

    public Account getAccountWithNumber(int accountNumber)
    {   
        return accounts.get(accountNumber);  
    }

    public void addCustomer(Customer o) 
    {
        //Each time this method is called it will add to the array
        customers.add(o);
    }

    // Added the addAccount() method when dynamic arrays are used.
    // Need to remove addAccount() for the new UML
    private void addAccount(Account o) 
    {
        //Each time this method is called it will add to the array
        accounts.add(o);
    }

    public void openAccount(Account o) 
    {

        addAccount(o);

        // I needed an extra boolean in order to make use of the .equals() method.
        // there were too many errors as it was and not enough example in the book.

        boolean compare = true;

        for(int i = 0; i < customers.size(); i++)
        {
            if (o.getOwner().equals(getCustomerAtIndex(i)) == true)
                {
                    compare = false;
                }
        }

        if (compare == true)
        {
            addCustomer(o.getOwner());
        }


    }

    public String customerList() 
    {
        String list = Arrays.toString(customers.toArray()).replace(", O", "O").replace(", O", "O");
        return list.substring(1,list.length()-1);

        // Using just the following causes brackets to appear
//                return list;

        // The following approach removed the brackets, but there were still extra commas
//                return list.substring(1,list.length()-1);

        // The following approach removed the extra commas, but also removed the commas I wanted so I couldn't use it
//                String list = Arrays.toString(customers.toArray()).replace(",", "").replace(",", "");
        // In order to make it work without using StringBuilder I focused on the fact that each line starts with N and made it work that way.
        // However, I consider this to be a poor approach. If the toString() class in Customer.java is changed the code will break so I am notating there

    }

    public String accountList() 
    { 
        String account = Arrays.toString(accounts.toArray()).replace(", [", "[").replace(", [", "[");
        return account.substring(1,account.length()-1);



    }

    @Override
    public String toString() 
    {
        return "Customers(" + customers.size() + ")\n" + customerList() + "\n" +
                "Accounts(" + accounts.size() + ")\n" + accountList();
    }
}

Customer.Java class:

package mp04;

import java.util.Objects;

public class Customer 
{
    private String first;
    private String last;

    public Customer(String first, String last) 
    {
        setFirst(first);
        setLast(last);
    }

    public final String getFirst() { return first;                         }
    public final String getLast()  { return last;                          }
    public String getName()  
        { 
            return getLast() + ", " + getFirst(); 
        }

    public final void setFirst(String first) 
        {
        this.first = first;
        }

    public final void setLast(String last) { this.last = last; }

    @Override
    public int hashCode() 
    {
        int hash = 7;
        hash = 37 * hash + Objects.hashCode(this.first);
        hash = 37 * hash + Objects.hashCode(this.last);
        return hash;
    }

    @Override
    public boolean equals(Object name) 
    {
        if (name == null) {
            return false;
        }
        if (getClass() != name.getClass()) {
            return false;
        }
        final Customer other = (Customer) name;
        if (!Objects.equals(this.first, other.first)) {
            return false;
        }
        if (!Objects.equals(this.last, other.last)) {
            return false;
        }
        return true;
    }



    @Override
    public String toString() 
    {
        // CAUTION: The Bank.java class depends on this return starting with O amd emdomg with "\n"
        // If this changes be sure to change the customerList() method in Bank.java class accordingly.
        return "Owner: " + getName() + "\n";
    }


}

Account.java class:

package mp04;

// Note: The Account class is a super class. I don't need getters and setters
// in any account type for this reason.

import java.text.DateFormat;
import java.util.Date;

public class Account 
{
    private int accountNumber;
    private Date dateOpened;
    private Customer owner;
    private double currentBalance;

    // For my own future reference: # in UML means protected
    protected Account(int accountNumber, Customer owner, double currentBalance) 
    { 
        setDateOpened(new Date()); 

        setAccountNumber(accountNumber);
        setOwner(owner);
        setCurrentBalance(currentBalance);
    }

    public int getAccountNumber() { return accountNumber; }
    public Customer getOwner()    { return owner;         }
    public double getCurrentBalance() { return currentBalance; }

    private void setAccountNumber(int accountNumber) { this.accountNumber = accountNumber; }
    private void setOwner(Customer owner)            { this.owner = owner;                 }
    private void setCurrentBalance(double currentBalance) { this.currentBalance = currentBalance; }

    //Note to self: The UML for this line was
    //
    //      +withdraw(amount: double): double
    //

    public double withdraw(double amount)
   {
        setCurrentBalance(currentBalance - amount);
        return currentBalance;
   }

    public double deposit(double amount)
    {
        setCurrentBalance(currentBalance + amount);
        return currentBalance;
    }

    public Date getDateOpened()                  { return dateOpened;            }
    private void setDateOpened(Date dateOpened)  { this.dateOpened = dateOpened; }

    @Override
    public String toString() 
    {
        DateFormat df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.SHORT);


        // CAUTION: The Bank.java class depends on this return starting with [ amd emdomg with "\n"
        // If this changes be sure to change the accountList() method in Bank.java class accordingly.
        return "[" + getAccountNumber() + "], " +
               "Opened: " + df.format(getDateOpened()) + 
               ", " + owner +
               "Balance: $" + currentBalance;
    }  
}

CheckingAccoung.java class:

package mp04;

public class CheckingAccount extends Account 
{
    private boolean freeChecks;
    private String freeChecksValue = "";

        public CheckingAccount(int accountNumber, Customer owner, double currentBalance, boolean freeChecks) 
    {
        super(accountNumber, owner, currentBalance);

        // This is the accessor
        this.freeChecks = freeChecks;
    }        

    @Override
    public String toString() 
    {

        if (freeChecks == true)
                {
                    freeChecksValue = "Yes";
                }
        else
                {
                    freeChecksValue = "No";
                }

        return super.toString() + ", " + "Free Checks: " + freeChecksValue + "\n\n";
    }
}

SavingsAccount.java class:

package mp04;

public class SavingsAccount extends Account
{
    private double interestRate;

        public SavingsAccount(int accountNumber, Customer owner, double currentBalance, double interestRate) 
    {
          super(accountNumber, owner, currentBalance);

          // This is the accessor:
          this.interestRate = interestRate;
    }    

    private void setInterestRate(double interestRate) 
        { 
            this.interestRate = interestRate; 
        }

    public double getInterestRate() 
        { 
            return interestRate; 
        }

    @Override
    public String toString() 
    {
          return super.toString() + ", " + "Interest Rate: " + interestRate + "%\n\n";
    }
}

accountInfo.txt :

10100,Adam,Apple,500.00,N
10101,Breatrice,Bagel,2000.00,Y
20100,Chris,Cucumber,5000.00,0.02
20101,David,Dakon,3500.00,0.02
10102,Ethel,Endame,1000.00,Y
20103,Adam,Apple,6000.00,0.02

transactions.txt :

10100,500.00
10101,-250.00
20100,450.00
20101,-100.00
10102,-300.00
20103,1000.00

The above runs and shows the following output (where everything before the Bank Account label in the text is just tests to verify I am collecting the data from the transactions file properly) :

run:
10101
20100
500.0
-250.0
450.0
-100.0
-300.0
1000.0
Bank Record:
--------------
Customers:(5) 
Owner: Apple, Adam
Owner: Bagel, Breatrice
Owner: Cucumber, Chris
Owner: Dakon, David
Owner: Endame, Ethel

Account list:
-------------
Accounts:(6) 
[10100], Opened: Oct 2, 2015 12:26 PM, Owner: Apple, Adam
Balance: $500.0, Free Checks: Yes

[10101], Opened: Oct 2, 2015 12:26 PM, Owner: Bagel, Breatrice
Balance: $2000.0, Free Checks: Yes

[20100], Opened: Oct 2, 2015 12:26 PM, Owner: Cucumber, Chris
Balance: $5000.0, Interest Rate: 0.02%

[20101], Opened: Oct 2, 2015 12:26 PM, Owner: Dakon, David
Balance: $3500.0, Interest Rate: 0.02%

[10102], Opened: Oct 2, 2015 12:26 PM, Owner: Endame, Ethel
Balance: $1000.0, Free Checks: Yes

[20103], Opened: Oct 2, 2015 12:26 PM, Owner: Apple, Adam
Balance: $6000.0, Interest Rate: 0.02%

However, the desired expected output after properly withdrawing/depositing transactions shows a different balance.

Edited by Elliander_1

3
Contributors
5
Replies
17
Views
2 Years
Discussion Span
Last Post by Elliander_1
0

You say you have a "Non-Static Method Cannot be referenced from static context.", but you forgot to tell us which line that was referring to.
But then you say you have incorrect output - which is impossible if you have the "Non-Static Method Cannot be referenced from static context." because that means the compile failed so you don; have anything to execute

0

@JamesCherrill I thought that was clear. I said that everything compiles and works without implementing the deposit/withdraw feature and that this is in the processTransactionsInFile() method in the Main.java class. I even commented out the problem area within the code and commented that it is the part that doesn't work. Obviously there would be no compiler errors if a problem area is commented out. See line 247 of Main.java - I edited the question accordingly.

Edited by Elliander_1

0

You don't need to post ALL of your code. Most of us don't have the time to read through it all. The error says enough. You are trying to access a member function without going through an instance of the object class where it is defined. IE, if method xyzzy() is defined as a member function of class Foo, then you cannot invoke it as Foo::xyzzy(). You need an instance of Foo, as in:

Foo bar = new Foo; bar.xyzzy();

0

I found my answer. My code has three problems:

In Main.java I should use:

Account account = bank.getAccountWithNumber(accountNumberInt);

Instead of what I was using:

bank.getAccountWithNumber(accountNumberInt);

I also had to change this snippet from the Main.java class:

                        if (transactionDouble < 0)
                            {
                                account.withdraw(transactionDouble);
                            }
                        else
                            {
                                account.deposit(transactionDouble);

                            }
                     }

To reflect the change in how I was loading the account numbers. This change alone caused an index error, but was fixed by changing the Bank.java class to either:

    public Account getAccountWithNumber(int accountNumber)
    {   
     for(Account account : accounts) {
      if(account.getAccountNumber() == accountNumber) {
       return account;
      }
     }
        return null;  
    }

or:

    public Account getAccountWithNumber(int accountNumber)
    {     
         return accounts.stream().filter(a -> a.getAccountNumber() == accountNumber).findFirst().get();
    }

Either works, but not what I was using:

public Account getAccountWithNumber(int accountNumber)
    {   
        return accounts.get(accountNumber);  
    }

After making all of these changes everything works perfectly. However, cleaning up my code this worked better than my if logic:

        try (Scanner transactions = new Scanner(new File(INPUT_TRANSACTIONS_FILE))) 
        {
            do {

                String[] temp1 = transactions.next().split(",");

                transactionList.add(temp1[ACCOUNT_NUMBER]);
                accountNumberList.add(temp1[TRANSACTION]); 

                } while (transactions.hasNext());
        }

I also had to change an N == variable to N.equals(variable)

Edited by Elliander_1

0

@rubberman Creating a new object would not have helped because the object was already created. The issue I was having was in loading the already created object, which I eventually figured out.

I didn't expect anyone to read all of the code, but by posting all of it and highlighting where my issue is that generally makes it easier for someone to spot what I might have missed. It also helps others who may find the code later since it gives a more complete picture of the problem and solution.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.