d2jsp
Log InRegister
d2jsp Forums > Off-Topic > Computers & IT > Programming & Development > Java & Android Questions > Continuous Over Semester
123Next
Add Reply New Topic New Poll
Member
Posts: 1,849
Joined: May 31 2008
Gold: 2,571.50
Jan 21 2015 11:56pm
background: I haven't taken java in a few semesters. It is safe to say that I'm really rusty with it and I don't remember a lot of the fundamentals. This semester I am taking Adv. Java and an Android class. Because my java skills are seriously lacking I've decided to make this thread to ask questions about the code I've written. Also to maybe get help fixing my code. This thread is very similar to those"Make me a better programmer" threads I've seen on these fourms.


Currently for class I'm making a two separate 'tip' calculators using java

The first tip calculator is to only use the main method, to execute all the code.
While the second tip calculator is to use a calculation class / printer class alongside the main method.


My teacher said you could just do the tip calculator 'right' (not just main method) and not worry about the first way. But since I feel like I'm relearning all this I decided to start with the main method way. To at least to get my output looking correct.

*Sidenote: I'm currently using notepad++ // cmd prompt for this assignment -- will be looking for a better environment for java after this assignment (any suggestions welcomed) in my Android class we are using android studio -- not sure if I can use that for strictly java assignments (havn't looked into yet)

first tip calculator
Code

import java.text.*;
import java.util.*;

public class week1lab1 {

public static void main(String[] args) {
//General scanner used to allow user input
//(self note: the java.util.* import includes the util.scanner which is needed for this code to run)
Scanner user_input = new Scanner(System.in);
DecimalFormat df = new DecimalFormat("#.##");

//not optional declares, asks for bill amount, than prompts user input.
//in lab2 make it
double currentBillAmount;
System.out.println("Enter current bill amount: ");
currentBillAmount = Double.parseDouble(user_input.next()); //Since user_input is seen as String converted to double

//declares, defines, asks for optional tip amount
int customTipNumber;
customTipNumber = 0; //Bad practice?
System.out.println("Enter custom tip (optional): ");

// Exception handles if a non int was entered
// user_input seems to require some sort of input, hitting enter doesn't do anything.
// Could just ask user to type 'anything' if they don't want a tip
try {
customTipNumber = user_input.nextInt();
}
catch (InputMismatchException e) {
user_input.nextLine();
}
//Basic math below
//variable names kind of unclear good spacing though
double tenPercentTip = (.1 * currentBillAmount);
double tenPercentTotal = (currentBillAmount + tenPercentTip);

double fifteenPercentTip = (.15 * currentBillAmount);
double fifteenPercentTotal = (currentBillAmount + fifteenPercentTip);

double eighteenPercentTip = (.18 * currentBillAmount);
double eighteenPercentTotal = (currentBillAmount + eighteenPercentTip);

double customPercentTip = (customTipNumber * currentBillAmount * .01);
double customPercentTotal = (currentBillAmount + customPercentTip);
//prints output, spacing was added for reading purposes
//DecimalFormat was used -- in order to use you need the import.text.*; (not sure which one specifically)
System.out.println("Bill Total: " + currentBillAmount + "\n");
System.out.println(" 10% 15% 18%");
System.out.println("Tip: " + df.format(tenPercentTip) + " " + df.format(fifteenPercentTip)
+ " " + df.format(eighteenPercentTip));
System.out.println("Total $: " + df.format(tenPercentTotal) + " " + df.format(fifteenPercentTotal)
+ " " + df.format(eighteenPercentTotal) +"\n");
System.out.println("Custom Tip%: " + customTipNumber + "\nTip: " + df.format(customPercentTip)
+ " Total $: " + df.format(customPercentTotal));
}
}


With this it mostly does whats required.

The problem I'm having is with the custom tip being "optional"
With this code if I just hit the 'enter' key after being prompted for user_input in command prompt it does nothing but go down a line, I would like it when the user hits enter for it to react the same way as the exception catch does. Ran out of ideas for that, suggestions?

Also if I had to guess defining my customTipNumber default as 0 is a bad practice. Comments?
is the way I found for 2 decimal places (the df.format) the way you would have choose?

I will be posting my solution for second tip calculator + probably some questions with it -- tomorrow. HOPEFULLY it will be a lot cleaner / not such an eye sore as this one!

