• 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.
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");
}
• 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.
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;
}
• 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.
• 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.
• 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.
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.
• 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.
• 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.
Remember that %d stands for decimal, not float!
• %.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.
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
• 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).
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);
}
}
}
• 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.
• 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
/**
* 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);
}
}
• 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.
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);
}
}
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);
}
}
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);
}
}
• 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.
• 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));
}
• 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;
• 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.
• 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.