Java-OOP I keep on getting this strange output - java

I am currently taking Computer Science at school and I am a bit stuck on my lab.
The directions are listed below and we are required to use an OOP.
The problem is that my output that I get is super strange and I really don't know what is going on.
The output that I get after running the file DiscountRunner.java (code listed below) is:
Enter the original bill amount :: 4000
Discount#1d1be4e
Why do I keep on getting the Discount#1d1be4e part?
/**==================================================================================================
* Objective : This lab was designed to teach you how to use if statements.
* Lab Description : Determine the amount of discount a person should receive.
* If the bill is more than 2000, then the person should receive a 15% discount.
* If the bill is 2000 dollars or less, the person does not receive a
* discount of any kind.
===================================================================================================*/
import static java.lang.System.*;
import java.util.Scanner;
public class DiscountRunner
{
public static void main( String [] args )
{
Scanner keyboard = new Scanner(System.in);
out.print("Enter the original bill amount :: ");
int amt = keyboard.nextInt();
int Discount;
Discount bill=new Discount();
bill.getDiscountedBill();
System.out.println(bill);
//instantiate a new Discount object called "bill"
//print the output of bill.getDiscountedBill() with amt as the parameter
}
}
That is file one.
Here is file two.
import static java.lang.System.*;
import java.util.Scanner;
public class Discount
{
//instance variables and constructors could be used, but are not really needed
int amt;
int bill;
//getDiscountedBill() will return final amount of the bill
// if the bill is >2000, the bill receives a 15% discount
public int getDiscountedBill()
{
if ( amt>2000)
bill=amt*(int).85;
if ( amt<=2000)
bill=amt*1;
return bill;
}
}

System.out.println() method will try to convert a object to a string before printing it out. In order to do this it will normally call Object.toString() method. The default implementation of said method is to generate a string containing the object type concatenated with the in-memory address of the object. This is what is happening to you.
To fix it you need to provide a toString() implementation to the Discount method.

You get this because of this line:
System.out.println(bill);
You are printing the object which calls the default toString() implementation of Discount (inherited from Object). You can overwrite toString() in Discount to get a custom representation but I guess you just want to remove this System.out statement there.

You had some little mistakes of Type conversions and some in receiving value from method.
Find below the working code
import static java.lang.System.*;
import java.util.Scanner;
public class DiscountRunner
{
public static void main( String [] args )
{
Scanner keyboard = new Scanner(System.in);
Discount bill=new Discount();
out.print("Enter the original bill amount :: ");
bill.amt = keyboard.nextInt();
int discount;
discount=bill.getDiscountedBill();
System.out.println(discount);
//instantiate a new Discount object called "bill"
//print the output of bill.getDiscountedBill() with amt as the parameter
}
}
import static java.lang.System.*;
import java.util.Scanner;
public class Discount
{
//instance variables and constructors could be used, but are not really needed
int amt;
int bill;
//getDiscountedBill() will return final amount of the bill
// if the bill is >2000, the bill receives a 15% discount
public int getDiscountedBill()
{
if ( amt>2000)
**bill=(int)(amt*.85);**
if ( amt<=2000)
bill=amt*1;
return bill;
}
}
Let me know if you are not getting something.
Accept the answer if it solves your Problem.

You didn't override the toString() method in the Discount class which is inherited by the Java class Object. This causes the output you listed.

Whenever you pass a Object to System.out.println it executes its toString method, Default implementation of toString prints ClassName with its hashCode. you can override toString method. add below code snnipet to your Discount Class and it will run as per your expectation
#Override
public String toString()
{
return "Bill Amount After Discount is " + bill ;
}

Related

Tester not working due to construtor parameter problems with array list