Thanks for your time! and please excuse my ignorance!!
Member
Posts: 2,754
Joined: Nov 26 2007
Gold: 1,339.81
Jan 22 2015 08:34am
You can use nextLine instead of nextInt and catch a NumberFormatException and do nothing with it, but doing this will require you to consume the current line.

Code
try {
user_input.nextLine( ); // consume current line
customTipNumber = Integer.parseInt( user_input.nextLine( )); // get next line
}
catch (NumberFormatException e) {
}



or you could just use a new scanner object

Code
try {
customTipNumber = Integer.parseInt( new Scanner(System.in).nextLine( ));
}
catch (NumberFormatException e) {
}


Also, it's okay to initialize customTipNumber to 0. And for formating currency, you should use
Code
NumberFormat df = NumberFormat.getCurrencyInstance( );




This post was edited by labatymo on Jan 22 2015 08:44am
Member
Posts: 1,849
Joined: May 31 2008
Gold: 2,571.50
Jan 22 2015 03:59pm
Alright so I started the second tip calculator. However I ran into a problem

*Note this is different from my original attempt (last post) -- I don't use scanner to create args, rather i use args[]

The problem I think is that my billAmount variable is actually 0.0 judging by how math turns out??

What I think I have right now: in my main method within the TipCalculation class
  • Creates an instance of the Tip class, and names it as tipTestA
  • The parameters being fed in are converted to double and Int (args0 = 120 and args1 = 20)
  • I print the object tipTestA -- the default toString is overridden in my other class


What I think I have right now: in my main method within the Tip class
  • Declare my argument variables (bill amount / customTip) (PROBLEM HERE?)
  • Declare PercentTipAmount variables and set them to value (OR PROBLEMS HERE?)
  • Declare totalWithTipAdded variables and set there values (ALSO HERE?)
  • I create my Tip constructor with the parameters of same type as my args (after the args were converted in main)
  • In constructor I define my instance billAmount = parameter billAmount -- same with customTipPercent
  • I have getters/setters for each variable I declare (Am i suppose to do math in these and why if yes?)
  • I @Override the toString() method to output my data


The output shows the Bill Total: and the Custom Tip%: correctly but nothing else
To my understanding my billAmount variable never changes when the instance is constructed?

Hopefully you guys can shine some light on where I'm going wrong, I listed briefly how I think my code works
Keep in mind I yet to add decimal formatting + exception logic

TipCalculation
Code
public class TipCalculation {



/**
* The entry point of application.
*
* @param args the input arguments
*/
public static void main(String[] args) {
// Creates an instance of the Tip class
Tip tipTestA = new Tip(Double.parseDouble(args[0]),Integer.parseInt(args[1]));

//System.out.println(Double.parseDouble(args[0]) + " " + Integer.parseInt(args[1]));
System.out.println(tipTestA);

}
}

Tip Class

