Skip to content

Methods — Parameters, Return Types, Overloading, Varargs, and Method References

DodaTech Updated 2026-06-28 7 min read

In this tutorial, you will learn about Methods. We cover key concepts, practical examples, and best practices to help you master this topic.

Java methods are reusable blocks of code that accept parameters, return values, and can be overloaded with different signatures. Methods are the fundamental unit of behavior in Java — every operation you perform, from System.out.println() to list.sort(), is a method call.

What You'll Learn

  • Method declaration syntax and the method signature
  • Pass-by-value semantics (including references)
  • Method overloading rules
  • Varargs and method references (::)

Why It Matters

Well-designed methods are the key to readable, testable, and maintainable code. Understanding overloading prevents ambiguous calls, and knowing pass-by-value semantics prevents bugs where you expect a method to modify the caller's variable.

Real-World Use

Every framework you use relies on method calls. Spring @Bean methods, JPA Repository methods, and stream pipeline methods all follow the same declaration rules. Method references make functional code more concise.


Method Declaration

A method declaration specifies access modifier, return type, name, parameter list, and body:

public static int add(int a, int b) {
    return a + b;
}
  • public — access modifier
  • static — belongs to the class, not instances
  • int — return type
  • add — method name
  • (int a, int b) — parameter list
  • return a + b — return statement

The Method Signature

The signature consists of the method name and parameter types: add(int, int). The return type and access modifier are not part of the signature. This distinction matters for overloading.

Parameters and Arguments

Java uses pass-by-value for all parameters:

public static void changeValue(int x) {
    x = 100; // only changes the local copy
}

int num = 5;
changeValue(num);
System.out.println(num); // still 5

For reference types, the reference is passed by value:

public static void changeName(StringBuilder sb) {
    sb.append(" World"); // modifies the object
    sb = new StringBuilder("New"); // does NOT affect caller's reference
}

StringBuilder builder = new StringBuilder("Hello");
changeName(builder);
System.out.println(builder); // "Hello World"

The method can modify the object through the reference, but it cannot change the reference itself.

Return Types

A method declares its return type; void means no return value:

public int square(int x) {
    return x * x;
}

public void greet(String name) {
    System.out.println("Hello, " + name);
    // no return needed
}

Early Returns

public boolean isEven(int number) {
    if (number % 2 == 0) {
        return true;
    }
    return false;
}

Returning Arrays and Objects

public int[] getFirstNNumbers(int n) {
    int[] result = new int[n];
    for (int i = 0; i < n; i++) {
        result[i] = i + 1;
    }
    return result;
}

Method Overloading

Overloading means multiple methods with the same name but different parameter lists:

public int add(int a, int b) {
    return a + b;
}

public int add(int a, int b, int c) {
    return a + b + c;
}

public double add(double a, double b) {
    return a + b;
}

The compiler selects the correct overload based on the argument types and count at compile time. This is compile-time polymorphism.

Rules

  • Methods must differ in parameter list (number, type, or order)
  • Return type alone is NOT sufficient for overloading
  • Changing the access modifier alone is NOT overloading
// INVALID: same signature, different return type
public int calculate() { return 1; }
public double calculate() { return 1.0; } // COMPILE ERROR

Overloading with Autoboxing and Varargs

The compiler resolves overloads in this order:

  1. Primitive widening (e.g., int to long)
  2. Autoboxing (e.g., int to Integer)
  3. Varargs
public void print(int i) { System.out.println("int: " + i); }
public void print(Integer i) { System.out.println("Integer: " + i); }
public void print(int... i) { System.out.println("varargs"); }

int x = 5;
print(x); // "int: 5" — widening beats boxing

Varargs

Varargs allow a method to accept zero or more arguments of a specified type:

public static int sum(int... numbers) {
    int total = 0;
    for (int n : numbers) {
        total += n;
    }
    return total;
}

System.out.println(sum());          // 0
System.out.println(sum(1));         // 1
System.out.println(sum(1, 2, 3));   // 6

Rules:

  • Only one varargs parameter per method
  • It must be the last parameter
  • Inside the method, it is treated as an array
