Java Return Values

In the last lesson you learned about Java method parameters, the inputs to a method. The other half is output. A method that adds two numbers should give the sum back so you can store or reuse it, and that is done with a return value.

🤔 Why return a value instead of printing?

Think of a vending machine. Pressing the button should drop the snack into your hands, not just flash its name on a screen. A method is the same.

Here is the print-only version. The result lands on the screen and is gone.

static void add(int a, int b) {
System.out.println(a + b); // ❌ prints, but the result is lost
}

A printed value is a dead end. A returned value comes back into your code, where you can:

  • Store it in a variable and use it later.
  • Pass it into another method so methods work together.
  • Test it, so your if statements can react to it.

🧩 The return statement

Returning a value takes two parts. Here is the general shape.

returnType methodName(parameters) {
// do some work
return someValue; // hand this value back to the caller
}

The two parts, plus the rule people miss:

  • Return type sits at the front of the header, before the name. It promises what kind of value comes out, like int, String, or boolean.
  • return statement sends the value back to the line that called the method.
  • return does two jobs at once: it sends the value and immediately ends the method, even if more lines sit below it.

💡 A method that returns a value

Here add returns the sum instead of printing it. The return type is int.

public class Calculator {
static int add(int a, int b) {
int sum = a + b;
return sum; // ✅ give the sum back to the caller
}
public static void main(String[] args) {
int result = add(5, 3); // store what add gives back
System.out.println("Sum: " + result);
System.out.println("Doubled: " + (result * 2));
}
}

Reading it from the top:

  • static int add(...) promises to hand back an int.
  • int sum = a + b; does the work in a local variable.
  • return sum; sends that value back and ends the method.
  • int result = add(5, 3); catches the returned value in result.

The key idea: the call add(5, 3) becomes the value 8 in your code, as if you typed int result = 8;. Now you own it: print it, double it, feed it into more math.

Output

Sum: 8
Doubled: 16

🔗 Using a returned value: store it, print it, pass it on

A call that returns a value can be used anywhere a value of that type fits. You can:

  • Store it in a variable, like int r = add(5, 3);.
  • Print it directly, like System.out.println(add(5, 3));.
  • Pass it on as an argument to another method.
  • Chain it by calling another method on the result.

This example passes a returned value straight into another call.

public class Calculator {
static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
// use the returned value directly, no variable needed
System.out.println("Total: " + add(10, add(20, 30)));
}
}

Java works add(10, add(20, 30)) from the inside out:

  • Inner add(20, 30) runs first and returns 50.
  • The line now reads add(10, 50), which returns 60.
  • Each call becomes a value the outer call can use as an argument.

This is exactly why returning beats printing.

Output

Total: 60

🚦 void vs a real return type

The choice comes down to one question: does the method produce a result you want back?

  • Use a real return type (int, String, boolean) when the method computes a value you want to use.
  • Use void when the method just does something, like printing, and has nothing to hand back.
  • void means “empty”, so you cannot store its call. int x = printResult(4); is an error.

Here is a void method beside a returning one.

public class Demo {
// ✅ returns a value
static boolean isEven(int n) {
return n % 2 == 0;
}
// ✅ returns nothing, just acts
static void printResult(int n) {
if (isEven(n)) {
System.out.println(n + " is even");
} else {
System.out.println(n + " is odd");
}
}
public static void main(String[] args) {
printResult(4);
printResult(7);
}
}
  • isEven returns a boolean. The expression n % 2 == 0 already is a boolean, so we return it directly.
  • printResult uses that boolean in its if, then just prints, so it is void.
  • A returning method becomes a clean building block inside another method.

Output

4 is even
7 is odd

🛑 Using return; to exit early from a void method

A void method returns nothing, but it can still use return:

  • Write return; with no value after it.
  • It means “stop here and go back to the caller now”.
  • No value is sent, because there is nothing to send. It is a clean early exit.

This void method checks for bad input and quits before the real work.

public class Greeter {
static void greet(String name) {
if (name == null) {
System.out.println("No name given.");
return; // ✅ stop here, skip the rest
}
System.out.println("Hello, " + name + "!");
}
public static void main(String[] args) {
greet(null);
greet("Riya");
}
}
  • First call: name is null, so we print the warning and return; jumps back. The greeting line never runs.
  • Second call: name is "Riya", so we skip the if and print the greeting.

So return; lets even a void method quit early when it needs to.

Output

No name given.
Hello, Riya!

🧱 Returning early with guard clauses

Early exit is even more useful in methods that do return a value. A guard clause is a check at the top that returns straight away for the unusual or invalid cases. The rest of the method then stays flat and focused on the normal case.

First, the nested version, where the real work is buried deep inside.

// ❌ deeply nested, hard to follow
static String classifyAge(int age) {
if (age >= 0) {
if (age < 13) {
return "child";
} else {
if (age < 20) {
return "teen";
} else {
return "adult";
}
}
} else {
return "invalid";
}
}

Now the guard-clause version. We handle the odd case first, then continue.