Code
public class Tip {

//Sets df as a DecimalFormat for currency
//DecimalFormat df = new DecimalFormat.getCurrencyInstance();

//Argument Variables
private double billAmount; //@!@!#!#!Bill amount is getting set to 0.0
private int customTipPercent = 0;


//Private variable declarations of the PercentTipAmount
private double tenPercentTipAmount = (billAmount * .1);
private double fifteenPercentTipAmount = (billAmount * .15);
private double eighteenPercentTipAmount = (billAmount * .18);
private double customPercentTipAmount = (billAmount * customTipPercent * .01);

//Private variable declarations of the totalWithTipAdded
private double totalWithTenTipAdded = (billAmount + tenPercentTipAmount);
private double totalWithFifteenTipAdded = (billAmount + fifteenPercentTipAmount);
private double totalWithEighteenTipAdded = (billAmount + eighteenPercentTipAmount);
private double totalWithCustomTipAdded = (billAmount + customPercentTipAmount);


//Constructors
//One with only billAmount parameter (override method)
public Tip(double billAmount, int customTipPercent) {
this.billAmount = billAmount;
this.customTipPercent = customTipPercent;
}
//public Tip(double billAmount) {
// this.billAmount = billAmount;
// }

//Getters and setters for all my variables below


public double getBillAmount() {
return billAmount;
}

public void setBillAmount(double billAmount) {
this.billAmount = billAmount;
}

public int getCustomTipPercent() {
return customTipPercent;
}

public void setCustomTipPercent(int customTipPercent) {
this.customTipPercent = customTipPercent;
}

public double getTenPercentTipAmount() {
return tenPercentTipAmount;
}

public void setTenPercentTipAmount(double tenPercentTipAmount) {
this.tenPercentTipAmount = tenPercentTipAmount;
}

public double getFifteenPercentTipAmount() {
return fifteenPercentTipAmount;
}

public void setFifteenPercentTipAmount(double fifteenPercentTipAmount) {
this.fifteenPercentTipAmount = fifteenPercentTipAmount;
}

public double getEighteenPercentTipAmount() {
return eighteenPercentTipAmount;
}

public void setEighteenPercentTipAmount(double eighteenPercentTipAmount) {
this.eighteenPercentTipAmount = eighteenPercentTipAmount;
}

public double getCustomPercentTipAmount() {
return customPercentTipAmount;
}

public void setCustomPercentTipAmount(double customPercentTipAmount) {
this.customPercentTipAmount = customPercentTipAmount;
}

public double getTotalWithTenTipAdded() {
return totalWithTenTipAdded;
}

public void setTotalWithTenTipAdded(double totalWithTenTipAdded) {
this.totalWithTenTipAdded = totalWithTenTipAdded;
}

public double getTotalWithFifteenTipAdded() {
return totalWithFifteenTipAdded;
}

public void setTotalWithFifteenTipAdded(double totalWithFifteenTipAdded) {
this.totalWithFifteenTipAdded = totalWithFifteenTipAdded;
}

public double getTotalWithEighteenTipAdded() {
return totalWithEighteenTipAdded;
}

public void setTotalWithEighteenTipAdded(double totalWithEighteenTipAdded) {
this.totalWithEighteenTipAdded = totalWithEighteenTipAdded;
}

public double getTotalWithCustomTipAdded() {
return totalWithCustomTipAdded;
}

public void setTotalWithCustomTipAdded(double totalWithCustomTipAdded) {
this.totalWithCustomTipAdded = totalWithCustomTipAdded;
}

@Override
public String toString() {
String output = "Bill Total: " + this.getBillAmount() + "\n" +
" 10% 15% 18%\n" +
"Tip: " + this.getTenPercentTipAmount() + "\t\t" + this.getFifteenPercentTipAmount() + "\t\t" + this.getEighteenPercentTipAmount() + "\n" +
"Total $: " + this.getTotalWithTenTipAdded() + "\t\t" + this.getTotalWithFifteenTipAdded() + "\t\t" + this.getTotalWithEighteenTipAdded() + "\n\n" +
"Custom Tip%: " + this.getCustomTipPercent() + "\n" +
"Tip: " + this.getCustomPercentTipAmount() + "\t\tTotal $: " + this.getTotalWithCustomTipAdded();
return output;
}

}


Thank you labatymo for your input. I will definitely look at the java API for NumberFormat.getCurrencyInstance() when i get to the decimal formatting part of this.

This post was edited by Noobtard on Jan 22 2015 04:00pm
Member
Posts: 2,754
Joined: Nov 26 2007
Gold: 1,339.81
Jan 23 2015 08:19am
you should initialize your variables in the constructor.

like this

Code
// Argument Variables
private double billAmount; // @!@!#!#!Bill amount is getting set to 0.0

private int customTipPercent = 0;

// Private variable declarations of the PercentTipAmount
private double tenPercentTipAmount;

private double fifteenPercentTipAmount;

private double eighteenPercentTipAmount;

private double customPercentTipAmount;

// Private variable declarations of the totalWithTipAdded
private double totalWithTenTipAdded;

private double totalWithFifteenTipAdded;

private double totalWithEighteenTipAdded;

private double totalWithCustomTipAdded;

private NumberFormat df;

// Constructors
// One with only billAmount parameter (override method)
public Tip( double billAmount, int customTipPercent ) {
this.billAmount = billAmount;
this.customTipPercent = customTipPercent;

tenPercentTipAmount = (billAmount * .1);
fifteenPercentTipAmount = (billAmount * .15);
eighteenPercentTipAmount = (billAmount * .18);
customPercentTipAmount = (billAmount * customTipPercent * .01);
totalWithTenTipAdded = (billAmount + tenPercentTipAmount);
totalWithFifteenTipAdded = (billAmount + fifteenPercentTipAmount);
totalWithEighteenTipAdded = (billAmount + eighteenPercentTipAmount);
totalWithCustomTipAdded = (billAmount + customPercentTipAmount);
df = NumberFormat.getCurrencyInstance( );
}



