SEN1001 · Week 5 · Methods

Methods: parameters, return, scope, overloading, Math and Random

Method header, parameter and argument, return and void, pass-by-value, scope, method overloading, the Math class and random number ranges. The foundation of the 'write a method' questions on the midterm.

methodmethod headerparameterargumentreturn typereturn statementvoidstatic methodmethod callpass-by-valuelocal variablescopemethod overloadingsignatureMath classRandomnextInt

A method is a named block of code that does one job. Instead of writing the same job in ten places, you write it once and call it from wherever you like. On the midterm it comes from two sides: “what do these calls print?” (tracing from the inside out, pass-by-value) and “write a method that does this job” (isPrime, sumDigits, max). In the second kind, writing the header correctly earns points on its own.

Golden rules:

  1. Header template: public static <return type> <name>(<parameters>).
  2. If it is not void, every path must have a return and the returned value must match the type.
  3. return ends the method immediately.
  4. Pass-by-value: a method cannot change the caller’s variable.
  5. Overloading = same name, different parameter list. A different return type alone is not enough.

Anatomy of a method

public static double average(int a, int b) {
    return (a + b) / 2.0;
}
PartIn this exampleMeaning
access modifierpubliccan be called from anywhere
staticstaticcalled directly, without creating an object (main is static too)
return typedoublethe type of the value the method gives back; void if it gives nothing
nameaveragestarts lowercase, like a verb: computeTotal, isEven
parameter list(int a, int b)the values the method takes from outside
body{ return ...; }where the work is done

A parameter is the variable in the header: a, b. An argument is the actual value given during the call: 3 and 4 in the call average(3, 4). The number, order and type of the arguments must match the parameters.

In this course, methods are written in the same class as main and are static because they are called from main. Defining a method does not run it; it runs only when it is called.

return and void

public static int twice(int n) { return n * 2; }
public static void greet(String name) { System.out.println("Hi " + name); }
public static int max(int a, int b) {
    if (a > b) return a;
    return b;
}
public static void line(int n, char c) {
    for (int i = 0; i < n; i++) System.out.print(c);
    System.out.println();
}
// in main:
System.out.println(twice(4));
greet("Deniz");
int t = twice(twice(3));     // inside out: twice(3) = 6, twice(6) = 12
System.out.println(t);
System.out.println(average(3, 4));
System.out.println(max(8, 11) + " " + max(5, 5));
line(5, '=');
8
Hi Deniz
12
3.5
11 5
=====
  • A method that returns a value is used inside an expression: it is printed, assigned to a variable, or becomes an argument to another call.
  • A void method does a job (like printing) and returns nothing. System.out.println(greet("x")) does not compile.

Return errors the compiler catches

static int f(int a) { return 2.5; }              // double does not fit in int
static void g() { return 5; }                    // void cannot return a value
static int h(int a) { if (a > 0) return 1; }     // no return when a <= 0
Ret.java:2: error: incompatible types: possible lossy conversion from double to int
Ret.java:3: error: incompatible types: unexpected return value
Miss.java:2: error: missing return statement

The missing return statement error says this: the compiler cannot know what the method will return when the condition is false. There must be a return at the end of every possible path.

Tracing calls and pass-by-value

When a method is called, Java:

  1. Computes the arguments.
  2. Copies their values into the parameters.
  3. Runs the method’s body.
  4. When it sees return, carries the value back to where the call was made.
public static void change(int x) {
    x = 100;
    System.out.println("inside: " + x);
}
// in main:
int a = 3;
change(a);
System.out.println("outside: " + a);
inside: 100
outside: 3

Not a itself but its value (3) went to change. x = 100 changed only the method’s own copy. This is called pass-by-value, and everything in Java is passed this way. (With arrays and objects this rule has an interesting consequence; you will see it in weeks 6 and 13.)

Scope

A variable lives only inside the block { } where it is declared.

  • A variable declared inside a method (a local variable) is not visible in another method.
  • Parameters are local too; they disappear when the method ends.
  • A counter declared in a for header does not exist after the loop.
