Java update value between classes - java

I'm pretty new to Java and need some help with a program I am writing. Basically I have 2 classes that are trying to change the balance of a bank account. One class is adding deposits while the other is withdrawing. I though the easiest way to share a balance between the classes was to make a third class that looks like this:
public class Balance {
static int balance;
public int getBalance(){
return balance;
}
public void returnBalance(int bal){
this.balance = bal;
}
}
I am correctly calling the getBalance method because that is pulling in the correct balance. However, when I use my object Balance balanceCall = new Balance(); to give the changed balance (after depositing), it is not updating the balance within the class. I think I am again calling the method correctly, but it does not appear to actually change the value of the balance variable in my balance class. Is the code in my balance class used incorrectly for the returnBalance method?
Thanks for your help!
UPDATE: I changed the integer to static int balance. It is now updating the value between classes, however it seems to be creating a new value every time i do a deposit.
This is what it looks like:
Thread 1 deposits $76 Balance is $76
Thread 8 withdraws $45 Balance is $31
Thread 7 withdraws $12 Balance is $64
Thread 6 withdraws $41 Balance is $35
Thread 3 deposits $89 Balance is $165
Thread 5 withdraws $10 Balance is $66
Thread 4 withdraws $17 Balance is $59
Thread 2 deposits $157 Balance is $157
Here is how I use the Balance instance:
balanceNum = balanceCall.getBalance();
balanceNum = balanceNum + 25;
balanceCall.returnBalance(balanceNum);
Hopefully this helps to clear things up.

If you want all your objects to share the same balance field you have to add the static modifier. Otherwise a new member will be created for every objects.

If you need just a copy with same balance,
public class Balance {
private int balance;
public int getBalance()
{
return balance;
}
public void setBalance(int b)
{
balance=b;
}
public Balance newBalance()
{
Balance b=new Balance();
b.setBalance(getBalance());
return b;
}
}
usage:
balanceCall=previousBalance.newBalance();
or you can clone too.

Assuming the methods are called correctly, you can share your balance variable by using the static keyword (ex. "static int balance;").
In doing so, you make the variable belongs to all classes within the project and is shared across them. To use this variable, just refer to its name, in this case use "balance = [insert formula];" (no longer need to use "this.balance").

You are creating a new instance of the balance class when you do new balance(). So essentially one class is still referring to the old instance, while the new class is referring to the new one.
The way you should go about this depends a bit on the rest of the program, but if you want to refer to the same instance, you should put an extra method in the balance class, called updateBalance() which changes the balance, or maybe decrements / increments it depending on whether it is a withdrawal or deposit.
However, your design seems to be a bit weird. It seems that both classes performing withdrawals or deposits should actually be referring to the same bank account. The balance class seems a bit redundant.

