Command Palette

Search for a command to run...

PHASE 3Beginner ~27 min· topic 2 of 11

Topic 3.2

Parameters and Return Values

In one line

Parameters let a method receive input values, and a return value lets it hand one result back to the caller. Together they turn a method into a reusable little machine: values go in, work happens, a result comes out.

Think of it like this

A juice machine. You put fruit in the slot (the arguments), the machine works, and a glass of juice comes out the bottom (the return value). The machine has labelled slots, "apple" and "orange" (the parameters), and it only accepts the right kind of fruit in each slot.

Words you'll meet

New words in this topic, in plain English. Come back here whenever one feels fuzzy.

Parameter
A variable listed in the method header, such as int x. It receives a value each time the method is called.
Argument
The actual value given in a call, such as 5 in square(5). It is copied into the matching parameter.
Return value
The result a method hands back to its caller with return. The call expression is replaced by this value.
Return type
The type written before the method name that says what kind of value comes back, or void for nothing.
Signature
A method's name plus its list of parameter types, such as square(int). The return type is not part of it.
Widening conversion
Turning a value into a bigger type that can hold every value of the smaller one, such as int to double. Java does it automatically.
Side effect
Anything a method does besides returning a value: printing, changing a variable outside itself, writing a file.
Pure method
A method whose result depends only on its arguments and that has no side effects. Easy to test and reason about.

Step by step

01Input: parameters

A method with no parameters always does the same thing. Add a parameter and it can work on whatever value the caller chooses.

In static void greet(String name), name is a parameter: a local variable that exists only inside greet. Each call fills it with the argument: greet("Asha") sets name to "Asha" for that call only.

Multiple parameters are separated by commas, and each needs its own type: (int width, int height), never (int width, height).

Main.javawhole filejava
static void greet(String name, int times) {
    for (int i = 0; i < times; i++) {
        System.out.println("Hello, " + name);
    }
}
// greet("Asha", 2);   prints Hello, Asha twice

02Output: return values

Replace void with a type, and the method must give back a value of that type with return. The call then becomes that value wherever you wrote it: int area = rectangleArea(3, 4); stores 12.

Because a call is an expression, you can use it anywhere a value fits: inside println, inside arithmetic, or as an argument to another call: square(square(2)) is 16.

return does two things at once: it sets the result and it ends the method immediately.

Main.javawhole filejava
static int rectangleArea(int width, int height) {
    return width * height;
}

int a = rectangleArea(3, 4);                 // 12
System.out.println(rectangleArea(2, 5) + 1); // 11

03Every path must return

For a non-void method the compiler checks every route through the body. If any route can reach the closing brace without a return, you get missing return statement.

In the example below, if a > b is false nothing is returned. The compiler doesn't run your code to see whether that can happen; it just checks the structure. Add a final return b; or use if/else with a return in both branches.

Main.javawhole filejava
static int max(int a, int b) {
    if (a > b) {
        return a;
    }
    // error: missing return statement (nothing returned when a <= b)
}

04How values are matched and converted

Arguments are matched by position. rectangleArea(3, 4) sets width = 3, height = 4. Swap them and you get a different meaning with no error, which is why methods with many same-typed parameters are risky.

Each argument must be assignable to its parameter type. An int fits into a double parameter (widened to 7.0). A double into an int parameter fails with incompatible types: possible lossy conversion from double to int. Cast explicitly, square((int) 2.5), if you really want to drop the fraction.

The same rule applies to return: in a method returning double, return 7; is fine (widened); in a method returning int, return 7.5; is a compile error.

05Order of evaluation is left to right

Before the body runs, Java evaluates each argument expression, from left to right, and only then copies the values into the parameters. JLS section 15.7.4 guarantees this order; in C it's unspecified.

This matters when arguments have side effects, such as a method that prints, or i++. With int i = 1; f(i++, i++); the method receives 1 and 2, always.

06What the bytecode shows

Parameters are just the first local variables of the method's frame. In add(int a, int b), a is local slot 0 and b is slot 1. The caller pushes the argument values, invokestatic creates the new frame with those values in slots 0 and 1, and ireturn hands the top value back.

The descriptor (II)I reads: two int parameters, returns int.

terminal
$ javap -c Main
── expected output ──
static int add(int, int);
Code:
0: iload_0
1: iload_1
2: iadd
3: ireturn
 
public static void main(java.lang.String[]);
Code:
0: iconst_2
1: iconst_3
2: invokestatic #7 // Method add:(II)I
5: istore_1
...
For `static int add(int a, int b) { return a + b; }` called as `add(2, 3)`.

07Returning more than one value

A method can only return one thing. When you need two results (say the smallest and largest number in a list), return a container holding both: an array now, and a record once you reach Topic 4.9 (record MinMax(int min, int max)), which is clearer because each part has a name.

Prefer pure methods where you can: take everything as parameters, return the result, and don't print or change anything else. They're the easiest to test and reuse. Keep printing in main or in methods whose job is printing.

Try it yourself

  1. 1

    Predict, then run

    In "Parameters in, result out", change average to divide by 3 instead of 3.0. Predict the new average line before running. (It becomes 81.0: 245 / 3 is integer division giving 81, then widened to double for the return.)

  2. 2

    Swap the arguments

    Write static int power(int base, int exp) using a loop. Call power(2, 10) and power(10, 2). Both compile, but the results are 1024 and 100: position, not meaning, decides which parameter gets which value.

  3. 3

    Trigger a missing return

    Write max(int a, int b) with only if (a > b) return a;. Read the compile error, then fix it two ways: with an else, and with a final return b;.