static void a() { int secret = 5; }
static void b() { System.out.println(secret); }
LocalScope.java:3: error: cannot find symbol

Different methods can have variables with the same name (n in main, n in counter); they are unrelated to each other.

Method overloading

A class can have several methods with the same name, as long as their parameter lists (count, type or order) differ. The combination of the method name and the parameter types is called the signature.

static int add(int a, int b) { return a + b; }
static double add(double a, double b) { return a + b; }
static int add(int a, int b, int c) { return a + b + c; }
// in main:
System.out.println(add(2, 3));       // int, int
System.out.println(add(2.0, 3));     // double, int → 3 widens → add(double, double)
System.out.println(add(1, 2, 3));    // three arguments
5
5.0
6

The selection rule: first an exact match is looked for. If there is none, Java goes to the nearest type the argument can widen to (int → long → float → double). Narrowing is never done automatically.

PITFALL · only the return type differs. static int k(int a) and static double k(int b) do not compile together: method k(int) is already defined. The parameter name and the return type are not part of the signature.

The Math class

The methods of Math are static: they are called as Math.name(...), no import is needed.

System.out.println(Math.pow(3, 2));
System.out.println(Math.sqrt(16));
System.out.println(Math.max(4, 9) + " " + Math.min(4, 9));
System.out.println(Math.max(4, 9.0));
System.out.println(Math.abs(-3.5) + " " + Math.abs(-7));
System.out.println(Math.round(3.49) + " " + Math.round(3.5) + " " + Math.round(-2.5));
System.out.println(Math.ceil(2.1) + " " + Math.floor(2.9) + " " + Math.ceil(-2.1));
System.out.println(Math.PI);
9.0
4.0
9 4
9.0
3.5 7
3 4 -2
3.0 2.0 -2.0
3.141592653589793
MethodWhat it doesReturn type
Math.pow(a, b)a to the power balways double
Math.sqrt(x)square rootdouble
Math.abs(x)absolute valuetype of the argument
Math.max(a, b), Math.min(a, b)larger, smallertype of the arguments (double if one is double)
Math.round(x)nearest integer, .5 rounds uplong (with a double argument)
Math.ceil(x)round updouble
Math.floor(x)round downdouble

PITFALL · Math.pow(2, 3) is 8.0, not 8. In output questions, remember that methods returning a double are printed with .0.

Math.round(-2.5) gives -2: the rule “.5 rounds up” means up on the number line, that is, toward the larger number.

Random numbers

There are two ways:

import java.util.Random;
Random rand = new Random();
int die = rand.nextInt(6) + 1;                  // 1..6
int r = rand.nextInt(11) + 10;                  // 10..20
int m = (int) (Math.random() * 100) + 1;        // 1..100

The smallest and largest values seen when each expression is run a million times:

1..6 10..20 1..100

The formula: for min..max, rand.nextInt(max - min + 1) + min. nextInt(k) produces k different values from 0 to k-1; + min shifts the range.

Math.random() gives a double between 0.0 and 1.0 (1.0 excluded). Multiply, cast, shift. The placement of the parentheses is critical: (int) Math.random() * 100 is always 0, because the cast is done before the multiplication.

Worked example: how a writing question earns points

In a question like “write isPrime”, partial credit comes in this order:

  1. Header: public static boolean isPrime(int n). If the answer is yes/no, the return type is boolean.
  2. Special case: if (n < 2) return false;
  3. Loop and condition: for (int i = 2; i * i <= n; i++) if (n % i == 0) return false;
  4. After the loop: return true;
  5. Test on paper with an example: for 9, i = 2 (remainder 1), i = 3 (remainder 0) → false. Correct.

PITFALL · putting return true in an else. If you write if (n % i == 0) return false; else return true;, the loop ends on the first iteration and you only check divisibility by 2. It says 9 is “prime”.

Common mistakes

