Unit 3 · 22 min
3.5 Methods: How to Write Them
A method's header is its promise: the return type says what comes back, the parameters say what goes in.
Summary, objectives and course and exam description (CED) codes
A void method does not return a value; a non-void method returns a single value of its return type, and this is called return by value. A return statement sends the flow of control back to the caller at once. Accessor methods give other classes a copy of a variable's value, mutator methods change it, and a primitive parameter is a copy of its argument.
By the end of this session you can
- 3.5.A Develop code to define behaviors of an object through methods written in a class using primitive values, and determine the result of calling these methods.
Reviewed against the CED on
1LearnThe notes, the traps and how to remember them
1. void and non-void methods
The method header tells you whether a method returns a value.
| Kind | Header | Returns |
|---|---|---|
| void method | public void refill() |
nothing; the keyword void comes before the method name 3.5.A.1 |
| non-void method | public int getAmount() |
a single value; the return type takes the place of void 3.5.A.2 |
Here is a complete class in the AP® free-response “class design” style. It is used in every section of this page.
public class WaterBottle
{
private static int bottlesMade = 0; // class variable
private int capacity; // in milliliters
private int amount; // in milliliters
public WaterBottle(int maxMilliliters)
{
capacity = maxMilliliters;
amount = maxMilliliters;
bottlesMade++;
}
// ----- accessor methods (non-void) -----
public int getAmount()
{
return amount;
}
public boolean isEmpty()
{
return amount == 0;
}
public double percentFull()
{
return 100.0 * amount / capacity;
}
public static int getBottlesMade()
{
return bottlesMade;
}
// ----- mutator methods (void) -----
public void drink(int milliliters)
{
if (milliliters > amount)
{
amount = 0;
}
else
{
amount -= milliliters;
}
}
public void refill()
{
amount = capacity;
}
public String toString()
{
return amount + "/" + capacity + " mL";
}
}
WaterBottle bottle = new WaterBottle(750);
bottle.drink(300);
System.out.println(bottle.getAmount());
System.out.println(bottle.percentFull());
bottle.drink(500);
System.out.println(bottle.isEmpty() + " " + bottle);
bottle.refill();
System.out.println(bottle);
Output:
450
60.0
true 0/750 mL
750/750 mL
Background: toString lets println show the bottle as text. You will read toString methods in class code, but writing one is outside the AP® exam.
A call to a void method is a statement on its own (bottle.refill();). A call to a non-void method is an expression: its value is printed, stored or used in a calculation.
2. Return by value
In a non-void method, a return expression that is compatible with the return type is evaluated, and that value is returned to the caller. This is called return by value 3.5.A.3.
public class Average
{
public static double mean(int a, int b)
{
return (a + b) / 2.0;
}
public static int meanRounded(int a, int b)
{
return (int) ((a + b) / 2.0 + 0.5);
}
}
System.out.println(Average.mean(7, 8));
System.out.println(Average.meanRounded(7, 8));
Output:
7.5
8
A double expression is not compatible with an int return type, so this does not compile:
public class BadAverage
{
public static int mean(int a, int b)
{
return (a + b) / 2.0;
}
}
Compiler says:
error: incompatible types: possible lossy conversion from double to int
A non-void method must return a value on every path through the method:
public class Grader
{
public static String letter(int score)
{
if (score >= 90)
{
return "A";
}
}
}
Compiler says:
error: missing return statement
3. return ends the method
The return keyword sends the flow of control back to the point where the method or constructor was called 3.5.A.4. Any code that comes after a return statement in sequence is never executed 3.5.A.4. A return statement inside a selection (if) or iteration (loop) statement stops that statement and exits the whole method or constructor 3.5.A.4.
This method searches a string and stops at the first digit it finds:
public class Finder
{
/** Returns the index of the first digit in s, or -1 if none */
public static int firstDigit(String s)
{
for (int i = 0; i < s.length(); i++)
{
String ch = s.substring(i, i + 1);
if ("0123456789".indexOf(ch) >= 0)
{
return i; // leaves the loop AND the method
}
}
return -1; // reached only if no digit was found
}
}
System.out.println(Finder.firstDigit("Room 42B"));
System.out.println(Finder.firstDigit("Lobby"));
Output:
5
-1
A void method can use return; with no value to exit early:
public class Launch
{
public static void countdown(int start)
{
for (int i = start; i >= 0; i--)
{
if (i == 2)
{
return;
}
System.out.println(i);
}
System.out.println("Liftoff!");
}
}
Launch.countdown(5);
Output:
5
4
3
“Liftoff!” is never printed: the return ended the method, not only the loop.
Code placed directly after a return statement can never run, so the compiler rejects it:
public class Doubler
{
public static int twice(int n)
{
return n * 2;
System.out.println("done");
}
}
Compiler says:
error: unreachable statement
4. Accessors and mutators
An accessor method lets objects of other classes obtain a copy of the value of an instance variable or a class variable. An accessor is a non-void method 3.5.A.5. In WaterBottle, getAmount returns a copy of amount, and the class method getBottlesMade returns a copy of the class variable bottlesMade.
A mutator method (also called a modifier method) changes the values of instance variables or class variables. A mutator is often a void method 3.5.A.6. In WaterBottle, drink and refill are mutators.
WaterBottle a = new WaterBottle(500);
WaterBottle b = new WaterBottle(1000);
int copy = a.getAmount();
copy = 0;
b.drink(250);
System.out.println(a.getAmount() + " " + b.getAmount());
System.out.println(WaterBottle.getBottlesMade());
Output:
500 750
2
Changing copy did not empty bottle a: the accessor handed out a copy of the value, not the instance variable itself.
| Method | Accessor or mutator? | void? |
|---|---|---|
getAmount() |
accessor | no, returns int |
isEmpty() |
accessor | no, returns boolean |
drink(int milliliters) |
mutator | yes |
refill() |
mutator | yes |
5. Parameters and primitive values
Methods with parameters receive values through them and use those values to do their task 3.5.A.7. When the argument is a primitive value (int, double, boolean), the parameter is initialized with a copy of that value. Changes to the parameter have no effect on the argument 3.5.A.8. Passing copies of argument values like this is called call by value (you met it with constructors in topic 1.13).
public class Bonus
{
public static int addBonus(int points)
{
points = points + 10;
return points;
}
}
int myPoints = 50;
int result = Bonus.addBonus(myPoints);
System.out.println(myPoints + " " + result);
Output:
50 60
Memory, step by step:
| Moment | myPoints (in the caller) |
points (parameter) |
result |
|---|---|---|---|
| Before the call | 50 | does not exist | does not exist |
Start of addBonus |
50 | 50 (a copy) | does not exist |
After points = points + 10 |
50 | 60 | does not exist |
| After the call returns | 50 | gone | 60 |
Watch out: if the method should change the caller’s variable, the caller must store the returned value: myPoints = Bonus.addBonus(myPoints);.
Lock it in: memory hooks
- void vs non-voidvoid: does a job, hands nothing back. Non-void: does a job, hands back exactly one value.
- returnreturn is an exit door: once you go through it, the method is over.
- Primitive parametersThe method gets a photocopy of the number. Scribbling on the photocopy does not change the original.
Common misconceptions
"A method can keep running after its return statement."
Not quite. return sends control back to the caller immediately. Code after it in the same block never runs (the compiler rejects it as unreachable), and a return inside a loop ends the loop and the method.
"If a method changes its int parameter, the caller's variable changes too."
Not quite. A primitive parameter is a copy of the argument's value. Changing the copy has no effect on the caller's variable.
"A method that prints a value returns it."
Not quite. Printing shows text in the console; returning gives a value back to the caller. A void method that prints cannot be used in an expression like int x = obj.show();
Exam traps
- A non-void method must return a value on every path, or it does not compile (missing return statement).
- Returning a double from an int method does not compile; returning an int from a double method is fine (widening).
- A return inside a for loop stops the loop on the first match; the rest of the loop is skipped.
- After void method calls, check whether the caller's variable was passed as a primitive: it never changes.
2PracticeRecall it, then check yourself
In 30 seconds
- void method: no return value, keyword void in the header. Non-void method: return type in place of void, returns a single value.
- The return expression must be compatible with the return type; its value is returned (return by value).
- return sends control back to the caller; code after it never runs; a return inside a loop or if exits the whole method.
- Accessor: non-void, gives a copy of an instance or class variable's value. Mutator: changes the value, often void.
- Parameters receive values; a primitive parameter is a copy, so changing it does not change the argument.
Cover this list, say the points out loud, then take the checkpoint without scrolling back up.
Checkpoint · 6 questions
Checkpoint: Methods: How to Write Them
Pick an answer to mark it. Every answer is explained, and you can try any question again. Your saved score counts first tries only, and stays in this browser.
3PrevailLock it in for exam day
By the numbers
- Kinds of method by return two kinds CED 3.5.A.1, 3.5.A.2
- void methodkeyword void before the name, returns nothing
- non-void methodreturn type before the name, returns a single value
- Methods that work with an object's data two kinds CED 3.5.A.5, 3.5.A.6
- accessora non-void method that gives a copy of the value of an instance or class variable
- mutator (modifier)changes the value of an instance or class variable, often void
- Where a return statement sends control two places CED 3.5.A.4
- back to the point where the method was called
- back to the point where the constructor was called
Key terms: flip the cards
Read the term, say the definition out loud, then flip to check. Struggling a little to remember is what makes it stick.
-
Return statementtap to flip
A statement that sends the flow of control back to the caller, and in a non-void method sends back a value compatible with the return type.
Example and CED codes -
Accessor methodtap to flip
A non-void method that lets objects of other classes obtain a copy of the value of an instance variable or class variable.
Example and CED codes -
Mutator methodtap to flip
A method that changes the values of instance variables or class variables; it is often a void method.
Example and CED codes -
Parametertap to flip
A variable declared in the header of a method or constructor. It receives the value passed in and can be used in the body.
Example and CED codes -
Argumenttap to flip
A value passed into a method or constructor when it is called.
Example and CED codes -
Return typetap to flip
The type of value a method sends back, written before the method name in the header, or void if it returns nothing.
Example and CED codes -
Class variabletap to flip
An attribute declared with the keyword static that belongs to the class, so all objects of the class share a single copy.
Example and CED codes -
Call by valuetap to flip
The way Java passes arguments: each parameter is initialized with a copy of the argument.
Example and CED codes -
toStringtap to flip
A method that returns a String representing an object; println and string concatenation call it automatically.
Example and CED codes
Questions students ask
What is the difference between a void and a non-void method?
A void method performs an action and returns nothing; its header has void before the name. A non-void method returns a single value; its header has a return type such as int, double, boolean or String instead of void.
What is the difference between an accessor and a mutator?
An accessor (getter) is a non-void method that returns a copy of an attribute's value without changing it. A mutator (setter or modifier) changes the value of an attribute and is often a void method.
Does Java pass primitive values by value?
Yes. When the argument is a primitive value, the parameter is initialized with a copy of that value, so changes to the parameter have no effect on the argument.
What happens to code after a return statement?
It is never executed. If it is in the same block, the compiler reports an unreachable statement error.