Skip to content
CodeKruPro

Your language · Java

Methods and functions

Parameters, return values, overloading or default arguments, and passing values.

Learn: Methods in Java: parameters, overloading and pass by value8 minute read

A method is a named block of code that does one job; in Java every function is a method that belongs to a class. Interview questions here test the rules behind everyday code: what makes two methods different, which overload the compiler picks, and what a method can change in the caller's variables. The last one, "is Java pass by value?", is asked in almost every Java interview.

Step 1: the parts of a method

public static int retryCount(String env, int defaultCount) throws IOException {
    ...
}

Reading left to right: modifiers (public, static), the return type (int, or void for nothing), the name, the parameter list, and a throws clause for checked exceptions (errors the compiler forces the caller to handle; see Exceptions). A method that returns a value must return one on every path.

The method's signature is its name plus the types of its parameters, in order. The return type, the parameter names and the throws clause are not part of it.

A static method belongs to the class and is called as ClassName.method(). It has no this (the word that means "the object this method was called on"), so it cannot use instance fields (the variables of one object) directly. An instance method is called on an object and can use that object's fields. A helper such as WaitUtils.waitForVisible(...) is often static, while loginPage.login(user) is an instance method because it needs the page's driver (the Selenium object that controls the browser).

Step 2: Java is always pass by value

When you call a method, Java copies the value of each argument into the parameter. For a primitive, that value is the number itself. For an object, the variable holds a reference (the address of the object), so the method gets a copy of the reference. Both copies point at the same object, which leads to two different results:

  • Calling a method that changes the object, such as list.add, is visible to the caller.
  • Assigning a new object to the parameter only changes the method's own copy of the reference.
import java.util.*;

public class Main {
    static void bump(int n) { n++; }
    static void addItem(List<String> list) { list.add("added"); }
    static void replace(List<String> list) {
        list = new ArrayList<>();
        list.add("lost");
    }

    public static void main(String[] args) {
        int count = 1;
        bump(count);
        System.out.println(count);

        List<String> items = new ArrayList<>(List.of("first"));
        addItem(items);
        replace(items);
        System.out.println(items);
    }
}
1
[first, added]

Step 3: overloading and how the compiler chooses

Overloaded methods share a name but differ in the number, types or order of parameters. Changing only the return type or the parameter names does not compile. The compiler picks an overload from the declared types of the arguments, in three phases. The declared type is the type written on the variable, for example Object in Object text = "hello";. The phases are: an exact or widening match first (widening means a smaller type fits into a bigger one, such as int to long), then boxing (int to Integer), and varargs last (a parameter that takes any number of values; step 4 explains it). If several methods match in one phase, it picks the most specific type, which is why type(null) chooses type(String) over type(Object). The choice happens at compile time (when the code is compiled, before it runs), so overloading is called compile-time polymorphism (one method name, several versions, chosen before the program runs).

public class Main {
    static String show(long x)    { return "long"; }
    static String show(Integer x) { return "Integer"; }
    static String show(int... x)  { return "varargs"; }

    static String type(Object o) { return "Object"; }
    static String type(String s) { return "String"; }

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

    public static void main(String[] args) {
        System.out.println(show(5));                 // widening wins
        System.out.println(type(null));              // most specific
        Object text = "hello";
        System.out.println(type(text));              // declared type decides
        System.out.println(sum() + " " + sum(1, 2, 3) + " " + sum(new int[] {4, 5}));
    }
}
long
String
Object
0 6 9

Step 4: varargs, optional arguments and recursion

A varargs parameter (int... nums) accepts zero or more values and is an ordinary array inside the method. A method can have only one, and it must come last. Java has no default parameter values, so a short overload calls the full one with the default:

public void waitForVisible(By locator) {
    waitForVisible(locator, Duration.ofSeconds(10));     // default timeout
}
public void waitForVisible(By locator, Duration timeout) {
    new WebDriverWait(driver, timeout).until(ExpectedConditions.visibilityOfElementLocated(locator));
}

For many optional values, a builder is clearer: an object that collects the settings one by one and then creates the final object (see Design patterns). A method may also call itself, which is called recursion. Each call adds a frame (a record of one method call) to the stack, the memory area that tracks active calls, so recursion without a correct stopping case ends in StackOverflowError.

How to answer in an interview

For pass by value, say the rule and then show the two cases: "Java is always pass by value. For objects, the value passed is a copy of the reference. So list.add inside the method is visible to the caller, but list = new ArrayList<>() is not." For an overload question, name the phase that wins: "show(5) prints long, because widening is tried before boxing."

Common mistakes

  • Saying "objects are passed by reference". Reassigning the parameter never changes the caller's variable.
  • Trying to overload by return type alone.
  • Thinking the runtime type picks the overload. The declared type does.
  • Passing null (no value) to mean "use the default". Write an overload instead.

Recap

A signature is the name plus the parameter types. Static methods belong to the class; instance methods use an object's fields. Java copies every argument: changes to a shared object are visible, reassignments are not. Overloads are chosen at compile time: widening, then boxing, then varargs. Use overloads or a builder for optional arguments.

9 questions0/9 solved

StatusQuestionDifficultyAsked in
Not startedChanging a parameter inside a methodEasyAsked in: Infosys
Not startedIs Java pass by value or pass by reference?MediumAsked in: Infosys
Pro+Which pairs are valid overloads?Easy-MediumAsked in: Accenture, Capgemini, Infosys +2
Pro+Which overload does the compiler pick?Medium
Pro+Varargs parametersEasy-Medium
Pro+A method that reassigns a list parameterMediumAsked in: Infosys
Pro+Java has no default parameter values: what do you do?Easy-Medium
Pro+What is part of a method signature?Easy-MediumAsked in: Accenture, Capgemini, Infosys +2
Pro+Calling an overloaded method with nullMedium-Hard
Not startedNot startedIn progressIn progressSolvedSolvedPro+Pro+

The first 2 questions of each topic are free. Pro+ opens every question.

Back to the plan