Wrong ideaThe truth
Defining a method runs itIt runs only when called
The returned value is written somewhere automaticallyIf you do not assign or print it, it is lost
Changing a parameter inside a method changes mainPass-by-value, the copy changes
Lines after return also runThe method ends there
return x; from a void methodOnly return; is allowed
Two methods differing only in return type = overloadingDoes not compile
Math.sqrt(16) → 44.0
Math.round(2.5) → 23
rand.nextInt(6) for a dieIt gives 0..5; add + 1
(int) Math.random() * 6 + 1 as a dieAlways 1; write (int) (Math.random() * 6) + 1
Accessing another method’s variableA local variable lives only in its own block

Test yourself

Exam-style questions. Solve them on paper first, then reveal the answer.

Question 1easy

What is printed?

static int f(int x) { return x + 3; }
static int g(int x) { return f(x) * 2; }
// in main:
System.out.println(g(4));
Show answer
14

g(4) first calls f(4): 4 + 3 = 7. Back in g: 7 * 2 = 14. The inner call always finishes first.

Question 2easy

What is printed?

static int mystery(int n) {
    int r = 0;
    for (int i = 1; i <= n; i++) {
        if (i % 2 == 1) r += i;
    }
    return r;
}
// in main:
System.out.println(mystery(6));
Show answer
9

It adds the odd numbers from 1 to 6: 1 + 3 + 5 = 9.

Question 3medium

What is printed?

static void swap(int a, int b) {
    int t = a; a = b; b = t;
    System.out.println("in swap: " + a + " " + b);
}
// in main:
int x = 5, y = 9;
swap(x, y);
System.out.println("in main: " + x + " " + y);
Show answer
in swap: 9 5
in main: 5 9

Java works by pass-by-value: copies of x and y go to the method. swap changes its own copies (it prints 9 5) but cannot touch x and y in main.

Question 4medium

What is printed?

static int early(int n) {
    if (n > 5) return 1;
    System.out.println("small");
    return 0;
}
// in main:
System.out.println(early(8));
System.out.println(early(2));
Show answer
1
small
0

early(8): 8 > 5 → return 1, the method ends immediately, small is not printed. early(2): the condition is false, small is printed, then 0 is returned and main prints it.

Question 5medium

What is printed?

static int counter(int n) {
    n++;
    return n;
}
// in main:
int n = 10;
n = counter(n);
counter(n);
System.out.println(n);
Show answer
11

The result of the first call (11) is assigned to n. The second call returns 12, but since the result is not assigned anywhere, it is lost. The n in main stays 11.

Question 6medium

What is printed?

static void show(int x)    { System.out.println("int: " + x); }
static void show(double x) { System.out.println("double: " + x); }
static void show(String s) { System.out.println("String: " + s); }
// in main:
show(7 / 2);
show(7 / 2.0);
show("" + 7 / 2);
Show answer
int: 3
double: 3.5
String: 3

The argument is computed first, then the method is chosen by its type. 7 / 2 = 3 (int) → show(int). 7 / 2.0 = 3.5 (double) → show(double). "" + 7 / 2: division first (3), then concatenation → the String "3" → show(String).

Question 7hard

Only these two overloads exist. What is printed?

static void p(double d) { System.out.println("double " + d); }
static void p(long l)   { System.out.println("long " + l); }
// in main:
p(5);
p(5.0f);
Show answer
long 5
double 5.0

There is no p(int). Java sends an int argument to the nearest type it can widen to: int → long comes before double. 5.0f is a float; it cannot go to long (narrowing), it widens to double.

Question 8medium

What is printed?

System.out.println(Math.pow(2, 3) + Math.max(2, 3));
System.out.println(Math.sqrt(25) + " " + Math.abs(-4) + " " + Math.round(2.5));
System.out.println(Math.ceil(4.1) + " " + Math.floor(4.9) + " " + (int) Math.ceil(4.1));
Show answer
11.0
5.0 4 3
5.0 4.0 5