Code & diagrams

Parameters in, result out New tab
Sign in to run this example in your browser.

Expected output

area = 12
average = 81.66666666666667
10 even? true
7 even? false
nested = 12
Arguments are evaluated left to right New tab

Each argument is fully evaluated, in order, before add3 starts.

Sign in to run this example in your browser.

Expected output

evaluating first
evaluating second
evaluating third
inside add3
sum = 6
inside add3
i++ twice: 3
i is now 3
Widening arguments and returning two values in an array New tab
Sign in to run this example in your browser.

Expected output

half(7) = 3.5
min = 7
max = 42
done

Break it on purpose

Errors are the best teachers. Make each change, read the error, guess what went wrong, then reveal the answer.

Break #1

Pass a double where an int is expected

Call square(2.5) where square takes an int.

Main.javawhole filejava
static int square(int x) { return x * x; }
public static void main(String[] args) {
    System.out.println(square(2.5));
}
terminal
$ javac Main.java
── what you'll see ──
Main.java:4: error: incompatible types: possible lossy conversion from double to int
System.out.println(square(2.5));
^
Note: Some messages have been simplified; recompile with -Xdiags:verbose to get full output
1 error

Break #2

Forget a return path

Return only inside an if, with nothing after it.

Main.javawhole filejava
static int max(int a, int b) {
    if (a > b) {
        return a;
    }
}
terminal
$ javac Main.java
── what you'll see ──
Main.java:6: error: missing return statement
}
^
1 error

Myth vs fact

Myth

Parameters and arguments are the same thing.

Fact

A parameter is the variable in the declaration. An argument is the value supplied in a call. The argument's value is copied into the parameter.

Myth

The parameter name must match the variable name used by the caller.

Fact

Names are unrelated. square(side) and square(5) both work; only position and type matter.

Myth

A method can return two values with return a, b;.

Fact

That doesn't compile. Return an array, an object or a record that holds both.

Myth

You must use a method's return value.

Fact

You may ignore it. Some tools warn when you ignore results that matter (like String.trim()), because strings are immutable and the result is the only change.

Pro corner

Extra depth for experienced readers. New to this? Skip it for now and come back later.

  • ▸

    The return type is not part of a method's Java signature, so you can't overload on return type alone (Topic 3.4). The JVM's descriptor does include it, which is how the compiler can emit *bridge methods* for generics and covariant returns (Topic 8.6).

  • ▸

    Parameters can be marked final (static int f(final int x)), which stops reassignment inside the body. It's a readability choice: it doesn't change the caller, and it doesn't appear in bytecode as a constraint on the caller.

  • ▸

    Long parameter lists of the same type ((int, int, int, int)) are a classic bug source because swapped arguments still compile. Seniors replace them with a parameter object or record, or with a builder (see the System Design course's Builder pattern).

Remember this

  1. 1

    A parameter is a variable declared in the method header, like int x in static int square(int x). An argument is the actual value you pass in the call, like the 5 in square(5). When the method starts, each parameter is set to a copy of its argument.

  2. 2

    The return type comes before the name: int, double, boolean, String, an array type, or void for no result. A non-void method must end every possible path with return <value>; of a compatible type, or the compiler reports missing return statement.

  3. 3

    Arguments are matched to parameters by position, not by name: the first argument goes into the first parameter, and so on. Java has no named or default arguments; overloading (Topic 3.4) is the usual substitute for defaults.

  4. 4

    Java checks types at compile time. An int argument can go into a double parameter (a safe widening conversion), but a double can't go into an int parameter without an explicit cast, because information might be lost (Topic 1.6).

  5. 5

    Arguments are evaluated left to right, fully, before the method body starts. This is guaranteed by the Java Language Specification, so side effects in arguments (like printing) happen in a predictable order.

  6. 6

    A method returns at most one value. To return several, return an array, an object, or (from Java 16) a record (Topic 4.9). The caller may also ignore a return value: Math.max(1, 2); on its own line compiles and the result is thrown away.

Explain it without notes

01

What is the difference between a parameter and an argument? Use one example call to show both.

02

Why does missing return statement appear even when you know the condition is always true at run time?

03

In what order are method arguments evaluated in Java, and why does it matter?

04

How would you return both the minimum and maximum of three numbers from one method?

Practice

01

Write static double celsiusToFahrenheit(double c) (F = C x 9 / 5 + 32) and print the result for 0, 37 and 100.

02

Write static boolean isLeapYear(int year) (divisible by 4, except centuries, unless divisible by 400) and test 1900, 2000, 2024 and 2023.

03

Write static int countVowels(String s) that returns how many of a e i o u (lower case) the string contains, and test it on "programming".

Trade-offs

  • ↔

    Pure methods (inputs in, result out, no printing) are easy to test and reuse, but at some point a program must print or save. Keep the side effects at the edges, in a few clearly named methods.

  • ↔

    Returning an array for multiple results is quick but unclear (result[0] means what?). A record costs one line and documents itself.

  • ↔

    Many parameters make a method flexible but easy to call wrongly. Past three or four, consider grouping them into an object.

Done when you can

  • Done when you can write a method with several parameters and a return value, and use the result.

  • Done when you can explain parameter vs argument with an example.

  • Done when you can fix missing return statement and possible lossy conversion errors.

  • Done when you can predict output when arguments have side effects.

  • Done when you can return two results from one method.