Hope you guys can help me (I know this is alot im sorry)
below is my Customer class
import java.util.*;
public class Customer{
//fields
int id;
String firstName;
String lastName;
double lastYear;
ArrayList<Order> orderList = new ArrayList<>();
//4 arg constructor
public Customer(String fN,String lN,int i){
id=i;
fN=firstName;
lN=lastName;
this.orderList=orderList;
}
//toString method
public String toString(){
return "Customer Information:"+"First Name: "+ firstName +" Last Name: "+ lastName+ "ID code"+ id;
}
//AveragePayment method
public void AveragePayment(){
double total=0;
for(Order currentObj : orderList){
total=total+currentObj.getTotalCost();
}
double avgCost = total / orderList.size();
}
}
this is my Order.java class
public class Order{
//fields
double salesTaxRate;
double price;
double shippingCost;
double total;
double salesTax;
//1 arg constructor
public Order(double set1){
salesTaxRate=set1;
price=0;
shippingCost=0;
total=0;
salesTax=0;
}
//setPrice method
public void setPrice(double p){
price=p;
salesTax=salesTaxRate*price;
double subTotal=(price+salesTaxRate);
if(subTotal<50){
shippingCost=0.8*subTotal;
}
else{
shippingCost=0;
}
}
//getTotalCost method
public double getTotalCost(){
return total;
}
//setTotalCost
public void setTotal(double total){
this.total=total;
}
}
finally the tester
import java.text.NumberFormat;
public class Tester
{
public static void main(String[] args)
{
double avgPurchase;
Order[] lastYear = new Order[4];
// I bought most stuff in Pennsylvania but..
lastYear[0] = new Order(0.06);
lastYear[1] = new Order(0.06);
// I did send one thing to my mom in New York City and had to pay their sales tax...
lastYear[2] = new Order(0.09);
lastYear[3] = new Order(0.06);
lastYear[0].setPrice(57.93);
lastYear[1].setPrice(257.93);
lastYear[2].setPrice(100.30);
lastYear[3].setPrice(15.67);
Customer me = new Customer("Christian" , "Turner" , 12321, lastYear);
// okay! ready to go !
System.out.println( me );
avgPurchase = me.AveragePayment();
NumberFormat fmt = NumberFormat.getCurrencyInstance();
System.out.println( "has spent an average of " + fmt.format(avgPurchase) + " per purchase.");
}
}
im getting an error in my tester that says
Customer cannot be applied to given types;
`Customer me = new Customer("Christian" , "Turner" , 12321, lastYear)`;
and also
Tester.java:32: error: incompatible types: void cannot be converted to double
avgPurchase = me.AveragePayment()
As you can see im specifically instructed to modify my Customer class's constructor to allow the user to initalize the array. I believed i did just that however the tester is unable to populate the array. I believe i need an extra argument to specifically initalize the array however I'm confused on how to do so. Also I believe my AveragePayment method in my customer class is wrong because the data type is unable to convert from double to void, but i dont know how to go about fixing this. As this is an assignment i am unable to modify the tester in anyway Any help would be appreciated! I know its gotta be some little error im missing in the AveragePayment method, but the constructor error im literally clueless on how to solve it
Since this is a homework assignment I don't want to give you the answer, however most of this code is close to correct and you are not that far from solving the assignment. I am going to try and break down some areas that are likely giving you issues.
To start, look at my comment about the two errors you are getting, hopefully that will help, if not you are welcome to respond and I can try and provide more clarity.
Order List uses the wrong type
Customer.java should use Order[] instead of ArrayList<Order>. Since you cannot modify Tester.java, it is a good idea to match type you are given. Look at how Order[] lastYear is initialized in tester.java
Constructor Issues
There is an additional issue with the constructor besides the incorrect number of arguments you mentioned in your question. Take a close look at how you are doing the assignments inside this constructor. Think about which variable needs to change, put that one on the left and side so it gets assigned a new value
//4 arg constructor
public Customer(String fN,String lN,int i){
id=i;
fN=firstName;
lN=lastName;
this.orderList=orderList;
}
setPrice method
Take a look at your setPrice() method in Order.java. What should the outcome of this method be. You are doing math correctly, but this method will not provide the outcome you are hoping for.
//setPrice method
public void setPrice(double p){
price=p;
salesTax=salesTaxRate*price;
double subTotal=(price+salesTaxRate);
if(subTotal<50){
shippingCost=0.8*subTotal;
}
else{
shippingCost=0;
}
}

My arraylist is displaying object address not object contents [duplicate]

