Methods and Formatted Output

advertisement

Methods and Formatted Output

Chapter 4

Overview

• Breaking down a big program into small methods.

• Formatting output

– using printf

– using DecimalFormat

Methods

• Methods are similar to friends .

• You can ask them to do you a favor.

• You can send some data to them (or you can call them without sending data).

• You can get back at most one piece of data (or no data).

• For example, the println method is like a friend that does some printing. You send to the method the data and he does the printing. The method does not return any information.

• Conversely, the nextInt method takes no input. However, it returns back an integer.

Example Program

import java.util.*; public class Remodel { public static void main(String[] args) { callBob(); callPeter();

} public static void callBob() {

System.out.println("Paint room");

}

} public static void callPeter() {

System.out.println("Install hardwood floor");

}

Notes

• For now, all methods are public and static .

• Calling a method transfers the flow of control to the method.

Once the method is executed, control goes back to the calling method ( main in our case).

• Method names start with a lowercase letter .

• We must always use parenthesis, i.e. method_name( ... ) when calling a method. This tells Java that we are calling a method and not referencing to a variable.

• A method must have a return type. Use void when it does not return anything.

Method Signature

import java.util.*; public class Remodel { public static void main(String[] args) { double bobPrice = callBob(8, 12); double peterPrice = callPeter(8, 12); double totalPrice = bobPrice + peterPrice;

System.out.println("Total price for the project: $"

+ totalPrice);

} public static double callBob(int width, int length) {

System.out.println("Paint room"); double pricePSF = 0.80; return pricePSF * width * length;

}

} public static double callPeter(int width, int length) {

System.out.println("Install hardwood floor"); double pricePSF = 3.20; return pricePSF * width * length;

}

Notes

• Two ways to call a method:

– m(...) <- use when method does not return anything (void method) and

– a = m( ...) <- use when method returns a value.

• When a method returns a value, we must save the value (or use it directly, e.g., print it).

• A common mistake is to call a method that computes something, but do not save the result. Then all the work that is done by the method will go to waste.

Atomic Variables

• Instance (i.e. nonstatic ) variables in Java are atomic (i.e., memory for them is automatically allocated and freed).

• The memory for a variable is allocated when the variable is defined.

• The memory is freed when the block in which the variable is defined finishes.

• Note that the variable is NOT valid outside the block in which it is defined.

• When a method is called, the variables of the first method will not be valid inside the method that is called.

Formal vs. Actual Parameters

• The formal parameters are defined in the signature of the method:

• public static double callPeter(int width , int length )

{...}

• Formal parameters are basically local variable for the method.

They are only defined inside the method.

• Actual parameters are the parameters that are sent to the method:

– double bobPrice = callBob( 8 , 12 );

• These could be literals , variables , or expressions .

• The formal parameters are initialize by the value of the actual parameters.

• Changing the value of a formal parameter variable does not change the value of an actual parameter variable.

Example Code

int x = 3; int y = 5; callBob(x,y);

• Note that the method call cannot change the value of the variables x and y.

• Any change to these variables inside the callBob method will only change the formal (i.e., local for the method variables) and not the actual parameters.

The return Statement

• Performs two tasks :

– always exits the method (including a void method) and

– returns back exactly one piece of information (or nothing for void methods).

• Use the following syntax when a method returns a value.

– a= m( ...) or

– System.out.println(m(...))

• Never use just m(...) when a method returns a value. All the work to compute the result will be wasted.

Formatting Output Using printf

• Example:

System.out.printf(" $%.2f on painting and"+ " $%.2f on hardwood for total of $%.2f,", bobPrice, peterPrice, totalPrice);

• Method has variable number of arguments.

• The first parameter is the string that is printed.

• Whenever a %... is found in the first parameter, it is replaced with the next parameter in the list.

• %.2f

means display a float (or a double ) with 2 digits after the decimal dot.

Examples Using printf

Remember that %d stands for decimal, not float!

Formatting Real Numbers Using printf

• %.3f -> 3 digits after the decimal dot. Result is rounded .

– For example: printf("%.3f",2.998) will print 3.000

• %6.2f -> 2 digits after the decimal dot and at least 6 total characters

– For example, printf("7.3f",2.998) will print " 3.000", where there are 2 spaces at the front.

• %-7.2f will justify it to the right.

• For example, printf("-7.3f",2.998) will print "3.000 ", where there are 2 spaces at the back.

Formatting Output Using DecimalFormat

