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).
Related
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.)
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
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
Hi and thanks for at least visiting.
I promise I've checked every question that's seemed relevant to what I need to do. I've tried every solution on the site and most on Google.
What I'm attempting to do is create a personality quiz that matches you to a certain trait. The desired program result is that the highest matched trait will display first. After the person tests, calculations are done to see what percentage a person is of each trait and that percentage is stored in doubles.
So I'm trying to order or sort an arraylist of objects based on this double. I've tried various strategies, but I'll give you the current two:
With Comparable
public static class results implements Comparable<results>
{
private double rPercent; //I've tried public and just leaving it double
public results(double percent)
{
this.rPercent = percent;
Percent*=100;
System.out.printf("You are %.2f," percent);
System.out.println();
}
public double getPercent()
{
return rPercent;
}
public int CompareTo(results Percent)
{
double p1 = (results Percent).getX();
double p2 = this.X - p1;
return (int)p2;
}
}
public static void main(String[] args) throws Exception
{
ArrayList<results> sortList = new ArrayList<results>();
sortList.add(new results(prcTrait1));
sortList.add(new results(prcTrait2));
sortList.add(new results(prcTrait3));
Collections.sort(sortList);
results beginResults = sortList.get(0);
results beginResults = sortList.get(1);
results beginResults = sortList.get(2);
//It prints out the traits in their original order. Always.
}
That's one solution I saw.
Then this is another thing I'm trying:
With Comparater
public class personalityQuiz
{
public double newPercent;
//. . .
public static class results
{
personalityQuiz v = new personalityQuiz();
//v for variable
//That and I wanted it to be short because I would be using it alot.
public results(double percent)
{
v.newPercent = percent;
percent*=100;
System.out.printf("You are %.2f", percent);
System.out.println();
}
}
public double getPercent
{
double xPercent = newPercent;
return xPercent;
}
public static void main(String[] args) throws Exception
{
ArrayList<results> sortList = new ArrayList<results>();
sortList.add(new results(prcTrait1));
sortList.add(new results(prcTrait2));
sortList.add(new results(prcTrait3));
Collections.sort(sortList, new Comparator<results>()
{
public int compare(results p1, results p2)
{
personalityQuiz v = new personalityQuiz();
double newP1 = p1.v.getPercent();
double newP2 = p2.v.getPercent();
if(newP1 < newP2)
{
return 1;
}
else if(newP2 < newP1)
{
return -1;
}
else
{
return 0;
}
});
results beginResults = sortList.get(0);
results beginResults = sortList.get(1);
results beginResults = sortList.get(2);
//still prints them in their original order
}
}
I apologize for the probable various mistakes in execution there.
I'm somewhat self-learning Java right now and what I know was basically self-taught as well.
Anyway, any help would be amazing.
And I'll try to be around to respond to any comments or answers quickly ^^~
In your first example, I think you missed a few things (and results should be Results, also CompareTo should be compareTo) -
public static class Results implements Comparable<Results>
{
private double rPercent; //I've tried public and just leaving it double
public Results(double percent)
{
this.rPercent = percent;
percent*=100;
System.out.printf("You are %.2f%n", percent);
}
public double getPercent()
{
return rPercent;
}
#Override
public int compareTo(Results result)
{
return new Double(getPercent()).compareTo(result.getPercent());
}
}
In your compare method, try Double.compare(double x, double y).
EDIT: Elliott Frisch expanded on that
I'm going to be honest and say some of your code was hard to follow, it would be beneficial for you to learn the 'standards' of the Java programming language, such as classes always starting with a capitol letter etc..
In your first example, the reason they were always coming out in the same order is probably because of a rounding error. When you're converting a double to a integer, it was most probably less than 1 (but greater than 0) in magnitude. Hence it was being rounded down (or up) to 0. Meaning that the collections API was not sorting them as there were being seen as 'equal'.
Your second example I was not able to follow, sorry.
-Thomas
Could someone look at the portion of my code where I'm trying to void and close an account? This is what I want to achieve:
"2. Add a method void close() to your Account class. This method should close the current account by appending “CLOSED” to the account name and setting the balance to 0. (The account number should remain unchanged.) Also decrement the total number of accounts."
When I tried to compile it, the program gave me an error about an identifier being expected. What am I missing?
//*******************************************************/
// Account.java
//
// A bank account class with methods to deposit to, withdraw from,
// change the name on, and get a String representation
// of the account.
//*******************************************************/
public class Account
{
private double balance;
private String name;
private long acctNum;
//----------------------------------------------
//Constructor -- initializes balance, owner, and account number
//----------------------------------------------
public Account(double initBal, String owner, long number)
{
balance = initBal;
name = owner;
acctNum = number;
}
//----------------------------------------------
// Checks to see if balance is sufficient for withdrawal.
// If so, decrements balance by amount; if not, prints message.
//----------------------------------------------
public void withdraw(double amount)
{
if (balance >= amount)
balance -= amount;
else
System.out.println("Insufficient funds");
}
//----------------
//Track how many accounts
//----------------
private static int numAccounts=0;
{
numAccounts++;
}
public static int getNumAccounts()
{
return numAccounts;
}
//----------------------------------------------
// Adds deposit amount to balance.
//----------------------------------------------
public void deposit(double amount)
{
balance += amount;
}
//----------------------------------------------
// Returns balance.
//----------------------------------------------
public double getBalance()
{
return balance;
}
//----------------------------------------------
// Returns account number.
//----------------------------------------------
public long getAcctNumber()
{
return acctNum;
}
//----------------
//Void and close the accounts
//----------------
public void close(Account)
{
balance = 0;
name = "CLOSE";
acctNum = number;
numAccounts--;
return Account;
}
//----------------------------------------------
// Returns a string containing the name, account number, and balance.
//----------------------------------------------
public String toString()
{
return "Name: " + name +
"\nAccount Number: " + acctNum +
"\nBalance: " + balance;
}
}
public void close(Account) needs a variable name. The declaration says it takes an Account parameter, but you also need to give the parameter a name e.g. public void close(Account account).
Note that I don't think that makes much sense. Given an account object you should probably be able to close it, so perhaps you should reconsider whether that parameter makes sense.
There are few problems:
public void close(Account) << why do you have Account as a parameter (half parameter)?
{
balance = 0;
name = "CLOSE"; << This is assignment, not addition
acctNum = number; << where number came from
acctNum--;
return Account; << this is a void method, why do you return something?
}
It should look like that:
public void close()
{
balance = 0;
name += "CLOSE"; << adding "close" to current account name
acctNum--;
}
Another thing, acctNum is the total number of accounts, it shouldn't be related to a specific object, so it should be declared as static.
EDIT
Clarification regarding the account count and account number:
For each account, there should be an account number, let's say the first account has account number = 1 and the second account has account number = 2 etc. so we'll call this variable accountNumber and declare it as private variable:
private int accountNumber;
You also want to track the number of active accounts, right? So you create another variable which is not bounded to a specific account, but is related to all, and call it accountCount and you should declare it as static variable:
private static int accountCount = 0;
When you close an account, you want to decrease the account count and keep the count number, so your method should look like:
public void close()
{
balance = 0;
name += "CLOSE";
accountCount--; << we decrease the account count, not the specific account number
}
Would be best to go for
public void close() { ... }
you'd be calling it on an instance of the account class (like myAccount.close()) so it's going to be working on itself. Adding stuff you don't need is almost always a bad idea :)
You don't specify a parameter name.
Change it to
public void close(Account acct){
//...
}
public void close() {
...
}
I think they're expecting you to add a method with that signature.
Also, it says to append "CLOSED" to the name not "set" the name to "CLOSED".
I don't think you need to modify anything with the acctNum variable.
Those should be enough hints to complete this.
This line needs to be inside of a method rather than part of your class declaration:
{
numAccounts++;
}
Try making it:
public void incrementAccountNumber() {
numAccounts++;
}
You need to specify an argument name for your close() method:
public void close(Account account) { ... }
Further to the other answers, you've got an unknown variable number:
acctNum = number;
public void close(Account)
should have a variable name. Something like this:
public void close(Account account)
{
balance = 0;
name = "CLOSE";
acctNum = number;
acctNum--;
}