Methods
Methods are the building blocks of every Java program. They let you name a reusable chunk of logic, call it whenever you need it, and keep your code clean and readable — whether you’re writing a ten-line script or a million-line enterprise app.
What Is a Method?
A method is a named block of code inside a class that performs a specific task. Instead of copy-pasting the same logic everywhere, you write it once in a method and call it by name.
public class Greeter {
// declaring a method
static void sayHello() {
System.out.println("Hello, World!");
}
public static void main(String[] args) {
sayHello(); // calling the method
sayHello(); // call it as many times as you want
}
}
Output:
Hello, World!
Hello, World!
Method Syntax
<access-modifier> <other-modifiers> <return-type> <methodName>(<parameters>) {
// body
return value; // only needed when return-type is not void
}
| Part | What it means |
|---|---|
| access modifier | public, private, protected, or package-private |
| other modifiers | static, final, abstract, synchronized, etc. |
| return type | the type of value the method gives back; void means nothing |
| method name | camelCase identifier (e.g., calculateTax) |
| parameters | comma-separated list of typed variables the caller passes in |
| body | the actual code that runs |
Tip: Follow Java naming conventions — method names start with a lowercase letter and use camelCase:
getUserName(),calculateTotal().
Parameters and Arguments
Parameters are the variables listed in the method declaration. Arguments are the actual values you pass when calling the method.
public class Calculator {
// two parameters: a and b
static int add(int a, int b) {
return a + b;
}
public static void main(String[] args) {
int result = add(3, 7); // 3 and 7 are arguments
System.out.println("Sum: " + result);
}
}
Output:
Sum: 10
Passing Multiple Parameters
static String buildGreeting(String name, int age) {
return "Hi " + name + ", you are " + age + " years old.";
}
Note: Java always passes primitives by value — the method gets a copy of the number, not a reference to the original variable. For objects, the reference is passed by value, meaning you can mutate the object’s fields but cannot reassign the caller’s variable. See Call by Value for a deeper dive.
Return Types
A method can return any type — a primitive, an object, an array, or nothing at all (void).
public class ShapeUtils {
// returns a double
static double circleArea(double radius) {
return Math.PI * radius * radius;
}
// returns a String
static String classify(int n) {
return (n % 2 == 0) ? "even" : "odd";
}
// returns void — nothing to return
static void printDivider() {
System.out.println("----------");
}
public static void main(String[] args) {
System.out.println(circleArea(5.0));
System.out.println(classify(7));
printDivider();
}
}
Output:
78.53981633974483
odd
----------
Warning: If your return type is anything other than
void, the compiler enforces that every code path returns a compatible value. Forgetting areturnin a branch causes a compile-time error.
Static vs Instance Methods
| Static method | Instance method | |
|---|---|---|
| Belongs to | The class | A specific object |
| Call syntax | ClassName.method() | objectRef.method() |
| Accesses | Only static fields/methods | Both static and instance fields/methods |
| Common use | Utility / factory methods | Business logic that needs object state |
public class Counter {
private int count = 0; // instance field
// instance method — needs the object's state
public void increment() {
count++;
}
public int getCount() {
return count;
}
// static utility — needs no object state
public static int add(int x, int y) {
return x + y;
}
public static void main(String[] args) {
Counter c = new Counter();
c.increment();
c.increment();
System.out.println(c.getCount()); // 2
System.out.println(Counter.add(10, 20)); // 30
}
}
Output:
2
30
For more on the static keyword, see static Keyword.
Method Overloading
Java lets you define several methods with the same name as long as their parameter lists differ (different number, types, or order of parameters). The compiler picks the right one at compile time — this is called compile-time polymorphism.
public class Printer {
static void print(int n) {
System.out.println("int: " + n);
}
static void print(double d) {
System.out.println("double: " + d);
}
static void print(String s) {
System.out.println("String: " + s);
}
static void print(int a, int b) {
System.out.println("two ints: " + a + ", " + b);
}
public static void main(String[] args) {
print(42);
print(3.14);
print("hello");
print(1, 2);
}
}
Output:
int: 42
double: 3.14
String: hello
two ints: 1, 2
Note: Return type alone does not distinguish overloaded methods.
int foo()andvoid foo()in the same class is a compile error.
Dive deeper at Method Overloading and Compile-Time Polymorphism.
Variable-Length Arguments (Varargs)
When you don’t know how many arguments the caller will pass, use a varargs parameter with .... Java bundles the values into an array for you.
static int sum(int... numbers) {
int total = 0;
for (int n : numbers) {
total += n;
}
return total;
}
public static void main(String[] args) {
System.out.println(sum(1, 2, 3)); // 6
System.out.println(sum(10, 20, 30, 40)); // 100
System.out.println(sum()); // 0
}
Output:
6
100
0
Tip: Varargs must be the last parameter in the list. Learn more at Varargs.
Recursive Methods
A method can call itself — this is called recursion. Each call adds a new frame to the call stack until the base case is reached.
static int factorial(int n) {
if (n <= 1) return 1; // base case
return n * factorial(n - 1); // recursive call
}
public static void main(String[] args) {
System.out.println(factorial(5)); // 120
}
Output:
120
Warning: Infinite recursion causes a
StackOverflowError. Always define a clear base case. See Recursion for a full guide.
Under the Hood
When you invoke a method, the JVM pushes a new stack frame onto the current thread’s Java stack. The frame holds:
- The local variable array — slots for all parameters and local variables.
- The operand stack — a working area for intermediate computation results.
- A reference back to the runtime constant pool of the class.
When the method returns, its frame is popped and control resumes in the calling frame.
Static dispatch vs dynamic dispatch
- A call to a
staticorprivatemethod is resolved at compile time (stored as ainvokestaticorinvokespecialbytecode instruction). The JVM jumps straight to the target. - A call to a non-final instance method uses
invokevirtual, which looks up the method in the object’s vtable at runtime — enabling runtime polymorphism.
JIT inlining
The JIT compiler watches which methods are called frequently (“hot methods”). Short methods — especially getters, setters, and small utilities — are often inlined: the callee’s bytecode is substituted directly into the caller, eliminating the frame-creation overhead entirely. This is why small, focused methods are not only more readable but also perform well in production. See JIT Compilation for the full picture.
Stack depth and recursion
The default thread stack size is typically 256 KB–1 MB (JVM-dependent). Each frame consumes memory for its locals and operand stack, so deeply recursive methods can exhaust the stack. For deep recursion, consider converting to an iterative approach or increasing the stack size with -Xss.
Common Mistakes
- Forgetting
return— if every code path must return a value, the compiler catches it, but conditional branches are easy to miss. - Returning the wrong type — a widening conversion (e.g.,
int→long) is fine; a narrowing one requires an explicit cast. - Overloading on return type only — Java does not support this; you must differ on parameters.
- Shadowing fields with local variables — inside an instance method, a local variable named
counthides the fieldthis.count. Usethis.countto refer to the field explicitly.
Related Topics
- Classes & Objects — methods live inside classes; understand the container first.
- Constructors — a special kind of method used to initialize objects.
- Method Overloading — declaring multiple methods with the same name.
- Method Overriding — redefining an inherited method in a subclass.
- static Keyword — when and why to make a method static.
- Recursion — writing methods that call themselves, with examples and pitfalls.