By WebNest Studio Engineering Team
Java - Core Tutorial
Java Methods and Method Overloading
A method is a named block of code that performs a specific task and can be invoked (called) whenever that task needs to be repeated. Methods let you break a program into small, reusable, testable pieces instead of writing one long block of instructions, and they are how objects in Java expose their behavior to the rest of the program.
Method overloading is the ability to define multiple methods in the same class that share the same name but differ in their parameter list. This is Java's form of compile-time polymorphism: the compiler decides which overloaded version to call based on the number, type, and order of arguments supplied at the call site.
Why it matters
Methods are how you name a piece of behaviour and reuse it. Overloading lets one name work for several kinds of input, which is why System.out.println accepts an int, a String or an object. The rules for which overload gets chosen are precise, and "which method is called here?" is a standard interview question.
Anatomy of a Method
A method declaration consists of an access modifier, an optional static keyword, a return type, a name, a parameter list in parentheses, and a body in braces. A method with return type void returns nothing; any other return type requires a return statement matching that type on every possible execution path.
Watch: Java Method Overloading, in Detail
Prefer to watch? This video explains method overloading: same method name, different parameter lists, and how the compiler chooses which one to call.
Rules for Overloading
For two methods with the same name to count as valid overloads, their parameter lists must differ in at least one of: the number of parameters, the types of the parameters, or the order of parameter types. The compiler resolves which overload to call by matching the arguments at the call site, using exact type matches first, then widening conversions, then autoboxing, and finally varargs, in that priority order.
void print(int a)andvoid print(int a, int b)— valid, different parameter count.void print(int a)andvoid print(double a)— valid, different parameter type.void print(int a, String b)andvoid print(String a, int b)— valid, different parameter order.
What Does NOT Count as Overloading
Changing only the return type while keeping the exact same name and parameter list is not valid overloading — it causes a compile-time error, because the compiler determines which method to call based on the arguments passed, not on what the caller does with the return value. Two methods with an identical signature (name + parameter types) cannot coexist no matter what their return types are.
How the Compiler Picks an Overload
When a call could match more than one overload, the compiler searches in phases and stops at the first phase that finds a match. Within a phase, it chooses the most specific method.
- 1. Exact match or widening — a parameter of the same type, or a wider primitive (
byte→short→int→long→float→double). - 2. Autoboxing — only if phase 1 found nothing, the compiler tries boxing an
inttoInteger(or unboxing the reverse). - 3. Varargs — a
...parameter is the last resort, used only when no fixed-parameter method fits.
Overloading You Already Use
The JDK relies on overloading everywhere. System.out.println has separate versions for int, double, char, boolean, String and Object, which is why one method name prints anything. Math.max and Math.abs have int, long, float and double versions so the result keeps the type you passed in. Overload when the operations really do the same job for different inputs; if they do different jobs, give them different names.
Examples
Overloading resolved by parameter count and type
public class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int add(int a, int b, int c) {
return a + b + c;
}
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(2, 3));
System.out.println(calc.add(2.5, 3.5));
System.out.println(calc.add(1, 2, 3));
}
}
5
6.0
6
Which overload runs: widening beats boxing, and varargs comes last
public class OverloadResolution {
static void show(long value) {
System.out.println("long version: " + value);
}
static void show(Integer value) {
System.out.println("Integer version: " + value);
}
static void show(int... values) {
System.out.println("varargs version: " + values.length + " values");
}
public static void main(String[] args) {
show(5); // no show(int): widening int -> long beats boxing to Integer
byte small = 3;
show(small); // byte also widens to long
show(Integer.valueOf(7)); // exact match for Integer
show(); // only varargs accepts zero arguments
show(1, 2, 3); // only varargs accepts three arguments
}
}
long version: 5
long version: 3
Integer version: 7
varargs version: 0 values
varargs version: 3 values
Common Mistakes
- Trying to overload two methods that differ only in return type — this is a compile error, not valid overloading.
- Expecting the compiler to pick an overload based on how the result is used rather than the argument list passed in.
- Confusing overloading (same class, same name, different parameters, resolved at compile time) with overriding (subclass, same signature, resolved at runtime).
- Passing an argument type that matches multiple overloads ambiguously (e.g. calling with a null literal when two reference-type overloads both apply), causing a compile-time "ambiguous method call" error.
Exercise
Write three overloaded area methods: one taking a single int (a square), one taking two ints (a rectangle), and one taking a double (a circle of that radius).
Expected output: 25, 12, then 3.141592653589793
public class Area {
// TODO: area(int side)
// TODO: area(int width, int height)
// TODO: area(double radius) using Math.PI
public static void main(String[] args) {
System.out.println(area(5));
System.out.println(area(3, 4));
System.out.println(area(1.0));
}
}
Show hints
- Overloads share a name and differ in the number or types of their parameters.
area(5)picks the int version;area(1.0)picks the double version.
Show solution
public class Area {
static int area(int side) {
return side * side;
}
static int area(int width, int height) {
return width * height;
}
static double area(double radius) {
return Math.PI * radius * radius;
}
public static void main(String[] args) {
System.out.println(area(5)); // 25
System.out.println(area(3, 4)); // 12
System.out.println(area(1.0)); // 3.141592653589793
}
}
Quick quiz
1. Can two methods in the same class have the same name and parameters but different return types?
- A. Yes, that is valid overloading
- B. Only if one is private
- C. Only if one is static
- D. No, it is a compile error
Show answer
D. The return type is not part of the method signature. Two methods that differ only in return type are duplicates.
2. A class has print(int x) and print(long x). Which one does print(5) call?
- A. print(long)
- B. print(int)
- C. It is ambiguous
- D. Neither
Show answer
B. The literal 5 is an int, and an exact match is always preferred over a widening conversion.
3. A class has only show(double d). What happens with show(5)?
- A. Compile error
- B. It works; the int is widened to double
- C. It throws an exception
- D. It prints 5 as an int
Show answer
B. With no exact match, the compiler applies a widening conversion from int to double.
Interview questions
What makes up a method signature in Java?
Show answer
The method name and the types of its parameters, in order. The return type, the parameter names, the access modifier and the exceptions it declares are not part of the signature. That is why overloads must differ in their parameter list.
How does the compiler choose between overloaded methods?
Show answer
It looks for the most specific match in stages. First an exact match of the argument types; then widening of primitives, such as int to long; then boxing and unboxing, such as int to Integer; and only last a varargs method. The choice is made at compile time from the declared types of the arguments.
Key Points to Remember
- Overloading requires a different parameter list — different count, types, or order.
- Return type alone is never enough to distinguish overloaded methods.
- Method overloading is compile-time (static) polymorphism, resolved by the compiler based on argument types.
- The compiler tries exact match or widening first, then autoboxing, then varargs, so show(5) prefers show(long) over show(Integer).
Practice in the playground
Write and run your own code for this topic, or start from the exercise or an example. Runs plain Java 17. Frameworks such as Spring, and databases, are not available here. Your code for each topic is kept in this browser.
Run the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Written by
WebNest Studio Engineering Team
Practical lessons from developers working with Java, Python, React, databases and production systems.
Led by Vansh Duggal, Founder, WebNest Studio · Full-stack & software engineering