The static behaviour approach as suggested by others definitely helps achieve a solution, but, keeping in mind your opening line that you're still a beginner in Java, I'd suggest you change your Class design altogether, to make it more in line with an Object Oriented design.
Create a class called Account, with Balance as its attribute. It makes sense to have an Account object (like in the real-world) that HAS a Balance attribute. The withdraw or deposit actions corresponding to an Account can be put within the same Account class, in line with the encapsulation paradigm of OOP/Java. This would help in making it more intuitive to understand the flow of variables within your program.
public class Account{
public int balance = 0;
public void setBalance(int balance){
this.balance = balance;
}
public int getBalance(){
return this.balance;
}
public deposit(int amount){
this.balance += amount;
}
public withdraw(int amount){
//Additional validations can be added to ensure non-negative balance, if needed
this.balance -= amount;
}
}
public AccountDemo{
public static void main(String[] args){
Account account1 = new Account();
account1.deposit(100);
Account account2 = new Account();
account2.deposit(50);
account2.withdraw(10);
//account1 has a balance of 100 & account2 has a balance of 40 at this point
AccountDemo.transferMoney(account1, account2, 20);
//account2 now has a balance of 80 (deducted by 20)
// & account2 has a balance of 60(increased by 20) after the transfer.
}
public static boolean transferMoney(Account source, Account destination, int amount){
if(source.getBalance() >= amount){
source.withdraw(amount);
destination.deposit(amount);
System.out.println("Transfer successful");
return true;
} else{
System.out.println("Sorry. Transfer failed due to
insufficient funds.");
return false;
}
}
}

This seems to be a problem with thread synchronization, namely lost update. This means, if you read and write the same value from multiple threads, some calculations will not be represented in the final result. You can solve this problem using the class AtomicInteger:
public class Balance {
private AtomicInteger value = new AtomicInteger();
public int get() {
return value.get();
}
public void set(int value) {
this.value.set(value);
}
public int addAndGet(int value) {
return this.value.addAndGet(value);
}
}
Right usage:
int value = balance.addAndGet(25);
Wrong usage:
int value = balance.get();
value = value + 25;
balance.set(25);
You have to use the addAndGet method to prevent the problem of lost update.
Also, you should definitely not declare the value attribute as static, because then all of your Balance instances will hold the same value which is probably not what you want.
See also:
Why are static variables considered evil?
Java - using AtomicInteger vs Static int

Related

How to synchronize threads in Java?

Considering the code below.
public class Account {
private static List<Double> log = new ArrayList<Double>();
private double balance;
public Account(){balance = 0.0;}
public synchronized void deposit(double val){
balance = balance + val;
log.add(val);
}
public synchronized void withdraw(double val){
balance = balance - val;
log.add(val);
}
}
Is the synchronization correct?
I would say yes, because the method that access the variable log are atomic (thanks to the word Synchronized).
I tested it in this way:
Account a = new Account();
Thread t = new Thread(()->a.deposit(30));
Thread j = new Thread(()->a.withdraw(20));
t.start();
j.start();
sleep(300);
System.out.println(Account.getLog());
It seems to me that blocking is fine, as long as one thread is using the log variable, the other is not using it.
However, the text shows this solution (not explaining why)(-> stands for substitution):
log.add(val)->
synchronized(log)
{
log.add(val)
}
log.add(-val)->
synchronized(log)
{
log.add(-val)
}
class Account {
private static List<Double> log = new ArrayList<Double>();
private double balance;
public Account() {
balance = 0.0;
}
public synchronized void deposit(double val) {
balance = balance + val;
synchronized (log) {
log.add(val)
}
}
public synchronized void withdraw(double val) {
balance = balance - val;
synchronized (log) {
log.add(-val);
}
}
}
Why should I lock the variable log? Is it not enough to synchronize the method?
The solution code looks thread-safe to me:
The balance variable for each account is updated while holding the account's mutex.
The log is updated while holding the list's mutex.
One small quibble is that log should be final. If anything was able to (for example accidentally) assign a new value to log, different threads are not guaranteed to be seeing / updating the same list object.
However, your version of the code is NOT thread-safe. It is not locking log while updating it. That means that two threads updating different Account objects could simultaneously attempt to update the log list. That could corrupt it.
There are various other things wrong with (both) solutions. The most critical one is that you are using double to represent currency values. That is a violation of normal accounting practice. (And some bank customers will get antsy if you "steal" some of their pennies ... due to floating point rounding errors.)

What is the function of the (.), or in other words, what does the period do? [duplicate]

This question already has answers here:
What is the purpose of Java DOT operator?
(3 answers)
Closed 3 years ago.
New to java programming. Can't seem to find what the period means when searching around...as in System.out.println() or when combining a Class with an instance variable, but CreditCard.balance may be an example. I came up with the following code partly by accident and partly by reason. Nonetheless, what is the (.)'s purpose.
public class CreditCard {
// data members
private static Person owner;
private static Money balance;
private static Money creditLimit;
public CreditCard(Person newCardHolder, Money creditLimit) {
CreditCard.owner = newCardHolder;
CreditCard.balance = new Money(0);
CreditCard.creditLimit = new Money(creditLimit);
}
public Money getBalance() {
Money balance = new Money(0.00);
return balance;
}
public Money getCreditLimit() {
Money creditLimit = new Money(1000.00);
return creditLimit;
}
public String getPersonals() {
return owner.toString();
}
public String getOwner() {
return owner.toString();
}
public void charge(Money amount) {
Money value = new Money(balance.add(amount));
value = balance;
if (value.compareTo(creditLimit) > 0) {
System.out.println("Exceeds credit limit");
} else {
balance = value;
System.out.println("Charge: " + amount);
}
}
public void payment(Money amount) {
Money value = new Money(balance.subtract(amount));
}
}
The output for the record here is
Diane Christie, 237J Harvey Hall, Menomonie, WI 54751
Balance: $0.00
Credit Limit: $1000.00
Attempting to charge $200.00
Charge: $200.00
Balance: $0.00
Attempting to charge $10.02
Charge: $10.02
Balance: $0.00
Attempting to pay $25.00
Balance: $0.00
Attempting to charge $990.00
Charge: $990.00
Balance: $0.00
if anyone wouldn't mind hinting at what I have done wrong in my execution, I'd appreciate that. My first question is the most crucial, however. Thank you to those who take the time to respond with their input.
Period indicates the namespace. It means that the method/variable after the period is belonging to the object before the period. It is not necessarily a function.
“Creditcard.balance” just tells compiler to access “balance” of neither global variable, nor any other object, but “Creditcard”.
As for your second question, I think it is a bit confusing.

How to set a variable as a class method and not as a static method

I'm trying to grasp some comments that were made to me by my professor on a programming assignment. The assignment was to write a program that calls upon another class. This program was to take 2 investors with different starting balances and show how much interest they would collect after a 15 month period.
Just so everyone is clear, my assignment has already been graded, so any critiques or changes would NOT be helping me complete my homework, but ONLY to help me understand what I did wrong and how I can fix it for future assignments. I received a 90% on my program for my grade.
The following comments were made about my assignment:
"Your setInterest method was to be a class method not an instance
method. Also, your call should have been
IWUnit4Ch13Investor.setInterest(rate);"
I'm not exactly following what I did wrong or how I can fix it. Can someone please show me what I did wrong and possibly explain why it's wrong so that I may correct my habits for future assignments and grasp how to correctly write code?
// IWUnit4Ch13.java
import java.util.*;
import java.util.Scanner;
// main class
public class IWUnit4Ch13 {
public static void main(String[] args) {
// Declares local variables
double rate, INTEREST_RATE;
// Instantiate investor1 & investor2 objects using a two parameter constructor
IWUnit4Ch13Investor investor1 = new IWUnit4Ch13Investor(1001, 2000);
IWUnit4Ch13Investor investor2 = new IWUnit4Ch13Investor(2001, 4000);
Scanner input = new Scanner(System.in);
// Receives the APR by the user
System.out.print("Please enter the APR in the form of .05 for 5%: ");
rate = input.nextDouble();
// Moves the decimal 2 places to the left (used later)
INTEREST_RATE = rate * 100;
// Sets the interest rate using a class variable
investor1.setInterestRate(rate);
investor2.setInterestRate(rate);
// Prints the header for the table
System.out.printf("Monthly balances for one year with %.2f annual interest:\n\n", rate);
System.out.println("Month Account # Balance Account # Balance");
System.out.println("----- --------- ------- --------- -------");
// Loop that prints each month on the table
// Uses class variables to add interest and get balance for display
for (int i = 1; i <= 15; i++) {
investor1.addInterest();
investor2.addInterest();
System.out.printf("%5d %9d %9.2f %9d %9.2f\n", i, investor1.getACCOUNT_NUMBER(), investor1.getBalance(), investor2.getACCOUNT_NUMBER(), investor2.getBalance());
}
// Prints the calculated interest earned by both investors
System.out.printf("\nInvestor1 earned : %.2f", investor1.getInterest());
System.out.printf(" interest in 15 months at %.2f", INTEREST_RATE);
System.out.print("%\n");
System.out.printf("Investor2 earned : %.2f", investor2.getInterest());
System.out.printf(" interest in 15 months at %.2f", INTEREST_RATE);
System.out.print("%\n\n");
} // end of internal main
} // end of main class
// Creates IWUnit4Ch13Investor.java which is used in IWUnit4Ch13.java
public class IWUnit4Ch13Investor extends IWUnit4Ch13 {
// All variables are declared private
private static double interestRate; // class variable
private final int ACCOUNT_NUMBER; // declare constant ACCOUNT_NUMBER
private double balance; // instance variable called balance
private double initialBalance; // to hold the initial balance
private double interest; // to count how much interest was made
private double INTEREST_RATE; // used to convert the float interestRate to int
// Two parameter constructor to initialize account number and balance
public IWUnit4Ch13Investor(int acctNum, double initialBalance) {
this.initialBalance = initialBalance;
this.ACCOUNT_NUMBER = acctNum;
balance = initialBalance;
}
// To return the balance to parent
public double getBalance() {
return balance;
}
// Class method to set the annual interest rate
public void setInterestRate(double rate) {
interestRate = rate;
}
// Method to add interest based on balance * interestRate / 12
public void addInterest() {
balance += balance * interestRate/12.0;
}
// To get account number in parent
public int getACCOUNT_NUMBER() {
return ACCOUNT_NUMBER;
}
// Used to get the amount of interested earned during 15 months
public double getInterest() {
interest = balance - initialBalance;
return interest;
}
} // end of class
Thank you all in advance for your help.
Terms
First of, please don't confuse terms. A variable is different to a method:
// A class
public class Dog {
// Member variable
private String name;
// Method
public void bark() {
// Variable
String textToBark = "Wuff";
// Call to a method
System.out.println(textToBark);
}
}
Elsewhere:
// Creating a new instance of class "Dog"
// and saving a reference to it inside a variable
Dog bello = new Dog("Bello");
Explanation
Your teacher said he wants the setInterest to be a class method instead of an instance method. What he wants to say with that is that it should be declared static and thus not belonging to instances of the class but to the class itself. Here is more on what static means for methods: Java: when to use static methods
Solution
So the method should look like this:
// Method to set the annual interest rate
public static void setInterestRate(double rate) {
IWUnit4Ch13Investor.interestRate = rate;
}
Where interestRate then also needs to be declared static (which you already did):
// To count how much interest was made
private static double interestRate;
To indicate the access of static variables one should add the class name before, so instead write it like this:
// Method to add interest based on balance * interestRate / 12
public void addInterest() {
balance += balance * IWUnit4Ch13Investor.interestRate / 12.0;
}
The same holds for calling static methods, instead of
investor1.setInterestRate(rate);
investor2.setInterestRate(rate);
do this
IWUnit4Ch13Investor.setInterestRate(rate);
Due to the nature of static you then also need to set this only once since static variables are shared by all instances of that class.
So a static variable is shared by all instances of the class.
If you want all investors to be forced to share the same interest rate, use a static variable.
Methods that only affect static variables should (https://www.ietf.org/rfc/rfc2119.txt) be declared static:
public static void setInterestRate(double rate) {
interestRate = rate;
}
private static double interestRate;
You would then call the static method by specifying the class name, not the instance variable. Note that you can call the static method before you even have any instances of the class, and you only need to call it once:
Investor.setInterestRate(0.05);
Investor i1 = new Investor();
Investor i2 = new Investor();
double r1 = i1.calculateBalance();
double r2 = i2.calculateBalance();
If you want each investor to be able to have different interest rates, do not use a static variable, use a member variable and method:
public void setInterestRate(double rate) {
interestRate = rate;
}
private double interestRate;
You then call the method by specifying the instance variable:
Investor i1 = new Investor();
Investor i2 = new Investor();
i1.setInterestRate(0.04);
i2.setInterestRate(0.06);
double r1 = i1.calculateBalance();
double r2 = i2.calculateBalance();
Also, none of that really matters because the output is wrong:
double monthly_rate = pow(10.0, log10(1.0 + yearly_rate) / 12.0) - 1.0;
The system shall not fail

How can i use field inside method?

to begin with, this is my first question in here.
I want to use double mebleg inside transfer method, and I has equaled mebleg to balance in constructor, but unfortunately, the amount of parameter of balance doesn't go with mebleg into transfer method. how can I solve this problem?
I am new at programming. that's why if my question was answered, could you suggest that links of answers?
class Acount {
static double mebleg;
public static void main(String[] args) {
Acount a = new Acount(100);
Acount b = new Acount(0.0);
Acount c = new Acount(0.0);
Acount.transfer(a, b, 50);
Acount.transfer(b, c, 25);
}
public Acount(double balance) {
mebleg = balance;
}
public static void transfer(Acount from, Acount to, double howMuch) {
System.out.println(Acount.mebleg - howMuch);
}
}
You should not make the field static if you want to use it for instances. If you change that, your transfer() method should use from.mebleg (or a associated getter).
double mebleg;
public Account(double initialBalance) { mebleg = initialBalance; }
public static void transfer(Acount from, Acount to, double howMuch)
{
from.mebleg -= howMuch;
to.mebleg += howMuch;
}
(Not discussing various existing issues like transactions, concurrency, error handling and usage of double for monetary units here).

Calling a method, but won't return the values. Java

So I have an assignment where I have to make a bank account. Long story short I have a class that has your actions (deposit, withdraw etc) in methods, and a Driver which would fills in the blanks (i.e client name, balance etc.) as well it calls the methods from the other class.
Now my issue. For an example, when I deposit, my variables send fine to the method and do the math correctly and have the correct balance, but returning the balance's new value is an issue. It is still the same value it was before in the driver.
This is my driver's deposit code
String deposit1 = JOptionPane.showInputDialog ("How much would you like to deposit?");
int deposit = Integer.parseInt (deposit1);
myBank.getDeposit(deposit, balance);
This is my deposit method code
public void getDeposit(int deposit, int balance)
{
if (deposit<0)
{
System.out.println ("Invalid Number");
deposit=0;
}
balance =balance + deposit;
}
Any help would be greatly appreciated, can't seem to find any solutions and I've been stuck for some time
Thanks
P.S This is my first time on these forums so sorry if I did anything wrong
P.P.S My java knowledge isn't that high, still just a beginner
Edit:
We have learned instance variables as well as touched a little upon return statements, we haven't learned anything about passby. By return I mean giving the driver the correct value, sorry if that threw you off
Edit2: Thank youuu so much user1710742, finally got it. I understand now. Makes sense
The problem is you are attempting to change a copy of the variable, not the exact one that you gave to the method. When you exit the method, the copy is destroyed, and you are left with just the unchanged original value.
The method can't return a value unless you tell it to with a return statement.
public int getDeposit(int deposit, int balance)
{
if (deposit<0)
{
System.out.println ("Invalid Number");
deposit=0;
}
return balance + deposit;
}
call with:
int total = myBank.getDeposit(deposit, balance);
You can add a new variable call dep with int data type :
int dep = myBank.getDeposit(deposit, balance);
after that change your method type from void to int and add return statement of variable that you want :
public int getDeposit(int deposit, int balance)
{
if (deposit<0)
{
System.out.println ("Invalid Number");
deposit=0;
}
balance =balance + deposit;
return balance;
}
start with the basics of the language. Yet, Keep in mind that understanding the problem is the only true way to reach the right solution. Don't let the language get in the way of the logic. You'll get the syntax down fast enough. You've got a good start. It's easy to get drawn into just finding A solution, instead of finding THE solution. The method of solving the problem is more important than having an answer. Try the link below for the basics on the return value.
http://www.homeandlearn.co.uk/java/java_methods.html
You should not name your method getDeposit() since the return type is void. Instead, just name it deposit(), because you actually do an action.
Use a private instance variable named balance, in your Bank class.
Use a getter for your balance field.
This snippet should work:
public class BankAccount {
private int balance;
public static void main(String[] args) {
BankAccount account = new BankAccount();
String deposit = JOptionPane.showInputDialog ("How much would you like to deposit?");
account.deposit(Integer.parseInt (deposit));
deposit = JOptionPane.showInputDialog ("How much would you like to deposit?");
account.deposit(Integer.parseInt (deposit));
System.out.println(account.getBalance());
}
public void deposit(int deposit){
if (deposit < 0){
System.out.println ("Invalid Number");
}else{
balance += deposit;
}
}
public int getBalance(){
return balance;
}
}
I am not totaly sure if you are actually doing what you want to do..
To me, it seems like you want to create a class called Bank and have a private variable there, called ballance. then methods for manipulating that value..
public static class Bank{
private int balance = 0;
// this method won't return any value. it will only change
// the banks internal state, therefor we write "void"!
public void deposit(int deposit){
if(deposit<0){
// using System.err instead of System.out will be handled differently
// by java. It is meant to be used for error messages. some consoles make
// these texts pop out more (like displyaing it in read)
System.err.println ("Invalid Number");
}else{
// balance += deposit is a short way of writing balance = balance + deposit;
balance += deposit;
}
}
// this method will return an int value to who ever called it.
// you can tell, because it says int after public
public int getBalance(){
return balance;
}
}
And then a main method which handles the bank:
Bank bank = new Bank();
bank.deposit(5);
bank.deposit(8);
int balance = bank.getBalance(); // will be 13
System.out.println("balance is "+balance);
More on System.err can be found in the oracle docs about System
Hope I could help

Categories