pow always returns a double: 8.0 + 3 = 11.0. sqrt is also a double: 5.0. abs and max keep the type of the argument: 4. round(2.5) is the nearest integer, .5 rounds up: 3. ceil/floor return a double: 5.0, 4.0. Converted to int with a cast, 5.

Question 9medium

What is printed?

static int square(int x) { return x * x; }
static int twice(int n)  { return n * 2; }
static int max(int a, int b) { if (a > b) return a; return b; }
// in main:
System.out.println(square(square(2)) + square(3));
System.out.println(max(square(3), twice(5)));
Show answer
25
10

square(2) = 4, square(4) = 16, square(3) = 9, 16 + 9 = 25. Second line: max(9, 10) = 10.

Question 10medium

Assume Random rand = new Random();. Which values can each expression produce? (a) rand.nextInt(6) + 1 (b) rand.nextInt(5) + 3 (c) (int) (Math.random() * 10) (d) (int) Math.random() * 10

Show answer
(a) 1..6 (b) 3..7 (c) 0..9 (d) always 0

nextInt(k) gives 0 to k-1. (a) 0..5 + 1. (b) 0..4 + 3. (c) Math.random() is 0.0 ≤ x < 1.0, × 10 → 0.0..9.99, cast → 0..9. (d) The cast applies first to Math.random(): (int) 0.73 = 0, 0 * 10 = 0. In verification the sum of 1000 trials came out 0.

Question 11medium

Write a static method isPrime(int n) that returns true if n is prime. Numbers less than 2 are not prime.

Show answer
if (n < 2) return false; for (int i = 2; i * i <= n; i++) if (n % i == 0) return false; return true;

You look for a divisor; finding one is enough. return true must be outside the loop: it runs only if no divisor was found.public static boolean isPrime(int n) { if (n < 2) return false; for (int i = 2; i * i <= n; i++) { if (n % i == 0) return false; } return true;}Primes from 1..30: 2 3 5 7 11 13 17 19 23 29. isPrime(49) → false, isPrime(97) → true. Writing i < n instead of i * i <= n is also correct, just slower.

Question 12medium

Write a static method sumDigits(int n) that returns the sum of the digits of a non-negative integer, using a while loop. Example: sumDigits(4823) returns 17.

Show answer
while (n > 0) { sum += n % 10; n /= 10; } return sum;

% 10 gives the last digit, / 10 removes it. When n becomes 0 there are no digits left.public static int sumDigits(int n) { int sum = 0; while (n > 0) { sum += n % 10; n /= 10; } return sum;}Test: 4823 → 17, 309 → 12, 7 → 7, 0 → 0 (the loop is never entered).

Verification: All outputs were run with JDK 26 (verify/SEN1001/W05.java). The Random ranges were observed over 1,000,000 trials (min..max). The compile errors were obtained by compiling verify/SEN1001/err/Ret.java, Miss.java and LocalScope.java with javac.

Review card

public static returnType name(type p1, type p2) { ... return value; } void → returns no value; return 5; in a void method does not compile (unexpected return value) return 2.5; in an int method → lossy conversion missing return in an if branch → missing return statement Parameter = variable in the header Argument = value in the call count, order, type must match return ends the method IMMEDIATELY, lines below do not run The inner call goes first: g(f(2)) if you do not use the returned value it is lost Pass-by-value: a COPY goes to the method, the variable in main does not change Scope: a variable lives inside the { } where it is declared; another method's local variable is not visible Overloading: same name, different parameter list (count/type/order). Only a return type difference → does not compile Choice: exact match, otherwise widening int → long → float → double Math.pow, sqrt, ceil, floor → double abs, max, min → keep the type round(2.5)=3 round(-2.5)=-2 Random rand = new Random(); import java.util.Random; min..max: rand.nextInt(max - min + 1) + min die: nextInt(6) + 1 (int)(Math.random() * n) → 0..n-1 (int) Math.random() * n → always 0