Also, your second constructor should just call this(billAmount,0). It would look like this
Code
public Tip( double billAmount ) {
this( billAmount, 0 );
}


Also use df to format the numbers in toString()

Code
@Override
public String toString( ) {
String output = "Bill Total: "
+ df.format( billAmount) + "\n"
+ " 10% 15% 18%\n" + "Tip: "
+ getTenPercentTipAmount( ) + "\t\t" + getFifteenPercentTipAmount( )
+ "\t\t" + getEighteenPercentTipAmount( ) + "\n"
+ "Total $: " + df.format( getTotalWithTenTipAdded( ) ) + "\t\t"
+ df.format( getTotalWithFifteenTipAdded( ) ) + "\t\t"
+ df.format( getTotalWithEighteenTipAdded( ) ) + "\n\n"
+ "Custom Tip%: " + getCustomTipPercent( ) + "\n" + "Tip: "
+ df.format( getCustomPercentTipAmount( ) ) + "\t\tTotal $: "
+ df.format( getTotalWithCustomTipAdded( ) );
return output;
}
Member
Posts: 1,849
Joined: May 31 2008
Gold: 2,571.50
Jan 24 2015 06:40pm
Thank you. To make sure I understand the main change / problem I was having: Before my code never was initializing my instance variables, thus leaving them to the default value of 0.

Not quite sure how this constructor works.

Quote

Also, your second constructor should just call this(billAmount,0). It would look like this
Code
public Tip( double billAmount ) {
this( billAmount, 0 );
}


When I read the code above I see: This constructor is called when only one argument is passed (billAmount). (right?)

I think i'm more confused what this line does: this(billAmount,0);

I would ideally want when no customTip argument is passed that the program still displays the 10 15 18% tips + totals. Having the custom tip stuff set to 0. Would I have to initialize my instance variables in the second constructor also? I feel like if I were to initialize a lot of the same stuff, that's probably really inefficient, is there a better way? Or when you override a method does is inherent? (havn't got the the constructor part of my book yet)


Thank you again for your time!
Member
Posts: 1,995
Joined: Jun 28 2006
Gold: 7.41
Jan 24 2015 08:39pm
this(billAmount, 0) referes to a constructor in this class defined as taking a double argument and an int argument. The benefit is reducing redundant code in your constructors by specifiying default values.


Consider the following:

Code
public class Account
{
private double balance;
private int accountNumber;
private String accountNickName;
private AccountType accountType;

/* Construct a new account with a starting balance
* with default values for the rest
*/

public Account(double balance)
{
this.balance = balance;

this.accountNumber = Account.generateAccountNumber();
this.accountNickName = "";
this.accountType = AccountType.Checking;
}

/* Construct a new account with a starting balance and account type
* with default values for the rest
*/

public Account(double balance, AccountType accountType)
{
this.balance = balance;
this.accountType = accountType;

this.accountNumber = Account.generateAccountNumber();
this.accountNickName = "";
}

/* Construct a new account with a starting balance, account type, and nick name
* with default values for the rest
*/

public Account(double balance, AccountType accountType, String accountNickName)
{
this.balance = balance;
this.accountType = accountType;
this.accountNickName = accountNickName;

this.accountNumber = Account.generateAccountNumber();
}

/* Construct a new account with a starting balance, account type, nick name, and account number
*/

public Account(double balance, AccountType accountType, String accountNickName, int accountNumber)
{
this.balance = balance;
this.accountType = accountType;
this.accountNickName = accountNickName;
this.accountNumber = accountNumber;
}

}


Now look how much cleaner it looks:
Code
public class Account
{
private double balance;
private int accountNumber;
private String accountNickName;
private AccountType accountType;

/* Construct a new account with a starting balance
* with default values for the rest
*/

public Account(double balance)
{
this(balance, AccountType.Checking);
}

/* Construct a new account with a starting balance and account type
* with default values for the rest
*/

public Account(double balance, AccountType accountType)
{
this(balance, accountType, "");
}

/* Construct a new account with a starting balance, account type, and nick name
* with default values for the rest
*/

public Account(double balance, AccountType accountType, String accountNickName)
{
this(balance, accountType, Account.generateAccountNumber());
}

/* Construct a new account with a starting balance, account type, nick name, and account number
*/

public Account(double balance, AccountType accountType, String accountNickName, int accountNumber)
{
this.balance = balance;
this.accountType = accountType;
this.accountNickName = accountNickName;
this.accountNumber = accountNumber;
}

}