public class Test { public static void main(String[] args){

DecimalFormat myFormatter = new DecimalFormat(" $###,###.00

");

System.out.println(myFormatter.format(32536.34));

}

} // will print $32,536.34

• Used when we want to format output using special characters, e.g. $32,536.34 is the output of the program.

• # means there may or may not be a number there

• 0 means there must be a number. If there is no number, put 0.

public class Test { public static void main(String[] args){

DecimalFormat myFormatter = new DecimalFormat("$000,000.00");

System.out.println(myFormatter.format(32536.34));

}

} // will print $032,536.34

Code Refactoring

• Refactoring meaning rewriting code without changing what it does.

• We want the code to be very clean and self-explanatory.

• Want to use methods.

• Every method must perform a single task . If a method performs multiple tasks, break it down into several methods.

• Try to make methods reusable . A method that makes a stickman jump and scratch their ear will not be reusable. Instead, create jump method and scratch ear method.

• If you have code that repeats multiple times, then try to move it to a method. This will make the code more compact and easy to understand.

• Always give methods meaningful names (usually starts with verb).

Previous Code to Print Diamond

for (int numStars =1, numSpaces = size-1; numSpaces >=0 ; numSpaces-=2, numStars+=2){ for (int i = 0; i < numSpaces; i++) {

System.out.print(" ");

} for (int i = 0; i < numStars; i++) {

System.out.print("* ");

}

System.out.println();

} for (int numStars=size-2, numSpaces = 2; numStars >=0 ; numSpaces+=2, numStars-=2 ) { for (int i = 0; i < numSpaces; i++) {

System.out.print(" ");

} for (int i = 0; i < numStars; i++) {

System.out.print("* ");

}

System.out.println();

}

import java.util.*; public class Diamond { public static void printStrings(String s, int n){ for(int i=0; i < n; i++){

System.out.print(s);

}

} public static void main(String[] args) {

Scanner keyboard = new Scanner(System.in);

System.out.print("Enter size of diamond: "); int size = keyboard.nextInt(); for (int numStars =1, numSpaces = size-1; numSpaces >=0 ; numSpaces-=2, numStars+=2) { printStrings(" ",numSpaces); printStrings("* ",numStars);

System.out.println();

} for (int numStars=size-2, numSpaces = 2; numStars >=0 ; numSpaces+=2, numStars-=2 ) { printStrings(" ",numSpaces); printStrings("* ",numStars);

System.out.println();

}

}

}

import java.util.*; public class Diamond { public static void printStrings(String s, int n) {

...

} public static void printLine(int numSpaces, int numStars) { printStrings(" ", numSpaces); printStrings("* ", numStars);

System.out.println("");

} public static void main(String[] args) {

Scanner keyboard = new Scanner(System.in);

System.out.print("Enter size of diamond: "); int size = keyboard.nextInt(); for (int numStars = 1, numSpaces = size - 1; numSpaces >= 0; numSpaces -= 2, numStars += 2) { printLine(numSpaces,numStars);

} for (int numStars = size - 2, numSpaces = 2; numStars >= 0; numSpaces += 2, numStars -= 2) { printLine(numSpaces, numStars);

}

}

}

Self-Documenting Code

• Always choose proper names for methods and variables

( starting with small letter ).

• The name of a method should explain what the method does.

• For example, the code on the last slide is self-explanatory, we do not need any documentation. The method printLine prints a line of the diamond, for example.

• Create a method for every task and name the method appropriately (describing what is the task). For big tasks, a method can call other methods to execute sub-tasks. For example, the printLine method calls the printStrings method.

Documenting Methods using JavaDoc

• In NetBeans, Type /**

• A template magically appears.

• Can be typed before a method or a class.

• Fill in the missing pieces.

• For methods, describe method purpose and parameters.

• For classes, describe class purpose.

• Can be used to generate HTML JavaDoc file.

• Just go to Run: Generate JavaDoc

JavaDoc Example

/**

* Prints a string multiple times on the same line.

* @param s The string to be printed.

* @param n The frequency.

*/ public static void printStrings(String s, int n) { for (int i = 0; i < n; i++) {

System.out.print(s);

}

}

Pass by Value

• Primitive types, e.g., int, double, etc., are passed by value.

• This means that a method cannot modify input parameters of these types.

• The variables for the formal parameters are local variables and they can change in a method.

• However, the calling method will not see the changes.

What will be printed?

import java.util.*; public class Example{ public static void inc(int i){ i++;

} public static void main(String[] args) { int i = 3; inc(i);

System.out.println(i);

}

}

What About Now?

import java.util.*; public class Example{ public static int inc(int i){ i++; return i;

} public static void main(String[] args) { int i = 3; i = inc(i);

System.out.println(i);

}

}

Third Example

import java.util.*; public class Example{ static int i; public static void inc(){ i++;

} public static void main(String[] args) { i = 3; inc();

System.out.println(i);

}

}

Method return type

• A method can return only one piece of data .

• If a method needs to return multiple pieces of data, then there are several options.

– Define the data global . The method can have void return type and will have access to the data.

– Break the method into several methods . Each method can return one piece of the data.

The Trading Game

• We can trade apples and pears.

• The game has 10 days.

• Every day the price changes randomly.

• The goal is to make the most $$$.

• Every day we can buy or sell apples or pears.

• We start with $100.

• There are restrictions.

– We can't buy more than what we can afford.

– We can't sell if we don't have the inventory.

• We will use a top-down approach to implement the game.

• We will first write the main method that calls other methods.

The other methods will be written later.

import java.text.*; import java.util.*; public class TradingGame { static final int NUMBER_OF_DAYS=10; static final double BASE_PRICE = 10; static final double VARIATION = 5;//in $ static final double INITIAL_CASH=100; static double cash = INITIAL_CASH; static int appleInventory = 0; static int pearInventory = 0; static double applePrice, pearPrice; public static void main(String[] args) { for (int day = 1; day <= NUMBER_OF_DAYS; day++) { applePrice = computePrice(BASE_PRICE, VARIATION); pearPrice = computePrice(BASE_PRICE, VARIATION);

System.out.println("Day: " + day + " out of “+

NUMBER_OF_DAYS); int choice; do{ printMenu(); choice = getChoice();

switch (choice) { case 1: // Print cash balance and inventory

System.out.println("Cash: " + currencyFormatter(cash));

System.out.println("Apple inventory: "+appleInventory);

System.out.println("Pear inventory: "+pearInventory); break; case 2: //Print today's prices

System.out.println("Price of apples is: "+ currencyFormatter(applePrice));

System.out.println("Price of pears is: "+ currencyFormatter(pearPrice)); break; case 3: { //Buy apples int amount = getQuantity("apples", "buy"); if (!buyApples(amount)) {

System.out.println("You don't have enough money");

} break;

} case 4: { // Sell apples int amount = getQuantity("apples", "sell"); if (!sellApples(amount)) {

System.out.println("You don't have enough apples");

} break;}

case 5: { // Buy Pears int amount = getQuantity("pears", "buy"); if (!buyPears(amount)) {

System.out.println("You don't have enough money");

} break;

} case 6: { // Sell Pears int amount = getQuantity("pears", "sell"); if (!sellPears(amount)) {

System.out.println("You don't have enough pears");

} break;

}

}

} while (choice != 7);

}

...

}

System.out.println("You finished with:"+ currencyFormatter(cash));

}

Notes

• Constants are defined as static final . All constants are defined at the beginning of the code. Constants use all capital letters.

• Lots of global variables. The reason is that most methods need to return several piece of data. For example, buyApples updates cash and appleInventory . In addition, it returns a Boolean value: was the operation successful.

• Price of apples and pairs ranges in the interval:

(BASE_PRICE -VARIATION, BASE_PRICE+VARIATION)

• getQuality method is used to get amount for buy/sell of apples/pairs.

public static void printMenu() {

System.out.println("1.Print cash balance and inventory");

System.out.println("2.Print today's prices");

System.out.println("3.Buy apples");

System.out.println("4.Sell apples");

System.out.println("5.Buy pears");

System.out.println("6.Sell pears");

System.out.println("7.I am done for today");

} public static int getChoice() {

Scanner keyboard = new Scanner(System.in); int choice; do {

System.out.print("Your choice: "); choice = keyboard.nextInt();

} while (choice > 7 || choice < 1); return choice;

} public static String currencyFormatter (double amount) {

DecimalFormat myFormatter = new DecimalFormat("$#,###.00"); return myFormatter.format(amount);

}

public static double computePrice (double basePrice, double variation) { double result = basePrice; if (Math.random() > 0.5) { result += Math.random() * variation;

} else { result -= Math.random() * variation;

} return ((int)(result*100))/100.0;//makes price 23.23

} public static int getQuantity (String product, String action)

{

System.out.print("How many " + product + " do you want to "

+ action + "? ");

Scanner keyboard = new Scanner(System.in); return keyboard.nextInt();

} public static boolean sellApples (int amount) { if (amount > appleInventory) { return false;

} cash += amount * applePrice; appleInventory -= amount; return true;

}

} public static boolean sellPears (int amount) { if (amount > pearInventory) { return false;

} cash += amount * pearPrice; pearInventory -= amount; return true;

} public static boolean buyApples (int amount) { if (amount * applePrice < cash) { cash -= amount * applePrice; appleInventory += amount; return true;

} return false;

} public static boolean buyPears (int amount) { if (amount * pearPrice < cash) { cash -= amount * pearPrice; pearInventory += amount; return true;

} return false;

Notes

• The buy/sell methods check to see if the operation is possible.

If it is not, they return false .

• The methods modify global variables.

• Every method performs one task. Can't easily combine buy/sell methods.

• We used DecimalFormat to format output.

• The following code is possible, but not preferred (too cryptic).

public static double computePrice(double basePrice, double variation) { return ((int)((basePrice +

(Math.random() > 0.5 ? 1 : -1) * variation)*100))/100.0;

}

• ((int)(result*100))/100.0; // Saves 2 digits after the dot.

Conclusion

• Use methods to break a big problem into smaller problems.

• Methods can be used to avoid repeating the same code multiple times.

• Methods should be short and perform a single task .

• Avoid writing methods that do one of several things based on input parameter.

• Methods cannot modify input data of primitive type .

• Methods can return back only a single piece of data.

• Use printf and DecimalFormat for formatted printing.

Download