This question already has answers here:
How do I print my Java object without getting "SomeType#2f92e0f4"?
(13 answers)
Closed 4 years ago.
arraylist displays object address not actual object , program usesinheritance where salesEmployee is the super class and salesAgent and salesPerson are the subclasses.
import java.util.Scanner;
import java.util.ArrayList;
public class tester {
public static void main(String[]args ) {
ArrayList <salesEmployee> listemps= new ArrayList <salesEmployee>();
Scanner user_input= new Scanner(System.in);
salesPerson emp1 = new salesPerson();
emp1.setName("Frank Long");
emp1.setppsNumber(65783);
System.out.println("Enter total value of sales earned by Frank Long");
double valeSale;
valeSale=user_input.nextDouble();
emp1.setvalSale(valeSale);
emp1.getCommission();
listemps.add(emp1);
for ( int j=0; j<listemps.size(); j++ )
System.out.println("element " + j + ": " + listemps.get(j) );
}
}
This is my salesPerson class
public class salesPerson extends salesEmployee{
public salesPerson() {
}
public salesPerson(String name, int ppsNumber, double valSale, double commission) {
super(name, ppsNumber,valSale,commission);
}
public void getCommission() {
commission=valSale*0.15;
}
public String toString2() {
return toString1()+"value of sales"+getvalSale()+"commission:"+commission;
}
}
I'll make it more elegant later for now I am just trying to get it to work
Updated: Based on the comments to my answer, there is a different issue at play. Here's what was added in the comments:
Enter total value of sales earned by Frank Long 22.00
Exception in thread "main" java.lang.StackOverflowError at
salesPerson.toString(salesPerson.java:21) at
salesPerson.toString(salesPerson.java:21) at
salesPerson.toString(salesPerson.java:21) at
salesPerson.toString(salesPerson.java:21) – lucylio 5 mins ago
Is what comes up – lucylio 5 mins
In order for something reasonable to be displayed, you need to implement toString method in your class. You do have toString1 and toString2, but seemingly, no toString. (You haven't posted the code for salesEmployee class - but most likely it also doesn't have toString implementation).
In absence of toString, default Object.toString is called, which displays the address of the object.
Implement toString - and you'll see your results.
UPDATE: As the error you indicated doesn't correspond to the code, I'll go on a whim and suggest that, probably your toString2 method is actually toString and your toString1 method is actually a toString defined in your parent class, i.e. salesEmployee.java. In this case, instead of calling toString() from inside your toString method, use super.toString() instead:
public class salesPerson extends salesEmployee {
...
public String toString2() {
return super.toString()+"value of sales"+getvalSale()+"commission:"+commission;
}
}

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

Looping the wrong way?