// ✅ guard clause first, then the flat main logic
static String classifyAge(int age) {
if (age < 0) {
return "invalid"; // deal with the bad case and leave
}
if (age < 13) {
return "child";
}
if (age < 20) {
return "teen";
}
return "adult";
}

Both give the same answers, but the second is far easier to read:

  • We knock out the invalid case immediately and return.
  • After that, every remaining line can assume the age is valid.
  • Early returns are a tool that keeps methods flat and readable, not a trick to avoid.

🔀 Many return statements, but only the first one reached runs

A method can have as many return statements as you like (classifyAge above has four). The rule:

  • Only one return runs for a single call.
  • The first return your code reaches ends the method on the spot.
  • Every return below it is skipped for that call.

This max method has two returns, but only one fires.

public class MathUtil {
static int max(int a, int b) {
if (a > b) {
return a; // if this runs, the method ends here
}
return b; // only reached when a is not greater than b
}
public static void main(String[] args) {
System.out.println("Max of 8 and 3: " + max(8, 3));
System.out.println("Max of 4 and 9: " + max(4, 9));
}
}
  • max(8, 3): 8 > 3 is true, so return a; runs and the method ends. return b; is never touched.
  • max(4, 9): 4 > 9 is false, so we skip the if and fall through to return b;, giving back 9.

Both returns exist, but each call uses exactly one.

Output

Max of 8 and 3: 8
Max of 4 and 9: 9

🧵 Returning a String (and matching the type)

You can return any type, including a String. The rule is always the same: the returned value must match the declared return type, or be safely convertible to it.

This method builds a String and returns it.

public class Welcome {
static String buildMessage(String name, int score) {
return "Hi " + name + ", you scored " + score + ".";
}
public static void main(String[] args) {
String msg = buildMessage("Alex", 95);
System.out.println(msg);
}
}
  • static String buildMessage(...) promises a String. The expression after return joins text and numbers into a String, so the types agree.
  • “Convertible”: a method declared double can return 5;. Java safely widens the int 5 into 5.0.
  • The reverse is blocked: returning a double where an int is promised needs an explicit cast, because you could lose part of the number.

Output

Hi Alex, you scored 95.

⚠️ Common Mistakes

A few return slip-ups trip up almost everyone at first.

Missing a return on some path. Every possible path through a method must return a value. If your if returns but nothing handles the other case, Java refuses to compile.

// ❌ what if a is NOT greater than b? No return on that path.
static int max(int a, int b) {
if (a > b) {
return a;
}
}
// ✅ every path returns a value
static int max(int a, int b) {
if (a > b) {
return a;
}
return b;
}

Unreachable code after a return. Once return runs, the method ends. Any line after it on the same path can never run, and Java reports an “unreachable statement” error.

// ❌ the print can never run
static int five() {
return 5;
System.out.println("done"); // unreachable, compile error
}

Ignoring the returned value. Calling a method but throwing away what it gives back is usually a mistake. The work was done, but the answer is lost.

// ❌ the sum is computed, then lost
add(5, 3);
// ✅ catch the value so you can use it
int total = add(5, 3);

Type mismatch. The value you return must match the declared type. Promising an int and returning text will not compile.

// ❌ method promises int but returns a String
static int getCount() {
return "ten";
}
// ✅ return a value of the declared type
static int getCount() {
return 10;
}

✅ Best Practices

Habits that make return values clean and reliable.

  • Return results, do not just print them. A returned value can be reused; let the caller decide whether to print.
  • Pick the smallest fitting return type. boolean for yes or no, int for whole numbers, String for text. The type tells the reader what to expect.
  • Use void only for pure actions like printing, where there is nothing to give back.
  • Use guard clauses to return early. Handle the odd case at the top so the main logic stays flat.
  • Return a value the moment you know it. As soon as the answer is certain, return it.

🧩 What You’ve Learned

Nicely done. Let’s recap return values.

  • ✅ A method sends a result back with the return statement, and its return type says what kind.
  • return does two things at once: it sends the value back and immediately ends the method.
  • ✅ Returning lets you store, print, pass on, or chain the result, unlike printing which loses it.
  • void means returns nothing, but return; can still be used to exit a void method early.
  • Guard clauses return early for odd cases, keeping the rest of the method flat.
  • ✅ A method can have many return statements, but only the first one reached runs.
  • ✅ Code after a return on the same path is unreachable, and a non-void method must return on every path.

Check Your Knowledge

Test what you learned. Pick an answer for each question, then click Check.

  1. 1

    What two things does the return statement do?

    Why: return hands a value back to whoever called the method and stops the method right there, both at once.

  2. 2

    Can a void method use return?

    Why: A void method can write return; (no value) to stop and go back to the caller early.

  3. 3

    A method has several return statements. How many run for a single call?

    Why: The first return reached ends the method, so every return below it is skipped for that call.

  4. 4

    What happens to code written after a return statement on the same path?

    Why: return ends the method, so code after it on that path is unreachable and is a compile error.

🚀 What’s Next?

Sometimes you want several methods with the same name that handle different inputs, like an add for two numbers and an add for three. Java lets you do this with method overloading. Let’s learn how.

Java Method Overloading

Share & Connect