Methods
You've already used one method in every program so far — main — without necessarily thinking of it as one. A method is a named, reusable chunk of behavior: give it a job once, and call it by name as many times as you need instead of retyping the same logic everywhere.
Defining and calling a method
A method declaration needs a return type, a name, and a parameter list — even if that list is empty. Everything inside main up to now has technically been running as static, and any helper method you call from it needs to be static too, for reasons that will make more sense once classes and objects show up next lesson.
public class DiscountCalc {
public static double applyDiscount(double price, double percentOff) {
return price - (price * percentOff / 100);
}
public static void main(String[] args) {
double finalPrice = applyDiscount(80.00, 25);
System.out.println("Final price: $" + finalPrice);
}
}
Final price: $60.0
applyDiscount takes two double parameters and returns a double. Notice it's declared entirely outside main, as a sibling method in the same class — main calls it just like it would call any other method, by name, with values filled into its parameter list.
void vs. a real return type
A method's declared return type is a promise. If it says double, every path through that method must end in a return statement handing back a double — the compiler checks this and refuses to build the program otherwise. A method that only performs an action and doesn't need to hand anything back is declared void, and simply doesn't use return with a value (though a bare return; is allowed, to exit early).
public class ReceiptPrinter {
public static void printLine(String item, double price) {
System.out.println(item + " - $" + price);
}
public static void main(String[] args) {
printLine("Coffee", 4.50);
printLine("Bagel", 3.25);
}
}
Coffee - $4.5 Bagel - $3.25
Parameters are local copies
When you pass a primitive value into a method, Java copies it. Whatever the method does to its own parameter has no effect on the variable you passed in from outside:
public class CopyDemo {
public static void tryToDouble(int n) {
n = n * 2;
System.out.println("Inside method: " + n);
}
public static void main(String[] args) {
int value = 10;
tryToDouble(value);
System.out.println("Back in main: " + value);
}
}
Inside method: 20 Back in main: 10
value in main never changes, because tryToDouble only ever had a copy of the number 10 to work with, under the local name n. This is worth sitting with, because it's not how object references behave — as mentioned in the arrays lesson, passing an array or any other object into a method passes a reference to the same underlying data, so changes made through that reference are visible to the caller. Primitives copy the value; objects copy the reference to the value.
Overloading — same name, different parameters
Java lets you define multiple methods with the same name, as long as their parameter lists are different enough for the compiler to tell them apart. This is called overloading, and it's how System.out.println itself works — there's a version for String, one for int, one for double, and so on, all sharing the same name.
public class OverloadDemo {
public static int add(int a, int b) {
return a + b;
}
public static double add(double a, double b) {
return a + b;
}
public static void main(String[] args) {
System.out.println(add(2, 3));
System.out.println(add(2.5, 3.1));
}
}
5 5.6
main method into smaller, well-named helper methods isn't just about avoiding repetition — a method named applyDiscount or printLine documents what a chunk of logic is for, which makes the calling code read almost like a sentence instead of a wall of arithmetic.