Static Methods — A First Look
Reusable named code: headers, parameters, returns, calls, and how scope works
You have been calling methods all quarter — System.out.println, Math.sqrt, s.length(), Integer.parseInt, sc.nextLine(). Every time you put a name, a dot, and () together, you made a method call. Now you will write your own. This is a first-look lesson; a later unit revisits methods in depth. The basics belong here because you will use them in every lab from this point on.
In a nutshell
A method is a named piece of code you can run from somewhere else by writing its name and (). A static method is the simplest kind: you call it on the class name itself, no objects required.
Methods exist for two reasons. First, code reuse — write a computation once, call it from twenty places. Second, decomposition — break a long main into small named pieces that each do one understandable thing.
By the end of this lesson you will be able to read a method header, explain the difference between a parameter and an argument, trace a method call by hand (watching values flow in and out), and understand why a variable declared in one method is invisible inside another.
Quick reference
Anatomy of a static method
public static int square (int n) { return n * n; }
// ^ ^ ^ ^ ^
// modifiers return name parameter body
// type list
Terminology
| Term | Meaning | Example |
|---|---|---|
| Method header | The first line: modifiers, return type, name, parameter list | public static int square(int n) |
| Return type | Type of the value the method gives back, or void for none |
int |
| Method name | camelCase convention | square, ageInYears |
| Parameter | The variable in the method definition | int n |
| Argument | The value passed at the call site | 5 in square(5) |
| Call / invoke | Running the method | square(5) |
return statement |
Ends the method and produces the value | return n * n; |
void |
“No return value”; the method ends at } or a bare return; |
public static void greet() { ... } |
Calling a method
int result = square(5); // passes 5; result gets 25
System.out.println(square(7)); // passes 7; prints 49
A call to a non-void method is an expression — it produces a value you can assign, print, or use inside a bigger expression.
Deep dive
1. Why methods exist — decomposition and reuse
Here’s a program that prints three different labeled banners:
public static void main(String[] args) {
System.out.println("**********************");
System.out.println("* Welcome! *");
System.out.println("**********************");
// ... other code ...
System.out.println("**********************");
System.out.println("* Session 2 *");
System.out.println("**********************");
// ... other code ...
System.out.println("**********************");
System.out.println("* Goodbye! *");
System.out.println("**********************");
}
Three copies of the same “print a boxed message” pattern. If you widen the box, you have to change three places. A typo in one breaks consistency. This is exactly the problem methods solve.
Factor out the pattern:
public static void printBox(String message) {
System.out.println("**********************");
System.out.println("* " + message + " *");
System.out.println("**********************");
}
public static void main(String[] args) {
printBox("Welcome! ");
printBox("Session 2 ");
printBox("Goodbye! ");
}
Same output. Nine lines of main became three. Change the box once; every caller gets the new version. That’s code reuse.
It’s also decomposition. main now reads like a table of contents: welcome, session 2, goodbye. The reader scanning main sees the program’s shape in one glance. The details of how each banner prints are tucked inside printBox, where you look only when you care.
Self-check. Why not just copy-paste the three
printlnlines everywhere? Give two concrete reasons.Answer
(1) Changes require editing in multiple places and you will forget one. (2) Each copy is another opportunity for a typo, so the copies drift apart silently.
2. Method anatomy — headers, parameters, returns
Here’s a method with parameters and a return value:
public static int max(int x, int y) {
if (x > y) {
return x;
} else {
return y;
}
}
Label every part:
public— a modifier. For now: “this method can be called from anywhere.” (More in Week 5.)static— another modifier. Means the method belongs to the class rather than to any particular object. That is why you call it on the class name:MyClass.max(3, 7).
staticis notfinal. These two modifiers get confused constantly because they both show up in front of method and field declarations. They do unrelated jobs:
staticcontrols who owns it:static= belongs to the class, call on the class name, no object needed. Non-static= belongs to an instance, requires an object.finalcontrols whether it can change or be overridden:finalon a variable means “cannot be reassigned after initialization.”finalon a method means “subclasses cannot override it.”finalon a class means “cannot be subclassed.”A method can be
staticalone,finalalone, both (public static final int MAX = 100;is a classic constant declaration), or neither. Same with fields. They do not imply each other.
int— the return type. This method hands back anint.max— the method name. Use a name that describes the answer it returns.(int x, int y)— the parameter list. Twointinputs, which the method callsxandy.{ ... }— the method body.return x;/return y;— return statements. Each one ends the method and produces the value that gets sent back.
A method that doesn’t produce a value uses void:
public static void greet(String name) {
System.out.println("Hi, " + name);
}
void methods do work (like printing) and then end. printBox above is a void method.
Parameter vs argument. These words are not synonyms. The parameter is the variable in the method definition — int n in square(int n). The argument is the value you pass at the call site — the 5 in square(5). When the call happens, Java takes the argument and assigns it to the parameter. You’ll hear people use these words interchangeably in casual speech, but the distinction matters when you are debugging.
public static int max(int x, int y) { ... } and the call max(5, 3), which is the argument?5 is a value. int x is the parameter — the variable inside the method that receives the value. When the call runs, Java assigns x = 5 and y = 3 inside max.
Self-check. What is the return type of
Integer.parseInt? Its parameter list?Answer
Return type:
int. Parameter list:(String s). You have been calling it asInteger.parseInt(sc.nextLine())all quarter: theStringreturned bynextLine()is the argument; theintreturned byparseIntis what you store in a variable.
3. Calling, tracing, and scope
Here is what happens step by step when you call a method:
public static int square(int n) {
return n * n;
}
public static void main(String[] args) {
int a = 5;
int result = square(a);
System.out.println(result);
}
Trace:
mainstarts. Java creates a local variablea = 5.- Java evaluates the argument
ainsquare(a)to get the value5. - Java calls
square, creating a new local variableninside the method and assigning it the value5.nis a copy of the argument. - The body runs:
return n * nevaluates to5 * 5 = 25and hands that value back. - Back in
main, the call expressionsquare(a)has produced25. Java stores25inresult. mainprints25and ends.
Two important things happen here.
Parameters are like local variables for the method. They exist only during the call. When the method returns, they disappear. n does not exist back in main after step 5 — there is no way to access it from outside.
Arguments are values, not shared variables. When you wrote square(a), Java did not share the variable a with square — it passed a’s current value (5) into the parameter n. If square reassigned n inside its body, the variable a in main would not change. This rule is called pass by value for primitives, and it keeps methods from accidentally corrupting the caller’s data.
Self-check. Trace:
public static void bump(int n) { n = n + 1; } public static void main(String[] args) { int x = 5; bump(x); System.out.println(x); }What does this print?
Answer
Prints
5. Insidebump, the parameternwas a copy of the value5.n = n + 1changed the copy to6, and then the method ended —nvanished, taking the modified copy with it.xinmainwas never touched.
Scope is the technical word for “where a variable is visible.” A parameter is visible only inside its method. A local variable declared in main is not visible inside other methods. Methods can only see what is explicitly passed to them via parameters.
That’s a feature, not a limitation. It is what lets you write and test methods in isolation: every method is a self-contained unit with a clear contract of “what I need in” and “what I give out.”
Reflection. Why can’t the caller read the parameter
nfrom insidesquare(int n)after the method returns? Put differently, what would break in the language design if parameters leaked into the caller’s scope — how would testing and debugging a long program change if every method could read and write every other method’s locals?
Self-check. Can
square(int n)access the variableresultdeclared inmain?Answer
No.
resultis a local variable ofmain— out of scope insidesquare. Forsquareto see any ofmain’s values, they have to be passed explicitly as arguments.
A beginner bug worth naming
Declaring a method does not run it. This trips students up every quarter:
public static void greet() {
System.out.println("Hi");
}
public static void main(String[] args) {
// never called greet() — "Hi" does not print
}
The presence of greet in the file is irrelevant. Only greet() — with the parentheses, somewhere execution actually reaches — runs the method. Defining a method is writing the recipe; calling it is cooking.
Before you leave
Methods let you reuse code and decompose a long program into named pieces. You write a header, a body, and a return if you are producing a value. You call by name, passing arguments that become parameters inside the method. Parameters are local variables that live only during the call.
This is the CS1 first-exposure version. A later unit revisits the topic and adds: passing objects (where the sharing rule changes), helper methods that call other helper methods, and designing a whole program as a set of cooperating methods.
The next lesson pairs with this one: preconditions and input validation. Methods make assumptions about their inputs. When callers violate those assumptions, a well-designed method announces the problem immediately rather than returning a nonsense answer that contaminates the rest of the program.
Want to practice parameter-passing traces? The Reges midterm parameter-mystery problems on the practice platform (filed under the Week 5 methods set) cover exactly this territory.