Method Signatures
- AP CSA 1.9 — Method Signatures (2025)
- Introduction
- Learning goals
- Quick reference
- Example: runnable Java class (overloading)
- What is and isn’t in a signature
- Not overloading by return type (concept)
- Runnable example: Overload resolution with literals and variables
- Ambiguity and overload selection (concept)
- Popcorn Hack: Write and test max overloads
- Popcorn Hack 1 Answer:
- Popcorn Hack: Overload print for int and String
- Popcorn Hack 2 Answer:
- Parameter passing (concept)
- FRQ-style runnable templates
- FRQ Answer Key:
- Anatomy of a method header (AP scope)
- Overloading checklist
- Common pitfalls
- Best practices
AP CSA 1.9 — Method Signatures (2025)
Introduction
In Java, a method’s signature determines which method is called. Understanding what is and is not part of a signature is essential for reading APIs and writing overloaded methods.
Learning goals
- Identify what constitutes a Java method signature (per AP): method name + parameter types and order.
- Distinguish parameters vs arguments; return type is NOT part of the signature.
- Explain method overloading and how Java selects an overload.
- Write valid method headers and call them correctly.
- Trace evaluation for calls with literals, variables, and expressions.
Quick reference
- Signature (AP scope):
methodName(type1, type2, ...)— only name + parameter types/order. - Not in signature: return type, parameter names, access modifiers.
- Overloading: same name, different parameter lists (type and/or arity and/or order).
- Calls: arguments must be compatible with the parameter types (with standard promotions/widening allowed).
- Return: a method declared
voidreturns nothing; non-void mustreturna value of its declared type. - Widening at call site:
int→doubleallowed; narrowing requires explicit cast.
Example: runnable Java class (overloading)
public class SigDemo {
public static int add(int a, int b) { // signature: add(int, int)
return a + b;
}
public static double add(double a, double b) { // signature: add(double, double)
return a + b;
}
public static int add(int a) { // signature: add(int)
return a + 1;
}
public static int increment(int a) { // different name
return a + 1;
}
public static void main(String[] args) {
System.out.println(add(3, 4)); // 7
System.out.println(add(3.0, 4)); // 7.0
System.out.println(add(5)); // 6
System.out.println(increment(9)); // 10
}
}
What is and isn’t in a signature
- In AP CSA scope, signature = name + parameter types and order:
name(T1, T2, ...). - NOT in signature: return type, parameter names, access modifiers,
throwsclauses. - Therefore, you cannot overload by changing only the return type.
Not overloading by return type (concept)
- Changing only the return type does not create a new signature.
- If two methods differ only by return type and are otherwise identical, it’s a compile-time error.
- Tip: Change parameter types/arity/order to overload correctly.
Runnable example: Overload resolution with literals and variables
public class OverloadPick {
static void show(int x) { System.out.println("int:" + x); }
static void show(double x) { System.out.println("double:" + x); }
static void show(long x) { System.out.println("long:" + x); }
public static void main(String[] args) {
show(5); // int literal → show(int)
show(5L); // long literal → show(long)
show(5.0); // double literal → show(double)
int i = 7; long L = 7L; double d = 7.0;
show(i); show(L); show(d);
}
}
Ambiguity and overload selection (concept)
- Java prefers the most specific applicable method without narrowing.
intliteral can widen tolongor convert tofloat; integral widening tolongis typically chosen.- Avoid ambiguous designs: provide distinct parameter lists or cast at the call site to disambiguate.
Popcorn Hack: Write and test max overloads
Instructions: Write two overloaded methods named max that each return the larger of two numbers.
One should accept two int values.
The other should accept two double values.
Then, test both versions in the main method.
public class PopcornMax {
// TODO: write int version of max
// TODO: write double version of max
public static void main(String[] args) {
System.out.println(max(3, 9)); // expected: 9
System.out.println(max(-2, -7)); // expected: -2
System.out.println(max(3.5, 2.9)); // expected: 3.5
System.out.println(max(2, 2.0)); // should call double version → 2.0
}
}
public class PopcornMax {
static int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
static double max(double a, double b) {
if (a > b) {
return a;
} else {
return b;
}
}
public static void main(String[] args) {
System.out.println(max(3, 9)); // expected: 9
System.out.println(max(-2, -7)); // expected: -2
System.out.println(max(3.5, 2.9)); // expected: 3.5
System.out.println(max(2, 2.0)); // should call double version → 2.0
}
}
PopcornMax.main(new String[]{});
9
-2
3.5
2.0
Popcorn Hack 1 Answer:
public class PopcornMax {
// int overload
public static int max(int a, int b) {
return a >= b ? a : b;
}
// double overload
public static double max(double a, double b) {
return a >= b ? a : b;
}
public static void main(String[] args) {
System.out.println(max(3, 9)); // 9
System.out.println(max(-2, -7)); // -2
System.out.println(max(3.5, 2.9)); // 3.5
System.out.println(max(2, 2.0)); // 2.0 (int 2 promoted to double → calls max(double,double))
}
}
Popcorn Hack: Overload print for int and String
Instructions:Implement two overloaded print methods — one that accepts an int and prints int:. Test with mixed types.
public class PopcornPrint {
// TODO: write print(int n)
// TODO: write print(String s)
public static void main(String[] args) {
print(42); // expected: int:42
print("hello"); // expected: str:hello
print('A' + "!"); // char + String → String → expected: str:A!
}
}
public class PopcornPrint {
// TODO: write print(int n)
static void print(int n) {
System.out.println("int: " + n);
}
// TODO: write print(String s)
static void print(String s) {
System.out.println("str: " + s);
}
public static void main(String[] args) {
print(42); // expected: int:42
print("hello"); // expected: str:hello
print('A' + "!"); // char + String → String → expected: str:A!
}
}
PopcornPrint.main(new String[]{})
int: 42
str: hello
str: A!
Popcorn Hack 2 Answer:
public class PopcornPrint {
static void print(int n) {
System.out.println("int:" + n);
}
static void print(String s) {
System.out.println("str:" + s);
}
public static void main(String[] args) {
print(42); // int:42
print("hello"); // str:hello
print('A' + "!"); // str:A!
}
}
Parameter passing (concept)
- Primitives are passed by value. Changing the parameter does not change the argument in the caller.
- E.g., calling
bump(a)does not modifyaoutside the method.
public class FrqTemplates {
// FRQ 1
// TODO: implement sumRange(start, end) — sum inclusive, return 0 if start > end
public static int sumRange(int start, int end) {
if (start > end) return 0;
int sum = 0;
for (int n = start; n <= end; n++) {
sum += n;
}
return sum;
}
// FRQ 2
// TODO: implement area(radius) -> circle area (double)
// TODO: implement area(width, height) -> rectangle area (int)
public static double area(double radius) {
return radius * radius * Math.PI;
}
public static int area(int width, int height) {
return width * height;
}
// FRQ 3
// TODO: implement formatScore(earned, total) -> "earned/total"
// TODO: implement formatScore(percent) -> "xx.x%"
public static String formatScore(int earned, int total) {
// returns something like "45/50"
return earned + "/" + total;
}
public static String formatScore(double percent) {
// returns something like "92.4%"
return String.format("%.1f%%", percent);
}
public static void main(String[] args) {
System.out.println(sumRange(1, 5)); // expected: 15
System.out.println(area(3.0)); // expected: ~28.27
System.out.println(area(3, 4)); // expected: 12
System.out.println(formatScore(45, 50)); // expected: 45/50
System.out.println(formatScore(92.35)); // expected: 92.4%
}
}
// Run
FrqTemplates.main(new String[]{});
15
28.274333882308138
12
45/50
92.4%
FRQ-style runnable templates
Instructions:Practice FRQ-style overloaded methods. Implement sumRange, overloaded area (circle and rectangle), and overloaded formatScore (fraction and percent).
FRQ Answer Key:
public class FrqTemplates {
// FRQ 1: Sum all integers from start to end (inclusive)
public static int sumRange(int start, int end) {
if (start > end) return 0;
int sum = 0;
for (int n = start; n <= end; n++) {
sum += n;
}
return sum;
}
// FRQ 2: Overload area for circle vs. rectangle
public static double area(double radius) {
return Math.PI * radius * radius;
}
public static int area(int width, int height) {
return width * height;
}
// FRQ 3: Overload formatScore for fraction vs. percent
public static String formatScore(int earned, int total) {
return earned + "/" + total;
}
public static String formatScore(double percent) {
return String.format("%.1f%%", percent);
}
public static void main(String[] args) {
System.out.println(sumRange(1, 5)); // 15
System.out.println(area(3.0)); // ~28.274333882308138
System.out.println(area(3, 4)); // 12
System.out.println(formatScore(45, 50)); // 45/50
System.out.println(formatScore(92.35)); // 92.4%
}
}
Anatomy of a method header (AP scope)
- General form:
modifiers returnType name(parameterList) - Signature considered in AP:
name(parameterTypesInOrder) - Examples:
public static int sum(int a, int b)→ signaturesum(int,int)private double area(double r)→ signaturearea(double)
Overloading checklist
- Different parameter count and/or parameter types and/or order
- Same method name
- Return type alone does not differentiate
Common pitfalls
- Ambiguity between numeric types (
int,long,float,double) - Unintended autowidening creates a different overload call than expected
- Shadowing due to parameter names does not matter to signature
Best practices
- Keep overloads consistent in behavior and naming
- Prefer clear, non-ambiguous parameter lists
- Add documentation examples showing which overload is picked