The assignment for my class asks me to create a program that tells a supermarket which customer, on a daily basis, has spent the most money in the store. The program must find this customer and display their name.
Goals of assignment - To work with multiple classes, work with ArrayLists and apply the knowledge gained.
My question:
How should I loop my two output statements in my main class? Is that right in my main method? I need it to loop until the sentinel is used.
How is this going to affect my sentinel?
What type of questions should I be asking myself when dealing with loops? I'd like to think I'm overthinking this portion.
I really want to understand what I am doing here, so any help in the right direction would be appreciated! Thanks, in advance, for taking the time to help me out!
import java.util.Scanner;
public class main {
public static void main(String[] args) {
System.out.println("* * * * * THE SUPERMARKET * * * * *");
System.out.println(" Written by Nate Irwin");
System.out.println();
double finalTotal = -1;
String anAccountName;
Scanner input = new Scanner(System.in);
Store store = new Store();
do {
System.out.println("Enter the customer name: ");
if(input.hasNextLine()){
anAccountName = input.nextLine();
System.out.println("Enter customer total price, hit 0 to QUIT: ");
finalTotal = input.nextDouble();
store.addAccount(anAccountName, finalTotal);
System.out.println();
}
} while (finalTotal != 0);
System.out.println(store.getHighestCustomerTotal() + " has spent the most with us today!");
}
}
Store class:
import java.util.ArrayList;
public class Store {
// Creates an ArrayList.
private ArrayList<CustomerAccount> accounts = new ArrayList<CustomerAccount>();
//
public void addAccount(String anAccountName, double finalTotal) {
accounts.add(new CustomerAccount(anAccountName, finalTotal));
}
// Gets the HIGHEST customer total.
public String getHighestCustomerTotal() {
CustomerAccount highest = accounts.get(0);
for (int i = 1; i < accounts.size(); i++) {
if (accounts.get(i).getTotal() > highest.getTotal())
{
highest = accounts.get(i);
}
}
return highest.getAccountName();
}
}
CustomerAccount class:
public class CustomerAccount {
// Variables defined to this class.
private String accountName;
private double total;
// Constructor.
public CustomerAccount(String anAccountName, double finalTotal) {
accountName = anAccountName;
total = finalTotal;
}
// Gets total from each customer.
public double getTotal() {
return total;
}
// Gets a customer's name.
public String getAccountName() {
return accountName;
}
}
I think your approach is fine, it gets the job done.
I'm not too sure what you're asking by saying how should you loop the two output statements, followed by if it should be in the main method. From what I understand, and by looking at your code, running this input loop is perfectly fine from the main class. The do-while is fine although I'd move the first 'introductory' output outside the loop so you don't see it every time the loop reiterates.
Also, I notice you're not actually calling/instantiating the Store class in your main method, there's no data being added to the Store class for when it iterates through the accounts ArrayList.
As far as the answer that stated a more "modern" approach, I think the for loop you used is fine. I think the person was referring to the for-each loop. It doesn't really matter how you loop through it with the little amount of data you have.
There's some error in the logic for that loop. The getHighestCustomerTotal() is referencing an empty accounts ArrayList. You declared an ArrayList within the Store class and tried to loop through it but it's empty unless you called the addAccount() method from your main method at some point, so you'd need some error checking on that.
Your loop in main:
Doesn't really use the data you type in... One would expect this data to be used to create CustomerAccount instances
Has a completely unnecessary while(Condition) test at the end. This kind of loop is normally done with a While True and some test in the loop breaks out of the loop.
In getHighestCustomerTotal()
you can use a more "modern" form of the for() where you iterate elements of the list directly instead of iterating the index.

Java HashMap - get value from HashMap, user input

I am learning HashMap and trying to write a mortgage program. I thought that I would use the following in my HashMap
30 Years 3.95
15 Years 3.25
Here is so far what I have written
Loan Class: Getting user input
import java.util.*;
public class Loan {
private static HashMap<Integer,Double> rate = new HashMap<Integer,Double>();
public int getYear() {
rate.put(15, 3.25);
rate.put(30, 3.95);
System.out.println("Enter year: 15/30");
Scanner userInput = new Scanner(System.in);
int year = userInput.nextInt();
if (rate.containsKey(year)) {
}
return year;
}
}
HomeValue class: Showing home value
public class HomeValue {
public int hValue= 300000;
}
CaclPrice class: This is where calculation happens based on user input of the year
public class CalcPrice {
Loan ln= new Loan();
HomeValue hv= new HomeValue();
public double getPrice() {
if (ln.getYear()==15) {
System.out.println("House price is " + hv.hvalue *???
}
}
}
My Question: I do no want to hard code the calculation (home value* 3.25%) is there a way to get value from the HashMap based on the user input?
Thank You.
Map offers a get method which take the key as parameter.
So you can simply do rate.get(year).
Note that null will be returned if no value match the key.
Might I suggest restructuring the code a little bit. In your Loan class, I would recommend implementing a getRate() function instead of getYear() function.
Now, your Loan class might look something like this....
public class Loan {
private static HashMap<Integer,Double> rate = new HashMap<Integer,Double>();
Loan()
{
//I would recommend populating the rate HashMap
//in the constructor so it isn't populated
//every time you call getRate
rate.put(15, 3.25);
rate.put(30, 3.95);
}
public double getRate(int year) {
//Now you can just the desired rate
return rate.get(year);
}
}
And you can refactor your CalcPrice to look something like this....
public double getPrice(){
//I would recommend asking the user for input here
//Or even better, ask for it earlier in the program
//and pass it in as a parameter to this function
//You can easily get the rate now that you have the year
double rate = ln.getRate(year);
}
Now, you can just use the rate to complete your calculation.

Categories