I'm learning Java on Codecademy and recently completed a project that calculates monthly payments for a car loan. The problem is that I don't understand the solution, and no one has responded to my question about it on the Codecademy forum.
Why are the instance variables created in the main method scope instead of just after the class has been declared? We haven’t seen any examples of this prior to this project and I don’t understand.
Here is the code:
//Calculates monthly car payment
public class CarLoan {
//Why aren't the variables created here rather than in the main method?
public static void main(String[] args) {
int carLoan = 10000;
int loanLength = 3;
int interestRate = 5;
int downPayment = 2000;
if (loanLength <=0 || interestRate <=0) {
System.out.println("Error! You must take out a valid car loan.");
} else if (downPayment >= carLoan) {
System.out.println("The car can be paid in full.");
} else {
int remainingBalance = carLoan - downPayment;
int months = loanLength * 12;
int monthlyBalance = remainingBalance / months;
int interest = (monthlyBalance * interestRate) / 100;
int monthlyPayment = monthlyBalance + interest;
System.out.println(monthlyPayment);
}
}
}
Variables defined within a method are local variables, they belong to an invocation of the method, not to an instance of an object.
The intent seems to be to provide an example that is understandable to beginners who haven't been introduced to constructors, instance variables, and methods. They want to teach local variable declaration, some simple calculating and if-statements, and printing to the console before getting into that other stuff.
As an exercise it would be fine for you to change the CarLoan class to give it instance variables, just to see another way to do it. Keep the variable values hard-coded, make an instance method that calculates the monthly payment, and have the main method print the result to the console.
Related
So I created Saving class, created also setters and getters. Now I need u method, which will calculate the total amount of deposits.
public class Saving {
private double deposits;
private double totalAmountOfDeposits;
public double getDeposits()
{
return deposits;
}
public void setDeposits(double deposits)
{
this.deposits = deposits + deposits;
}
public double getTotalAmountOfDeposits()
{
double total = 0;
return total = total + deposits;
}
}
When I use this class in the program I got a wrong calculation. The program just add first value of deposit to the first value.
import java.util.Scanner;
public class SavingDemo {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Saving save = new Saving();
System.out.println("Deposit amount");
double depositeAmount = input.nextDouble();
save.setDeposits(depositeAmount);
System.out.println("Deposit amount");
double depositeAmount2 = input.nextDouble();
save.setDeposits(depositeAmount);
System.out.println("Deposit amount");
double depositeAmount3 = input.nextDouble();
save.setDeposits(depositeAmount);
System.out.println("The total amount has been deposited is " + save.getTotalAmountOfDeposits());
}
}
And here is the output:
Deposit amount
12
Deposit amount
34
Deposit amount
56
The total amount has been deposited is 24.0
As you can see its just added 12 to 12. Just want to mention that I'm totally new in programming. Les than a month.
I see two problems in your code. Take a look at the commented line. The reason you are seeing 12 + 12 is because that is exactly what you are instructing the JVM to do.
System.out.println("Deposit amount");
double depositeAmount = input.nextDouble();
save.setDeposits(depositeAmount);
System.out.println("Deposit amount");
double depositeAmount2 = input.nextDouble();
save.setDeposits(depositeAmount); // <= adds the wrong variable
System.out.println("Deposit amount");
double depositeAmount3 = input.nextDouble();
save.setDeposits(depositeAmount); // <= adds the wrong variable
System.out.println("The total amount has been deposited is " + save.getTotalAmountOfDeposits());
Secondly, it looks like you may have a design flaw in your implementation of the Saving class.
You'll want to brush up on variable scope
If you take a look at your implementation on your total:
public double getTotalAmountOfDeposits()
{
double total = 0;
return total = total + deposits;
}
You have the total starting at 0 every time this method getTotalAmountOfDeposits() is called. the total variable in this method is local to it's method. So what you currently have is a method variable
You'll want to do some research into class variable. This will maintain that the instance of the object will have this variable assigned through the life cycle of the instantiated object.
When you have variables of the same name, you can get the instance variable with this keyword.
So when dealing with your setter
public void setSomething(double something) {
this.something // class variable
something // method variable
}
If you want your object to maintain state, you can set it on your object itself, and have your set deposit modify that state. Some pseudo code to get you moving forward.
public class Saving {
private double totalAmountOfDeposits; // you can modify this value with public methods
public void setDeposit(_) {
// Setter implementation
// increment totalAmountOfDeposits;
public double getTotalAmountOfDeposits(_)
// return totalAmountOfDeposits;
}
You should write a method
public void addDeposits(double deposits)
{
this.deposits = this.deposits + deposits;
}
and change setDeposits to
public void setDeposits(double deposits)
{
this.deposits = deposits;
}
after this call addDeposits to add deposits
To eliminate confusion within the Saving Class change the argument name for the setDeposits() method to double newDeposit instead of double deposits which is also a class field name. Although the construct is legal it does make it a wee bit confusing. Inside the setDeposits() method use:
this.deposit+= newDeposit;
As a matter of fact, you can get rid of the deposits field altogether since you also have the field named totalAmountOfDeposits. Use that instead:
this.totalAmountOfDeposits+= newDeposit;
You might also want a clearDeposits() method in your Saving Class:
public void clearDeposits() {
this.totalAmountOfDeposits = 0.0;
}
Your getTotalAmountOfDeposits() method within the Saving Class doesn't really make any sense either. Since you are always summing deposits anyways you can just return what is held within the totalAmountOfDeposits field:
public double getTotalAmountOfDeposits() {
return totalAmountOfDeposits;
}
The above method is would now of course be very mush the same as the getDeposits() method which could be changed to getTotalDeposits(). You can then change the getTotalAmountOfDeposits() method name to getTotalNumberOfDeposits() and add a additional class field named numberOfDeposits:
private double totalAmountOfDeposits;
private int numberOfDeposits = 0;
public double getTotalDeposits() {
return totalAmountOfDeposits;
}
public int getTotalNumberOfDeposits() {
return numberOfDeposits;
}
and in your setDeposits() method add the code line:
numberOfDeposits++;
So that it would look something like:
public void setDeposits(double newDeposit) {
totalAmountOfDeposits+= newDeposit;
numberOfDeposits++;
}
If you do add a clearDeposits() method to your Saving Class then don't forget to add the code line: numberOfDeposits = 0; into that method as well. It might now look something like:
public void clearDeposits() {
totalAmountOfDeposits = 0.0;
numberOfDeposits = 0;
}
You also have some issues within your main() method of your SavingDemo Class. Take a real close look at each call you make to the setDeposits() method for each value the User supplies. Each User supplied value goes into a specific double type variable name. Is that what you are passing to the setDeposits() method? ;)
Once you've got all that taken care of you can display to console:
System.out.println("The total amount has been deposited is " +
save.getTotalDeposits() + " by making " +
save.getTotalNumberOfDeposits() + " deposits.");
I need to write a program and, in one step of it, I need to construct a function that calculates the number of rabbits.
The problem is that Eclipse shows a message saying that the variable I created "cannot be resolved to a variable" and I don't understand why it happens. Can someone help me?
Here is part of my code
I am showing all my code because it would get bigger and it is not needed, in order to solve this problem
class Rabbits {
static int nbRabbits = initRabbits; // ERROR HERE!!!!!!!!!!!!!!!!!!!!!!!!!!
static int nbFoxes = initFoxes; // ERROR HERE!!!!!!!!!!!!!!!!!!!!!!!!!!
int rabbits = 0;
public static int calculateRabbits(int rabbits, int foxes, double AttackRate) {
for (int i = 0; i < Duration; ++i) {
rabbits = nbRabbits;
nbRabbits *= (1.0 + Rabbits_growth_rate - AttackRate * nbFoxes);
}
return nbRabbits;
}
public static void main(String[] args) {
Scanner keyb = new Scanner(System.in);
// Enter initial population
int initFoxes = enterPopulation("foxes", 2, keyb); //at least 2 foxes
int initRabbits = enterPopulation("rabbits", 5, keyb); //at least 5 rabbits
// SOME MORE CODE HERE
} // end main
} // end of class
initRabbits and initFoxes are variables entered by the user when I call enterPopulation method.
I'm new to Java and, unfortunately, I cannot change the logic of this code. For example, I cannot put the calculateRabbits method inside the main neither change the begin or the end of the code.
initRabbits only exists within the main method. That is it's scope.
You are attempting to statically reference something it can't see. You are attempting to populate nRabbits before a value for innitRabbits exists. This is impossible.
Your trying to assign a value to your nb variables from a variable that hasn't been created yet. Skip making four variables and just assign the nbs to 0 outside of your main class, then give them the value you want inside it. They will then retain that value outside of the main class and be visible.
static int nbRabbits = 0;
static int nbFoxes = 0;
//in main class
nbFoxes = enterPopulation("foxes", 2, keyb); //at least 2 foxes
nbRabbits = enterPopulation("rabbits", 5, keyb); //at least 5 rabbits
I am having issues with the output of my code. Seems I am missing something in my method that I created... I had instructions to return the total number of inches. I places totInches after return and get an error stating that totInches is not a variable. Not certain what is missing here as I am only supposed to be creating a method. Most of this code was written and the only portion I was supposed to created was the second convertToInches method.. Any advice?
import java.util.Scanner;
public class FunctionOverloadToInches {
public static double convertToInches(double numFeet) {
return numFeet * 12.0;
}
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
public static void main (String [] args) {
double totInches = 0.0;
totInches = convertToInches(4.0, 6.0);
System.out.println("4.0, 6.0 yields " + totInches);
totInches = convertToInches(5.9);
System.out.println("5.9 yields " + totInches);
return;
}
}
The variable totInches is not defined in the scope of your function:
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
The only variables you can use in this function are the ones you create and the ones defined as formal parameters: numFeet and numInches. So you have to come up with an equation that takes numFeet and converts it to inches, taking into account the additional inches provided in numInches.
You declared the double variable "totInches" inside of your main method, but you are trying to access it inside of your "convertToInches" method. When declaring a variable in a particular method, that variable is ONLY accessible by that method. Your "convertToInches" knows of only two variables: numFeet and numInches, which you passed to it in the parameter. It then looks at your return statement, sees "totInches" and has no idea what it is.
I also don't understand what this is trying to do...
public static double convertToInches(double numFeet, double numInches) {
return totInches * 12.0;
}
Why are you passing it the double variables numFeet and numInches? The function isn't using them. I also don't understand why you need both the number of feet AND the number of inches if the method, by its name, is trying to convert something into inches.
public static double convertToInches(double numFeet, double numInches) {
return (numFeet * 12) + numInches;
This takes into account any variable amount entered by user for height of 5 feet 7 inches or 6 feet even
So I am trying to write a simple program for my Java class and I have asked the teacher for help however, this is a distance learning class and am not getting much help from that direction. So here I am.
The problem we have been asked to solve is to create a program that will
(1) ask the user for a number ,
(2) find the sum of all user defined numbers ,
(3) find the average of these numbers ,
(4) then out put them back to the user.
I use the numbers not only to line through things I have finished but because they must be separate modules to be called.
How can i get the userNum variable to update durring the while statments. Currently they are not. OR is there a simpler way to do this that im overlooking. Any help is greatly appreciated. Thank you.
public class P2 {
public static void main(String[] args) {
int userNumCount = 1;
double userNum = input();
double userSum = sum(userNum);
double userAverage = average(userSum, userNumCount);
sum(userNum);
while (userNum != 0 && sum(userNum) <= 100){
++userNumCount;
output(userSum, userAverage);
input();
sum(userNum);
average(userSum, userNumCount);
}//end else
while (userNum != 0 && sum(userNum) >=100){
++userNumCount;
JOptionPane.showMessageDialog (null, "Warning, your sum is currently over 100!!!!!");
output(sum(userNum), userAverage);
input();
sum(userNum);
average(userSum, userNumCount);
}//end else
if (input() == 0){
output(userSum, userAverage);
JOptionPane.showMessageDialog (null, "Thank you for using this program have a nice day.");
}//end else if
}//end main module
public static double input(){
String userNumString;
userNumString = JOptionPane.showInputDialog("Please enter your number or input 0 to end the program.");
double userInput = Double.parseDouble (userNumString);
return userInput;
}//end input module
public static double sum(double userNum){
double userSum =+userNum;
return userSum;
}//end sum module
public static double average (double userSum, int userNumCount){
double userAverage = userSum/userNumCount;
return userAverage;
}//end average module
public static void output (double userSum, double userAverage){
JOptionPane.showMessageDialog (null, "The sum of the numbers input so far is: " + userSum + ". And the Average is " + userAverage + "." );
}//end output module
}//end class
All of the values returned from methods in your main are just returning their values to nothing. When you pass variables to a function, they are passed by value. For example:
public void main(String args[]){
int f = 5;
doSomething(f);
System.out.println(f);
}
public int doSomething(int i){
i+=1;
return i;
}
The value returned by doSomething is 6, but the program outputs 5. When you call a function the int i is recreated independently of f. As of now, your program is just throwing those values away and keeping the old ones.
Also you have the variables in main called userSum, and userAverage, and in sum and average you redefine these in a different scope. When code flow comes into sum and average it creates new variables for that method. If you want these values to be the same you need to make them static, by defining them outside of your main method and declaring them static.
I think the problem you might be struggling with is scope. Pretty much every time you have an opening bracket the program changes scope. When a block is closed (when there is a closing bracket}, the scope of the variables ends, ie. they don't exist anymore. For example:
class someClass
{
//Block 0
static int staticNum = 0;
public static main(String args[])
{
//Block 1
int level1 = 0;
if(true)
{
//Block 2
int level2 = 0;
} else {
//Block 3
level1++; //ok because the level1 is accessible from here
staticNum++; //ok because staticNum is static
}
//resume block 1
level2++; //not ok because level2 was in a different scope
doSomething(level1)
}
public static void doSomething(int i){
//Block 5
int level1 = 0; //different than the one in the main method
i++; //ok but once execution leaves i wont exist anymore
staticNum++; //ok because staticNum is static and exists in the class's scope
level1++; //not ok because level1 is not defined for this scope
}
}
While execution is in a block, it can access any variable in blocks 'above' it in nesting level. Looking at the above, in Block 2 and 3 you can access anything in block 1 or block 0. Block 3 doesn't have access to the variables in block 2 because they are out of scope of one another, because when a block closes all variables instantiated in that block are freed. Block 5 has a completely different scope than block 1,2 and 3.
Block 0 is special because it is associated with the class. Anything outside of method bodies declared static are class wide variables, as in you can access it where ever you have access to the class. You would use something like ClassName.staticNum to access it in another class. Also when you access it inside of the class, any methods that you use the static values in need to be declared static as well.
Anything not declared static in the class body is an instance variable. It is associated with an instances of the class, these instances called objects. A class defines the template of an object. For example, lets say we have two objects of type Computer. The class Computer defines what variables each individual computer has(instance variables), and what variables every computer shares(static variables). So if I have Computer A with instance variables mouse and keyboard, it is completely different from another Computer B instance variables mouse and keyboard, but they can share a static variable called Computer.innernette.
This is incorrect.
public static double sum(double userNum){
double userSum =+userNum;
return userSum;
}
In a basic pseudo-language this is happening each time this method is called
receive userNum
create userSum
set userSum = 0
add userNum to userSum
give userSum
each time the method will return the value it is given, not the running total I think you are expecting.
If you have two variables declared with the same name, they are still different. What you want to do is refer to the same variable, to do this you need to have the references in the scope where the variable is declared.
to get the running total
public class P2 {
public static double userSum = 0;
//because this is a public member it's scope is global i.e. you can refer to it anywhere.
...
public static void main(String[] args) {
...
/* do not declare userSum here.
if you do any reference to userSum will use the local variable
not the global variable.
double userSum = 0; <-- declare local variable it's scope is until the
end of this method nothing outside the method
can see it but you can pass it as a parameter
userSum = 1; <-- local variable is set to 1
P2.userSum = 2; <-- local variable is set to 1 global is set to 2
*/
input();// for this the input method is called and returns a value,
// but you haven't said to put it anywhere so java will throw it away
// all that effort for nothing.
userNum = input(); // in this case it will put the new value in userNum.
}
public static double sum(double userNum){
userSum =+userNum; // do not declare userSum use it from the class context
return userSum;
}
...
}
for further reference scope
In my do while loop, the body works fine initially, but when it loops, it prints the first two statements like it should but it does not allow me to enter the name instead it goes straight to enter pin and whatever I enter it skips the rest and asks me if I want another transaction.
I have an array object partially filed. The variables in the object are name, pin, account number and balance. When I add a new object and set the balance, the new balance I enter causes the balance for the previous objects to change as well. I think it has something to do with the balance variable being declared as static but I don't make it static, i can the error "Cannot make a static reference to the non-static method withdraw(double) from the type CustomerRecord". (SOLVED) Thank you.
public class BankCustomers
{
public static void main(String[] args)
//------------------------------------------------
//Part4: Find a customer record from anotherArray
//to do transaction(s) and update the record's balance
char repeat; // User control to repeat or quit
Scanner keyboard = new Scanner(System.in); //creating the scanner
String aName;
int aPin;
double aWithdraw;
double aDeposit;
do{
//Read customer information before search
System.out.println();
System.out.println("Lets make a transaction");
System.out.println("Enter customer full name");
aName = keyboard.nextLine( );
System.out.println("Enter Pin");
aPin = keyboard.nextInt();
//Search an Array for equal aName and aPin
for (int i = 0; i < index; i++)
{
CustomerRecord cRecord = anotherArray[i];
if((cRecord.getName().equalsIgnoreCase(aName)) && (cRecord.getPin() ==(aPin)))
{
System.out.println(cRecord);
System.out.println("Enter Withdraw Amount");
aWithdraw = keyboard.nextDouble();
CustomerRecord.withdraw(aWithdraw);
System.out.println("Enter Deposite Amount");
aDeposit = keyboard.nextDouble();
CustomerRecord.deposit(aDeposit);
System.out.println(cRecord);
}
}
System.out.println("\nAnother Transaction? (y for yes)");
repeat = keyboard.next().charAt(0);
}while(repeat == 'y' || repeat == 'Y');
//Print the records on screen
for (int i = 0; i < index; i++)
System.out.print(anotherArray[i]);
}
Remove the static from
private static double balance
and
public static void deposit(double aDeposit)
and
public static void withdraw(double aWithdraw)
you don't want them to be static as you are going to call these methods directly from the objects you created, so they will be specific to each CustomerRecord.
Then in your code, change these lines:
CustomerRecord.deposit(aDeposit);
CustomerRecord.withdraw(aDeposit);
by:
cRecord.deposit(aDeposit);
cRecord.withdraw(aDeposit);
The modifications made now will be applied to each CustomerRecord balance variable and not to a single balance variable (unique for the whole program) as it was the case when it was static.
public class CustomerRecord implements Serializable
{
private String name;
private int pin;
private int account;
private double balance;
}
public void deposit(double aDeposit)
{
balance = balance + aDeposit;
}
public void withdraw(double aWithdraw)
{
if (balance >= aWithdraw) balance = balance - aWithdraw;
else System.out.println("Withdraw cannot be negativeegative");
}
Make balance non-static, as you mentioned. This will fix the bug.
Make the CustomerRecord#deposit() and #withdraw() methods non-static as well. This will fix the compile error caused by #1.
You're correct that the problem is that you made things static. None of balance, deposit, withdraw should be static because all of them are things that apply to a particular customer record rather than to all customer records simultaneously.
The fact that your code doesn't work when you don't make them static is related to the way in which you're calling the withdraw method: CustomerRecord.withdraw(aWithdraw). Can you see what's wrong with that, now that your attention is drawn to it?
In your instance variables for CustomerRecord you have balance declared as a static variable.
This means that anytime you change balance in one instance of the class that it will change in all instances. For example, the deposit and withdraw methods.
I assume you needed to make balance static in order for these two methods to work, but you should just take the static declaration out of all three. Then, you need to change all calls from
CustomerRecord.withdraw();
CustomerRecord.deposit();
to use an instance of a class rather than just the static class. So,
// Whatever values you want here, you seem to have 4 already declared so you can use those
CustomerRecord c = new CustomerRecord("", 0, 0, 0);
c.withdraw();
c.deposit();
Your problem is twofold:
First, balance istatic, which means it is associated with the class, not any of its instances (objects), or in other terms it is shared between all instances of that class.
Second, as you pointed it out, your static method withdraw is accessing balance. The consideration about static applies here just as well -- the method is associated with the class, and cannot access memebers that are non-static.
To solve the second problem, remove static from the withdraw declaration (and remove static from balance as well. Thyis will make your code CustomerRecord.withdraw() not compile, becuase withdraw is now not associated with the class itself, but an instance of it. So you need to use an instance and call withdraw on that
cRecord.withdraw(aWithdraw);
Similarly for deposit