public void log(String format, Object... args) {
    System.out.printf(format, args);
}

Method References (Java 8+)

Method references provide a shorthand for lambda expressions that call a single method:

List<String> names = List.of("Alice", "Bob", "Charlie");

// Lambda
names.forEach(name -> System.out.println(name));

// Method reference
names.forEach(System.out::println);

Four Types of Method References

Type Syntax Example
Static method ClassName::staticMethod Math::max
Instance method of a particular object instance::method System.out::println
Instance method of any object of a specific type ClassName::instanceMethod String::length
Constructor ClassName::new ArrayList::new
// Static method reference
Function<Integer, String> converter = String::valueOf;

// Instance method of an arbitrary object
Function<String, Integer> lengthFunc = String::length;

// Constructor reference
Supplier<List<String>> listSupplier = ArrayList::new;

Common Mistakes

  1. Confusing pass-by-value with pass-by-reference. Java always passes a copy. For primitives, the method cannot modify the caller's variable. For references, the method can modify the object but not reassign the reference.
  2. Overloading methods with the same erasure. Due to type erasure, List<String> and List<Integer> have the same runtime type. Overloading with different generic types compiles but creates ambiguity.
  3. Using varargs in overloaded methods. Calling sum() matches both sum(int...) and sum() if it exists, causing ambiguity.
  4. Forgetting the return statement in a non-void method. This is a compile error — the compiler checks all code paths.
  5. Calling overloaded methods with null. print(null) when print(String) and print(Integer) both exist: the compiler reports ambiguity because both are equally specific.

Practice Questions

1. Can you have two methods with the same name and parameter list but different return types?
No. The method signature does not include the return type. The compiler would see duplicate method declarations.

2. Does Java pass objects by reference?
No. Java passes object references by value. The method receives a copy of the reference, can modify the object through it, but cannot make the caller's reference point to a different object.

3. What is the difference between a method signature and a method declaration?
The signature is the method name + parameter types. The declaration includes the return type, access modifier, and throws clause.

4. How does the compiler resolve overloaded methods?
It finds methods with matching names, then selects the most specific match using widening, autoboxing, and varargs in that priority order.

5. What is the purpose of method references?
To pass an existing method as a functional argument — a more concise alternative to a lambda when the lambda only calls one existing method.

Challenge Question:
Write a method void assertEquals(Object expected, Object actual) that prints "PASS" if the two objects are equal (using .equals()) and "FAIL" with details otherwise. Then overload it for int, long, and double primitives. Finally, write a varargs version void assertEquals(Object... pairs) that accepts expected/actual pairs.

FAQ

Why does Java not have default parameter values like Python or C++?

Java does not support default parameter values. Instead, use method overloading to provide multiple versions with different parameter counts, or use the Builder pattern for methods with many optional parameters.

Can I return multiple values from a method?

A method can return only one value. To return multiple values, create a class (like a record), return an array, or use a container like Pair or List.

What is the `void` keyword?

void indicates that a method does not return a value. It is not a type — you cannot declare a variable of type void.

Can a method throw multiple exceptions?

Yes, a method can declare multiple exceptions in its throws clause. Java 7+ allows catching multiple exception types in a single catch block.

What is a static method?

A static method belongs to the class itself, not to instances. It can be called without creating an object (ClassName.method()). Static methods cannot access instance fields or this.

Mini Project

Write a program MethodPlayground.java that:

  1. Defines a static method max(int... numbers) that returns the maximum value from varargs
  2. Overloads max(double... numbers) for doubles
  3. Creates a printTable method that prints a formatted table from a 2D int[][] with variable column widths
  4. Implements a repeat method using method references: public static void repeat(int n, Runnable action) that calls action.run() n times
  5. Tests pass-by-value with a method that tries to swap two integers but fails, then shows the correct approach using an array or wrapper

Run each section and verify the output.

What's Next

Methods work with data, and the most common data type in Java is the String. Lesson 10 explores strings in depth — the String pool, immutability, StringBuilder and StringBuffer for efficient concatenation, and text blocks for multi-line strings.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro