Survey
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the work of artificial intelligence, which forms the content of this project
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. non-static) 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");
}
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.