Your constructors no longer duplicate code. And you are only specifying the defaults once. If you ever need to refactor, or change the defaults it will only have to be done in 1 place as opposed to in each constructor.
Member
Posts: 1,849
Joined: May 31 2008
Gold: 2,571.50
Jan 24 2015 09:53pm
In the constructor below is it missing accountNickName in the this()?

Code
/* Construct a new account with a starting balance, account type, and nick name
* with default values for the rest
*/

public Account(double balance, AccountType accountType, String accountNickName)
{
this(balance, accountType, Account.generateAccountNumber());
}


I think I understand the re-factored code.

Basically if the user only had balance, the first constructor would run.
Within that constructor it would call the constructor below it, not only would this constructor have the balance, but it would have the default AccountType you declared when you called this constructor
...this keeps happening and setting the defaults for the rest.


^ I hope I understood your example correctly.

When I attempt to call my Tip(Constructor) with only 1 argument I get an error. Works fine with both. So i changed my main to:

Code
public static void main(String[] args) {
// Creates an instance of the Tip class
Tip tipTestA;

if (args.length > 1){
tipTestA = new Tip(Double.parseDouble(args[0]),Integer.parseInt(args[1]));
} else {
tipTestA = new Tip(Double.parseDouble(args[0]));
}


System.out.println(tipTestA);

}


I feel like this might also be a bad way to do what I want? Or is that acceptable -- I just feel its probably not reusable.
I still have to add exception handling to this, but I haven't gotten that far in my book yet. So i will look more into that probably tomorrow.

***A bit off-topic
In my book I just got to <arraylists>
--Are arrays only used if the array you want is going to be a fixed size? It seemed to me there was a great deal of benefits to arraylists > arrays. Opinions?


Thanks for the helps guys!!! Definitely has helped me understand a lot better!

This post was edited by Noobtard on Jan 24 2015 09:54pm
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Jan 24 2015 10:07pm
Quote
In my book I just got to <arraylists>
--Are arrays only used if the array you want is going to be a fixed size? It seemed to me there was a great deal of benefits to arraylists > arrays. Opinions?


do you know what an arraylist is? look at the source code.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java

it's a wrapper around arrays to make them easier to use. by using an arraylist, you are using an array.

look at what add(..) does. in particular, ensureCapacity(..)

This post was edited by carteblanche on Jan 24 2015 10:09pm
Member
Posts: 1,849
Joined: May 31 2008
Gold: 2,571.50
Jan 25 2015 08:59pm
Quote (carteblanche @ Jan 24 2015 11:07pm)
do you know what an arraylist is? look at the source code.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java

it's a wrapper around arrays to make them easier to use. by using an arraylist, you are using an array.

look at what add(..) does. in particular, ensureCapacity(..)


Correct me if I'm wrong but after reading a bit more about them, my new understanding of the ArrayList is an wrapper that deals with arrays.
One of many things the arraylist provides is the add(). This add() provides a set of instructions on how to add a 'thing' to an array when using the arraylist. Without the arraylist this wouldn't be as easy and require a lot more code.

Also, I gotta think of it more as an API resource that I can import and than use whenever suitable. Before I was thinking of it as a variable type.

I think i understand it now? But i wanna make sure.

EDIT: What are some other common wrappers I might use?

This post was edited by Noobtard on Jan 25 2015 09:03pm
Member
Posts: 32,925
Joined: Jul 23 2006
Gold: 3,804.50
Jan 25 2015 09:26pm
Yes.

some other utilities i enjoy:
apache commons (http://commons.apache.org/proper/commons-lang/) i like the StringUtils in particular, but a lot of goodies in here. there's also a math module for any statistics / etc you need.
log4j (http://logging.apache.org/log4j/2.x/) no more System.out.println for your logging purposes. there are many different logging frameworks, but this is the one i'm most familiar with, not necessarily the best.
xstream (http://xstream.codehaus.org/) for xml <-> pojo mapping
GSON (http://code.google.com/p/google-gson/) for json <-> pojo mapping


JPA / Hibernate. personally i prefer JDBC, but these are an alternative if you dont like direct sql.

i played with lombok some years ago, but i havent used it at work. you might find some fun with i if you use eclipse.
http://projectlombok.org/features/index.html

This post was edited by carteblanche on Jan 25 2015 09:29pm
Go Back To Programming & Development Topic List
123Next
Add Reply New Topic New Poll